Regulating step speed in game - java

I am developing a game and I need to create a method to create a movement. What it needs to do is take x y and target x y values and create a float[] with the movement inside of it defined to a certain time. The movement will be used every frame for a certain amount of frames until it has reached the target in a specific time. Here is what I have so far.
public void calculateRoute(int time) {
if(x > tx){
movement[0] = -((x - tx) / time);
}else if(x < tx){
movement[0] = ((tx - x) / time);
}else if(x == tx){
movement[0] = 0;
}
if(y > ty){
movement[1] = -((y - ty) / time);
}else if(y < ty){
movement[1] = ((ty - y) / time);
}else if(y == ty){
movement[1] = 0;
}
}
The problem with this is that the farther the target, the quicker the movement is. I want to have the movement regulating to a certain speed but still reach its target. Basically I need to calculate the time variable to a speed that will always be the same, no matter the distance. I tried this with setting the movement to 1 but it would miss its target since x could be 500, and the y could be 700. It would end up being x = 700, y = 700. Any help is appreciated! :)
Also some sample code would be nice!

Some things to consider:
In today's multi-core, multi-tasking computers you cannot reliably predict how much time will elapse between each rendered frame or each logic/physics/AI update.
As you've discovered with your solution, your speed calculation is based on distance, when it needs to be some units moved per unit of time (perhaps pixels/second, or blocks/second - whatever unit of measure makes sense in your game).
When you're moving things around in your world, it's often best to measure the time elapsed since the last time you moved things around, and then multiply the time elapsed by your speed, because speed*time=distance moved
If you're using a game engine, which would be a really good idea because this is a solved problem, they will provide some kind of "delta" time that tells you how much time has elapsed since the last logic/physics/AI update. You can use that value.
Here's an explanation of how deltaTime works in Unity, a popular game engine these days
Here's some sample code I wrote in Java that uses Slick2D, but the concept is the same in any game/game engine.

Maybe what you're asking is, given:
a distance between point A and point B
a fixed distance per step let's call this stepSize
You want to have in a float []:
One element for every step it will take to travel distance, one stepSize at a time. So:
stepSize = speed / 60.0; // 60 fps
stepCount = distance / stepSize;
Then a for loop that goes from 0 to stepCount-1, moving stepSize distance on each step.
I don't know what you need a float[] for in that case. If your step size doesn't evenly divide the distance you need to travel, and on the last step you've overshot you're target a bit, then on the last step simply set the (x, y) to the target (x, y)

Related

Why do I get inaccuracies when working with large scale/speed projectiles, is it due to Eulerian Integration?

