javascript - 无法弄清楚如何在 block 之间添加一点空间

标签 javascript html css

我在这篇文章的底部写了小蛇游戏。

现在我想通过 block 之间的一点点(黑色)空间将每个蛇体 block 分开,以便绿色 block 彼此明显分开。

类似于[s] [s] [s] [s][s] 现在是一个绿色的蛇身 block ,但我不知道如何在它们之间添加 空间。

我对 JS 很满意,但 CSS 的这些细节对我来说仍然是个谜。我什至不确定我是否首先使用正确的方法来“绘制”蛇。

let _game;
var gameLoopHandle;
var pollingHandle;
let Snake = function(forGame,startingDirection, startingBody){
  this.going = startingDirection || "RIGHT";

  this.go = function(direction){
    let snakeHead = {x:this.getHead().x,y:this.getHead().y};
    

    switch(direction.toLowerCase()){
      case "left":
        snakeHead.y--;
        this.going = "LEFT";
        break;
      case "right":
        snakeHead.y++;
        this.going = "RIGHT";
        break;
      case "up":
        snakeHead.x--;
        this.going = "UP";
        break;
      case "down":
        snakeHead.x++;
        this.going = "DOWN";
        break;
    }
    let newBlock = 
    generateBlock(snakeHead.x,snakeHead.y,
      this.gameInstance.boardSizeX,this.gameInstance.boardSizeY);



    if (this.posIsApple(newBlock)) {
      this.gameInstance.score++;
      this.gameInstance.genApple = true;
    } else {
      this.removeBockTailFromSnake();
    }
    if (this.posIsTail(newBlock)){
      
      this.gameInstance.ended = true;
    }

  
    this.addBlockHeadToSnake(newBlock);
  };

  this.body = startingBody || [
    {x:9,y:8},
    {x:9,y:9},
    {x:9,y:10},
    {x:9,y:11}

  ];

  this.gameInstance = forGame;
  this.getHead = function(){
    return this.body[this.body.length-1];
  };

  this.posIsTail = function(pos){
    for (let i = 0; i<this.body.length;i++){
      if (pos.x === this.body[i].x && pos.y === this.body[i].y) {
        return true;
      }
    }
    return false;
  };

  this.posIsApple = function(pos){
    return pos.x === this.gameInstance.apple.x && pos.y === this.gameInstance.apple.y;
  };

  this.addBlockHeadToSnake = function(block){
    this.body.push(block);
  }

  this.removeBockTailFromSnake = function(){
    this.body.shift();
  }
}
let serverListener = function(keyEvents){
  console.log(keyEvents);
  for (let i = 0; i<keyEvents.length;i++) {
    var event = new Event('keydown');
    event.key="Arrow" + capitalizeFirstLetter(keyEvents[i].toLowerCase());
    document.dispatchEvent(event);
  }
}




let SnakeGame = function(){
  this.board = [];
  this.snake = {};
  this.apple = {};
  this.score = 0;
  this.speed = 500;
  this.ended = false;
  this.genApple = true;
  this.boardSizeX = 20;
  this.boardSizeY = 20;
  this.manager = {};
}

SnakeGame.prototype.init = function(options){
  options = options || {};
  this.boardSizeX = options.boardSizeX || 20;
  this.boardSizeY = options.boardSizeY || 20;
  
  this.snake = options.snake || new Snake(this);
  
}

SnakeGame.prototype.setSnake = function(){
  // sets snake to provided params
}

SnakeGame.prototype.generateBoard = function(){
  this.board = [];
  for (let i=0;i<this.boardSizeX;i++){
    let boardRow=[];
    for (let j = 0; j < this.boardSizeY; j++) {
      let havePixel = false;
      for (let k = 0; k<this.snake.body.length;k++){
        if (this.snake.body[k].x === i && this.snake.body[k].y === j ){
          havePixel = true;
        }
      }
      if (havePixel) {
        boardRow.push(1);
      } else {
        boardRow.push(0);
      }
    }
    this.board.push(boardRow);
  }
}

