Java Bouncing Ball Wall - java

I'm trying to understand these code:
/*
* File: BouncingBallWalls.java
* ---------------------
* This is exercise 15 in chapter 4 of "The Art and Science of Java."
* It requires me to write a program that makes an animated bouncing
* ball on the screen, bouncing off the window edges.
*/
import java.awt.*;
import acm.program.*;
import acm.graphics.*;
public class BouncingBallWalls extends GraphicsProgram {
public void run() {
GOval ball = new GOval (getWidth()/2 - BALL_SIZE/2, getHeight()/2 - BALL_SIZE, BALL_SIZE, BALL_SIZE); /* Centers the ball */
ball.setFilled(true);
ball.setFillColor(Color.BLUE);
ball.setColor(Color.BLUE);
add(ball);
double dx = (getWidth()/N_STEPS);
double dy = (getWidth()/N_STEPS);
while(true) {
ball.move(dx, dy); /* Movement for the ball */
pause(PAUSE_TIME);
if (ball.getY() > getHeight() - BALL_SIZE) { /* Each "if" statement reverses the direction of the ball on one */
dy = dy * -1; /* axis if it hits a boundry */
}
if(ball.getX() > getWidth()- BALL_SIZE) {
dx = dx * -1;
}
if(ball.getY() < 0) {
dy = dy * -1;
}
if(ball.getX() < 0) {
dx = dx * -1;
}
}
}
private static final double N_STEPS = 1000;
private static final double PAUSE_TIME = 2;
private static final double BALL_SIZE = 50.0;
}
I understand everything except the following, why do you divide your gameWidth by N_STEPS? and what is N_STEPS?
double dx = (getWidth()/N_STEPS);
double dy = (getWidth()/N_STEPS);
private static final double N_STEPS = 1000;
Reference: http://tenasclu.blogspot.co.uk/2012/12/first-few-days-of-learning-to-program.html

You divide screen size by N_STEPS to get dx and dy, which represent the distance you want the ball to move during each loop. N_STEPS defines the movement in terms of the available screen width so that the relative movement/speed is the same regardless of screen size.
Another way of looking at N_STEPS, is that it controls the smoothness and speed of the ball. It does so in a way that makes the smoothness and speed consistent regardless of screen size. A higher N_STEPS will result in smoother/slower ball movement per loop.
Note that your code:
double dx = (getWidth()/N_STEPS);
double dy = (getWidth()/N_STEPS);
Should probably:
double dx = (getWidth()/N_STEPS);
double dy = (getHeight()/N_STEPS);

Basically what the tuorial is demonstrating is animating the motion of the ball. Now in each iteration of the while loop the ball has to move a certain distance in x and a certain distance in y. This incremental change is denoted as dx and dy.
To calculate how much the ball should move in each increment, the total distance the ball should move is divided by the number of iterations. This is to create the sensation of smooth movement. If the number of steps was too low and the total distance needed to travel was too high, then the ball would jump from one spot to the next.

N-STEPS is the distance in pixels/unit on screen. Different devices have different sizes. Say you have a device that has a screen of 800 pixels in width. Regardless of the device size, you may want to make an imaginary grid. Say if we divide the size by 20, we get 40 (800/20=40). This gives us 40 pixels or 1 unit. So, if we move something, we can move 40 pixels or 1 unit at a time horizontally. This helps when dealing with different screen sizes.

Related

Java libgdx Shooting bullet at direction with constant speed

I am trying to get my bullets to fire towards (input coords) at a constant speed.
So far I was able to get it to shoot at the direction but the farther I click (touch, android game) the faster the bullet goes. I have tried different methods by scaling but failed miserably, I have started coding just a month ago and using this as a project to increase my knowledge of how things work before I work on a full game but having too much trouble with this.
This is what I have been using to get the bullet to move towards the direction I want it to, the codes with // in front were other samples I got while browsing through the internet in hopes of getting what I wanted. I have thought of not using velocity to set the direction, but I have no clue of another method for this.
EDIT: All in short, I cannot get all the bullets to move in the same speed, farther I click, higher velocity bullet has.
Any help guys? Thanks a bunch
Player Class :
public void update(float delta) {
if (Gdx.input.isTouched()) {
if (System.currentTimeMillis() - lastShot >= FIRE_RATE) {
bullets.add(new Bullet(position.x + 6,position.y + 6,4,4,Gdx.input.getX() / 2,Gdx.input.getY() / 2));
lastShot = System.currentTimeMillis();
}
}
for (int i=0;i<bullets.size();i++) {
bullets.get(i).update(delta);
}
}
Bullet Class :
public Bullet(float x, float y, int width, int height, float targetX, float targetY) {
this.width = width;
this.height = height;
position = new Vector2( x , y );
velocity = new Vector2( 0 , 0 );
velocity.set(targetX - position.x,targetY - position.y);
//velocity.set(targetX - position.x, targetY - position.y).nor().scl(Math.min(position.dst(targetX, targetY), speedMax));
}
public void update(float deltaTime) {
//position.add(position.x + speedMax * deltaTime * ax,position.y + speedMax * deltaTime * ay);
position.add(velocity.x * deltaTime, velocity.y * deltaTime);
//velocity.scl(1 - (0.98f * deltaTime));
// Linear dampening, otherwise the ball will keep going at the original velocity forever
}
Well, normalizing vectors should be rather straightforward. Take your components, square them, and add them together (pythagorean theorem) and then divide each component by this result. I.e. vX = (targetX - position.x)/Math.sqrt(((targetX - position.x) * (targetX - position.x)) + ((targetY - position.y) *(targetY - position.y )))
Then you can multiply vX by some constant, and do the same for a vY and then set your velocity.

