Gravity in a Java ball bouncing program that refreshes every game tick - java

Hey I am trying to figure out the best way to implement gravity in my program that is simply a ball bouncing. The program uses a method that is called 50 times a second (the rate at which the gametimer ticks) and in this method I call the gravity method. In the gravity method I currently have
public void Gravity(){
this.currentPositionY = this.currentPositionY + 9;
if (this.currentPositionY >= 581){
this.currentPositionY=581;
}
}
Problems with my code: In gravity velocity is not constant it varies with the time, but I am unsure of how to implement time with the gravity method being called so often. Also currently I have it so that the ball stops at 581, so that it does not fall through the screen. How would I implement a bounce that is higher when the ball falls for longer and shorter when the ball falls less? Thanks for your time!

Have a variable outside of the method for its y-velocity. Every tick, increase its velocity accounting for gravity.
If the ball is past a boundary, set it to the boundary and set the velocity to -1*velocity to make it "bounce" in the other direction.
Maybe something like this:
private int currentVelocityY = 0;
private int gravity = 3;
public void Gravity(){
this.currentPositionY = this.currentPositionY + this.currentVelocityY;
if (this.currentPositionY >= 581){
this.currentPositionY=581;
this.currentVelocityY = -1 * this.currentVelocityY;
}
currentVelocityY = currentVelocityY + gravity;
}

Related

Optimal Path-finding technique in a non-standard maze

So, my problem is that I'm currently working on a path-finding technique in an open world with tiles of various sizes. The object needs to find an optimal path to a destination inside an infinite world (it generates on the fly), which is filled with tiles of various sizes (which are not located on a set grid - they can have any location and size - and neither have to be integers). (The object has access to the data of all the tiles via and ArrayList). Now some factors that make this problem more difficult:
The objects itself has a size and cannot move through tiles. Therefore, it is possible for a path to exist that is too narrow for the object to move through.
The target destination may itself be a moving object.
It is possible for there to be dozens of such objects at the same time - so it is necessary for the algorithm to either be light on the system or for the path to be calculated in a few separate ticks of the program.
I tried implementing solutions for maze-solving techniques, but the main problem is the in most mazes, the tiles can only have very specific coordinates (such as whole numbers) and are always the same size.
I also tried rendering the scene as a giant conventional maze where tiles are actually pixels of tiles (so if i have a 20x40 tile it becomes a 20x40 block of 1x1 tiles), but ran into performance issues and the still didn't solve the issue with a path potentially being to narrow for the object to fit through.
EDIT:
Terribly sorry for my poor wording before, that happens when I'm trying to rush to a solution without fully understanding the question. So what I'm using the algorithm for at the moment is for NPC enemies to find their way to the player around obstacles. Here is an example of a scene:
The black circle with an arrow is the player, the black bush-like blobs are the NPC enemies. So this my my current algorithm I'm using for the enemy AI:
void move() { //part of the Enemy class, this function is called once each tick for every enemy
PVector velocity = new PVector(speed*game.dt, 0); //speed is a pre-set float denoting the enemy's speed, game.dt is deltatim
velocity.rotate(atan2(game.player.location.y-location.y, game.player.location.x-location.x)); //game.player.location is a PVector of the player's position, location is a PVector of this enemy's position
boolean init_collision = getTileCollision(); //getTileCollision is a boolean of whether this enemy is colliding with any tile
location.add(velocity);
boolean collision = getTileCollision();
if (!init_collision && collision) { //if the enemy happens to spawn inside a tile, let is move out of it before checking for collision
location.sub(velocity);
if (desired_heading != -1) { //desired heading is the angle, in radians, of which 90-degree angle the enemy wants to move in, by default set to -1 (see my descrition of this algorithm below)
velocity = new PVector(speed*game.dt, 0);
velocity.rotate(desired_heading);
location.add(velocity);
if (getTileCollision()) {
location.sub(velocity);
velocity = new PVector(speed*game.dt, 0);
velocity.rotate(current_heading); //current heading the an angle, in radians, of which 90-degree angle the enemy is currently moving in. set to -1 by default but can not equal -1 if desired_heading is not -1
location.add(velocity);
if (getTileCollision()) {
location.sub(velocity);
desired_heading = -1;
current_heading = -1;
}
} else {
desired_heading = -1;
current_heading = -1;
}
} else {
float original_heading = velocity.heading();
desired_heading = radians(round(degrees(velocity.heading())/90.0)*90.0); //round to the nearest 90 degrees
velocity = new PVector(speed*game.dt, 0);
velocity.rotate(desired_heading);
location.add(velocity);
if (getTileCollision()) {
location.sub(velocity);
}
float turn = radians(90);
while (true) { //if it cant move, try rotating 90 degrees and moving
velocity.rotate(turn);
location.add(velocity);
if (!getTileCollision() && abs(round(degrees(current_heading)) - round(degrees(velocity.heading()))) != 180) {
current_heading = velocity.heading();
break;
} else {
location.sub(velocity);
}
}
}
} else {
desired_heading = -1;
current_heading = -1;
}
}
So what my terrible code hopes to accomplish is the the enemy first tries to move directly at the player. If it encounters an obstacle, it will round its angle to the nearest 90 degrees, set desired_heading to this and try to move through. If it cant, it will rotate another 90 degrees and so forth, always keeping the original rounded angle in mind.
This doesn't work remotely well as first of all, rotating 90 degrees has a 50% chance to go in the exact wrong diretion, so I tried adding
if (abs(original_heading - velocity.heading()+turn) < abs(original_heading - velocity.heading()-turn)) {
turn = radians(-90);
}
right before the while (true) but that broke the algorithm completely (sometimes the enemy will freeze in deep thought and not move ever again).
What am I doing terribly wrong? Should I try a different algorithm or does this one have potential?
I hope this is a better question now...

