Vue3+Canvas实现坦克大战游戏(二)

目录
  • 前言
  • 敌方坦克的生成
  • 坦克移动的算法
  • 子弹击中物体的算法
  • 爆炸效果的实现
  • 生成障碍物(石墙、砖墙等)
  • 总结

前言

接着上篇讲,本篇主要给大家讲解一下子弹击中物体、物体销毁、敌方坦克构建生成、运动算法、爆炸效果、以及障碍物的生成;了解了这些我相信你可以不依赖游戏引擎实现大部分小游戏的开发。

Es5版本: 在线游戏 源代码

W/上 S/下 A/左 D/右 F/射击

让我们开始吧!

敌方坦克的生成

我们可以使用 for 循环和Tank 构造函数,批量制造多个敌方坦克,x,y 为其在画布中的坐标,direction 为坦克当前方向,type 为精灵图中截取坦克图片的信息,包含了坐标,尺寸,类型等

for(let t=0; t<20; t++) {
  let tank = new Tank(new TankConfig({
    x: 100 + t*30,
    y: 100,
    direction: DIRECTION.DOWN,
    type: TANK_TYPE.ENEMY0,
    is_player: 0
  }))
  tank.star();
}

ENEMY0: {
  type: 'ENEMY1',
  dimension: [30, 30],
  image_coordinates: [129, 1, 129, 33]
}

坦克移动的算法

emove 函数就是就是物体移动状态下每帧都会执行的函数,将根据当前方向修改下帧的坐标,当下帧坐标到达地图边缘时将执行 dir 函数更新坦克方向,如果是子弹则将销毁。