SnakeGame.prototype.setSpeed = function(speed){
  this.speed = speed;
}

SnakeGame.prototype.setScore = function(score){
  this.score = score;
}

let generateBlock = function(x,y,limitX,limitY){
  let block = {};
  if (x===limitX) {
    block.x = 0;
  } else if (x == -1) {
    block.x = limitX-1;
  } else {
    block.x = x;
  }

  if (y===limitY) {
    block.y = 0;
  } else if (y == -1) {
    block.y = limitY-1;
  } else {
    block.y = y;
  }

  return block;
}

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

let genericDiv = function(color){
  let returnDiv = document.createElement("div");
  returnDiv.style.height = "10px";
  returnDiv.style.width = "10px";
  returnDiv.style.background = color;

  return returnDiv;
}

let snakeDiv = function(){
return genericDiv("lime");
}

let emptyDiv = function(){
return genericDiv("black");
}

let appleDiv = function(){
return genericDiv("red");
}

function updateDOM(game) {
  var el = document.getElementById("gameboard");
  el.innerHTML = "";
  el.style.position = "relative";
  var scoreEl = document.getElementById("score");
  scoreEl.innerText = game.score;
  if (game.genApple) {
    generateAppleNoCollision(game);
  }

  for (let i =0;i<game.board.length;i++){
    let snakeRowDiv = document.createElement("div");
    //snakeRowDiv.style.position = "absolute";
    for (let j=0;j<game.board[i].length;j++){
      let whichDiv = null;
      if (game.board[i][j]){
        whichDiv = snakeDiv();
      } else if (i==game.apple.x && j == game.apple.y){
          whichDiv = appleDiv();
      } 
      
      if (whichDiv == null){
        whichDiv = emptyDiv();
      }
       
      whichDiv.style.position = "absolute";
      whichDiv.style.left = j * (parseInt(whichDiv.style.width)) + "px";
      whichDiv.style.top = (i * (parseInt(whichDiv.style.height)) + 100)  + "px";
      snakeRowDiv.appendChild(whichDiv);
    
    }

    el.appendChild(snakeRowDiv);
  }
}

function generateDomListener(game){
  return function(event){
    switch (event.key) {
      case "ArrowUp":
        if (game.snake.going != "DOWN"){
          game.snake.going = "UP";
        }
        break;
      case "ArrowDown":
        if (game.snake.going != "UP"){
          game.snake.going = "DOWN";
        }
        break;
      case "ArrowLeft":
        if (game.snake.going != "RIGHT") {
          game.snake.going = "LEFT";
        }
        
        break;
      case "ArrowRight":
        if (game.snake.going != "LEFT") {
          game.snake.going = "RIGHT";
        }
        break;
    }
  }
}

function capitalizeFirstLetter(string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
}

function decreaseDifficulty(game){
  if (game.speed <= 900) {
    game.speed += 50;
  }
  clearInterval(gameLoopHandle);
  gameLoopHandle = setInterval(gameLoop(game), game.speed);
}
function restart(game){
  game.ended = false;
  game.genApple = true;
  game.score = 0;
  game.speed = 500;
  game.apple = {x:null,y:null}

  game.snake.body = [
    {x:9,y:8},
    {x:9,y:9},
    {x:9,y:10},
    {x:9,y:11},
  ]
  game.snake.going = "RIGHT";

  clearInterval(gameLoopHandle);
  gameLoopHandle = setInterval(gameLoop(game), game.speed);
  
}
function generateAppleNoCollision(game){
  while(true){
    game.apple.x = getRandomInt(0,game.board.length-1);
    game.apple.y = getRandomInt(0,game.board.length-1);
    let hasCollision = false;
    for (let i = 0; i<game.snake.body.length;i++){
      if(game.apple.x === game.snake.body[i].x && 
        game.apple.y === game.snake.body[i].y) {
          hasCollision = true;
        }
    }
    if (!hasCollision) {
      console.log("no collision, continuing with this apple")
      break;
    }
    console.error("found collision, searching once more")
  }
  game.genApple = false;
}
function increaseDifficulty(game){
  if (game.speed >= 100) {
    game.speed -= 50;
  }
  clearInterval(gameLoopHandle);
  gameLoopHandle = setInterval(gameLoop(game), game.speed);
}

