Sunday, July 25, 2010

Game in Progress: Move the character

Alright, so it was a bit too ambitious to immediately start on level design after getting animation down. It's downright foolish to create the world around your character without being comfortable about how they will move around! This post will probably be easier to follow because I'll write it alongside changes to the code, instead of after the fact. Our goal for this session is to create a move function for the player character, and bind it to keyboard input that will initiate movement.

EDIT! When I had originally started this article my plan was to bind document.onkeydown to a function that would call Sprite.move(), which would change the character's x/y coordinates accordingly. That went horribly bad because onkeydown will sometimes fire repeated button presses based on the operating system's key repeat functionality! This revised article explains how I got around this by monitoring both onkeydown and onkeyup.

I can't sit still!

So Mega Man has a problem right now, specifically that as soon as you load him up he's on the run. In order to test out how the transition from still movement to running will appear, we'll add another sequence to his animation graphic that's only one frame of him standing still. Thanks to our Animation class, it's only a matter of expanding the graphic in Photoshop and adding two standing still frames (one facing left, the other right):

It's a good time to note that you should make sure each frame has a common foot height so the animation doesn't wiggle around

To keep things organized in the animation graphics, I'm keeping each animation on a separate layer in Photoshop named after the animationName. After uploading the graphic, I call addAnimation() two more times in the init() function for the megaMan object. A single frame technically isn't an animation so I should probably edit the Animation class to ignore the animation code for single-frame sequences. For now, I'll just add them and assume we're fine.

  1. megaMan.addAnimation("StandLeft", new Animation(megaManImage, 0, 60, 25, 30, 1, 5));
  2. megaMan.addAnimation("StandRight", new Animation(megaManImage, 0, 90, 25, 30, 1, 5));

I've also changed megaMan's startAnimation to "StandRight", so he can actually catch his breath before you start mashing the arrow keys. After loading the demo, Mega Man is straight chillin' cold.

Movin' on up...

Movement for our character should stay with the Sprite class, as it is a representation of the character on-screen. startMove() and stopMove() are added to the Sprite class, which enable/disable boolean variables for direction that have also been added.

  1. Sprite.prototype.startMove = function(direction) {
  2.   // Enable direction
  3.   switch (direction) {
  4.     case 'left':
  5.       this.left = true;
  6.       break;
  7.     case 'right':
  8.       this.right = true;
  9.       break;
  10.   }
  11. }
  12. Sprite.prototype.stopMove = function(direction) {
  13.   // Enable direction
  14.   switch (direction) {
  15.     case 'left':
  16.       this.left = false;
  17.       break;
  18.     case 'right':
  19.       this.right = false;
  20.       break;
  21.   }
  22. }

Our final step involves capturing keyboard input and attaching it to our character's behavior.

Keyboard Input

Capturing keyboard input is relatively simple for our purposes, because we're not going to worry about simultaneous keypresses for now. All we want to do is move the character left and right whenever those arrow keys are pressed. In order to do that, we bind a custom function to the document.onKeyDown event that the browser provides, and use that custom function to determine which keys are pressed:

  1. document.onkeyup = checkKeyUp
  2. document.onkeydown = checkKeyDown;
  3. // Custom functions to handle keyboard input
  4. function checkKeyDown(e)
  5. {
  6.   var currentKey = e.which;
  7.   switch (currentKey)
  8.   {
  9.     case 37: // Left arrow
  10.       megaMan.startMove("left");
  11.       megaMan.setAnimation("RunLeft");
  12.       break;
  13.     case 39: // Right arrow
  14.       megaMan.startMove("right");
  15.       megaMan.setAnimation("RunRight");
  16.       break;
  17.   }
  18. }
  19. function checkKeyUp(e)
  20. {
  21.   var currentKey = e.which;
  22.   switch (currentKey)
  23.   {
  24.     case 37: // Left arrow
  25.       megaMan.stopMove("left");
  26.       megaMan.setAnimation("StandLeft");
  27.       break;
  28.     case 39: // Right arrow
  29.       megaMan.stopMove("right");
  30.       megaMan.setAnimation("StandRight");
  31.       break;
  32.   }
  33. }

This code changes the animation to either running left or right depending on which key is being pressed, and changes it to standing left or right based on which key was released. At this point the demo functions properly, but there's one minor issue: multiple keypresses at the same time. If left arrow is held down while right arrow is pressed, this can result in a situation where megaMan.x is still being modified even though the key has been released. To fix this, I simply added code to the startMove switch clauses that stopped left or right movement if the opposite key is pressed. This is almost where we want to be, as there is some confusion if onkeyup fires before another onkeydown (resulting in some backwards sliding). However I'm tired and it will have to wait until part 2.

For now, the next post will most likely be about fixing movement, getting Mega Man in a test "room", and giving him some jumping skills (ooh physics!) Here are links to the code as it stands now:

Demo
Sprite/Animation classes

No comments:

Post a Comment