简体   繁体   中英

adding a margin to a fillRect with JavaScript canvas

I am making a snake game for fun, to practice JavaScript/canvas, and what I have so far is a while loop that says while i is < 100, then add a square and the square is added by using fillRect(10, 10, xCoord, yCoord) and in the while loop I have xCoord = xCoord + 11; so it moves the square to the right with a space in between... here is a link:

http://brycemckenney.com/snake_canvas

And the relevant code:

while(i < 100) {
    // fillRect(x, y, width, height)... x is horizontal and y is vertical...
    context.fillRect(xCoord, yCoord, sW, sH);

    // We want each squere to have one pixel in between them, so we increment by 11, not 10.
    xCoord = xCoord + 11;

    // When i (0) gets to numOfSquares (3), then make the rest white so that you can't see them...
    if (i >= numOfSquares) {
        context.fillStyle = "#FFFFFF";
    }

    //Increment by 1 every loop, so that the squares keep going
    i++;

}

I am trying to get the snake to animate, and I have tried many different options. Now I am trying to just add a margin-right the the 4 squares, so it looks like it's moving... is it possible to add margin to those? Here is a snapshot of what I have:

在此处输入图片说明

Well, since you're making the game of snake, we know what you want to do and I think it would be more useful if we tried to get you on the right track instead of modifying your existing code.

Lets suppose our logical game grid is 60x60. So snake-pieces can be anywhere in this grid, having X and Y values between 0 and 59. This means:

  • A piece of snake in the top-left corner is at [0, 0]

  • A piece of snake in the top-right corner is at [59, 0]

Let us further suppose that a snake is made up of a number of segments. How about 4 segments to start. This means that we need to keep an array of the 4 positions:

[position1, position2, position3, position4]

We have to pick a front, so lets say that the end of the array is the "front" of the snake. If we pick the top left 4 positions the snake would be:

var mySnake = [[0, 0], [1,0], [2,0], [3,0]]

Which on the board looks like this:

++++OOOOOOOO
OOOOOOOOOOOO
OOOOOOOOOOOO

That means its 4 snake-pieces going from left to right, just like you have so far. The thing is, by saving these locations we've gone and added some persistent state to our program.

Now snake is a funny game, because "moving" the snake really means two things:

  1. Taking the last (tail) piece away
  2. Adding a new piece to the snake

So we should make a function for moving the snake that does both of these. We'll make one based on direction:

// modifies a snake's array
function moveSnake(snake, direction) {
  // First we must remove a piece of the snake's tail, which is at the start of the array
  // There's a built in command in JavaScript for this called shift()
  snake.shift();

  // Now we must add the new piece!

  // To tell where we need to go we must look at the last location:
  var lastLoc = snake[snake.length - 1];
  // Just to be a little more clear:
  var lastX = lastLoc[0];
  var lastY = lastLoc[1];
  switch (direction) {
    case 'up':
      snake.push([lastX, lastY-1]);
      break;
    case 'down':
      snake.push([lastX, lastY+1]);
      break;
    case 'left':
      snake.push([lastX-1, lastY]);
      break;
    case 'right':
      snake.push([lastX+1, lastY]);
      break;
  }
  // redraw after every move!
  drawSnake(ctx, mySnake);
}

With this method we could do:

var mySnake = [[0, 0], [1,0], [2,0], [3,0]];
moveSnake(mySnake, 'down');
// mySnake is now [[1,0], [2,0], [3,0], [3,1]];

The snake now looks like this:

O+++OOOOOOOO
OOO+OOOOOOOO
OOOOOOOOOOOO

Now this method is pretty dumb, and in a real game of snake we'd need to add some conditions. Typically:

  1. If the new piece of snake is on top of a piece of food, the tail piece is NOT removed, instead the snake is +1 block longer
  2. If the new piece is outside of out 60x60 grid, the user loses the game
  3. If the new piece is at a location that any of the other snake pieces already exist, the user loses the game

Alas those are not done here


We still need to draw it all, but since we are keeping track of the snake's location that's easy peasy. We can just draw one square for each piece of the snake:

function drawSnake(context, snake) {
  // Remember to clear the board!
  ctx.clearRect(0, 0, 600, 600);

  var length = snake.length;
  for (var i = 0; i < length; i++) {
    context.fillStyle = 'teal';
    // position is its own array and looks like: [x, y]
    var position = snake[i];
    // our logical snake board is 60x60, but the real canvas is 600x600,
    // so we multiply x and y by 10.
    // We also use "9" for the width and height so theres a tiny gap
    context.fillRect(position[0]*10, position[1]*10, 9, 9);
  }
}

See the completed demo here.

http://jsfiddle.net/FsqXE/

Note that it allows arrow keys to control the snake to show off the moveSnake method, but the regular snake game has the movement controlled by a timer, and the user can usually only change the next-possible-direction.

The canvas element is a 2D drawing surface, so it doesn't support (higher level) things like CSS margins.

To do animation, you'll need to continually clear the canvas and redraw the scene, each time slightly adjusting the position of moving objects (so that they appear to move). In your case, this means redrawing the squares, each time with a starting position 4 pixels away from the last time you redrew the frame.

You may want to have a look at the Basic animations page at MDN (part of their canvas tutorial).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM