Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (494)
Games in Android Showcase (114)
games submitted by our members
Games in WIP (563)
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  
  Weird moving around the map issue [SOLVED]  (Read 1862 times)
0 Members and 1 Guest are viewing this topic.
Offline MashedPotatoe

Senior Newbie





« Posted 2012-07-25 21:50:05 »

Something is wrong in the moving section of my game engine and I just can't figure out what it is. Maybe you guys can help.

I'm using java2D and the game is basically JFrame->JPanel->Canvas. It is tile based with "smooth" movement between the tiles. Now to the problem:

Moving in different directions seems to go at different speed. Moving left is approx. twice as fast as moving right. Moving up is twice as fast as moving down. I am compensating for that right now by adjusting the speed for the different direction but I just can't figure out why this is happening. Every movement is basically using the same parameters and only the direction is different.

Sample code of how the movement is done.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
private void moveLeft(int delta) {
   if (x - delta * .1f <= targetX) {
      x = targetX;
   } else {
      x -= delta * .1f;
   }
}

private void moveRight(int delta) {
   if (x + delta * .1f >= targetX){
      x = targetX;
   } else {
      x += delta * .1f;
   }
}

 

The following is called when the left key is pressed. No moving is actually done here. Only setting up the destination, the sprite for the direction and telling update() via moving that there is moving to be done.

1  
2  
3  
4  
5  
direction = DS.LEFT;
current = DS.playerLeftSprite;
moving = true;
targetX = x - DS.tileSize;
targetY = y;


And respectively for the right key.

1  
2  
3  
4  
5  
direction = DS.RIGHT;
current = DS.playerRightSprite;
moving = true;
targetX = x + DS.tileSize;
targetY = y;


I will leave out the up and down movement since it's basically the same on the y-axis.

The moveLeft() and moveRight() methods are called during each update as long as the entity has not reached it's destination. Delta is also provided from the update() method. DS is my data storage for several constants and stuff. So besides the direction there is no difference between moving left and right.

I'm really at a loss right now. I can adjust the code so the speed is the same for all directions but I want to know why this weird stuff is happening.

Hopefully you guys can shed some light on this.

Thanks in advance.

PS: if you need additional code please let me know
Offline UprightPath
« Reply #1 - Posted 2012-07-25 22:16:54 »

My advice would be to check if there's a noticeable difference in frame rates when you press Up opposed to Down or Right opposed to Left. It could be that some sort of handling code in your program is causing there to be some sort of spike that causes your game to render less often resulting in an apparent 'longer' moving time.

On another note, check the references to x and make sure that it's not getting set anywhere else than in those methods. It could be that you might have another call that somehow resets it or causes other issues.

If you do want us to see the rest of your code, please make sure to use the pastebin link provided beneath the posting textarea. (If it's larger than, say, thirty or so lines do so, so that the flow of the posts/responses isn't gummed up with the wall of code. It makes finding other posts, reading responses to other posts easier. :3 )

Offline MashedPotatoe

Senior Newbie





« Reply #2 - Posted 2012-07-26 03:21:27 »

Thanks for the quick answer. Sadly I still haven't found an answer. I double checked and the only place where the coordinates are changed is during the move methods. FPS counter is not available at moment. When I implement it I will post the difference if any. I tried to isolate the problem by switching the keys for left and right and up and down just to see if by chance there was something going on. Still the same. Up and left are faster than down and right no matter what key I press.

I put some more code in the paste-bin although not really certain what really is relevant and what is not at this point. Snippets from basically every class involving movement.

read turrible code here

thanks again
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline UprightPath
« Reply #3 - Posted 2012-07-26 03:31:16 »

Okay, looking at your code, I can't find any specific places where there are issues/mistakes; however, I can make a few 'suggestions' on how to clean it up. This might well help you get over your movement issues as well, however I've got a few questions really quick.

Is this game actually tile based? Such that your player character should be completely, utterly grid aligned?

Offline MashedPotatoe

Senior Newbie





« Reply #4 - Posted 2012-07-26 05:11:25 »

Any suggestion is highly appreciated. The game is/will be tilebased. Still working on the map though so the character is just moving around the blank screen in tile sized steps. 32x32 pixels are the measurements for the tiles. Every entity can only move from tile to tile but while moving they will be between tiles obviously because the movement is supposed to be smooth and not warping from one tile to the next. There will be simple animations at some point and not just static images. I haven't come around to implementing the animations, yet.

The code is not set in stone and will be refined over time. It's just what I've got until now. If you could tell me what in particular needs cleaning up/can be done better, I'll gladly take any advice since I'm still learning a lot every day.
Offline UprightPath
« Reply #5 - Posted 2012-07-26 05:25:34 »

Okay, my suggestion would be to separate the actual 'rendering' movement from the 'logical' movement.

The logical movement should be somewhat instant. It's a change in state that says that 'Mob is now at tile (X,Y)'. This will allow you to simply some of your other logic, since you'll no longer have to keep track of the Mob's non-tile based positioning.

