Simple collsion not working to the left or top - collision

This should be a very easy question, basically I have two squares, and I'm trying to see if they overlap. So far I've figured out the right and bottom collisions, but I can't figure out collisions from the left and top. Here's my code:
if (e.getX() >= player.getX() && e.getX() <= player.getX() + Entity.SIZE && e.getY() >= player.getY() && e.getY() <= player.getY() + Entity.SIZE) {
return true;
Let e be the entity that I'm checking and Entity.SIZE be the size for both the squares. What am I doing wrong?

I would suggest just making the player and every entity have a bounding rectangle using java's Rectangle class. You can do easy operations like:
if(e.boundingBox.intersects(player.boundingBox)){...}
where each entity has something like:
private Rectangle boundingBox;

Silly me, I forgot to check for the size on the x and y axis when above or next to a rectangle. Here's the new code:
e.getX() + Entity.SIZE >= player.getX() && e.getX() <= player.getX() + Entity.SIZE && e.getY() + Entity.SIZE >= player.getY() && e.getY() <= player.getY() + Entity.SIZE

Related

Building a Conditional JPQL Statement

Here is a JPQL statement that I currently have defining a repository method in Spring Boot.
#Query("SELECT s FROM Station s WHERE s.latitude <= (:latitude + .5) AND"
+ "s.latitude >= (:latitude - .5) AND "
+ "s.longitude <= (:longitude + .5) AND "
+ "s.longitude >= (:longitude - .5)")
List<Station> findAllNear(#Param("latitude") double latitude,
#Param("longitude") double longitude);
The premise behind this statement is I want to find any and all stations within a 1 degree by 1 degree box around the given coordinates if any. I am not concerned with actual distance, as the results will be refined by my business logic elsewhere.
The problem I have is this will not work well around the 180 degree longitude (nor around the poles, but I am not as concerned about that as the likelihood at this juncture of us querying that far north is slim)
Specifically, if someone were to ask for a location at or around 180 degrees longitude, it would not find stations at -179.5 or closer.
How should I adjust the JPQL to handle these cases? Is the only approach to also test for +- 360 degrees on the longitude? Is it possible to cluster groups in this way using JPQL?
A && B && ((C && D) || (E && F) || (G && H))
The JPQL Language documentation says that parentheses are allowed in an expression, but it lists AND and OR as between expression operators. Can AND and OR exist within parentheses?
Also, is there an easier way to do this?
Yes, JPQL allows in between expressions within parentheses, so an argument of the form
A && B && ((C && D) || (E && F) || (G && H))
is valid. Changing my select statement to:
#Query("SELECT s FROM Station s WHERE (s.latitude <= (:latitude + .5) AND"
+ "s.latitude >= (:latitude - .5)) AND "
+ "(s.longitude <= (:longitude + .5) AND s.longitude >= (:longitude - .5)) OR "
+ "(s.longitude <= (:longitude + 360.5) AND s.longitude >= (:longitude +359.5)) OR "
+ "(s.longitude <= (:longitude - 359.5) AND s.longitude >= (:longitude - 360.5)))")
List<Station> findAllNear(#Param("latitude") double latitude,
#Param("longitude") double longitude);
Accomplished what I set out to do.

Check if one line contains a part of the other

Given two horizontal lines on a 1 dimension plane. I want to check if they overlap at any point.
Below I show some examples of overlap. Please note that, intervals like [1,2] and [2,3] have borders "touching" but they don't overlap each other.
[1,2] is basically a line going from 1 on the x axis, to 2 on the x axis.
My question is, what are the exhaustive set of checks for such a condition. These are the ones I came up with, assuming that the first line is called, a, and the second line is called b.
b.s <= a.s && b.e > a.s
b.s <= a.s && b.e >= a.e
b.s < a.e && b.e >= a.e
b.s > a.s && b.e < a.s
Is it really this complicated? Isn't there an easier way to figure out if two lines overlap/one line contains a part of the other?
Aliter
By looking at the negation condition
public boolean isOverlap(Interval i1, Interval i2)
{
// if(i2.start <= i1.start && i2.end > i1.start)
// return true;
//
// if(i2.start <= i1.start && i2.end >= i1.end)
// return true;
//
// if(i2.start < i1.end && i2.end >= i1.end)
// return true;
//
// if(i2.start >= i1.start && i2.end <= i1.end)
// return true;
//
// return false;
if(i2.start <= i1.start && i2.end <= i1.start)
return false;
if(i2.start >= i1.end && i2.end >= i1.end)
return false;
return true;
}
An alternative method is to consider them on the same axis and check for disconnectedness.
Then you can say "what is the left most point?"
I'll use .l for "left" and .r for "right."
leftmost = a.l < b.l ? a : b
rightmost = leftmost == a ? b : a
Now you know the left most one and the right most one. In order for them to be connected the right most one must have a left part in between the the left and right of the leftmost one.
Assuming every line must have at least length 1 then you can simply do:
connected = rightmost.l < leftmost.r

How can I transform the code I wrote down below?

I am suppose to code the snake game in java with processing for IT classes and since I had no idea how to do it I searched for a YouTube tutorial. Now I did find one but he used the keys 'w','s','d','a' to move the snake around - I on the other hand want to use the arrow keys. Could someone explain to me how I transform this code:
if (keyPressed == true) {
int newdir = key=='s' ? 0 : (key=='w' ? 1 : (key=='d' ? 2 : (key=='a' ? 3 : -1)));
}
if(newdir != -1 && (x.size() <= 1 || !(x.get(1) ==x.get(0) + dx[newdir] && y.get (1) == y.get(0) + dy[newdir]))) dir = newdir;
}
into something like this:
void keyPressed () {
if (key == CODED) {
if (keyCode == UP) {}
else if (keyCode == RIGHT) {}
else if (keyCode == DOWN) {}
else if (keyCode == LEFT) {}
}
This is my entire coding so far:
ArrayList<Integer> x = new ArrayList<Integer> (), y = new ArrayList<Integer> ();
int w = 900, h = 900, bs = 20, dir = 1; // w = width ; h = height ; bs = blocksize ; dir = 2 --> so that the snake goes up when it starts
int[] dx = {0,0,1,-1} , dy = {1,-1,0,0};// down, up, right, left
void setup () {
size (900,900); // the 'playing field' is going to be 900x900px big
// the snake starts off on x = 5 and y = 30
x.add(5);
y.add(30);
}
void draw() {
//white background
background (255);
//
// grid
// vertical lines ; the lines are only drawn if they are smaller than 'w'
// the operator ++ increases the value 'l = 0' by 1
//
for(int l = 0 ; l < w; l++) line (l*bs, 0, l*bs, height);
//
// horizontal lines ; the lines are only drawn if they are smaller than 'h'
// the operator ++ increases the value 'l = 0' by 1
//
for(int l = 0 ; l < h; l++) line (0, l*bs, width, l*bs);
//
// snake
for (int l = 0 ; l < x.size() ; l++) {
fill (0,255,0); // the snake is going to be green
rect (x.get(l)*bs, y.get(l)*bs, bs, bs);
}
if(frameCount%5==0) { // will check it every 1/12 of a second -- will check it every 5 frames at a frameRate = 60
// adding points
x.add (0,x.get(0) + dx[dir]); // will add a new point x in the chosen direction
y.add (0,y.get(0) + dy[dir]); // will add a new point y in the chosen direction
// removing points
x.remove(x.size()-1); // will remove the previous point x
y.remove(y.size()-1); // will remove the previous point y
}
}
It's hard to answer general "how do I do this" type questions. Stack Overflow is designed for more specific "I tried X, expected Y, but got Z instead" type questions. That being said, I'll try to answer in a general sense:
You're going to have a very difficult time trying to take random code you find on the internet and trying to make it work in your sketch. That's not a very good way to proceed.
Instead, you need to take a step back and really think about what you want to happen. Instead of taking on your entire end goal at one time, try breaking your problem down into smaller steps and taking on those steps one at a time.
Step 1: Can you store the state of your game in variables? You might store things like the direction the snake is traveling the location of the snake, etc.
Step 2: Can you write code that just prints something to the console when you press the arrow keys? You might do this in a separate example sketch instead of trying to add it directly to your full sketch.
Step 3: Can you combine those two steps and change the state of your sketch when an arrow key is pressed? Maybe you change the direction the snake is traveling.
The point is that you need to try something instead of trying to copy-paste random code without really understanding it. Break your problem down into small steps, and then post an MCVE of that specific step if you get stuck. Good luck.
You should take a look into Java API KeyEvent VK_LEFT.
And as pczeus already told you, you need to implement a capturing of the keystrokes! This can be checked here (Link from this SO answer).

Change the inequality in binary search code

shouldn't be
if(a[mid] < t)return BS(mid+1,high);
else return BS(low,mid);
the same as
if(a[mid] > t)return BS(low,mid-1);
else return BS(mid,high);
But the second one doesn't work, why?
Edit: I mean by doesn't work, that the code doesn't reach the base case.
In calculating mid as (low+high)/2 it uses integer division.
In Bref. By example
Let low = 3 , high = 4 , a[3] >= t
so by calling BS(low,high)
mid = (3+4)/2 = 3 #Integer_division
Since a[mid] >=t So return BS(mid,high) which is equivalent to BS(low,high) #infinite_loop
The solution use the integer division in your side So the code should be like
if(a[mid] >= t)return BS(low,mid);
else return BS(mid+1,high);
Think this will solve your issue.

How to detect if a certain range resides (partly) within an other range?

Lets say I've got two squares and I know their positions, a red and blue square:
redTopX;
redTopY;
redBotX;
redBotY;
blueTopX;
blueTopY;
blueBotX;
blueBotY;
Now, I want to check if square blue resides (partly) within (or around) square red. This can happen in a lot of situations, as you can see in this image I created to illustrate my situation better:
alt text http://www.feedpostal.com/etc/ranges.gif
Note that there's always only one blue and one red square, I just added multiple so I didn't have to redraw 18 times.
My original logic was simple, I'd check all corners of square blue and see if any of them are inside square red:
if (
((redTopX >= blueTopX) && (redTopY >= blueTopY) && (redTopX <= blueBotX) && (redTopY <= blueBotY)) || //top left
((redBotX >= blueTopX) && (redTopY >= blueTopY) && (redBotX <= blueBotX) && (redTopY <= blueBotY)) || //top right
((redTopX >= blueTopX) && (redBotY >= blueTopY) && (redTopX <= blueBotX) && (redBotY <= blueBotY)) || //bottom left
((redBotX >= blueTopX) && (redBotY >= blueTopY) && (redBotX <= blueBotX) && (redBotY <= blueBotY)) //bottom right
) {
//blue resides in red
}
Unfortunately, there are a couple of flaws in this logic. For example, what if red surrounds blue (like in situation 1)?
I thought this would be pretty easy but am having trouble coming up with a good way of covering all these situations.. can anyone help me out here?
Regards,
Tom
A test that checks whether red rectangle resides completely outside the blue rectangle looks as follows
bool outside =
redBotX > blueTopX || redTopX < blueBotX ||
redBotY > blueTopY || redTopY < blueBotY;
Now, the negative of that will tell you whether red rectangle intersects the blue rectangle
bool intersects =
!(redBotX > blueTopX || redTopX < blueBotX ||
redBotY > blueTopY || redTopY < blueBotY);
If you wish, you can apply the De Morgan rule and rewrite it as
bool intersects =
redBotX <= blueTopX && redTopX >= blueBotX &&
redBotY <= blueTopY && redTopY >= blueBotY;
Of course, the above tests assume that the coordinates are "normalized*, i.e.
assert(redBotX <= redTopX && redBotY <= redTopY);
assert(blueBotX <= blueTopX && blueBotY <= blueTopY);
Also, the comparisons might be strict or non-strict depending on whether you consider touching rectangles as intersecting or not.
EDIT: I see that you use a different convention for rectangle coordinates: Top is the lower coordinate and Bot is the higher one, i.e.
assert(redTopX <= redBotX && redTopY <= redBotY);
assert(blueTopX <= blueBotX && blueTopY <= blueBotY);
To handle this case you just need to swap the Bot and Top coordinates in all conditions. For example, the last one will now look as follows
bool intersects =
redTopX <= blueBotX && redBotX >= blueTopX &&
redTopY <= blueBotY && redBotY >= blueTopY;
Assuming both squares are aligned, as you've indicated:
The squares intersect if all of the following hold:
The left side of Red is left of the right side of Blue.
The right side of Red is right of the left side of Blue.
The top of Red is above the bottom of Blue.
The bottom of Red is below the top of Blue.
(Convince yourself that this is true!)
One formula for intersection of two rectangles would be
! ( (redTopX > blueBotX) || (blueTopX > redBotX) || (redTopY < blueBotY) || (blueTopY < redBotY))
You can use DeMorgan's Theorem to simplify.
if (blueTopY < redBotY) return (0);
if (blueBotY > redTopY) return (0);
if (blueBotX < redTopX) return (0);
if (blueTopX > redBotX) return (0);
return (1); // there must clash
for each blue corner:
if corner is between all four red sides:
return true
return false
For higher-dimensional ranges or if you want to check a lot of ranges it might be worthwhile to store your ranges (e.g. their centers) in a R tree and search for it for where the corners of your range are.

Resources