2015-12-26 2 views
2

Vous avez peut-être joué à Snake, un jeu où vous devez manger pour croître et vous échouez si vous heurtez le corps du serpent ou certains obstacles. La première partie était facile, mais la dernière semble impossible à réaliser.Jeu de serpent: comment vérifier si la tête entre en collision avec son propre corps

J'ai essayé de faire une vérification de boucle for si le dernier élément de ma matrice de serpent est en collision avec ses autres parties. Ma condition était comme ceci: si la position x du dernier article dans mon tableau est plus grande que n'importe quelle position des articles du tableau x, et plus petite que leur position x plus leur largeur, et ainsi de suite. Cela n'a pas fonctionné.

Voici mon code:

<!DOCTYPE html> 
<html> 
<head> 
</head> 
<body> 
<canvas id="myCanvas" width="200px" height="200px" style="border:1px solid black"/> 
<script> 
var canvas = document.getElementById("myCanvas"); 
var ctx = canvas.getContext("2d"); 
var yPos = 20; 
var width = 15; 
var variable = 1; 
var currentDir = 1; 
//var xPos = (width+5)*variable; 
var xPos = 20; 
var myArr = [{myX:xPos,myY:yPos},{myX:xPos,myY:yPos},{myX:xPos,myY:yPos}]; 
var downPressed = false; 
var upPressed = false; 
var leftPressed = false; 
var rightPressed = false; 
var first = [0,20,40,60,80,100,120,140,160,180]; 
var firstX = Math.floor(Math.random()*10); 
var firstY = Math.floor(Math.random()*10); 
var okayed = first[firstX]; 
var notOkayed = first[firstY]; 
var maths = myArr[myArr.length-1]; 
function drawFood() { 
ctx.beginPath(); 
ctx.rect(okayed,notOkayed,15,15); 
ctx.fillStyle = "red"; 
ctx.fill(); 
ctx.closePath();  
} 

function drawRectangle() { 

    ctx.clearRect(0,0,200,200); 
    drawFood(); 

    for(var i = 0;i<myArr.length;i++) { 
    ctx.beginPath(); 
    ctx.rect(myArr[i].myX,myArr[i].myY,width,15); 
    ctx.fillStyle = "blue"; 
    ctx.fill(); 
    ctx.closePath(); 
    } 

    requestAnimationFrame(drawRectangle); 
} 


setInterval("calledin()",100); 
function calledin() { 
    var secondX = Math.floor(Math.random()*10); 
    var secondY = Math.floor(Math.random()*10); 
    var newobj = {myX:myArr[myArr.length-1].myX+20,myY:myArr[myArr.length-1].myY}; 
    var newobjTwo = {myX:myArr[myArr.length-1].myX,myY:myArr[myArr.length-1].myY+20}; 
    var newobjLeft = {myX:myArr[myArr.length-1].myX-20,myY:myArr[myArr.length-1].myY}; 
    var newobjUp = {myX:myArr[myArr.length-1].myX,myY:myArr[myArr.length-1].myY-20}; 
    var okayNewObj = {myX:myArr[1].myX - 20,myY:myArr[1].myY}; 


if(myArr[myArr.length-1].myX > 180 || myArr[myArr.length-1].myX < 0 || myArr[myArr.length-1].myY > 180 || myArr[myArr.length-1].myY < 0) 
     {alert("Game Over");window.location.reload();} 

    if(myArr[myArr.length-1].myX > okayed-5 && myArr[myArr.length-1].myX < okayed+20 && myArr[myArr.length-1].myY < notOkayed+20 && 
    myArr[myArr.length-1].myY > notOkayed-5) { 
     okayed = first[secondX]; 
     notOkayed = first[secondY]; 
     myArr.unshift(okayNewObj); 
    } 

    if(currentDir == 1) { 
    myArr.push(newobj); 
    myArr.shift();} 

    if(currentDir == 2) { 
     myArr.push(newobjTwo); 
     myArr.shift(); 
    } 

    if(currentDir == 4) { 
     myArr.push(newobjLeft); 
     myArr.shift(); 
    } 


    if(currentDir == 3) { 
     myArr.push(newobjUp); 
     myArr.shift(); 
    } 

    for(var i = 0;i<myArr.length-2;i++) { 
    if(myArr[myArr.length-1].myX > myArr[i].myX && 
    myArr[myArr.length-1].myX < myArr[i].myX + 15 && myArr[myArr.length-1].myY > myArr[i].myY && myArr[myArr.length-1].myY > myArr[i].myY + 15) 
    {alert("Game over");window.location.reload();} 
} 

} 


