Tuesday, October 26, 2010

Angular Character Movement

So as you've probably noticed the past few posts have been about character movement, the first being Basic Character Movement where I went over briefly a few movement style options you have for making a game. This post is going to be another extension of the character movement snippets, where the character will only be moving forward but this time the right and left arrow keys will turn the character right or left. This gives you full 360 degree movement.

The code changes are fairly minimal as we still are only interested in whether the up, left, or right arrow keys are pressed. We need to utilize some trigonometric functions sin and cos to determine the amount to move the characters position in the x and y directions, respectively. Here is the new update function:
// angular movement is based on a radian angle for direction

  if (right) {
   this.direction += -0.2; // angular turning speed

  if (left) {
   this.direction += 0.2; // angular turning speed

  if (up) {
   // the movement calculations, sin and cos are used to get the
   // distance in x and y directions respectively. We multiply by the
   // timed passed so that we get more accurate movement and then the
   // speed variable controls how fast the block moves. And it has
   // specific units which are pixels per second.
   basicBlock.x += Math.sin(direction) * dt * speed;
   basicBlock.y += Math.cos(direction) * dt * speed;
As you can see it's not that many lines of code, the right and left arrow keys will change the direction angle which is in radians. You can put it in degrees if you want but radians gives us more precision.

You might want to play around with this snippet a little and try enhancing the turning speed. If you multiply the amount to turn the character by the time passed you can make movement a bit more smooth and consistent. You can also easily add in some basic collision detection and make a nice little game out of this snippet. Combine it with the Game State Machine and the Keyboard Input: Polling System in Java possibly the Toggle Fullscreen Mode and a few other snippets I've posted and you've got a decent basis for a nice little Java game. Then the only limitation is your creativity in gameplay.

So here is the snippet for you to play around with:

Next -> Mouse Movement


Anonymous said...

The square doesn't rotate; the canvas around it rotates. This isn't practical if the user needs to paint anything other than the square

Nick said...

If you want to paint anything that isn't rotated with the square (player) you wouldn't use the graphics object created to draw the player.

The transformations (i.e, rotate, translate, scale) are applied each graphics object instance using the AffineTranform object.

You can easily make a new graphics object using the Graphics.create method which will have the same transformation as the object that created it.

In the Snippet
Insert anything you don't want rotated with the player block where the todo line is in the example and use the bkG object to draw it.

// TODO: Draw your game world, or scene or anything else here.

I used the above lines to test and make sure that that rectangle would not get rotated with the player. Let me know if that works if it doesn't I'll update the snippet.

Nick said...

Additionally the square is indeed rotated before it is drawn to the canvas, though any draw operations on a graphics object (g in the snippet) that is "rotated" will be rotated as well.

The Graphics object uses an AffineTransform object to manipulate the each point in any shape before rasterizing it or filling the backing buffers pixels, the backing image buffer does not get manipulated but drawn to, each graphics object can have different transforms and each transform can be manipulated and used as a general points transformation.

For instance if you wanted to rotate some Points objects and use it for your physics calculations or other game logic you can pass the Point to the AffineTransform and let it do translations scaling and rotations for you. This is usefull if you don't feel like figuring out the math yourself. Use the AffineTransform.transform methods.

Hope this clarifies things a little bit.

Post a Comment