Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (576)
games submitted by our members
Games in WIP (497)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Collision detection and Thread.sleep()  (Read 1543 times)
0 Members and 1 Guest are viewing this topic.
Offline VilleK

Senior Newbie





« Posted 2013-07-25 19:40:27 »

I\m trying to create a simple platformer and trying to do collision detection with platforms. Also using the following gameloop "run()". Unfortunately when I try to match player (x, y) coordinates with platforms (x, y) coordinates, because of Thread.sleep(10) (I think, but not sure.), the character skips it like 9/10 times and no collision happens.

If I remove Thread.sleep(), collision happens accurately, but when I move my character, he starts moving with immense speed. Could anyone please advise how to account for this?

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
public void run(){
        long previous = 0, start = 0;
        double delta = 1;
       
         while(true){
            start = System.nanoTime();
           
            if(previous != 0){
                delta = start - previous;
            }  
           
            doGameUpdates(delta);
           
           
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
           
           
            previous = start;
            repaint();
        }        
    }

private void doGameUpdates(double delta){
       
       
        for(Platform p : plats){
            if(player.collidesWithPlatform(p)==true){
               //Do something
           }
        }
        player.Move(delta);
       
    }
Offline jonjava
« Reply #1 - Posted 2013-07-25 20:21:40 »

That's not how you should do interpolation (delta time).

Please, do yourself a favor and read this article from beginning to end. It also goes over how to correctly do delta time.

http://www.java-gaming.org/index.php?topic=24220.0

Delta is a relational value (In other words a decimal value that you multiply). In an ideal game the delta value would be 1.0 all the time. Anyway, the article explains it much better!

Offline Redocdam

Senior Member


Medals: 17



« Reply #2 - Posted 2013-07-25 20:25:45 »

It looks like you're doing movement updates based on a time delta, which kicks over every hundredth of a second.
And as you pointed out, running the loop without a sleep timer goes much faster. This also means you'll be running a lot more collision checks in a short span of time. It also means your delta time would be significantly less.

What you're seeing is a hopping issue, though it's likely not as noticeable. Your character is moving a much larger distance in between checking the collision, because a lot more time has elapsed between collision checks.

A Simplified Example:
Your point of collision is at 0,0
Your character is falling from a position of 0,10

In the non-sleep version of the game loop, your character falls at -0.1y every cycle.
In the sleep version, the character falls at -1.5y every cycle.

If we were to check when chracter.y == 0, we would never encounter it in the second version.

Solution
It's possible your bounds for collision may be too small, or you may need to calculate the penetration value of a collision and adjust for that.
Think like a character encountering a border. Instead of letting them transition beyond the border, we move them back to a place where they're within the border.

edit: Also what JonJava said.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline VilleK

Senior Newbie





« Reply #3 - Posted 2013-07-25 20:28:37 »

I did look at that and tried to implement the variable step, but simplified it, since I thought that it would've been good enough for my simple game. I guess I will try again. Thanks for the tip!
Offline VilleK

Senior Newbie





« Reply #4 - Posted 2013-07-26 16:33:20 »

So, I've updated my code and it seems to be working, eg. character is now always hitting the platforms when on his way down (except for a minor glitch). Could someone please comment whether this is any better/good?

The minor glitch is that I see my character warp a few pixels up/down, depending on which way he is jumping, every few seconds.

Game class:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
public void run(){
        long lastLoopTime = System.nanoTime();
        final int TARGET_FPS = 60;
        final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;      
       
        while (gameRunning)
        {
            long now = System.nanoTime();
            long updateLength = now - lastLoopTime;
            lastLoopTime = now;
            double delta = updateLength / ((double)OPTIMAL_TIME);
            doGameUpdates(delta, OPTIMAL_TIME);
            repaint();

            try{
                Thread.sleep( Math.abs(lastLoopTime-System.nanoTime() + OPTIMAL_TIME)/1000000 );
              } catch (InterruptedException e) {
                      e.printStackTrace();
              }
        }
}


