21天徒手撸一个游戏引擎(5)开火和分数

codetyphon

设置一个子弹数组:

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

现在,可以开火了。但是炮弹还没有碰撞检测:

image

在子弹的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)
    }
  })
})

image

分数

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

效果如下:
image

阅读 608

17 声望
0 粉丝
0 条评论
17 声望
0 粉丝
文章目录
宣传栏