关于小游戏:21天徒手撸一个游戏引擎5开火和分数

6次阅读

共计 5536 个字符,预计需要花费 14 分钟才能阅读完成。

设置一个子弹数组:

const bullets = []

加载子弹素材

loader.add('bullet', 'images/bullet.png')

增加点击事件:

wx.onTouchEnd((result) => {if (!gameover) {const bullet = new Sprite(0, 0, res['bullet'], 0.1)
     bullet.setPosition(player.x, player.y)// 子弹的坐标,就是 player 的坐标。bullets.push(bullet)
  }
})

step 中,update 减少:

bullets.map(bullet => {bullet.y -= 5;})

step 中,draw 减少:

enemys.map(enemy => {enemy.draw(context)
})

当初,能够停火了。然而炮弹还没有碰撞检测:

在子弹的 update 中,加上碰撞检测

bullets.map((bullet, bullet_index) => {
        bullet.y -= 5;
        if (bullet.y <= bullet.height) {bullets.splice(bullet_index, 1)
        } else {enemys = enemys.filter((enemy) => {
            if (enemy.x + enemy.width * collision_buff > bullet.x &&
              enemy.x < bullet.x + enemy.width * collision_buff && bullet.y + bullet.height * collision_buff > enemy.y &&
              bullet.y < enemy.y + enemy.height * collision_buff) {bullets.splice(bullet_index, 1)
            } else {return enemy}
          })
        }
})

当初成果如下

game.js 全副代码

import './libs/weapp-adapter'
import './libs/symbol'
import {
  ResLoader,
  Sprite
} from './codetyphon/index'
const context = canvas.getContext('2d')
const {
  windowWidth,
  windowHeight
} = wx.getSystemInfoSync()

let time = 0
let enemys = []
const bullets = []
let gameover = false
const collision_buff = 0.8

function rand(min, max) {return Math.round(Math.random() * (max - min) + min);
}
const loader = new ResLoader()
loader.add('player', 'images/player.png')
loader.add('enemy', 'images/enemy.png')
loader.add('gameover', 'images/gameover.png')
loader.add('bullet', 'images/bullet.png')
loader.on_load_finish((res) => {const player = new Sprite(0, 0, res['player'], 0.5)
  player.setPosition(windowWidth / 2, windowHeight - player.height)
  const step = (timestamp) => {context.clearRect(0, 0, windowWidth, windowHeight)
    //update
    if (!gameover) {
      time += 1;
      if (time % 150 == 0) {const enemy = new Sprite(0, 0, res['enemy'], 0.5)
        enemy.setPosition(rand(0, windowWidth), 0)
        enemys.push(enemy)
      }
      player.update()
      enemys.map((enemy, enemy_index) => {
        enemy.y++;
        if (enemy.y >= windowHeight) {enemys.splice(enemy_index, 1)
        } else {
          //collision
          if (enemy.x + enemy.width * collision_buff > player.x &&
            enemy.x < player.x + enemy.width * collision_buff && player.y + player.height * collision_buff > enemy.y &&
            player.y < enemy.y + enemy.height * collision_buff) {gameover = true}
        }
      })
      bullets.map((bullet, bullet_index) => {
        bullet.y -= 5;
        if (bullet.y <= bullet.height) {bullets.splice(bullet_index, 1)
        } else {enemys = enemys.filter((enemy) => {
            if (enemy.x + enemy.width * collision_buff > bullet.x &&
              enemy.x < bullet.x + enemy.width * collision_buff && bullet.y + bullet.height * collision_buff > enemy.y &&
              bullet.y < enemy.y + enemy.height * collision_buff) {bullets.splice(bullet_index, 1)
            } else {return enemy}
          })
        }
      })
    }
    //draw
    player.draw(context)
    enemys.map(enemy => {enemy.draw(context)
    })
    bullets.map(bullet => {bullet.draw(context)
    })
    if (gameover) {context.drawImage(res['gameover'], windowWidth / 2 - res['gameover'].width / 4, windowHeight / 2 - res['gameover'].height / 4, res['gameover'].width / 2, res['gameover'].height / 2)
    }
    window.requestAnimationFrame(step);
  }
  window.requestAnimationFrame(step);
  wx.onTouchMove(function (res) {if (!gameover) {const x = res.changedTouches[0].clientX
      const y = res.changedTouches[0].clientY
      player.setPosition(x, y)
    }
  })
  wx.onTouchEnd((result) => {if (!gameover) {const bullet = new Sprite(0, 0, res['bullet'], 0.1)
      bullet.setPosition(player.x, player.y)
      bullets.push(bullet)
    }
  })
})

