javascript_snake

html


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <p>Score: 0</p>
  <div style="margin-bottom: 10px;"><button>reset</button></div>
  <canvas width="400" height="400" style="border: 1px solid;"></canvas>
</body>
<script src="script.js"></script>
</html>

javscript

const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
const scoreElem = document.querySelector('p')
const reset = document.querySelector('button')
const mapWidth = canvas.width
const mapHeight = canvas.height
const speed = 100

let snakeDirection_x = 0, snakeDirection_y = 0
let food, snake
let score  = 0
let gameOver = false
let timer

class Food {
  constructor(position) {
    this.x = position.x
    this.y = position.y
    this.size = 20
  }
  draw() {
    ctx.fillStyle = 'greenyellow'
    ctx.fillRect(this.x, this.y, this.size, this.size)
  }
}

class Snake {
  constructor() {
    this.x = 40
    this.y = 0
    this.size = 20
    this.body = [ { x: this.x, y: this.y }]
  }
  draw() {
    ctx.fillStyle = 'red'
    this.body.forEach(body => {
      ctx.fillRect(body.x, body.y, this.size - 1, this.size - 1)
    });
    ctx.fillStyle = 'blue'
    ctx.fillRect(this.body[score].x, this.body[score].y, this.size-1,this.size-1)
  }
  move() {
    if(!snakeDirection_x && !snakeDirection_y) return false 
    this.x += snakeDirection_x
    this.y += snakeDirection_y
    console.log(this.x);
    this.body.shift()
    this.body.push({ x: this.x, y: this.y })
  }
}

setup()
function setup() {
  snake = new Snake()
  food = new Food(randomFoodPosition())
  update()
}

function checkEatFood() {
  if(snake.x === food.x && snake.y === food.y) {
    snake.body.unshift(food.x, food.y)
    snake.body.shift()
    food = new Food(randomFoodPosition())
    score += 1
    updateScore()
  }
}

function randomFoodPosition() {
  const x = Math.floor(Math.random() * (mapWidth / 20)) * 20
  const y = Math.floor(Math.random() * (mapWidth / 20)) * 20
  // 防止food与snake重合
  for (let i = 0; i < snake.body.length; i++) {
    const body = snake.body[i];
    if(body.x === x && body.y === y) {
      return randomFoodPosition()
    }
  }
  return {x,y}
}

function checkSnakeBorder() {
  const head = snake.body[score]
  if (head.x < 0) {
    snake.x = mapWidth
  }else if(head.x >= mapWidth) {
    snake.x = -20
  }else if(head.y < 0) {
    snake.y = mapHeight
  }else if(snake.y >= mapHeight) {
    snake.y = -20
  }
}

function checkSnakeHeadEatBody() {
  const head = snake.body[score]
  for (let i = score-1; i >= 0; i--) {
    const body = snake.body[i];
    if (head.x === body.x && head.y === body.y) {
      gameOver = true
    }
  }
}

function updateScore() {
  scoreElem.innerHTML = `Score: ${score}`
}

function update() {
  if(gameOver) return false
  ctx.clearRect(0, 0, mapWidth, mapHeight)
  food.draw()
  snake.move()
  snake.draw()
  checkEatFood()
  checkSnakeBorder()
  checkSnakeHeadEatBody()
  timer = setTimeout(update, speed);
}

window.addEventListener('keydown', keyDown)
const keyUp = 87
const keyRight = 68
const keyBottom = 83
const keyLeft = 65
let keyFlag = false
function keyDown(e) {
  // console.log(e.keyCode);
  switch (e.keyCode) {
    case keyUp:
      if(snakeDirection_y === 20 || keyFlag) return
      snakeDirection_x = 0
      snakeDirection_y = -20
      keyFlag = true
      setTimeout(() => {
        keyFlag = false
      }, speed);
      break;
    case keyRight:
      if(snakeDirection_x === -20 || keyFlag) return
      snakeDirection_x = 20
      snakeDirection_y = 0
      keyFlag = true
      setTimeout(() => {
        keyFlag = false
      }, speed);
      break;
    case keyBottom:
      if(snakeDirection_y === -20 || keyFlag) return
      snakeDirection_x = 0
      snakeDirection_y = 20
      keyFlag = true
      setTimeout(() => {
        keyFlag = false
      }, speed);
      break;
    case keyLeft:
      if(snakeDirection_x === 20 || keyFlag) return
      snakeDirection_x = -20
      snakeDirection_y = 0
      keyFlag = true
      setTimeout(() => {
        keyFlag = false
      }, speed);
      break;
    default:
      break;
  }
}

reset.onclick = () => {
  clearTimeout(timer)
  score = 0
  updateScore()
  gameOver = false
  snakeDirection_x = 0
  snakeDirection_y = 0
  setup()
}
posted @ 2022-11-04 20:07  d浩然  阅读(20)  评论(0编辑  收藏  举报