LibGDX - Best way to adjust fire rate in a loop

I'm making a 2D platformer / shooter with LibGDX. I'm having this loop where holding fire-button down causes bullets to fly from the main character's gun the whole duration while the fire-button is pressed down (rapid fire). That part works perfectly and as intended. However, I'd like the rate of fire to be a bit slower. Currently the loop just adds a bullet to the world on each game frame which means the rate of fire is ridiculously high.
I've been trying to find a good way to do this, to no avail. Any suggestions would be vastly appreciated.
the loop:
if (keys.get(Keys.FIRE)) {
player.setState(State.FIRING);
world.addBullet(new Bullet(1f,1f,0));
}
You can use a delay mechanism by having a variable which counts down the time and every time it hits 0, you make one shot and reset the time, for example to 0.2f when you want the player to shoot every 0.2s:
private float fireDelay;
public void render(float deltaTime) {
fireDelay -= deltaTime;
if (keys.get(Keys.FIRE)) {
player.setState(State.FIRING);
if (fireDelay <= 0) {
world.addBullet(new Bullet(1f,1f,0));
fireDelay += 0.2;
}
}
}
Use a constant to hold the fire rate and add a timing mechanism, like so:
public static final long FIRE_RATE = 200000000L;
public long lastShot;
if(System.nanoTime() - lastShot >= FIRE_RATE) {
world.addBullet(new Bullet(1f,1f,0));
lastShot = System.nanoTime();
}
I have seen #noone s answer and it is correct. I just answer you, because i had to add the same to my game. What i did: I had a variable boolean attacking, which stores if you are holding firebutton. Then i had 2 more variables: float bps, which stores how many bullets you can shoot per second and float reloadTime, which stores how long it takes to reload an empty magazin, if you use one. I also store a long time and a boolean reloading. Time stores the TimeUtils.millis() of your last shot, the reloading stores if you are reloading the magazin or just shooting. Then in the attack method i call a method: public boolean readyToAttack(), in which i compare TimeUtils.millis() to my variable time. If reloading = true, TimeUtils.millis() - reloadTime has to bigger then time. If not, TimeUtils.millis() - (1000 / bps) has to be bigger then time. If this is the case the method returns true and i can shoot. Noones solution is simpler, but for me bps is easier to understand so i used this.
Hope it helps

Delay in how sprite rotates

I'm trying to make this vehicle movement seem more realistic.
This works perfect except for how instant the rotation is.
It could do 180 instantly. I don't want it to turn around so fast.
public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY) {
final Body carBody = CityRacerActivity.this.mCarBody;
final float rotationInRad = (float)Math.atan2(-pValueX, pValueY);
if ((pValueX == 0) && (pValueY == 0)) {
//Don't turn the body/sprite of the car
}else {
carBody.setTransform(carBody.getWorldCenter(), rotationInRad);
//turn the car body in the direction of movement
CityRacerActivity.this.mCar.setRotation(MathUtils.radToDeg(rotationInRad));
}
//set the velocity
final Vector2 velocity = Vector2Pool.obtain(pValueX * 5, pValueY * 5);
carBody.setLinearVelocity(velocity);
Vector2Pool.recycle(velocity);
}
I want it to have more play like driving a car.
The method setRotation changes the body's "facing direction" immediately.
You can use setAngularVelocity instead. It will also make your game much more reallistic because a car can't really rotate on the spot, so with an angular velocity the car will rotate during the physics world update, when it also moves according to your regular velociy. So it rotates as it moves, and that what's happening in our world.
I'd give setAngularVelocity a parameter depending on how sharp the turn is, 90 degrees should be the maximum IMO (But decide it after your own tests).