function gameLoop(game){
  return function(){
    if (!game.ended) {
      game.snake.go(game.snake.going);
      game.generateBoard();
      updateDOM(game);
    } else {
      clearInterval(gameLoopHandle);
      alert ("GAME OVER");
    }
  }
}
function polling(game){
  return function(){
  var scriptsDiv = document.getElementById("scripts");
  var script = document.createElement('script');
    script.src="http://172.168.1.22/snake_relay/?command=get&callbackname=serverListener";
    if (game.scripts) {
      if (game.scripts.length == 100){
        let msg = "too many scripts, clearing the div";

        scriptsDiv.innerHTML = ""
      }
      game.scripts.push(script);
    } else {
      game.scripts = [script];
    }
    scriptsDiv.appendChild(script);
  }
}
document.addEventListener("DOMContentLoaded", function(event) {
  var game = new SnakeGame();
  _game =game;
  game.init();
  game.generateBoard()
  updateDOM(game);
  document.addEventListener("keydown", generateDomListener(game));
  //pollingHandle = setInterval(polling(game), 100);

  gameLoopHandle = setInterval(gameLoop(game), game.speed);
})
<div id="gameboard"></div>
<div>
  <h1>Score: <span id="score">0</span></h1>
  <button onclick="increaseDifficulty(_game)">Increase difficulty</button>
  <button onclick="decreaseDifficulty(_game)">Decrease difficulty</button>
  <button onclick="restart(_game)">Restart</button>
</div>
<div id="scripts"></div>

最佳答案

您可以在 genericDiv 中设置边框,并将必要的值传递给 snakeDiv

let snakeDiv = function(){
   return genericDiv("lime", "1px solid #000000");
}

您可以将边框大小设置为您需要的任何大小。

let _game;
var gameLoopHandle;
var pollingHandle;
let Snake = function(forGame,startingDirection, startingBody){
  this.going = startingDirection || "RIGHT";

  this.go = function(direction){
    let snakeHead = {x:this.getHead().x,y:this.getHead().y};
    

    switch(direction.toLowerCase()){
      case "left":
        snakeHead.y--;
        this.going = "LEFT";
        break;
      case "right":
        snakeHead.y++;
        this.going = "RIGHT";
        break;
      case "up":
        snakeHead.x--;
        this.going = "UP";
        break;
      case "down":
        snakeHead.x++;
        this.going = "DOWN";
        break;
    }
    let newBlock = 
    generateBlock(snakeHead.x,snakeHead.y,
      this.gameInstance.boardSizeX,this.gameInstance.boardSizeY);



    if (this.posIsApple(newBlock)) {
      this.gameInstance.score++;
      this.gameInstance.genApple = true;
    } else {
      this.removeBockTailFromSnake();
    }
    if (this.posIsTail(newBlock)){
      
      this.gameInstance.ended = true;
    }

  
    this.addBlockHeadToSnake(newBlock);
  };

  this.body = startingBody || [
    {x:9,y:8},
    {x:9,y:9},
    {x:9,y:10},
    {x:9,y:11}

  ];

  this.gameInstance = forGame;
  this.getHead = function(){
    return this.body[this.body.length-1];
  };

  this.posIsTail = function(pos){
    for (let i = 0; i<this.body.length;i++){
      if (pos.x === this.body[i].x && pos.y === this.body[i].y) {
        return true;
      }
    }
    return false;
  };

  this.posIsApple = function(pos){
    return pos.x === this.gameInstance.apple.x && pos.y === this.gameInstance.apple.y;
  };

  this.addBlockHeadToSnake = function(block){
    this.body.push(block);
  }

  this.removeBockTailFromSnake = function(){
    this.body.shift();
  }
}
let serverListener = function(keyEvents){
  console.log(keyEvents);
  for (let i = 0; i<keyEvents.length;i++) {
    var event = new Event('keydown');
    event.key="Arrow" + capitalizeFirstLetter(keyEvents[i].toLowerCase());
    document.dispatchEvent(event);
  }
}