this.emove = function (d, obstacle_sprites) {
    this.direction = d
    switch (d) {
      case DIRECTION.UP:
        if (
          (obstacle_sprites && !this.checkRangeOverlap(obstacle_sprites)) ||
          !obstacle_sprites
        ) {
          this.y -= this.speed

          if (this.y <= 10) {
            this.dir()
          }
        } else {
          this.dir()
        }
        break
    ...

dir 函数用来随机修改移动的方向,当然这个函数不能每帧都调用,否则坦克将像无头苍蝇一样了;那么什么时候需要修改方向呢,我们认为当坦克和物体相撞的时候或者到达地图边缘时修改方向是合理的;子弹也可以认为是一个物体,所以子弹到达坦克周边一定距离时也将引起坦克规避动作,也就是将触发dir 函数。

this.dir = function () {
    if(Math.floor(Math.random()*10) === 0 || Math.floor(Math.random()*10) === 1) {
      this.direction = DIRECTION.UP;
    };
    if(Math.floor(Math.random()*10) === 2 || Math.floor(Math.random()*10) === 3) {
      this.direction = DIRECTION.DOWN;
    };
    if(Math.floor(Math.random()*10) === 4 || Math.floor(Math.random()*10) === 5) {
      this.direction = DIRECTION.LEFT;
    };
    if(Math.floor(Math.random()*10) === 6 || Math.floor(Math.random()*10) === 7) {
      this.direction = DIRECTION.RIGHT;
    };
    if(Math.floor(Math.random()*10) === 8 || Math.floor(Math.random()*10) === 9) {
      this.dir();
    }
}

子弹击中物体的算法

我们定义 checkRangeOverlap 函数来判断两个物体是否相撞,uiobjs 为画布中所有的元素对象列表,包含 坦克、子弹、障碍物等;

this.getFrontPoints() 函数将根据当前方向返回包含三个顶端点坐标数组,形成判断区域;

uiobjs[o].getCornerPoints() 函数返回当前元素的四个边角坐标数组,形成判断区域;

然后getFrontPoints() 的三个点坐标 将分别和 uiobjs[o].getCornerPoints() 的四边坐标进行点对点判断,根据x, y 数值满足下方四个条件时则认为此点坐标在元素内部。

 // 判断点坐标是否在区域内部,以识别是否相撞
  CanvasSprite.prototype.checkRangeOverlap = function (uiobjs) {
    for (let o in uiobjs) {
      let obstacle_cp = uiobjs[o].getCornerPoints()
      let fp = this.getFrontPoints()

      for (let idx = 0; idx < fp.length; idx++) {
        if (
          fp[idx].x > obstacle_cp[0].x &&
          fp[idx].x < obstacle_cp[1].x &&
          fp[idx].y > obstacle_cp[0].y &&
          fp[idx].y < obstacle_cp[2].y
        ) {
          return true
        }
      }
    }
    return false
  }
// 返回当前物体顶端三坐标
  CanvasSprite.prototype.getFrontPoints = function () {
    let front_point
    switch (this.direction) {
      case DIRECTION.UP:
        front_point = [
          new Point(this.x, this.y),
          new Point((2 * this.x + this.width) / 2, this.y),
          new Point(this.x + this.width, this.y),
        ]
        break
      ... 缩略,下左右方向
    }
    return front_point
  }
// 返回元素四边坐标形成的矩形区域范围
  CanvasSprite.prototype.getCornerPoints = function () {
    var corner_points
    switch (this.direction) {
      case DIRECTION.UP:
        corner_points = [
          new Point(this.x, this.y),
          new Point(this.x + this.width, this.y),
          new Point(this.x + this.width, this.y + this.height),
          new Point(this.x, this.y + this.height),
        ]
        break
        ... 缩略,下左右方向
    }
    return corner_points
  }

啊 坦克搞多了!但是可以看到子弹击中效果是成功的,你发现了没,击中后有一个爆炸效果,这个是怎么实现的呢?

爆炸效果的实现

当识别到击中后将此坦克将触发explode 爆炸效果,然后每帧 判断 isDestroied 是否销毁,后续每帧将 explosion_count++ 从 0 到 5,然后更改alive 状态为0 代表已销毁。

if (s instanceof Tank && s.alive && s.isDestroied()) {
    s.explode()
}
this.isDestroied = function () {
    return explosion_count > 0
  }

this.explode = function () {
    if (explosion_count++ === 5) {
      this.alive = 0
    }
  }

然后 explosion_count 的数值,从0 到 5 代表爆炸效果图的5帧

  this.getImg = function () {
    if (explosion_count > 0) {
      return {
        width: TANK_EXPLOSION_FRAME[explosion_count].dimension[0],
        height: TANK_EXPLOSION_FRAME[explosion_count].dimension[1],
        offset_x: TANK_EXPLOSION_FRAME[explosion_count].image_coordinates[0],
        offset_y: TANK_EXPLOSION_FRAME[explosion_count].image_coordinates[1],
      }
    } else {
      return {
        width: width,
        height: height,
        offset_x: this.type.image_coordinates[0],
        offset_y: this.type.image_coordinates[1],
      }
    }
  }

到现在我们的坦克游戏已经基本可玩了,只不过现在是一片大平原,毫无遮拦,我们该为画布增加一些障碍物如墙体,石头等,增加游戏可玩性。

生成障碍物(石墙、砖墙等)

有了之前tanke 和 子弹的构建函数,现在这个 Block 就简单多了,只需要定义好基本的信息,如坐标,宽高、状态、方向,然后借用 apply 来使用 CanvasSprite 上的通用方法。

    let Block = function (x, y, direction, type) {
      type = type || BLOCK_TYPE.BLOCK_BRICK
      let alive = 1
      let width = type.dimension[0]
      let height = type.dimension[1]
      let explosion_count = 0
      this.type = type

      this.x = x
      this.y = y
      this.genre = 'block'
      this.direction = direction || DIRECTION.UP

      CanvasSprite.apply(this, [
        {
          alive: 1,
          border_y: HEIGHT,
          border_x: WIDTH,
          speed: 0,
          direction: direction,
          x: x,
          y: y,
          width: width,
          height: height,
        },
      ])

      this.isDestroied = function () {
        return explosion_count > 0
      }

      this.explode = function () {
        if (explosion_count++ === 5) {
          this.alive = 0
        }
      }

      this.getImg = function () {
        if (explosion_count > 0) {
          return {
            width: TANK_EXPLOSION_FRAME[explosion_count].dimension[0],
            height: TANK_EXPLOSION_FRAME[explosion_count].dimension[1],
            offset_x: TANK_EXPLOSION_FRAME[explosion_count].image_coordinates[0],
            offset_y: TANK_EXPLOSION_FRAME[explosion_count].image_coordinates[1],
          }
        } else {
          return {
            width: width,
            height: height,
            offset_x: type.image_coordinates[0],
            offset_y: type.image_coordinates[1],
          }
        }
      }

      this._generateId = function () {
        return uuidv4()
      }

      sprites[this._generateId()] = this
    }

定义好后,使用时只需批量生成Block 的实例,将坐标,类型等信息传递进去就可以在下一帧渲染出来。

  for(let i=0; i<=2; i++) {
    for(let j=0; j<=2; j++) {
      let block = new Block(j*16, 140 + i*16, DIRECTION.UP, BLOCK_TYPE.BLOCK_STONE)
    }
  }

好了我们看看最终的效果吧!

总结

ok 坦克大战基本上完成了,你可以修改子弹发射速度,敌方坦克数量,障碍物也可以自己随意画,可玩性还是挺好的,当然还有很多细节可以完善,如 预制几种不同的地图,做成通关类,预制几条生命等。如果你想试一下,可以 star 下 github 仓库自己来改造自己的坦克大战吧。

以上就是Vue3+Canvas实现坦克大战游戏(二)的详细内容,更多关于Vue3 Canvas坦克大战的资料请关注我们其它相关文章!

(0)

相关推荐

  • VUE+Canvas 实现桌面弹球消砖块小游戏的示例代码

    大家都玩过弹球消砖块游戏,左右键控制最底端的一个小木板平移,接住掉落的小球,将球弹起后消除画面上方的一堆砖块. 那么用VUE+Canvas如何来实现呢?实现思路很简单,首先来拆分一下要画在画布上的内容: (1)用键盘左右按键控制平移的木板: (2)在画布内四处弹跳的小球: (3)固定在画面上方,并且被球碰撞后就消失的一堆砖块. 将上述三种对象,用requestAnimationFrame()函数平移运动起来,再结合各种碰撞检查,就可以得到最终的结果. 先看看最终的效果: 一.左右平移的木板 最底

  • VUE+Canvas实现财神爷接元宝小游戏

    之前的canvas小游戏系列欢迎大家戳: <VUE实现一个Flappy Bird~~~> <猜单词游戏> <VUE+Canvas 实现桌面弹球消砖块小游戏> <VUE+Canvas实现雷霆战机打字类小游戏> 如标题,这个游戏大家也玩过,随处可见,左右方向键控制财神移动,接住从天而降的金元宝等,时间一到,则游戏结束.先来看一下效果: 相比于之前的雷霆战机要打出四处飞的子弹,这次元素的运动轨迹就很单一了,垂直方向的珠宝和水平移动的财神爷,类似于之前的代码,这里就

  • Vue3+Canvas实现坦克大战游戏

    目录 前言 架构搭建 Canvas构造函数 画布绘制 文本渲染 画布重绘前的clear 核心:绘制函数 BattleCity构造函数 实现坦克的移动 坦克发射子弹的逻辑 总结 前言 记得几年前刚做前端开发的时候,跟着师傅用纯 es5 实现了这款坦克大战,可以说我入行前端是从 javaScript 小游戏开始的,时间已匆匆过去了数年,前端发展日新月异,各种新框架.新概念层出不穷,很容易就迷失在对各种新技术的盲目学习和应用中,真正的编程是什么呢?值得思考的问题. 我准备用 vue3 重新实现一下这款

  • vue+canvas实现拼图小游戏

    利用 vue+canvas 实现拼图小游戏,供大家参考,具体内容如下 思路步骤 一个拼图拼盘和一个原图参照 对原图的切割以及随机排序 通过W/A/D/S或上下左右进行移动 难度的自主选择 对拼图是否完成的判定 JS实现部分 数据分析 row:拼图的总行数:column:拼图的总列数. (用来设置拼图难度,也是每个拼图块宽高的设置规则) pic[{x,y,row,column,index}]:小拼图的集合,其内元素为小拼图的数据结构. (x.y:拼图块在canvas的绘制规则,初始化后不会进行改变

  • VUE+Canvas实现简单五子棋游戏的全过程

    前言 在布局上,五子棋相比那些目标是随机运动的游戏,实现起来相对简单许多,思路也很清晰,总共分为: (1)画棋盘: (2)监听点击事件画黑白棋子: (3)每次落子之后判断是否有5子相连,有则赢. 最复杂的恐怕就是如何判断五子棋赢了,那么就先从简单的开始,画个棋盘吧~ 1.画棋盘 棋盘很简单,我们画个15*15的棋盘,横线竖线相交错: drawCheckerboard() { // 画棋盘 let _this = this; _this.ctx.beginPath(); _this.ctx.fil

  • Vue3+Canvas实现坦克大战游戏(二)

    目录 前言 敌方坦克的生成 坦克移动的算法 子弹击中物体的算法 爆炸效果的实现 生成障碍物(石墙.砖墙等) 总结 前言 接着上篇讲,本篇主要给大家讲解一下子弹击中物体.物体销毁.敌方坦克构建生成.运动算法.爆炸效果.以及障碍物的生成:了解了这些我相信你可以不依赖游戏引擎实现大部分小游戏的开发. Es5版本: 在线游戏 源代码 W/上 S/下 A/左 D/右 F/射击 让我们开始吧! 敌方坦克的生成 我们可以使用 for 循环和Tank 构造函数,批量制造多个敌方坦克,x,y 为其在画布中的坐标,

  • Vue3+Canvas实现坦克大战游戏(一)

    目录 前言 架构搭建 Canvas 构造函数 画布绘制 文本渲染 画布重绘前的 clear 核心:绘制函数 BattleCity 构造函数 实现坦克的移动 坦克发射子弹的逻辑 总结 前言 记得几年前刚做前端开发的时候,跟着师傅用纯 es5 实现了这款坦克大战,可以说我入行前端是从 javaScript 小游戏开始的,时间已匆匆过去了数年,前端发展日新月异,各种新框架.新概念层出不穷,很容易就迷失在对各种新技术的盲目学习和应用中,真正的编程是什么呢?值得思考的问题. 我准备用 vue3 重新实现一

  • 经典再现 基于JAVA平台开发坦克大战游戏

    一.需求描述  1.功能性需求 在功能需求分析阶段,我们的主要任务是指定系统必须提供哪些服务,定义软件完成哪些功能,提供给那些人使用,功能需求是软件开发的一项基本需求,是需求分析必不可少的一部分.坦克大战是一款经典游戏了,本游戏学习了一些前辈们的经验,整体来说讲,游戏分为敌我双方,主要参与战斗的坦克有玩家控制,敌人坦克可以智能随机出现在屏幕上,并且移动,发射一定数量的子弹:玩家可以在规定的区域内随意移动坦克,当有子弹击中玩家时,玩家死亡,游戏结束:敌人坦克智能运行,敌方坦克由于需要具有一定智能性

  • js实现坦克大战游戏

    本文实例为大家分享了js实现坦克大战游戏的具体代码,供大家参考,具体内容如下 <!DOCTYPE html> <html> <head> <title>tank</title> <style type="text/css"> body { margin: 0px; padding: 0px; border: 0px; } .map { position: absolute; top: 30px; width: 39

  • java实现坦克大战游戏

    本文实例为大家分享了java实现坦克大战游戏的具体代码,供大家参考,具体内容如下 一.实现的功能 1.游戏玩法介绍 2.自定义游戏(选择游戏难度.关卡等) 3.自定义玩家姓名 4.数据的动态显示 二.程序基本结构 三.主要的界面 1)游戏首页 2)自定义游戏页面 3)游戏介绍 4)开始游戏,自定义玩家姓名 5)游戏主页面 四.主要代码 1)数据的初始化类 public class Data { public static boolean isRestart=false; public stati

  • Java Swing实现坦克大战游戏

    一.引言 90坦克大战,很经典的一款游戏,当年与小伙伴一人一个手柄,搬上小板凳坐在电视机前,身体时不时跟随手柄摇晃着,时而表情严肃.眉头紧锁,时而欢呼雀跃.喜笑颜开,全身心投入到游戏中,在消灭一只只坦克.守住关卡.坦克升级.晋级通关的时候,更是手舞足蹈.击掌庆祝,如今想想也是记忆犹新.回味无穷!于是乎就我就自己用java写了一个,找一下当年的感觉,顺便虐一下电脑,嘻嘻嘻嘻嘻(ming式笑声). 二.效果图 三.实现 绘图时将这个鹰的图标用 g.drawImage 的方式绘制在界面中央最下方,然后

  • python实现双人版坦克大战游戏

    游戏介绍: 双人版的<坦克大战>的基本规则是玩家消灭出现的敌方坦克保卫我方基地. 中间还会随机出现很多特殊道具吸收可获得相应的功能,消灭玩即可进入下一关. 方向键:上下左右移动即可.另一个方向键则是:WSAD. 环境配置: Python3. Pycharm .Pygame. 第三方库的安装:pip  install pygame 效果展示: 开始界面一一 开始即可上手玩游戏,还有背景音乐辅助!游戏玩儿起来更带感!  游戏界面-- 代码演示: 1)游戏主程序 import pygame impo

  • Pygame坦克大战游戏开发实战详解代码

    导语 哈喽!哈喽——我是木木子 今天来升级下之前写的坦克大战游戏嘛,哈哈哈 其实也不算是修改,就是稍微的调试一下!​​ 因为之前写的界面都是英文的 ,有的小伙伴儿英文一点儿都不会的可能看着别扭,今天来一款中 文版的给大家嘛! 俗话说的好:“雨露均沾”.哈哈哈.jpg 小简介: <坦克大战>,1985年由日本开发商南梦宫(Namco)开发,是第一款可以双打的红白机游戏. 当时使用的还是小霸王. 很多小朋友以学习的名义买了以后偷偷打的打游戏还被家长发现了有 没得! <坦克大战>红白机原

  • Java版坦克大战游戏源码示例

    整理文档,搜刮出一个Java版坦克大战游戏的代码,稍微整理精简一下做下分享. package tankwar; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.io.File; import java.io.FileInputStream; imp

随机推荐