Java game timing movements

I'm trying to make balls fall from the top of the window. I store ball objects in an ArrayList and, at the moment, I am doing this.
for (int i = 0; i < balls.size(); i++) {
Ball b = (Ball) balls.get(i);
if (b.isVisible()) {
b.move();
}
the move function just changes the y co-ordinate of the ball so it drops down the screen.
At the moment, it is all being painted at exactly the same time and fall at exactly the same time.
e.g. http://puu.sh/xsGF
How do I make it so they fall at random intervals?
My move() function is as follows.
public void move() {
if (y > 480) {
this.setVisible(false);
System.out.println("GONE");
}
y += 1;
}
You could add balls randomly during the game loop.
//add new balls randomly here:
if(<randomtest>) {
balls.add(new Ball());
}
for (int i = 0; i < balls.size(); i++) {
Ball b = (Ball) balls.get(i);
if (b.isVisible()) {
b.move();
}
else {
//also might be good idea to tidy any invisible balls here
//if you do this make sure you reverse the for loop
}
}
There are 2 things you can do:
Add a Timer. When the Timer goes off (every 10 ms for example), select a random ball, and let that one drop 1px. (Mind, you will get balls that will fall at different speeds at different times, because of the random factor)
Use a random value for the speed when initializing the ball. Increase the y coordinate by that speed value, so the balls will all fall at a different rate through the sceen.
The simplest approach, if you want constant velocity, is to place them im random positions putside the top of your viewport.
Since I guess you already draw them outside the screen just add a random displacement there and you are done. eg:
ball.y = -radius + random.nextInt(100);
Ok, seeing your move function, this is not really physically correct. You should have a acceleration. This makes the ball fall more realistically (of course there is air resistance etc, but I think this is enough for now). In order the let them fall at random times, you could either add them at random times (make them existing/visible at random time instances) or so.
class Ball {
private double acc = 9.81; // or some other constant, depending on the framerate
private double velocity = 0;
private double startFallTime = Math.random()*100; // set from outside, not here!
public void move() {
// check if ball is already here
if (startFallTime-- > 0) return;
if (y > 480) {
this.setVisible(false);
System.out.println("GONE");
}
velocity += acc;
y += velocity;
}
}
EDIT: Of course the acceleration stuff is optional, depending on what you want. If you want linear movement, then your approach is fine, it just looks better if the ball has an acceleration. ;) Also, I recommend adding the balls at random instances and not work with this startFallTime that I used, because this is physically not really correct. Depends on your needs though, so you have to figure out the right way by yourself.

Trying to move an object from a fixed starting point to the coordinates of a mouse click

Im trying to get a rectangle to move from a fixed location, to a click point in my game. I have it working to the point that im getting good coordinates from the e.getX and e.getY methods in the mouse listener class. I also have the rectangle moving in straight lines to the side or up and down by increasing and decreasing the positionX and Y values but i need a way to move it to any point that i click on, basically i need to set the change in x and y. The way i was thinking is to compute the rise and run of the line from the click points and the start point and then set the x and y values to the rise and run. If i do it this way, i need a way to decrease the rise and run values down to their lowest terms so it moves fluidly. Or if there is a way im not thinking of that you can offer any guidence that would be helpfull.
How are you drawing it at the moment? Below is a method I used to shoot bullets in a little game that I made/really should finish sometime.
This is by no means all the code you will need, and in some places there are better ways to do things (which I'm sure people will start to tell me in the comments section after :) ) but it should give you a basis to work from.
The one thing missing from this is regulating the speed at which it repaints (fps), sorry but I can't remember the simple way to do this right now (need to get back to my actual job!) Hope it helps.
The barebones of it will be something like this:
//these set out the current position of your rectangle
double recX, reYy, recH, recW;
//this gives something to manage speed
int speed;
public void paintComponent(Graphics g) {
g.drawRectangle(recX,rexY,recH,recW);
}
//here we work out the movement
public void clickedScreen(double x, double y){
double newX = x;
double newY = y;
//calculate the speed to move at
vX = newX - recX;
vY = newY - recY;
//get the distance
length = Math.sqrt((v1*v1)+(v2*v2));
//make it a unit vector
v1 = v1/length;
v2 = v2/length;
}
public moveRec(){
recX = recX+(v1*speed);
recY = recY+(v2*speed);
}
while(true) {
moveRec();
repaint();
}

Categories

Resources