Pytanie Wąż porusza się poziomo


Próbuję stworzyć prostą grę w węża.

(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

Problem 

Za każdym razem, gdy łapię jedzenie, wąż staje się dłuższy, ale kiedy naciskasz klawisz w dół lub w górę, porusza się poziomo.

Może rozwiązanie

Oto, co moim zdaniem może być rozwiązaniem: Wąż powinien być tablicą! Za każdym razem, gdy klawisz jest wciśnięty, zdefiniuj pozycję HEAD węża i przesuń węża krok po kroku, ponieważ jest to tablica. Ciało podąża za głową. Ale w tym przypadku nie mam pojęcia, jak utworzyć z niego tablicę.

Może są inne rozwiązania. Każda pomoc będzie doceniona!


18
2018-04-01 23:56


pochodzenie


W przeszłości, kiedy tworzyłem grę Snake, nie zapisywałem pozycji ciała, ale zamiast tego zapisałem pozycję głowy i tablicę "kierunków", które przeszło ciało. Prześledź go do tyłu, aby narysować węża. Jeśli w dowolnym momencie rysunek ciała kończy się na tej samej płytce, co głowa, gracz rozbił się i można na nim wykryć stan gry. - Niet the Dark Absol
Wydaje się, że fragment kodu działa, jeśli ustawisz ostrość strony, wydarzenia robią to, co chcesz (w górę, w dół, w lewo, w prawo) - Kyle B
Niet ma właściwy pomysł. - Robert Talada


Odpowiedzi:


Musisz utrzymać array punktów aktualnie zajmowanych przez ciało węża i dodać nowy punkt (unshift) do tablicy, gdy wąż zbliża się i usuwa punkt z tylnej części tablicy (pop). Poniższy kod jest starterem, musisz zrobić to sam :).

(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;
        }
    });
})();
canvas {
    background-color: #000022;
    float: left;
}
<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>


12
2018-04-07 17:24





Ponieważ miałem trochę wolnego czasu, stworzyłem własnego węża JS, aby pokazać, jak można to zrobić. Najważniejsze części znajdują się w this.snakeBody, gdzie przechowywana jest tablica ciał i this.moveForward (), gdzie można zobaczyć, jak ciało jest aktualizowane.

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);
        }
    }
},

Starałem się uczynić go tak czytelnym, jak tylko mogłem, ale zauważ, że jest to niedokończony przykład i wymagałoby wielu ulepszeń, aby można go było zagrać w grę.


7
2018-04-10 17:02





Myślę, że trafiłeś w odpowiedź z tablicą. W przeszłości odkryłem, że Snake działa najlepiej z tablicą, śledząc każdy blok węża i sprawdzając, czy dwa bloki znajdują się w tej samej pozycji. Jednak aby poruszać się, musisz bezpośrednio kontrolować głowę, a ciało powinno podążać za pozycją przestrzeni tablicowej przed nią. Głowa węża będzie pierwszym elementem w tablicy. Nie jestem pewien, co masz na myśli mówiąc o niezrozumieniu implementacji tablicy, ale współrzędne dla każdego bloku będą pozycją w tablicy.


3
2018-04-07 12:58





Miej zmienną długości i ustaw rozmiar x lub y na podstawie kierunku, na przykład:

(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;
    }
  });
})();
canvas { background-color: #000022 }
<canvas id="canvas" width="400" height="400"></canvas>


1
2018-04-14 01:57





Robię grę przy pomocy C ++ soi, mogę zrobić nowy obiekt dla każdego kafelka węża, aw ruchu ustaw go na pozycję rodzica

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


1
2018-04-14 09:24





Aby zdiagnozować twój problem w dół lub w górę, dodawałbym pewne wywołania console.log ("message") w twoim kodzie do debugowania.

W szczególności dodaj kilka komunikatów konsoli w instrukcji switch, aby wiedzieć, że odpowiednie zdarzenie i gałąź są zwalniane. Na przykład:

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

Następnie dodaj więcej i więcej debugowania komunikatów dziennika, aż znajdziesz problem.

Możesz wyświetlać komunikaty konsoli w narzędziach programistycznych F12 w wybranej przeglądarce podczas uruchamiania gry.

Upewnij się również, że nie wywołujesz ctx.translate (...) w kontekście canvas, aby odwrócić płótno, to zmieniłoby kierunek osi X i / lub Y.


0
2018-04-10 14:38