Circle-Rectangle collision side detection in libgdx

I have spent hours looking for the solution to this: I am developing a little top-down game with libgdx (maybe it matters what engine i am using). Now i have to implement the collision detection between my character (circle) and the wall (rectangle). I want the character to slide along the wall on collision, if sliding is possible.
Let me explain:
If i am moving 45 degrees right up i can collide with the down, the
left or the corner of a wall.
If i collide with the left i want to stop x-movement and move only up. If i leave the wall then i want to go on moving right up. The same
with the down side (stop y-movement)
If i collide with the Corner i want to stop movement (sliding not possible).
What i am doing actually is to check if the left line of the rectangle intersects my circle. Then i check intersection between the left line of wall and my circle and the bottom line of wall and my circle. Depending on which intersection occuret i set back x/y possition of my circle and set x/y Speed to 0. The Problem is, that most times not a collision bt an overlap occures. So the bottom check returns true, even if in reality the circle would only collide with the right. In this case both intersection test would return true and i would reset both speeds like on the Corner collision.
How can i solve this Problem? Is ther a better way to detect collision and collision side or corner?
I don't Need the exact Point of collision just the side of the rectangle.
Edit:
I have to say, that the rects aren't rotated just parallel to the x-axis.
You can find an explanation for circle/rectangle collision below, but please note that this type of collision might not be necessary for your needs. If, for example, you had a rectangle bounding box for your character the algorithm would be simpler and faster. Even if you are using a circle, it is probable that there is a simpler approach that is good enough for your purposes.
I though about writing the code for this, but it would take too long so here is only an explanation:
Here is a example movement of your character circle, with its last (previous) and current positions. Wall rectangle is displayed above it.
Here is that same movement, dotted lines represent the area the circle sweeps in this move. The sweep area is capsule shaped.
It would be difficult to calculate the collision of these two object, so we need to do this differently. If you look at the capsule on the previous image, you will see that it is simply the movement line extended in every direction by the radius of the circle. We can move that "extension" from the movement line to the wall rectangle. This way we get a rounded rectangle like on the image below.
The movement line will collide with this extended (rounded) rectangle if and only if the capsule collides with the wall rectangle, so they are somehow equivalent and interchangeable.
Since this collision calculation is still non-trivial and relatively expensive, you can first do a fast collision check between the extended wall rectangle (non-rounded this time) and the bounding rectangle of the movement line. You can see these rectangles on the image below - they are both dotted. This is a fast and easy calculation, and while you play the game there will probably NOT be an overlap with a specific wall rectangle >99% of the time and collision calculation will stop here.
If however there is an overlap, there is probably a collision of the character circle with wall rectangle, but it is not certain as will be demonstrated later.
Now you need to calculate the intersection between the movement line itself (not its bounding box) and the extended wall rectangle. You can probably find an algorithm how to do this online, search for line/rectangle intersection, or line/aabb intersection (aabb = Axis Aligned Bounding Box). The rectangle is axis-aligned and this makes the calculation simpler. The algorithm can give you intersection point or points since it is possible that there are two - in this case you choose the closest one to the starting point of the line. Below is an example of this intersection/collision.
When you get an intersection point, it should be easy to calculate on which part of the extended rectangle this intersection is located. You can see these parts on the image above, separated by red lines and marked with one or two letters (l - left, r - right, b - bottom, t - top, tl - top and left etc).
If the intersection is on parts l, r, b or t (the single letter ones, in the middle) then you are done. There is definitely a collision between character circle and wall rectangle, and you know on which side. In the example above, it is on the bottom side. You should probably use 4 variables called something like isLeftCollision, isRightCollision, isBottomCollsion and isTopCollision. In this case you would set isBottomCollision to true, while the other 3 would remain at false.
However, if the intersection is on the corner, on the two-letter sections, additional calculations are needed to determine if there is an actual collision between character circle and wall rectangle. Image below shows 3 such intersections on the corners, but there is an actual circle-rectangle collision on only 2 of them.
To determine if there is a collision, you need to find an intersection between the movement line and the circle centered in the closest corner of the original non-extended wall rectangle. The radius of this circle is equal to the radius of character circle. Again, you can google for line/circle intersection algorithm (maybe even libgdx has one), it isn't complex and shouldn't be hard to find.
There is no line/circle intersection (and no circle/rectangle collision) on bl part, and there are intersections/collisions on br and tr parts.
In the br case you set both isRightCollision, isBottomCollsion to true and in the tr case you set both isRightCollision and isTopCollision to true.
There is also one edge case you need to look out for, and you can see it on the image below.
This can happen if the movement of previous step ends in the corner of the the extended rectangle, but outside the radius of the inner rectangle corner (there was no collision).
To determine if this is the case, simply check if movement staring point is inside the extended rectangle.
If it is, after the initial rectangle overlap test (between extended wall rectangle and bounding rectangle of movement line), you should skip line/rectangle intersection test (because in this case there might not be any intersection AND still be a circle/rectangle collision), and also simply based on movement stating point determine which corner you are in, and then only check for line/circle intersection with that corner's circle. If there is intersection, there is a character circle/wall rectangle collision, otherwise not.
After all of this, the collision code should be simple:
// x, y - character coordinates
// r - character circle radius
// speedX, speedY - character speed
// intersectionX, intersectionY - intersection coordinates
// left, right, bottom, top - wall rect positions
// I strongly recomment using a const "EPSILON" value
// set it to something like 1e-5 or 1e-4
// floats can be tricky and you could find yourself on the inside of the wall
// or something similar if you don't use it :)
if (isLeftCollision) {
x = intersectionX - EPSILON;
if (speedX > 0) {
speedX = 0;
}
} else if (isRightCollision) {
x = intersectionX + EPSILON;
if (speedX < 0) {
speedX = 0;
}
}
if (isBottomCollision) {
y = intersectionY - EPSILON;
if (speedY > 0) {
speedY = 0;
}
} else if (isTopCollision) {
y = intersectionY + EPSILON;
if (speedY < 0) {
speedY = 0;
}
}
[Update]
Here is a simple and I believe efficient implementation of segment-aabb intersection that should be good enough for your purposes. It is a slightly modified Cohen-Sutherland algorithm. Also you can check out the second part of this answer.
public final class SegmentAabbIntersector {
private static final int INSIDE = 0x0000;
private static final int LEFT = 0x0001;
private static final int RIGHT = 0x0010;
private static final int BOTTOM = 0x0100;
private static final int TOP = 0x1000;
// Cohen–Sutherland clipping algorithm (adjusted for our needs)
public static boolean cohenSutherlandIntersection(float x1, float y1, float x2, float y2, Rectangle r, Vector2 intersection) {
int regionCode1 = calculateRegionCode(x1, y1, r);
int regionCode2 = calculateRegionCode(x2, y2, r);
float xMin = r.x;
float xMax = r.x + r.width;
float yMin = r.y;
float yMax = r.y + r.height;
while (true) {
if (regionCode1 == INSIDE) {
intersection.x = x1;
intersection.y = y1;
return true;
} else if ((regionCode1 & regionCode2) != 0) {
return false;
} else {
float x = 0.0f;
float y = 0.0f;
if ((regionCode1 & TOP) != 0) {
x = x1 + (x2 - x1) / (y2 - y1) * (yMax - y1);
y = yMax;
} else if ((regionCode1 & BOTTOM) != 0) {
x = x1 + (x2 - x1) / (y2 - y1) * (yMin - y1);
y = yMin;
} else if ((regionCode1 & RIGHT) != 0) {
y = y1 + (y2 - y1) / (x2 - x1) * (xMax - x1);
x = xMax;
} else if ((regionCode1 & LEFT) != 0) {
y = y1 + (y2 - y1) / (x2 - x1) * (xMin - x1);
x = xMin;
}
x1 = x;
y1 = y;
regionCode1 = calculateRegionCode(x1, y1, r);
}
}
}
private static int calculateRegionCode(double x, double y, Rectangle r) {
int code = INSIDE;
if (x < r.x) {
code |= LEFT;
} else if (x > r.x + r.width) {
code |= RIGHT;
}
if (y < r.y) {
code |= BOTTOM;
} else if (y > r.y + r.height) {
code |= TOP;
}
return code;
}
}
Here is some code example usage:
public final class Program {
public static void main(String[] args) {
float radius = 5.0f;
float x1 = -10.0f;
float y1 = -10.0f;
float x2 = 31.0f;
float y2 = 13.0f;
Rectangle r = new Rectangle(3.0f, 3.0f, 20.0f, 10.0f);
Rectangle expandedR = new Rectangle(r.x - radius, r.y - radius, r.width + 2.0f * radius, r.height + 2.0f * radius);
Vector2 intersection = new Vector2();
boolean isIntersection = SegmentAabbIntersector.cohenSutherlandIntersection(x1, y1, x2, y2, expandedR, intersection);
if (isIntersection) {
boolean isLeft = intersection.x < r.x;
boolean isRight = intersection.x > r.x + r.width;
boolean isBottom = intersection.y < r.y;
boolean isTop = intersection.y > r.y + r.height;
String message = String.format("Intersection point: %s; isLeft: %b; isRight: %b; isBottom: %b, isTop: %b",
intersection, isLeft, isRight, isBottom, isTop);
System.out.println(message);
}
long startTime = System.nanoTime();
int numCalls = 10000000;
for (int i = 0; i < numCalls; i++) {
SegmentAabbIntersector.cohenSutherlandIntersection(x1, y1, x2, y2, expandedR, intersection);
}
long endTime = System.nanoTime();
double durationMs = (endTime - startTime) / 1e6;
System.out.println(String.format("Duration of %d calls: %f ms", numCalls, durationMs));
}
}
This is the result I get from executing this:
Intersection point: [4.26087:-2.0]; isLeft: false; isRight: false; isBottom: true, isTop: false
Duration of 10000000 calls: 279,932343 ms
Please note that this is desktop performance, on an i5-2400 CPU. It will probably be much slower on Android devices, but I believe still more than sufficient.
I only tested this superficially, so if you find any errors, let me know.
If you use this algorithm, I believe you don't need special handling for that case where starting point is in the corner of the extended wall rectangle, since in this case you will get the intersection point at line start, and the collision detection procedure will continue to the next step (line-circle collision).
I suppose you determine the collision by calculating the distance of the circles center with the lines.
We can simplify the case and tell that the circle colliding with the corner if both distances are equal and smaller than the radius. The equality should have a tolerance of course.
More - may be not necessary- realistic approach would be to consider x,y speed and factor it in the equality check.