let SnakeGame = function(){
  this.board = [];
  this.snake = {};
  this.apple = {};
  this.score = 0;
  this.speed = 500;
  this.ended = false;
  this.genApple = true;
  this.boardSizeX = 20;
  this.boardSizeY = 20;
  this.manager = {};
}

SnakeGame.prototype.init = function(options){
  options = options || {};
  this.boardSizeX = options.boardSizeX || 20;
  this.boardSizeY = options.boardSizeY || 20;
  
  this.snake = options.snake || new Snake(this);
  
}

SnakeGame.prototype.setSnake = function(){
  // sets snake to provided params
}

SnakeGame.prototype.generateBoard = function(){
  this.board = [];
  for (let i=0;i<this.boardSizeX;i++){
    let boardRow=[];
    for (let j = 0; j < this.boardSizeY; j++) {
      let havePixel = false;
      for (let k = 0; k<this.snake.body.length;k++){
        if (this.snake.body[k].x === i && this.snake.body[k].y === j ){
          havePixel = true;
        }
      }
      if (havePixel) {
        boardRow.push(1);
      } else {
        boardRow.push(0);
      }
    }
    this.board.push(boardRow);
  }
}

SnakeGame.prototype.setSpeed = function(speed){
  this.speed = speed;
}

SnakeGame.prototype.setScore = function(score){
  this.score = score;
}

let generateBlock = function(x,y,limitX,limitY){
  let block = {};
  if (x===limitX) {
    block.x = 0;
  } else if (x == -1) {
    block.x = limitX-1;
  } else {
    block.x = x;
  }

  if (y===limitY) {
    block.y = 0;
  } else if (y == -1) {
    block.y = limitY-1;
  } else {
    block.y = y;
  }

  return block;
}

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

let genericDiv = function(color, border){
  let returnDiv = document.createElement("div");
  returnDiv.style.height = "10px";
  returnDiv.style.width = "10px";
  returnDiv.style.background = color;
  returnDiv.style.border = border;

  return returnDiv;
}

let snakeDiv = function(){
return genericDiv("lime", "1px solid #000000");
}

let emptyDiv = function(){
return genericDiv("black");
}

let appleDiv = function(){
return genericDiv("red");
}

function updateDOM(game) {
  var el = document.getElementById("gameboard");
  el.innerHTML = "";
  el.style.position = "relative";
  var scoreEl = document.getElementById("score");
  scoreEl.innerText = game.score;
  if (game.genApple) {
    generateAppleNoCollision(game);
  }

  for (let i =0;i<game.board.length;i++){
    let snakeRowDiv = document.createElement("div");
    //snakeRowDiv.style.position = "absolute";
    for (let j=0;j<game.board[i].length;j++){
      let whichDiv = null;
      if (game.board[i][j]){
        whichDiv = snakeDiv();
      } else if (i==game.apple.x && j == game.apple.y){
          whichDiv = appleDiv();
      } 
      
      if (whichDiv == null){
        whichDiv = emptyDiv();
      }
       
      whichDiv.style.position = "absolute";
      whichDiv.style.left = j * (parseInt(whichDiv.style.width)) + "px";
      whichDiv.style.top = (i * (parseInt(whichDiv.style.height)) + 100)  + "px";
      snakeRowDiv.appendChild(whichDiv);
    
    }

    el.appendChild(snakeRowDiv);
  }
}

function generateDomListener(game){
  return function(event){
    switch (event.key) {
      case "ArrowUp":
        if (game.snake.going != "DOWN"){
          game.snake.going = "UP";
        }
        break;
      case "ArrowDown":
        if (game.snake.going != "UP"){
          game.snake.going = "DOWN";
        }
        break;
      case "ArrowLeft":
        if (game.snake.going != "RIGHT") {
          game.snake.going = "LEFT";
        }
        
        break;
      case "ArrowRight":
        if (game.snake.going != "LEFT") {
          game.snake.going = "RIGHT";
        }
        break;
    }
  }
}