So I am trying to make a Physics Simulation, which aims to simulate a missile going off a long distance away, (for my example I have used 1.6km) and I have a AA weapon at this 1.6km distance; when the missile is launched, due to maths I have worked out when I need to release the AA weapon to hit the missile. So cool the maths all checks out, and I am 99% certain mathematically this should work; but the error seems to occur in the animation stage, and I feel this is something to do with how I am handling gravity.
The issue is instead of the flight path of the missile following a lovely parabola, it is instead taking a path consisting of many different linear functions (hence the Eulerian integration speculation(Source: http://natureofcode.com/book/chapter-5-physics-libraries/)); and I believe the reason for this is to do with my scale. I am using a scale of 1 pixel = 1 meter. The image updates every 60 seconds, so I am saying every cycle, take the vertical velocity - (9.81 / 60) and then update the position by (Vertical velocity / 60). The problem is, it only wants to round to the nearest pixel, so in the first 2 seconds or so, it only wants to have the vertical position change at 4 pixels per cycle, and then it goes to 5, then 6... This causes the flight path (when the missile was launched at 200m/s at 50 degrees and the AA launched at 70degrees with the same speed) to look like:
If anyone knows how I can fix this issue to turn the inaccurate linear representation into a nice parabolic one that was still accurate to the time, (the time after launch is about 3 seconds for this). If anyone has any suggestions and/or solutions, or if you are able to explain why this is happening and don't mind spending a little time explaining it to me to get a better understanding of the problem, that would be greatly appreciated! If you require any more information to help you help me, then just leave a comment and I will provide you with any info. The relevant pieces of code are:
public void gravity(){
for (int i = 0; i < rockets.size(); i++){
if(timeToStart <= milliSecondTimer){
rockets.get(1).fired = true;
//Trail of other rocket
if (milliSecondTimer > 0.1 * count){
rockets.add(new Ball(rockets.get(1).x - 20 ,rockets.get(1).y - HEIGHT + 100,5,0,0,false));
}
}
if(rockets.get(i).fired){
rockets.get(i).vSpeed -= 9.81 / 60;
rockets.get(i).move(0, (int) (rockets.get(i).vSpeed / 60));
rockets.get(i).move(1, (int) (rockets.get(i).hSpeed / 60));
} else if (timeToStart==1110){
//function to work out the time displacment
derr(1);
}
//For the trail
if (milliSecondTimer > 0.1 * count){
rockets.add(new Ball(rockets.get(0).x - 20 ,rockets.get(0).y - HEIGHT + 100,5,0,0,false));
count++;
}
}
}
public static void main(String[] args) throws InterruptedException{
JFrame frame = new JFrame("App Name");
Rockets app = new Rockets();
frame.setSize((int)(WIDTH * SCALER),(int)(HEIGHT * SCALER));
frame.add(app);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.requestFocus();
long lastLoopTime = System.nanoTime();
int fps = 0, lastFpsTime = 0, count = 1;
final int TARGET_FPS = 60;
final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;
//Game Loop
while(true){
long now = System.nanoTime();
long updateLength = now - lastLoopTime;
lastLoopTime = now;
delta = updateLength / ((double)OPTIMAL_TIME);
lastFpsTime += updateLength;
fps++;
if (lastFpsTime > 100000000 * count){
milliSecondTimer += 0.1;
count++;
}
if (lastFpsTime >= 1000000000){
System.out.println("(FPS: "+fps+")");
lastFpsTime = 0;
fps = 0;
count = 1;
}
loopsGone++;
app.repaint();
Thread.sleep( (lastLoopTime-System.nanoTime() + OPTIMAL_TIME)/1000000 );
}
}
Thank you,
Sam
Perhaps you can change your x and y rocket coordinates to a float (I'm assuming they are int right now). And then when you are drawing, that is when you add the (int) cast. For instance,
rockets.get(i).move(0, (int) (rockets.get(i).vSpeed / 60));
Should not have an int cast.
Also, you're going to want to change
(rockets.get(i).vSpeed / 60));
to
(rockets.get(i).vSpeed / 60.0));
You want your position to retain precision, which it's not doing currently with the int cast. This is what using a float would achieve.
It doesn't look like scale is the issue. It would be an issue if you are trying to draw a parabola on an image that is, say, 10 x 10 pixels.
Could you post your rocket class? I'd like to run this, looks interesting.
Thanks for accepting my answer. Here is another issue I saw.
For much better precision in position, you will want to update your position function much more frequent, meaning more than once every time you repaint. This is how my game loop looks.
public void run() {
long lastTime=System.nanoTime();
final double amountOfTicks=60.0;
double ns=1000000000/amountOfTicks;
double delta=0;
int updates=0;
int frames=0;
long timer=System.currentTimeMillis();
while (running) {
long now=System.nanoTime();
delta +=(now-lastTime) / ns;
lastTime=now;
if (delta>1) {
update(); <--- this is where your gravity() method belongs
delta--;
updates++;
}
render(); <---- this will be your repaint method
frames++;
if (System.currentTimeMillis()-timer>1000) {
timer+=1000;
currUpdates=updates;
currFrames=frames;
updates=0;
frames=0;
}
}
}
What it does is updates spaceship positions once every millisecond, but only renders in 60 fps.

Bicycle Computer Dead Reckoning

I am creating a device where you can do video game bike racing by putting your bicycle on a trainer and hooking it up to your tablet/phone, which will count the pulses from a reed switch or hall effect sensor and calculate your speed, distance, etc in the same manner as a regular bike computer, and use that to move your avatar in the game world. It's written in Java with libGDX.
I'm stuck trying to get the digital bike to coast to a stop. If you are going a given speed, such that the time between pulses is normally 100ms, then if we check the time delta and it's been 200ms since the last click, we know you can't be going more than half of your former speed, and we should adjust down accordingly every time we update your speed, eventually passing some threshold where we decide you've effectively stopped.
I want the speed to decay along a roughly logarithmic curve so that hopefully I can approximate the speed envelope that your bike would have out on pavement. I also need to be smart about estimating the distance you've traveled since the last click, so that your distance doesn't jump ahead if we suddenly get a click.
How can I accomplish getting the bike to coast to a stop, and how should I go about positioning the bike in the game world with the uncertainty of how far we have to go until the next click? I have scoured the Internet looking for examples of code for a bicycle computer, and haven't found any yet, let alone any that have the added restriction that they need to be able to render their current position in the game world.
Here's the code:
The click function runs every time we get another pulse from the bike sensor:
public void click() {
currentTime = System.currentTimeMillis();
int delta = (int) (currentTime - lastClick);
// If we have less than N samples, just add it to the list.
// Otherwise pop one off and fill it in with the new value.
if (samples.size() == SAMPLE_RESOLUTION) {
samples.remove(0);
}
samples.add(delta);
clicks += 1;
lastClick = currentTime;
}
And the averageSamples function averages the last N samples to smooth out the speed. It's just a simple average right now, but later I intend on making it weighted such that new data is weighted more than old data.
public double averageSamples() {
Integer sum = 0;
if (!samples.isEmpty()) {
for (Integer sample : samples) {
sum += sample;
}
return wheelCircumference / (sum.doubleValue() / samples.size());
}
return sum.doubleValue();
}
And finally, the update function runs every frame of the game, so about once every 60th of a second. It's supposed to calculate your speed and distance, guessing how far you've gone since the last click based on the amount of time that's passed since then:
public void update() {
double newSpeed;
currentTime = System.currentTimeMillis();
int delta = (int) (currentTime - lastClick);
// The below line needs to adjust your speed downward if it's been too long since the last click. We're hoping for a smooth curve on the way to coasting to a stop.
newSpeed = averageSamples();
elapsedTime = currentTime - startTime;
instSpeed = newSpeed;
avgSpeed = (avgSpeed + instSpeed) / 2;
maxSpeed = Math.max(newSpeed,instSpeed);
/* This line needs to guess how far you've gone since the last click. Right now I'm using this value directly to draw the bike at a certain place in the game world, so we need to do this in a way that if we suddenly get a click, you don't end up jumping forward. */
distance = (long) (clicks * wheelCircumference);
}

LibGDX Android: Lag with 25+ sprites despite use of TimeKeeping

The Problem I have ArrayList of "pellets". I'm pushing around 25 of them and they all bounce. However, for some reason they seem to go faster while render() is slower / takes more time (wut?) Please help me make it so that the 25 sprites smoothly glide about at a constant speed. It also jerks when only 5 sprites are onScreen.
Tried this stuff:
Reading around SO. They recommended getDeltaTime
Gdx.graphics.getDeltaTime() multiplying by pelletSpeed (no Change)
In the current code the pellets hop, jerk, and inconsistently sputter about almost unpredictably. I am assuming that it's going constant speed underneath the hood but honestly it's hard to tell
For Loop in Render:
String currentDir = pelletList.get(i).getDir();
String currentColor = pelletList.get(i).getColor6();
pelletSpeedElapsedTime = TimeUtils.nanoTime();
if(currentDir.equals("Up")) {
pelletList.get(i).y -= pelletSpeed * TimeUtils.timeSinceNanos(pelletSpeedElapsedTime);
if(pelletList.get(i).y < 0 ) {
pelletList.get(i).setDir("Down");
}
} else if (currentDir.equals("Down")) {
pelletList.get(i).y += pelletSpeed * TimeUtils.timeSinceNanos(pelletSpeedElapsedTime);
if(pelletList.get(i).y > screenHeight) {
pelletList.get(i).setDir("Up");
}
} else if (currentDir.equals("Left")) {
pelletList.get(i).x -= pelletSpeed * TimeUtils.timeSinceNanos(pelletSpeedElapsedTime);
if(pelletList.get(i).x < 0) {
pelletList.get(i).setDir("Right");
}
} else if (currentDir.equals("Right")) {
pelletList.get(i).x += pelletSpeed * TimeUtils.timeSinceNanos(pelletSpeedElapsedTime);
if(pelletList.get(i).x > screenWidth) {
pelletList.get(i).setDir("Left");
}
}
Thanks
The pelletSpeedElapsedTime = TimeUtils.nanoTime(); looks suspicious to me - you're getting this time, and then calculating elapsed time for bullets immediately afterward. Almost no time will have elapsed by then, and you won't be accounting at all for whatever time passes before the next call to whatever method this is.
I think (guessing at what the rest of your code is like) that you want to move that pelletSpeedElapsedTime assignment to the end of this method. The idea here is that you want to capture the time where you finished this update, so that the next time you update you know how much time has passed between updates (e.g. time spent rendering, sleeping, whatever.)
Doing this would mean that you'd have to handle the case where pelletSpeedElapsedTime hasn't been initialized, as well (maybe initialize it in the constructor? again, not sure of the broader context.) Also, I don't think all those TimeUtils.timeSinceNanos calls or necessary - I would call that once at the start of this section of code and use the value (to make sure the moving entities all get a consistent time delta, and to avoid the redundant call/calculation.)

Slow Rendering in Mdpi and Ldpi android phones

Hi,
I am developing a game with the help of LibGDX and using Box2d in it. The problem is that when run my game on hdpi or tablets it run fine but in case of ldpi and mdpi the box2d bodies are not acting accordingly.
I think, it is taking much more time to render on those phones. So, how can I optimize my game for ldpi and mdpi phones.The values I am passing in world.step isworldbox.step(Gdx.graphics.getDeltaTime(), 10, 2000);
Thanks.
It is bad idea to use frame rate as time step. Box2D manual says:
A variable time step produces variable results, which makes it difficult to debug. So don't tie the time step to your frame rate (unless you really, really have to).
Also, you use too big values for velocity and position iterations. Box2D manual says:
The suggested iteration count for Box2D is 8 for velocity and 3 for position.
Try fixed time step and recomended iteration count like this:
float mAccomulated = 0;
float mTimeStep = 1.0f / 60.0f;
int mVelocityIterations = 8;
int mPositionIterations = 3;
void updatePhysicWorld()
{
float elapsed = Gdx.graphics.getDeltaTime();
// take into account remainder from previous step
elapsed += mAccomulated;
// prevent growing up of 'elapsed' on slow system
if (elapsed > 0.1) elapsed = 0.1;
float acc = 0;
// use all awailable time
for (acc = mTimeStep; acc < elapsed; acc += mTimeStep)
{
mWorld->Step(mTimeStep, mVelocityIterations, mPositionIterations);
mWorld->ClearForces();
}
// remember not used time
mAccomulated = elapsed - (acc - mTimeStep);
}

A player-falling system (basically gravity)

I am making a game that is similar to Doodle Jump, getting your player as high as possible. Now, I got my player working, and moving. But, the problem is, I don't have gravity, or anything that will make the player fall down onto the ground again. Do you guys have any idea of doing this? I tried having the player get a constant force, being pushed down at all times, but, it's not smooth, and it doesn't act like real falling. Can I have some help with making this player-falling system?
Edit:
GRAVITY = 10;
TERMINAL_VELOCITY = 300;
vertical_speed = 0;
public void fall(){
this.vertical_speed = this.vertical_speed + GRAVITY;
if(this.vertical_speed > TERMINAL_VELOCITY){
this.vertical_speed = TERMINAL_VELOCITY;
}
this.y = this.y - this.vertical_speed;
}
I made this, didn't work, shoots my player up in the air.
In the real world gravity will increase the rate of a fall by a constant amount over time (9.8 meters per second per second). You could simulate this by giving the player a vertical speed (when they jump or fall off a platform) and then subtracting a constant amount from that value every time round the main game loop so that they accelerate over time. You'll want to put a maximum limit on this (terminal velocity) otherwise when they fall a long way they could hit ludicrous speed fairly quickly. The pseudo-code would look something like this:
const GRAVITY = 10;
const TERMINAL_VELOCITY = 300;
object Player
{
int vertical_speed = 0;
int vertical_position;
function fall ()
{
this.vertical_speed = this.vertical_speed + GRAVITY;
if (this.vertical_speed > TERMINAL_VELOCITY)
{
this.vertical_speed = TERMINAL_VELOCITY;
}
this.vertical_position = this.vertical_position - this.vertical_speed;
}
}
EDIT: 9.8 Metres Per Second Per Second is correct! Please don't edit it! Acceleration is measured as change in velocity over time, expressed in metres per second per second. 9.8 meters per second per second means that after 1 second a stationary object would have accelerated enough to be travelling at 9.8 m/s. After 2 seconds, it will have attained a speed of 19.6 m/s. After 3 seconds it will have attained a speed of 29.4 m/s and so on.
I honestly don't believe I even had to explain that.
Do you know the formula for gravity?
velocity = acceleration * time
acceleration is the gravitational acceleration.
time is the amount of time that has passed.
Also,
distance = 1/2 * acceleration * time**2
A formula to compute the height of an entity with gravity at any given time is like so:
g * t ^ 2
s(t) = --------- + v * t + h
2
Where s is the function of time (time to height), g is the gravity factor (9.8 for metres), v is the original upwards velocity, and h is the original height.
Instead of having a constant force acting on the person, you need to have the person accelerate while they fall.
They should start falling with 0 velocity. Then, you should increase the force as they fall.
To do this, you will need to update their velocity over time:
Something like this:
if (stillFalling) {
velocity = velocity + (gravity_constant) * time_interval;
} else {
velocity = 0;
}
You will want to continuously update the velocity.
You will find explanations and a demo on that website. I suggest too that you read a book on physics or at least some wiki article about gravity.
From my Experience, do something like this.
public void run() {
if(velY+g>TerminalVel) {
velY=TerminalVel;
} else {
velY+=g;
}
y+=velY;
}
The method run() should be in a loop.

Categories