蛇水平移动

时间:2018-04-01 23:56:12

标签: javascript

我正在尝试创建一个简单的蛇游戏。

(function() {
  var canvas = document.getElementById('canvas'),
      ctx = canvas.getContext('2d'),
      x = 0,
      y = 0,
      speed = 2; 
      x_move = speed,
      y_move = 0,                          
      food_position_x = Math.floor(Math.random() * canvas.width / 10) * 10,
      food_position_y = Math.floor(Math.random() * canvas.height / 10) * 10,
      size_x = 10;    

  function eat() {   
   console.log('food_x:' + food_position_x + ' x:' + x + ' / food_y:' + food_position_y + ' y:' + y);
    if (Math.floor(y / 10) * 10 == food_position_y && Math.floor(x / 10) *10  == food_position_x) {  
    	size_x += 2;
      //throw new Error("MATCH!"); // This is not an error. Just trying to stop the script
    }
  }
  
  // Drawing
  function draw() {
    eat();
    requestAnimationFrame(function() {      
      draw();      
    });    
    // Draw the snake
    ctx.beginPath();
    ctx.rect(Math.floor(x/10)*10, Math.floor(y/10)*10, size_x, 10);
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = '#ffffff'; 
    ctx.fill();
    ctx.closePath();

    // Draw the food
    ctx.beginPath(); 
    ctx.rect(Math.floor(food_position_x/10)*10, Math.floor(food_position_y/10)*10, 10, 10);
    ctx.fillStyle = "blue";
    ctx.fill();
    ctx.closePath();

    // Increase the value of x and y in order to animate
    x = x + x_move;
    y = y + y_move;       
  } 
  draw();

  // Key Pressing
  document.addEventListener('keydown', function(event) {
    switch(event.keyCode) {
      case 40: // Moving down
        if (x_move != 0 && y_move != -1) {
          x_move = 0;
          y_move = speed;
        }
      break;
      case 39: // Moving right
        if (x_move != -1 && y_move != 0) {
          x_move = speed;
          y_move = 0; 
        }
      break;
      case 38: // Moving top
        if (x_move != 0 && y_move != 1) {
          x_move = 0;
          y_move = -speed; 
        }
      break;
      case 37: // Moving left
        if (x_move != 1 && y_move != 0) {
          x_move = -speed;
          y_move = 0; 
        }
      break;
    }
  });
})();
canvas { background-color: #000022 }
<canvas id="canvas" width="400" height="400"></canvas>

jsfiddle

问题

每次当我抓到食物时,蛇变长,但当你按下向下或向上键时,它会水平移动。

也许是解决方案

这是我认为解决方案可能是: 蛇应该是一个阵列!每按一次键,定义蛇的HEAD的位置并逐步移动蛇,因为它是一个数组。所以身体跟着头部。但在这种情况下,我不知道如何从中制作数组。

也许有其他解决方案。任何帮助将不胜感激!

6 个答案:

答案 0 :(得分:12)

你需要维持蛇体当前占据的array个点,并在蛇接近时从阵列中添加新点(unshift)并从阵列背面移除点(pop)。以下代码是启动器,您需要使它成为您自己的:)。

&#13;
&#13;
(function () {
    const COLORS={ SNAKE:'#ff7bf5', FOOD:'blue' };
    var canvas = document.getElementById('canvas'),
        ctx = canvas.getContext('2d');
    var snake=[], score=0;
    var x, y, food_position_x, food_position_y, x_move, y_move;
    var frameCount=0, framesRequiredToMove=10;
    //the less the framesToMove the faster the sname moves
    function draw(){
        if(++frameCount==framesRequiredToMove){
            frameCount=0;
            move();
        }
        requestAnimationFrame(draw);
    }
    function init(){
        snake = [{x:3,y:0},{x:2,y:0},{x:1,y:0},{x:0,y:0}];
        snake.forEach((p)=>{plot(p.x,p.y,COLORS.SNAKE)})
        x=snake[0].x;y=snake[0].y;
        score=0;x_move=1;y_move=0;
        scoreboard.innerText=score;
        newfood();
        setTimeout(draw,1000);
    }
    function plot(x,y,color){
        ctx.beginPath();
        ctx.rect(x * 10, y * 10, 10, 10);
        ctx.fillStyle = color;
        ctx.fill();
        ctx.closePath();
    }
    function move(){
        snakepx.innerText = x;
        snakepy.innerText = y;
        x = x + x_move;
        y = y + y_move;
        // Advance The Snake
        plot(x,y,COLORS.SNAKE);
        snake.unshift({x:x,y:y});
        // Check food encounter
        if(x==food_position_x && y==food_position_y){
            scoreboard.innerText=++score;
            newfood();
        }
        else{
            var last=snake.pop();
            ctx.clearRect(last.x * 10, last.y * 10, 10, 10);
        }
    }
    function newfood(){
        food_position_x=Math.floor(Math.random() * canvas.width / 10);
        food_position_y=Math.floor(Math.random() * canvas.height / 10);
        plot(food_position_x,food_position_y,COLORS.FOOD);
        foodpx.innerText = food_position_x;
        foodpy.innerText = food_position_y;
    }
    init();

    // Key Pressing
    document.addEventListener('keydown', function (event) {
        event.preventDefault();
        switch (event.keyCode) {
            case 40: // Moving down
                if (x_move != 0 && y_move != -1) {
                    x_move = 0;
                    y_move = 1;
                }
                break;
            case 39: // Moving right
                if (x_move != -1 && y_move != 0) {
                    x_move = 1;
                    y_move = 0;
                }
                break;
            case 38: // Moving top
                if (x_move != 0 && y_move != 1) {
                    x_move = 0;
                    y_move = -1;
                }
                break;
            case 37: // Moving left
                if (x_move != 1 && y_move != 0) {
                    x_move = -1;
                    y_move = 0;
                }
                break;
        }
    });
})();
&#13;
canvas {
    background-color: #000022;
    float: left;
}
&#13;
<canvas id="canvas" width="400" height="180"></canvas>
<div style="margin-left: 410px">
    Snake: (<span id="snakepx"></span>, <span id="snakepy"></span>)<br>
    Food: (<span id="foodpx"></span>, <span id="foodpy"></span>)<br>
    Score: <span id="scoreboard"></span>
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:7)