private void doGameUpdates(double delta, long OPTIMAL_TIME){
       
        for(Platform p : plats){
            if(player.collidesWithPlatform(p)== true && !player.getIfJumping()){
                player.setFloor(p.getY()-player.getHeight());
                break;
            }
            else {
                player.setFloor(500);
            }
        }
       
        player.Move(delta, OPTIMAL_TIME);
}  
   


Excerpt of Player class:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
public void Move(double delta, long time) {
...

if(y >= floor){
            jumping = true;
            yVelocity = yVelocity * (-1);
            y -= yVelocity * delta * time/1000000000;
        } else{
            yVelocity += gravity;
            y -= yVelocity * delta * time/1000000000;
           
            if(yVelocity <= 0){
                jumping = false;
            }
        }
...
}

public boolean collidesWithPlatform(Platform platform){
       
        if( ((int)this.getY() + this.getHeight()) <= (platform.getY() + 10)
                && (int)this.getX() + this.getWidth() >= platform.getX()
                && (int)this.getX() <= (platform.getX() + platform.getWidth()) ){
            return true;
        }
        return false;
}
Offline jonjava
« Reply #5 - Posted 2013-07-26 17:39:17 »

First of all, why are you passing in OPTIMAL_TIME into our update method and using it as a second delta value?

1  
y -= yVelocity * delta * time/1000000000;


Don't do that. Also, you should multiply delta with ALL values that you use. That's one of the things you need to remember and be careful with when you're using variable time steps. In other words, you should multiply with delta when you're adding the gravity to your ySpeed:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
if(y >= floor){
            jumping = true;
            yVelocity = yVelocity * (-1); /* This line looks odd. */
--          y -= yVelocity * delta * time/1000000000;
++          y -= yVelocity * delta;
        } else{
--            yVelocity += gravity;
++            yVelocity += gravity * delta;
--            y -= yVelocity * delta * time/1000000000;
++            y -= yVelocity * delta;
           
            if(yVelocity <= 0){
                jumping = false;
            }
        }


 *Line 3 looks a bit odd. Why is it there?

Offline VilleK

Senior Newbie





« Reply #6 - Posted 2013-07-26 17:52:00 »

Well, I figured that I need the time of the update/frame, so I used optimal time for each frame. If I remove that piece "time/100000000", and try your solution, the character starts jumping super super fast and also jumps through platforms. So I don't really know how to fix that if I remove "time/100000000".

Line 3 means that when the character comes down from a jump, he jumps back up with same velocity as he came down, eg. character is constantly jumping. Velocity only gradually slows down and gets near zero towards the peak of the jump.
Offline jonjava
« Reply #7 - Posted 2013-07-26 18:32:14 »

What's the value of your gravity constant?

Offline VilleK

Senior Newbie





« Reply #8 - Posted 2013-07-26 18:40:11 »

gravity = -9.81

If I make the changes that you proposed and decrease/increase gravity, the character still jumps faster than I need and most of the time through the platforms.
Offline jonjava
« Reply #9 - Posted 2013-07-26 19:00:33 »

Well, the issue here seems like your gravity constant is way too high! Look at your code that changes yPosition:

1  
y -= yVelocity * delta;


If, ideally, delta 1.0 it won't have any effect (usually delta is pretty close to 1,0). You're essentially adding HUGE amounts of pixels changes to your y position since the you are adding the gravity of almost 10 to your yVelocity. In just two steps of your game loop yVelocity would be about 20 and you'd be going up or down in y position 20 pixels at a time. in 3 steps you'd be going 30 pixels. Each step is just 1/60th of a second.

Change gravity to 

1  
gravity = -0.0981;


and play around with it until you get it right. It doesn't need to be similar to the g we have here on earth. I usually go with around 0.2 for gravity.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline VilleK

Senior Newbie





« Reply #10 - Posted 2013-07-26 19:06:57 »

