复制步骤:
访问http://playclassicsnake.com/play
见3个绿色方块和1个红色圆圈
调整屏幕的大小,使其足够小,以使蛇居住的网格更小
红色圆圈将被适当地调整大小和替换,1个绿色正方形也将被适当地替换,看起来console.log(SG.snake.links.length);
查看蛇上确实有3个链接。如果用SG.snake.links[k].pos.x
,SG.snake.links[k].pos.y
分别查看这三个坐标中的每个坐标,您将看到它们位于同一坐标上。
问题根源:
源代码必须是处理板和板上元素大小调整的函数的实现它是
this.rescale = function ( newWidth )
{
// newWidth: new width of the div containing
this.board.setSize(newWidth, newWidth); // set the size of the board to be that of the containing div
var blockWidth = this.board.getSize().width / this.numBlocks; // width in pixels of a block on the board
this.food.elem.remove(); // remove old food element
this.food.elem = this.board.circle(this.food.pos.x * blockWidth + blockWidth / 2, this.food.pos.y * blockWidth + blockWidth / 2, blockWidth / 2).attr('fill', '#cf6a4c'); // create food element to replace old one, in same grid location (see http://raphaeljs.com/reference.html#Paper.circle)
for (var i in this.snake.links)
{
var thisLink = this.snake.links[i];
thisLink.elem.remove(); // remove old link element
thisLink.elem = this.board.rect(thisLink.pos.x * blockWidth, thisLink.pos.y * blockWidth, blockWidth, blockWidth).attr('fill', '#19FF19'); // creata new link to replace old one http://raphaeljs.com/reference.html#Paper.circle
}
}
代码转储:
如果你想看到代表游戏的对象的完整逻辑,它如下所示。
// define game object
function Game ( board, numBlocks ) {
// board: Raphael object that the snake will live on
// numBlocks: Number of blocks both horizontally AND vertically -- the grid structure should be squares
this.board = board;
this.numBlocks = numBlocks;
this.snake; // Snake object on the board
this.coords = []; // map whose key-value pairs represent whether a coordinate is open or taken
this.food = null; // food element on board
this.getCoords = function ( )
{
// returns a nested list gridList of all grid coordinates on the canvas,
// acting like a map so that gridList[i,j]=true if the coordinate i,j is
// occupied, and gridList[i,j]=false if the coordinate is not occupied
var gridList = [];
for (var i = 0; i < this.numBlocks; ++i)
{
var innerList = [];
for (var j = 0; j < this.numBlocks; ++j) innerList.push(true);
gridList.push(innerList);
}
return gridList;
}
this.elementOnGrid = function (elem, xpos, ypos) {
// elem: Rapael element (see: http://raphaeljs.com/reference.html#Element)
// xpos, ypos: x and y grid coordinates of the current position of the element
return { elem: elem, pos: { x: xpos, y: ypos } };
}
this.rescale = function ( newWidth )
{
// newWidth: new width of the div containing
this.board.setSize(newWidth, newWidth); // set the size of the board to be that of the containing div
var blockWidth = this.board.getSize().width / this.numBlocks; // width in pixels of a block on the board
this.food.elem.remove(); // remove old food element
this.food.elem = this.board.circle(this.food.pos.x * blockWidth + blockWidth / 2, this.food.pos.y * blockWidth + blockWidth / 2, blockWidth / 2).attr('fill', '#cf6a4c'); // create food element to replace old one, in same grid location (see http://raphaeljs.com/reference.html#Paper.circle)
for (var i in this.snake.links)
{
var thisLink = this.snake.links[i];
thisLink.elem.remove(); // remove old link element
thisLink.elem = this.board.rect(thisLink.pos.x * blockWidth, thisLink.pos.y * blockWidth, blockWidth, blockWidth).attr('fill', '#19FF19'); // creata new link to replace old one http://raphaeljs.com/reference.html#Paper.circle
}
}
this.Snake = function ( game )
{
// game: the Game function/object containing this function
this.links; // list of
this.createNew = function ( )
{
this.links = [];
var blockWidth = game.board.getSize().width / game.numBlocks; // width in pixels of a block on the board
var centerCoordXY = Math.round(game.numBlocks / 2); // x-y grid coordinate of center
for (var i = 0; i < 3; ++i) // start with 3 blocks in the center-ish
{
var newX = centerCoordXY + i;
this.links.push(new game.elementOnGrid(
game.board.rect(newX * blockWidth, centerCoordXY * blockWidth, blockWidth, blockWidth).attr('fill', '#19FF19'), // http://raphaeljs.com/reference.html#Paper.circle
centerCoordXY,
centerCoordXY
) // add element of type elementOnGrid to the links
);
game.coords[newX][centerCoordXY] = false; // indicate that coordinates of element just added to snake is no longer open
}
}
}
this.placeFood = function ( )
{
do {
var randXCoord = randInt(0, this.coords.length), randYCoord = randInt(0, this.coords.length);
}
while (this.coords[randXCoord][randYCoord] === false); // get random unused x-y coordinate
var blockWidth = this.board.getSize().width / this.numBlocks; // width in pixels of a block on the board
if (this.food == null) // if food element hasn't been initialized
{
// initialize the food element
this.food = new this.elementOnGrid(
this.board.circle(randXCoord * blockWidth + blockWidth / 2, randYCoord * blockWidth + blockWidth / 2, blockWidth / 2).attr('fill', '#cf6a4c'), // place circle in random location on the board (see http://raphaeljs.com/reference.html#Paper.circle)
randXCoord,
randYCoord
); // set food to be new element of type elementOnGrid
}
else // food element has been initialized (game is in play)
{
// move the food element
// ...
}
this.coords[randXCoord][randYCoord] = false; // indicate that coordinates of the good element is not open
}
this.startNew = function ( ) {
this.coords = this.getCoords();
this.snake = new this.Snake(this);
this.snake.createNew();
this.placeFood();
}
}
$(function () { // equivalent to $(document).ready(function() {
// div that holds the game area
var snakeBoardHolder = $('#snake-board-holder');
// make it have the same height as width
snakeBoardHolder.height(snakeBoardHolder.width());
// draw canvas for the snake to live on
// http://raphaeljs.com/reference.html#Raphael
if (!Raphael.svg) throw new Error("Your browser does not support SVG elements! Game won't work.");
snakeBoard = Raphael("snake-board-holder", snakeBoardHolder.width(), snakeBoardHolder.height());
// start new snake game
SG = new Game(snakeBoard, 16);
SG.startNew();
// make the game area (div) have height always equal to width,
// and make the Raphel object (canvas) inside it and all its elements
// to be resized proportionally
$(window).resize(function () {
var w = snakeBoardHolder.width();
snakeBoardHolder.height(w);
SG.rescale(w);
});
});
如果您能帮助您确定导致错误的逻辑,我们将不胜感激!
最佳答案
在这个.Snake中,我认为createNew()应该是:
this.createNew = function ( )
{
this.links = [];
var blockWidth = game.board.getSize().width / game.numBlocks; // width in pixels of a block on the board
var centerCoordXY = Math.round(game.numBlocks / 2); // x-y grid coordinate of center
for (var i = 0; i < 3; ++i) // start with 3 blocks in the center-ish
{
var newX = centerCoordXY + i;
this.links.push(new game.elementOnGrid(
game.board.rect(newX * blockWidth, centerCoordXY * blockWidth, blockWidth, blockWidth).attr('fill', '#19FF19'), // http://raphaeljs.com/reference.html#Paper.circle
newX,
centerCoordXY
) // add element of type elementOnGrid to the links
);
game.coords[newX][centerCoordXY] = false; // indicate that coordinates of element just added to snake is no longer open
}
}
在this.links.push中,我用newx替换了centercoordxy的一个实例。
你有很多重复的数据(位置存储在3个不同的地方,有两种不同的格式?)如果你不能使它们保持同步,很可能会导致这样的问题。最好使用画布而不是svg。如果您设置了SVG,我建议使用更多的helper函数例如,而不是
new game.elementOnGrid(
game.board.rect(newX * blockWidth, centerCoordXY * blockWidth, blockWidth, blockWidth).attr('fill', '#19FF19'), // http://raphaeljs.com/reference.html#Paper.circle
newX,
centerCoordXY
)
考虑一个函数,它允许您执行如下操作
newGridElement(newX, centerCoordXy, "#19FF19");
不管怎样,祝你好运!