function capitalizeFirstLetter(string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
}

function decreaseDifficulty(game){
  if (game.speed <= 900) {
    game.speed += 50;
  }
  clearInterval(gameLoopHandle);
  gameLoopHandle = setInterval(gameLoop(game), game.speed);
}
function restart(game){
  game.ended = false;
  game.genApple = true;
  game.score = 0;
  game.speed = 500;
  game.apple = {x:null,y:null}

  game.snake.body = [
    {x:9,y:8},
    {x:9,y:9},
    {x:9,y:10},
    {x:9,y:11},
  ]
  game.snake.going = "RIGHT";

  clearInterval(gameLoopHandle);
  gameLoopHandle = setInterval(gameLoop(game), game.speed);
  
}
function generateAppleNoCollision(game){
  while(true){
    game.apple.x = getRandomInt(0,game.board.length-1);
    game.apple.y = getRandomInt(0,game.board.length-1);
    let hasCollision = false;
    for (let i = 0; i<game.snake.body.length;i++){
      if(game.apple.x === game.snake.body[i].x && 
        game.apple.y === game.snake.body[i].y) {
          hasCollision = true;
        }
    }
    if (!hasCollision) {
      console.log("no collision, continuing with this apple")
      break;
    }
    console.error("found collision, searching once more")
  }
  game.genApple = false;
}
function increaseDifficulty(game){
  if (game.speed >= 100) {
    game.speed -= 50;
  }
  clearInterval(gameLoopHandle);
  gameLoopHandle = setInterval(gameLoop(game), game.speed);
}

function gameLoop(game){
  return function(){
    if (!game.ended) {
      game.snake.go(game.snake.going);
      game.generateBoard();
      updateDOM(game);
    } else {
      clearInterval(gameLoopHandle);
      alert ("GAME OVER");
    }
  }
}
function polling(game){
  return function(){
  var scriptsDiv = document.getElementById("scripts");
  var script = document.createElement('script');
    script.src="http://172.168.1.22/snake_relay/?command=get&callbackname=serverListener";
    if (game.scripts) {
      if (game.scripts.length == 100){
        let msg = "too many scripts, clearing the div";

        scriptsDiv.innerHTML = ""
      }
      game.scripts.push(script);
    } else {
      game.scripts = [script];
    }
    scriptsDiv.appendChild(script);
  }
}
document.addEventListener("DOMContentLoaded", function(event) {
  var game = new SnakeGame();
  _game =game;
  game.init();
  game.generateBoard()
  updateDOM(game);
  document.addEventListener("keydown", generateDomListener(game));
  //pollingHandle = setInterval(polling(game), 100);

  gameLoopHandle = setInterval(gameLoop(game), game.speed);
})
<div id="gameboard"></div>
<div>
  <h1>Score: <span id="score">0</span></h1>
  <button onclick="increaseDifficulty(_game)">Increase difficulty</button>
  <button onclick="decreaseDifficulty(_game)">Decrease difficulty</button>
  <button onclick="restart(_game)">Restart</button>
</div>
<div id="scripts"></div>

关于javascript - 无法弄清楚如何在 block 之间添加一点空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50286441/

相关文章:

javascript - JavaScript 中的窗口宽度

javascript - babel 在 React Native 中做了什么?

javascript - 内联进度条动画,更改触发器以从加载滚动?

html - HTML5 是否改变了 HTML 评论的标准?

html - 基于 Bootstrap 的移动网站 - 删除额外的填充

javascript - IE 的非冒泡提交事件的解决方法

html - 更改内容时如何使页面上的 div 垂直居中?

html - 使用 css 将背景图像居中时出现水平查看问题

html - 如何创建没有滚动条的水平可滑动菜单?

javascript - Ajax 请求,使用 javascript 更新 html 但样式不存在