因为我有空闲时间,所以我创建了自己的JS蛇,以向您展示如何完成它。最重要的部分是在this.snakeBody中存储了body的数组,而this.moveForward()在这里你可以看到如何更新body。

https://jsfiddle.net/nooorz24/p8xtdv3h/13/

moveForward: function() {
    var next = this.getNextfieldValue();

    if (next == "frame" || next == "body") {
        console.log("You lose!")
        this.isAlive = false;
    } else {
        var newHead = this.getNextfieldCoords();
        this.draw.snake(newHead.x, newHead.y);
        this.body.unshift(newHead);
        if (next == "food") {
            this.generateFood();
            this.snakeSize++;
        } else {
            var last = this.body.pop();
            this.draw.empty(last.x, last.y);
        }
    }
},

我试图让它尽可能地可读,但请注意,这是未完成的示例,需要大量改进才能成为可玩的游戏

答案 2 :(得分:3)

我认为你用数组来回答答案。在过去,我发现Snake最适合使用数组,跟踪蛇的每个块并检查任何两个块在同一位置。但是,对于移动,您必须直接控制头部,并根据阵列空间前面的位置使主体跟随。蛇头将是阵列中的第一个项目。我不确定你不理解数组的实现是什么意思,但是每个块的坐标都是数组中的一个项目。

答案 3 :(得分:1)

有一个长度变量,并根据方向制作x或y大小,如下所示:

&#13;
&#13;
(function() {
  var canvas = document.getElementById('canvas'),
      ctx = canvas.getContext('2d'),
      x = 0,
      y = 0,
      speed = 2,
      x_move = speed,
      y_move = 0,                          
      food_position_x = Math.floor(Math.random() * canvas.width / 10) * 10,
      food_position_y = Math.floor(Math.random() * canvas.height / 10) * 10,
      size_x = 10,
			size_y = 10,
			snake_length = 10;    

  function eat() {   
   console.log('food_x:' + food_position_x + ' x:' + x + ' / food_y:' + food_position_y + ' y:' + y);
    if (Math.floor(y / 10) * 10 == food_position_y && Math.floor(x / 10) *10  == food_position_x) {  
    	snake_length += 2;
      //throw new Error("MATCH!"); // This is not an error. Just trying to stop the script
    }
  }
  
  // Drawing
  function draw() {
    eat();
    requestAnimationFrame(function() {      
      draw();      
    });    
    // Draw the snake
    ctx.beginPath();
    ctx.rect(Math.floor(x/10)*10, Math.floor(y/10)*10, size_x, size_y);
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = '#ffffff'; 
    ctx.fill();
    ctx.closePath();

    // Draw the food
    ctx.beginPath(); 
    ctx.rect(Math.floor(food_position_x/10)*10, Math.floor(food_position_y/10)*10, 10, 10);
    ctx.fillStyle = "blue";
    ctx.fill();
    ctx.closePath();

    // Increase the value of x and y in order to animate
    x = x + x_move;
    y = y + y_move;       
  } 
  draw();

  // Key Pressing
  document.addEventListener('keydown', function(event) {
    switch(event.keyCode) {
      case 40: // Moving down
        if (x_move != 0 && y_move != -1) {
          x_move = 0;
          y_move = speed;
					size_x = 10;
					size_y = snake_length;
        }
      break;
      case 39: // Moving right
        if (x_move != -1 && y_move != 0) {
          x_move = speed;
          y_move = 0; 
					size_x = snake_length;
					size_y = 10;
        }
      break;
      case 38: // Moving top
        if (x_move != 0 && y_move != 1) {
          x_move = 0;
          y_move = -speed; 
					size_x = 10;
					size_y = snake_length;
        }
      break;
      case 37: // Moving left
        if (x_move != 1 && y_move != 0) {
          x_move = -speed;
          y_move = 0; 
					size_x = snake_length;
					size_y = 10;
        }
      break;
    }
  });
})();
&#13;
canvas { background-color: #000022 }
&#13;
<canvas id="canvas" width="400" height="400"></canvas>
&#13;
&#13;
&#13;

答案 4 :(得分:1)

我使用C ++制作游戏soi可以建议为每个蛇牌创建一个新对象,并在移动时将其设置为父位置

function Tile(x, y)
{
  this.x = x;
  this.y = y;
}

答案 5 :(得分:0)

要调试你的向下或向上问题,我会在你的代码中添加一些console.log('message')调用来进行调试。

具体来说,在switch语句中添加一些控制台消息,以便您知道正确的事件和分支正在触发。例如:

switch(event.keyCode) {
  case 40: 
    console.log('down');
    ...
  case 39: 
    console.log('right');
    ...
}

然后添加越来越多的调试日志消息,直到找到问题为止。

您可以在运行游戏时在所选浏览器中查看F12开发人员工具中的控制台消息。

另外,请确保您没有在画布上下文中调用ctx.translate(...)来翻转画布,这会改变x和/或y轴的方向。