2015-07-27 2 views
0

репрография шаги:Почему ссылки моей змеи на место друг друга?

  1. Посетите http://playclassicsnake.com/play
  2. См 3 зеленых квадратов и 1 красного круга
  3. Изменить размер экрана достаточно мала, чтобы сделать сетку, что змея живет на быть меньше
  4. Красным кругом будет изменен и заменен соответствующим образом, и так будет 1 зеленый квадрат, казалось бы,
  5. console.log(SG.snake.links.length);, чтобы увидеть, что на самом деле есть 3 ссылки на змею. Если вы посмотрите на координаты сетки каждого из трех отдельно с SG.snake.links[k].pos.x, SG.snake.links[k].pos.y за k=1,2,3, вы увидите, что они живут на одной и той же координате.

Источник задачи:

Источник должен быть моя реализация функции, которая обрабатывает изменения размера платы и элементов на плате. Это

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

}); 

Любая помощь в определении фрагмента логики, вызывающего ошибку, будет с благодарностью оценена!

+1

«Источником должна быть моя реализация функции, которая обрабатывает изменение размера доски и элементов на доске». Я не уверен в этом. Вы говорите, что использование SG.snake.links [k] .pos одинаково для всех ссылок, размещенных на одном и том же месте. Мне кажется, что this.rescale() только читает из pos и не пишет ему. Если я правильно понял, значит, ваша проблема должна быть раньше. (У меня нет времени, чтобы точно определить, где именно, но, надеюсь, это помогает) –

+1

@YM_Industries Вы были правы. Я понял это, и это было нечто другое. Благодаря! – user5124106

+0

Если я правильно понял (скажите, если я ошибаюсь), вы перемещаете змею, заменяя каждую ссылку по одному? Почему бы вам просто не удалить последний в хвосте и добавить его в голову при перемещении? – ChatterOne

ответ

1

Внутри this.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 я заменил экземпляр centerCoordXY с newX.

У вас есть много дублированных данных (позиции хранятся в трех разных местах и ​​в двух разных форматах?), Которые могут вызвать такие проблемы, если вы не сможете синхронизировать их все. Возможно, лучше использовать Canvas, а не SVG. Если вы настроены на SVG, я бы рекомендовал больше вспомогательных функций. Например, вместо

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"); 

В любом случае, удачи!

Смежные вопросы