function downed(e) { 
    if(e.keyCode==40) {if(currentDir != 3) {currentDir = 2;}} 
    if(e.keyCode==38) {if(currentDir != 2) {currentDir = 3;}} 
    if(e.keyCode==39) {if(currentDir != 4) {currentDir = 1;}} 
    if(e.keyCode==37) {if(currentDir != 1) {currentDir = 4;}} 

} 

function upped(e) { 
    if(e.keyCode == 40) {downPressed = false;} 
} 
document.addEventListener("keydown",downed,false); 
document.addEventListener("keyup",upped,false); 

drawRectangle(); 
</script> 
</body> 
</html> 
+1

Quelle est votre question? –

+0

Je veux que le jeu soit terminé chaque fois que le serpent entre en collision avec son corps – Taurus

+1

http://stackoverflow.com/help/how-to-ask –

Répondre

3

Supposons que le serpent est représenté par un tableau appelé snake dans lequel la tête est à l'index snake.length - 1. Nous devons comparer la position de la tête contre les positions des segments du corps aux indices 0 à snake.length - 2.

Le code suivant définit okay à false si la tête de serpent est entrée en collision avec un segment de corps. Sinon, okay reste true.

var head = snake[snake.length - 1], 
    x = head.x, 
    y = head.y, 
    okay = true;   
for (var i = snake.length - 2; i >= 0; --i) { 
    if (snake[i].x == x && snake[i].y == y) { 
    okay = false; 
    break; 
    } 
} 

est Ci-dessous un extrait dans lequel j'ai modifié votre code pour clarifier la logique du jeu et de simplifier la plupart des calculs. Au lieu de travailler directement avec les coordonnées de toile, je représente chaque position avec l'index de colonne x et l'index de ligne y d'une cellule de grille virtuelle. Cela nous permet de calculer les positions de la grille voisine en ajoutant 1 ou -1 à x ou y. Quand vient le temps de peindre la toile, nous multiplions les coordonnées virtuelles par la taille de la cellule.

J'ai remplacé la plupart de vos valeurs littérales par des variables. Par exemple, au lieu de fixer les dimensions de toile à 200 par 200, nous pouvons le faire:

canvas.width = numCols * cellSize; 
canvas.height = numRows * cellSize; 

Cela nous permet de changer numCols et numRows en un seul endroit pour redimensionner l'ensemble grille de jeu. Tous les calculs fonctionnent car ils évaluent les variables au lieu d'utiliser des littéraux.

J'ai modifié la gestion des événements clés pour reconnaître les codes de touche pour les touches W-A-S-D en plus des touches fléchées. Lorsque le jeu est intégré à une longue page Web, comme c'est le cas ici, vous voudrez probablement utiliser les touches W-A-S-D pour que la page ne défile pas de haut en bas pendant que vous jouez.

var canvas, 
 
    ctx, 
 
    currentDir, 
 
    startX = 1, 
 
    startY = 1, 
 
    startSnakeLength = 3, 
 
    snake, 
 
    cellSize = 18, 
 
    cellGap = 1, 
 
    foodColor = '#a2302a', 
 
    snakeBodyColor = '#2255a2', 
 
    snakeHeadColor = '#0f266b', 
 
    numRows = 10, 
 
    numCols = 10, 
 
    canvasWidth = numCols * cellSize, 
 
    canvasHeight = numRows * cellSize; 
 

 
var food = {}; 
 

 
function placeFood() { 
 
    // Find a random location that isn't occupied by the snake. 
 
    var okay = false; 
 
    while (!okay) { 
 
    food.x = Math.floor(Math.random() * numCols); 
 
    food.y = Math.floor(Math.random() * numRows); 
 
    okay = true; 
 
    for (var i = 0; i < snake.length; ++i) { 
 
     if (snake[i].x == food.x && snake[i].y == food.y) { 
 
     okay = false; 
 
     break; 
 
     } 
 
    } 
 
    } 
 
} 
 

 
function paintCell(x, y, color) { 
 
    ctx.fillStyle = color; 
 
    ctx.fillRect(x * cellSize + cellGap, 
 
       y * cellSize + cellGap, 
 
       cellSize - cellGap, 
 
       cellSize - cellGap); 
 
} 
 

 
function paintCanvas() { 
 
    ctx.clearRect(0, 0, canvasWidth, canvasHeight); 
 
    paintCell(food.x, food.y, foodColor); 
 
    var head = snake[snake.length - 1]; 
 
    paintCell(head.x, head.y, snakeHeadColor); 
 
    for (var i = snake.length - 2; i >= 0; --i) { 
 
    paintCell(snake[i].x, snake[i].y, snakeBodyColor); 
 
    } 
 
} 
 
    
 