When I lower my gravity, the height of the jump increases. with a gravity less than 1 the character jumps out of the screen Sad
Offline jonjava
« Reply #11 - Posted 2013-07-26 19:10:19 »

Yeah you just need to lower your jump speed. Possible also make the bounce come to a stop with something like:

1  
2  
3  
//bounce
jumping = true;
yVelocity = -(yVelocity * 0.7);

Offline VilleK

Senior Newbie





« Reply #12 - Posted 2013-07-26 19:35:19 »

Yea, you're exactly right, I just needed to lower the yVelocity that was set in the constructor. Now it works, except for the minor warping glitch I mentioned. Thanks a lot for your help, and also the Bounce tip!!!
Offline jonjava
« Reply #13 - Posted 2013-07-26 20:02:26 »

I suspect the warp glitching has something to do with how you're rendering the sprite. If you're rendering exactly based on the x and y values and your x and y values happen to be double's then you'd probably want to cast them as int's before you render. Something like this:

1  
draw(myImage, (int) x, (int) y);

Offline jonjava
« Reply #14 - Posted 2013-07-26 20:06:40 »

Casting them as int's basically just gets rid of all the numbers after the decimal.

e.g: 5.623 becomes 5 and 3.002133 becomes 3 and 54.91283 becomes 54. If you don't do that you would be trying to render sort of in between pixels and 3.54356 would be rounded up to 4 and 3.4566 would be rounded down to 3. When you cast them as int's you are always consistently rounding them down (same effect as calling Math.floor(double value)).

Offline VilleK

Senior Newbie





« Reply #15 - Posted 2013-07-26 20:17:27 »

I am actually casting them as int, because the function that I draw with doesn't take anything else as parameters:
1  
graphics.drawImage(img, (int)x, (int)y, null);
Offline jonjava
« Reply #16 - Posted 2013-07-26 20:25:57 »

Can't really say what's going wrong without seeing it or the code really. Perhaps your delta value is fluctuating erratically because of inconsistent Thread.sleep() times so that you get jerky movement? Just guessing here.

Offline VilleK

Senior Newbie





« Reply #17 - Posted 2013-07-26 20:33:42 »

Yea, you are right again. if I change this:

1  
Thread.sleep( Math.abs(lastLoopTime-System.nanoTime() + OPTIMAL_TIME)/1000000 );


To for example:

1  
Thread.sleep( 10 );


then there is no warping, at least as far as I can see. Is it then better to use just a constant value instead of the first example of code?
Offline jonjava
« Reply #18 - Posted 2013-07-26 21:07:22 »

Possibly. That Thread.sleep() method looks very wonky and I wouldn't use it :V

But that's the beauty of variable time steps. Running at consistent speed regardless of how much FPS you have. In other words, if you change that to Thread.sleep(5) the game will run just as fast except it will be less jerky. Or if you change it to Thread.sleep(20) it will still be just as fast but more jerky.

That said though, I've almost never used variable time step for anything. Fixed time step is all one mostly ever needs in my opinion. That doesn't mean one is better than the other - they're just different.

Offline VilleK

Senior Newbie





« Reply #19 - Posted 2013-07-26 23:17:32 »

Ok, I understand. Thank you very much for all your help and explanations! I have learned a lot in these two days Smiley I will have to look into fixed time step next then. Thanks again!!!
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (12 views)
2014-04-15 18:08:23

BurntPizza (11 views)
2014-04-15 03:46:01

UprightPath (24 views)
2014-04-14 17:39:50

UprightPath (10 views)
2014-04-14 17:35:47

Porlus (27 views)
2014-04-14 15:48:38

tom_mai78101 (49 views)
2014-04-10 04:04:31

BurntPizza (108 views)
2014-04-08 23:06:04

tom_mai78101 (208 views)
2014-04-05 13:34:39

trollwarrior1 (176 views)
2014-04-04 12:06:45

CJLetsGame (182 views)
2014-04-01 02:16:10
List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:05:20
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!