分数

let score = 0

在 bullets 的碰撞检测代码 bullets.splice(bullet_index, 1) 上面加上:

score += 1

在 step 的 drew 中减少:

context.font = 'normal 20px sans-serif';
context.fillStyle = '#fff'
context.fillText(score, 10, 30)

game.js 当初代码如下:

import './libs/weapp-adapter'
import './libs/symbol'
import {
  ResLoader,
  Sprite
} from './codetyphon/index'
const context = canvas.getContext('2d')
const {
  windowWidth,
  windowHeight
} = wx.getSystemInfoSync()

let time = 0
let enemys = []
const bullets = []
let gameover = false
const collision_buff = 0.8
let score = 0

function rand(min, max) {return Math.round(Math.random() * (max - min) + min);
}
const loader = new ResLoader()
loader.add('player', 'images/player.png')
loader.add('enemy', 'images/enemy.png')
loader.add('gameover', 'images/gameover.png')
loader.add('bullet', 'images/bullet.png')
loader.on_load_finish((res) => {const player = new Sprite(0, 0, res['player'], 0.5)
  player.setPosition(windowWidth / 2, windowHeight - player.height)
  const step = (timestamp) => {context.clearRect(0, 0, windowWidth, windowHeight)
    //update
    if (!gameover) {
      time += 1;
      if (time % 150 == 0) {const enemy = new Sprite(0, 0, res['enemy'], 0.5)
        enemy.setPosition(rand(0, windowWidth), 0)
        enemys.push(enemy)
      }
      player.update()
      enemys.map((enemy, enemy_index) => {
        enemy.y++;
        if (enemy.y >= windowHeight) {enemys.splice(enemy_index, 1)
        } else {
          //collision
          if (enemy.x + enemy.width * collision_buff > player.x &&
            enemy.x < player.x + enemy.width * collision_buff && player.y + player.height * collision_buff > enemy.y &&
            player.y < enemy.y + enemy.height * collision_buff) {gameover = true}
        }
      })
      bullets.map((bullet, bullet_index) => {
        bullet.y -= 5;
        if (bullet.y <= bullet.height) {bullets.splice(bullet_index, 1)
        } else {enemys = enemys.filter((enemy) => {
            if (enemy.x + enemy.width * collision_buff > bullet.x &&
              enemy.x < bullet.x + enemy.width * collision_buff && bullet.y + bullet.height * collision_buff > enemy.y &&
              bullet.y < enemy.y + enemy.height * collision_buff) {bullets.splice(bullet_index, 1)
              score += 1
            } else {return enemy}
          })
        }
      })
    }
    //draw
    player.draw(context)
    enemys.map(enemy => {enemy.draw(context)
    })
    bullets.map(bullet => {bullet.draw(context)
    })
    context.font = 'normal 20px sans-serif';
    context.fillStyle = '#fff'
    context.fillText(score, 10, 30)
    if (gameover) {context.drawImage(res['gameover'], windowWidth / 2 - res['gameover'].width / 4, windowHeight / 2 - res['gameover'].height / 4, res['gameover'].width / 2, res['gameover'].height / 2)
    }
    window.requestAnimationFrame(step);
  }
  window.requestAnimationFrame(step);
  wx.onTouchMove(function (res) {if (!gameover) {const x = res.changedTouches[0].clientX
      const y = res.changedTouches[0].clientY
      player.setPosition(x, y)
    }
  })
  wx.onTouchEnd((result) => {if (!gameover) {const bullet = new Sprite(0, 0, res['bullet'], 0.1)
      bullet.setPosition(player.x, player.y)
      bullets.push(bullet)
    }
  })
})

成果如下:

正文完
 0