how can i make a graphic object solid in java?

I'm working on a simple game and i need these squareBumpers which simply stands idle and when got hit, collides and reflects the ball. But currently the ball just flies through my squareBumpers. I can only use java awt and swing libraries. Here's the code:
class squareBumper {
private int x = 300;
private int y = 300;
private Color color = new Color(66,139,139);
public void paint(Graphics g) {
Rectangle clipRect = g.getClipBounds();
g.setColor(color);
g.fillRect(x, y, 31, 31);
}
}
class BouncingBall {
// Overview: A BouncingBall is a mutable data type. It simulates a
// rubber ball bouncing inside a two dimensional box. It also
// provides methods that are useful for creating animations of the
// ball as it moves.
private int x = 320;
private int y = 598;
public static double vx;
public static double vy;
private int radius = 6;
private Color color = new Color(0, 0, 0);
public void move() {
// modifies: this
// effects: Move the ball according to its velocity. Reflections off
// walls cause the ball to change direction.
x += vx;
if (x <= radius) { x = radius; vx = -vx; }
if (x >= 610-radius) { x = 610-radius; vx = -vx; }
y += vy;
if (y <= radius) { y = radius; vy = -vy; }
if (y >= 605-radius) { y = 605-radius; vy = -vy; }
}
public void randomBump() {
// modifies: this
// effects: Changes the velocity of the ball by a random amount
vx += (int)((Math.random() * 10.0) - 5.0);
vx = -vx;
vy += (int)((Math.random() * 10.0) - 5.0);
vy = -vy;
}
public void paint(Graphics g) {
// modifies: the Graphics object <g>.
// effects: paints a circle on <g> reflecting the current position
// of the ball.
// the "clip rectangle" is the area of the screen that needs to be
// modified
Rectangle clipRect = g.getClipBounds();
// For this tiny program, testing whether we need to redraw is
// kind of silly. But when there are lots of objects all over the
// screen this is a very important performance optimization
if (clipRect.intersects(this.boundingBox())) {
g.setColor(color);
g.fillOval(x-radius, y-radius, radius+radius, radius+radius);
}
}
public Rectangle boundingBox() {
// effect: Returns the smallest rectangle that completely covers the
// current position of the ball.
// a Rectangle is the x,y for the upper left corner and then the
// width and height
return new Rectangle(x-radius, y-radius, radius+radius+1, radius+radius+1);
}
}
Take a look at the classes that implement the Shape interface. There are ellipses and other shapes, and they all implement a intersects(Rectangle2D) method. It might help you if you don't want to perform intersection yourself.
As for dealing with the collision, well, it depends on the level of accuracy you want. Simply deflecting the ball of edges is quite easy. Just determine whether the collided side of the rectangle is vertical or horizontal, and negate the corresponding velocity component accordingly. If you want to handle the corners, well that is a bit more complicated.
You need to detect when the ball has collided with the bumper. You have the boundingBox() method of BouncingBall, this will get you a rectangle that contains your ball. So you need to check if this rectangle intersects your square bumper (which implies a collision), and then do something with that.