function updateGame() { 
 
    var head = snake[snake.length - 1], 
 
     x = head.x, 
 
     y = head.y; 
 

 
    // Move the snake. 
 
    var tail = snake.shift(); 
 
    switch (currentDir) { 
 
    case 'up': 
 
     snake.push(head = { x: x, y: y - 1 }); 
 
     break; 
 
    case 'right': 
 
     snake.push(head = { x: x + 1, y: y }); 
 
     break; 
 
    case 'down': 
 
     snake.push(head = { x: x, y: y + 1 }); 
 
     break; 
 
    case 'left': 
 
     snake.push(head = { x: x - 1, y: y }); 
 
     break; 
 
    } 
 
    paintCanvas(); 
 
    x = head.x; 
 
    y = head.y; 
 

 
    // Check for wall collision. 
 
    if (x < 0 || x >= numCols || y < 0 || y >= numRows) { 
 
    stopGame('wall collision'); 
 
    return; 
 
    } 
 

 
    // Check for snake head colliding with snake body. 
 
    for (var i = snake.length - 2; i >= 0; --i) { 
 
    if (snake[i].x == x && snake[i].y == y) { 
 
     stopGame('self-collision'); 
 
     return; 
 
    } 
 
    } 
 

 
    // Check for food. 
 
    if (x == food.x && y == food.y) { 
 
    placeFood(); 
 
    snake.unshift(tail); 
 
    setMessage(snake.length + ' segments'); 
 
    } 
 
} 
 

 
var dirToKeyCode = { // Codes for arrow keys and W-A-S-D. 
 
     up: [38, 87], 
 
     right: [39, 68], 
 
     down: [40, 83], 
 
     left: [37, 65] 
 
    }, 
 
    keyCodeToDir = {}; // Fill this from dirToKeyCode on page load. 
 

 
function keyDownHandler(e) { 
 
    var keyCode = e.keyCode; 
 
    if (keyCode in keyCodeToDir) { 
 
    currentDir = keyCodeToDir[keyCode]; 
 
    } 
 
} 
 

 
function setMessage(s) { 
 
    document.getElementById('messageBox').innerHTML = s; 
 
} 
 

 
function startGame() { 
 
    currentDir = 'right'; 
 
    snake = new Array(startSnakeLength); 
 
    snake[snake.length - 1] = { x: startX, y: startY }; 
 
    for (var i = snake.length - 2; i >= 0; --i) { 
 
    snake[i] = { x: snake[i + 1].x, y: snake[i + 1].y + 1 }; 
 
    } 
 
    placeFood(); 
 
    paintCanvas(); 
 
    setMessage(''); 
 
    gameInterval = setInterval(updateGame, 200); 
 
    startGameButton.disabled = true; 
 
} 
 

 
function stopGame(message) { 
 
    setMessage(message + '<br> ended with ' + snake.length + ' segments'); 
 
    clearInterval(gameInterval); 
 
    startGameButton.disabled = false; 
 
} 
 

 
var gameInterval, 
 
    startGameButton; 
 

 
window.onload = function() { 
 
    canvas = document.getElementById('gameCanvas'), 
 
    ctx = canvas.getContext('2d'); 
 
    canvas.width = numCols * cellSize; 
 
    canvas.height = numRows * cellSize; 
 
    Object.keys(dirToKeyCode).forEach(function (dir) { 
 
    dirToKeyCode[dir].forEach(function (keyCode) { 
 
     keyCodeToDir[keyCode] = dir; 
 
    }) 
 
    }); 
 
    document.addEventListener("keydown", keyDownHandler, false); 
 
    startGameButton = document.getElementById('startGameButton'); 
 
    startGameButton.onclick = startGame; 
 
}
body { 
 
    font-family: sans-serif; 
 
} 
 
#gameCanvas { 
 
    border: 1px solid #000; 
 
    float: left; 
 
    margin-right: 15px; 
 
} 
 
#startGameButton, #messageBox { 
 
    font-size: 16px; 
 
    margin-top: 15px; 
 
} 
 
#messageBox { 
 
    line-height: 24px; 
 
}
<canvas id="gameCanvas"></canvas> 
 

 
<button id="startGameButton">Start game</button> 
 

 
<div id="messageBox"></div>