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.
Related
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.
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);
}
:D
I'm currently making an RPG, made the combat system, if a player attack makes contact with the enemy it deals damage, now what I want to do is add critical strike into the mix and blocking.
How it should work? well first it will roll the chances of the monster blocking based on his blocking chance, if it blocks the incoming damage gets reduced to zero, if it doesnt it rolls the chance of critical strike based on the players critical strike chance, if its critical it will deal x bonus amount of damage based on the players critical strike multiplier.
Now what I want to know is how to calculate the percentage chance, I've seen several posts but they usually turn the percentage into a whole number, and probably my players will start with low rolls as 1.7% or 3.9%, but not 1-2-3-5, flat percentages. Anyone got suggestions on how to make it?
so far the code goes like this:
public class Player{
private double criticalStrikeChance = 0.009; <--- thats 0.9% chance.
private double criticalStrikeMultiplier = 1.2; <--- thats 120% moar damage
public double getCritStrk(){
return criticalStrikeChance;
}
}
public class Monster(){
private double blockingChance = 0.3; <--- thats 30%
private double blockingReduction = 0.75; <--- thats 75% reduced damage when blocking
}
public class Game(){
public void checkIfDamaged(){
if(intersects){
// blockroll should be done here based on the monster chance
if(blockRoll >= minimum he had to roll){
//means its successfull
monster.getHit(0); //PEANUT DAMAGE ACHIEVED GREAT SUCCESS
}else{
//Critical strike chance should be rolled here based on player
//chance
if(critstrike successful){
incdamage + (incdamage * player.criticalStrikeMultiplier;
monster.getHit(incdamage);
}
}else{//Crit didnt roll with cinnamon
monster.getHit(player.getDamage);
}
}
}
}
Ok so that's pretty much it as pseudo-code because my code looks way different but thats simple and should give you guys an idea on how it should work, so please help me senpais! I SHALL GIVE YOU CHOCO COOKIES + a nice shield with 100% block rate :D to whoever halps me!
If you are just looking to roll a random percentage, you can use the Random class in java.
Random rand = new Random();
Double pickedNumber = rand.nextDouble();
Running that, will result in pickedNumber being some double between 0 and 1. For example:
0.3650998187710377
Then check if that percentage is less than whatever your block/crit chance is. For example:
if(pickedNumber < blockChange)
//doBlock();
A full example, for a test case could be something like:
private static Random rand = new Random();
public static void main(String[] args) {
double blockChance = .5; // 50% chance to block the attack
Double pickedNumber = rand.nextDouble(); // Roll to see if we block the attack
System.out.println(pickedNumber); // output roll for debug purposes
if(pickedNumber < blockChance){ // if the attack was blocked
System.out.println("Blocked"); // do block logic
}else{ // if the attack wasn't blocked
System.out.println("Damaged"); // do damage logic
}
}
Which gave me the output:
0.2768592334674802
Blocked
And:
0.8762124334674802
Damaged
Another approach:
To get 0.75:
if (Math.random() < 0.75) {
//do this with probability 0.75
}
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)
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);
}