Move in the same angle from point to point?

I need to be able to move my player x and y pixels in the same direction as a point to a point. It's hard to explain, but this is what I am trying to do:
Angles 1 and 2 have to be the same. Point 1 stays the same at (100, 100), however point 2 constantly changes and so must the angles. I have tried this:
moveRectangle.setX(touchEvent.getX());
moveRectangle.setY(touchEvent.getY());
float theta = (float) Math.toDegrees(Math.atan2(touchEvent.getY() - 100,touchEvent.getY() - 100));
float velX = (float) (getSpeed() * Math.cos(theta));
float velY = (float) (getSpeed() * Math.sin(theta));
player.move(velX, velY);
The above code is constantly run when the user puts his finger on moveRectangle (Point 2) and moves it. But the above code does not work. The player just moves in one of two directions. player.move just adds velX and velY velocity. So how can I get the two angles and move the player in the right direction? Thanks.
Would it be easier to approach this problem using a cartesian approach (vectors) versus polar approach (angle and magnitude)? So, if the player is at point p0 and the "finger" is at point p1, then the direction the player should be moving v is given by the vector p1-p0. You can then scale the resulting vector v by the player's speed, and add the player's speed to his position. You can do this easily on a frame-by-frame basis.
Do you need just to know velocity on X and Y axis? You can do it without using trigonometry (just use Pythagorean theorem).
final float deltaX = touchEvent.getX() - player.x; // player.x is point1.x
final float deltaY = touchEvent.getY() - player.y; // player.y is point1.y
final float length = Maths.sqrt((deltaX)^2 + (deltaY)^2);
final float itterations = length / getSpeed();
final float velX = deltaX / itterations;
final float velY = deltaY / itterations;
player.move(velX, velY);
Or you need a code of player moving in cycle?
Remove Math.toDegrees().
From the Math.sin() / cos() Javadoc:
Parameters:
a - an angle, in radians.
Returns:
the sine of the argument.