Whenever a movement happens, you should put some sort of action/animation into some sort of list structure (Has to be ordered, otherwise your preference). Your renderer will understand how to take these actions/animations and transform them into something meaningful for the player to view.

Some code for you! To explain how you can make a simple animation thinger. :3 Please note that I didn't test it or anything and I left a lot of it out for simplicity's sake. However, you can do a bunch of different things with it.


Note: I think that the issue might be that you end up doing some sort of logical rounding somewhere, either a floor or a ceiling (Check if the paint methods you're using take int or float). And it's also a FPS issue. Delta * .1f, if your x/y is an int means that only Delta / 10 > 1 will result in a change of position. All other delta values will result in change at all. Except when you're moving in the 'negative' direction. Since Swing's oriented with the top left corner as (0,0), with positive values of X going right and positive values of Y going down, when you subtract anything > 0 from your int it will decrease by one (Truncates off the remainder of the FP rather than rounding), which means that every tick will result in a move up or left, where as only a tick with a delta > 10 will result in a down or right. Cheesy

Offline MashedPotatoe

Senior Newbie





« Reply #6 - Posted 2012-07-26 15:23:47 »

Thanks for your input! I will surely incorporate some of the ideas.

Concerning the wonky movement being a internal cast conversion you might be right. I actually had the positions initially as floats but I couldn't figure out how to draw a BufferedImage using float as coordinates on a Graphics2D object unless I cast them to ints. All the drawImage methods in g2d only take ints so I figured I use them instead of floats. Losing precision of course but movement distance is so small I thought it wouldn't really show.

I tried to increase the tile size and removing the factor for delta so everything can be straight ints without implicit type casting and it seemed to solve the speed issue. Although the movement is very fast and I have to measure it to be sure. Delta is always around 14-16 so that's a lot of pixel movement in one update cycle. Next I'll try the float approach again to see if it works any better. There must be some way to draw with float coordinates.

I'll mess around a bit and report later.

EDIT: So I converted all coordinates to floats and that seemed to solve the problem. Still I don't understand why there would be different speeds for the directions since the calculations for every direction are the same. Now I only have to find a way of drawing without casting to int which I still have to do now:
1  
g.drawImage(current, (int) (x - DS.cam.camX), (int) (y - DS.cam.camY), null);
Offline Ultroman

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Reply #7 - Posted 2012-07-26 16:17:21 »

Thanks for your input! I will surely incorporate some of the ideas.

Concerning the wonky movement being a internal cast conversion you might be right. I actually had the positions initially as floats but I couldn't figure out how to draw a BufferedImage using float as coordinates on a Graphics2D object unless I cast them to ints. All the drawImage methods in g2d only take ints so I figured I use them instead of floats. Losing precision of course but movement distance is so small I thought it wouldn't really show.

I tried to increase the tile size and removing the factor for delta so everything can be straight ints without implicit type casting and it seemed to solve the speed issue. Although the movement is very fast and I have to measure it to be sure. Delta is always around 14-16 so that's a lot of pixel movement in one update cycle. Next I'll try the float approach again to see if it works any better. There must be some way to draw with float coordinates.

I'll mess around a bit and report later.

EDIT: So I converted all coordinates to floats and that seemed to solve the problem. Still I don't understand why there would be different speeds for the directions since the calculations for every direction are the same. Now I only have to find a way of drawing without casting to int which I still have to do now:
1  
g.drawImage(current, (int) (x - DS.cam.camX), (int) (y - DS.cam.camY), null);


Why don't you just do all your calculations using the floats, and then Math.round(float) the end result? You can't really show that anything has moved half a pixel anyway. As long as the calculations are done using the floats, it should look smooth.

- Jonas
Offline MashedPotatoe

Senior Newbie





« Reply #8 - Posted 2012-07-26 16:44:33 »

That is actually more accurate since (int) always rounds down/just cuts off after the dec point, I guess. Thanks for the suggestion. It's gone right into the code  Wink

@UprightPath
Is there any particular reason to creating objects for every movement to be processed? I mean is this more efficient than say just processing all the movement from the entities themselves? Or is it just to "bundle" up related actions to be processed together? This MobMovementAnimation is basically just references anyway.
Offline Ultroman

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Reply #9 - Posted 2012-07-26 16:57:34 »

That is actually more accurate since (int) always rounds down/just cuts off after the dec point, I guess. Thanks for the suggestion. It's gone right into the code  Wink
You're welcome Smiley
Yeah, you should never just cast to int blindly, unless you know that you do not want the decimals to be taken into account.
About your original problem...that is very weird. The best way to combat rounding errors and obscure hidden errors, is to System.out EVERYTHING! Even simple things like for this
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
private void moveLeft(int delta) {
   if (x - delta * .1f <= targetX) {
      x = targetX;
   } else {
      x -= delta * .1f;
   }
}

private void moveRight(int delta) {
   if (x + delta * .1f >= targetX){
      x = targetX;
   } else {
      x += delta * .1f;
   }
}

I'd print the incoming delta, the X, the targetX, and each calculation. Then you can see where it goes wrong.

I just found out today, that the reason why my player sometimes jumped through the walls, was due to my deltaTime suddenly spiking at times, meaning he jumped 30px in 1 frame, instead of the 6-7 he normally does. I spent hours trying to fix it, and ended up cleaning a lot of code to no avail...and then it was just LAG! Sad
Found that out using that "print all, know all" method ^^

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

Senior Newbie





« Reply #10 - Posted 2012-07-26 17:18:04 »

That's a good idea. I already incorporated a pseudo debug mode displaying relevant coordinates and such things on the screen when enabled. Monitoring the delta went right into the debug mode. At least until now it is always between 14-16. Hopefully there won't be any "overshooting" the target since I check before actually committing the new coordinates.
Offline Axeman

Senior Member


Medals: 7



« Reply #11 - Posted 2012-07-26 17:47:54 »

Sorry for the semi-hi jack: Is there a way to insert "system.out.println()" kind of like a break point? Just double click on a line, insert a variable and let Eclipse insert the system.out for me. And then by a click of a mouse delete them all... I often find myself typing a lot of system.out.println() just for debugging and then when the problem is sorted I spend a lot of time trying to find all my system.outs. Smiley
Offline sproingie

JGO Kernel


Medals: 202



« Reply #12 - Posted 2012-07-26 17:55:18 »

You might be interested in adding a "watch", something you can add while in debug mode.  If the window isn't visible already in the debug perspective, go to Window->Show View->Expressions and add a watch expression.

See http://people.cs.uchicago.edu/~amr/121/labs/eclipsetute/tute1-3.html for some screenshots of the process.

If you really want them logged to stderr or some file or whatever, I highly recommend you use a logging facility.  java.util.logging is all right, but log4j and slf4j+logback are much nicer.  (but watch out for log4j in web apps, it will leak permgen space every reload!).  When you use a logger, you can switch to DEBUG level to see your debug prints, then back to INFO for your normal operation -- and you can do it on a class-by-class basis (and with log4j, while the application is running).

Offline MashedPotatoe

Senior Newbie





« Reply #13 - Posted 2012-07-26 22:19:48 »

Thanks for the help everybody! Since changing my coordinates from int to float has solved this weird issue I will mark it as solved, although I'm still not sure why java apparently only had problems with certain directions. Anyway I will put it under java internal calculation weirdness in my data base  Wink

Thanks again.
Offline UprightPath
« Reply #14 - Posted 2012-07-26 22:37:37 »

The issue is due to the way that Integer arithmetic works. Instead of rounding during an operation, it cuts the fraction portion of the result or truncates.
1 + 1 = 2
1 + .5 = (1.5) = 1
1 - 1 = 0
1 - .5 = (.5) = 0

So when you're moving at a delta of 1, you get this:
10 - .1 = (9.9) = 9 <=== Is moving Up/Left
10 + .1 = (1-.1) = 10 <=== Is moving Down/Right

If your delta is 11, you get this:
10 - 1.1 = (8.9) = 8 <=== Up/Left
10 + 1.1 = (11.1) = 11 <=== Down/Right

Only when the delta % 10 = 0 will you have the desired result.
10 - 1.0 = (9.0) = 9
10 + 1.0 = (11.0) = 11

Offline MashedPotatoe

Senior Newbie





« Reply #15 - Posted 2012-07-26 23:55:46 »

Thanks for spelling it out for my dumb brain  Grin Now I actually understand the "why" and all that without having figured it out myself. I should probably polish up my math skills to avoid such things in the future.
Offline davidllanos22

Junior Member


Projects: 2


I'm just a learner!


« Reply #16 - Posted 2012-07-27 00:02:40 »

Sorry for the semi-hi jack: Is there a way to insert "system.out.println()" kind of like a break point?

In Eclipse you can write Sysout and then press ctrl+space and it will automatically write system.out.println()! I'ts not what you want, but hey, it's much faster! And with ctrl+D you can delete an entire line! Try it! Hope it helps! Smiley

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.

Dwinin (22 views)
2014-09-12 09:08:26

Norakomi (55 views)
2014-09-10 13:57:51

TehJavaDev (67 views)
2014-09-10 06:39:09

Tekkerue (33 views)
2014-09-09 02:24:56

mitcheeb (55 views)
2014-09-08 06:06:29

BurntPizza (39 views)
2014-09-07 01:13:42

Longarmx (24 views)
2014-09-07 01:12:14

Longarmx (30 views)
2014-09-07 01:11:22

Longarmx (30 views)
2014-09-07 01:10:19

mitcheeb (37 views)
2014-09-04 23:08:59
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
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!