javascript - reptan - porque las serpientes se arrastran
La serpiente se mueve horizontalmente (6)
Bueno, como tuve un poco de tiempo libre, creé mi propia serpiente JS para demostrarte cómo se puede hacer. La mayoría de las partes importantes se encuentran en this.snakeBody donde se almacena la matriz del cuerpo y this.moveForward () donde puede ver cómo se actualiza el cuerpo.
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);
}
}
},
Intenté hacerlo lo más legible posible, pero tenga en cuenta que este es un ejemplo inacabado y necesitaría muchas mejoras para ser un juego jugable.
Estoy tratando de crear un juego de serpientes simple.
(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>
El problema
Cada vez que atrapo la comida, la serpiente se alarga, pero cuando presionas la tecla hacia abajo o hacia arriba, se mueve horizontalmente.
Tal vez una solucion
Esto es lo que creo que la solución podría ser: ¡La serpiente debería ser una matriz! Cada vez que se presiona la tecla, defina la posición de CABEZA de serpiente y mueva la serpiente paso a paso, porque es una matriz. Entonces el cuerpo sigue la cabeza. Pero en este caso, no tengo idea de cómo hacer una matriz a partir de ella.
Tal vez hay otras soluciones. Cualquier ayuda sería apreciada!
Creo que has acertado en la respuesta con una matriz. En el pasado, he encontrado que Snake funciona mejor con una matriz, rastreando cada bloque de la serpiente y verificando que dos bloques estén en la misma posición. Sin embargo, para el movimiento, debe controlar directamente la cabeza y hacer que el cuerpo la siga en función de la posición del espacio de la matriz que está delante de ella. La cabeza de serpiente sería el primer elemento de la matriz. No estoy seguro de lo que quiere decir acerca de no entender la implementación de la matriz, pero las coordenadas de cada bloque serían un elemento de la matriz.
Hago el juego usando C ++. Soi puede aconsejarte hacer un nuevo objeto para cada ficha de serpiente y al moverla ponla en la posición de padre.
function Tile(x, y)
{
this.x = x;
this.y = y;
}
Para depurar su problema hacia abajo o hacia arriba, agregaría algunas llamadas de console.log (''mensaje'') en su código para la depuración.
Específicamente, agregue algunos mensajes de la consola en la instrucción de cambio para que sepa que el evento y la rama correctos se están activando. Por ejemplo:
switch(event.keyCode) {
case 40:
console.log(''down'');
...
case 39:
console.log(''right'');
...
}
Luego, agregue más y más mensajes de registro de depuración hasta que encuentre su problema.
Puede ver los mensajes de la consola en las herramientas de desarrollo F12 en el navegador que elija mientras ejecuta su juego.
También asegúrese de que no está llamando a ctx.translate (...) en el contexto del lienzo para voltear el lienzo, esto cambiaría la dirección de los ejes x y / o y.
Tenga una variable de longitud y haga que el tamaño de x o y se base en la dirección, así:
(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>
unshift
mantener una array
de los puntos actualmente ocupados por el cuerpo de la serpiente, y agregar un nuevo punto (sin unshift
) a la matriz a medida que la serpiente se acerca y eliminar el punto de la parte posterior de la matriz ( unshift
pop
). El siguiente código es un motor de arranque, debes hacerlo a tu gusto :).
(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>