Android - problem with Math.atan2

So in my android game I'm making with andengine, I have it set up so as I touch and drag the player sprite, it continously rotates so that the character is always facing the direction it is traveling.
public class Player extends AnimatedSprite {
private float lastX = Game.centerX;
private float lastY = Game.centerY;
private static int angle = 0;
// ...
#Override
public boolean onAreaTouched(final TouchEvent sceneTouchEvent, final float touchAreaLocalX, final float touchAreaLocalY) {
Body body = OrbCatch.physicsWorld.getPhysicsConnectorManager().findBodyByShape(this);
if (sceneTouchEvent.getAction() == TouchEvent.ACTION_MOVE) {
float currentX = sceneTouchEvent.getX();
float currentY = sceneTouchEvent.getY();
angle = (int) (Math.atan2(currentY - lastY, currentX - lastX) * 180 / Math.PI);
lastX = currentX;
lastY = currentY;
}
body.setTransform(new Vector2(sceneTouchEvent.getX(),sceneTouchEvent.getY() )
.mul(1/PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT),angle);
return true;
}
}
The key line is this:
angle = (int) (Math.atan2(currentY - lastY, currentX - lastX) * 180 / Math.PI)
It takes the last known coordinates and the current coordinates, calculates the angle between them, and converts it from radians to degrees. Well, this was all working fine yesterday, but despite changing none of this code today it's behaving strangely. The sprite's orientation changes erratically, with no apparent pattern. If I move it in a straight path, it continuously alternates between 2 or 3 distinctly different angles(usually one of them is the correct one).
edit: solved, see below
The problem was that Body.setTransform angle parameter takes values in radians, not degrees. Andengine is so poorly documented...
math.todegree(math.atan(....))....
You should use toDegree().

Categories