vue3 + canvas 实现坦克大战系列(二):核心原理讲解(上)

简介: 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();
    }
}


1687779144023.png


子弹击中物体的算法


我们定义 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
  }


1687779132381.png


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

目录
相关文章
|
4天前
|
缓存 监控 UED
升级 Vue3 时,如何减少打包体积的增加?
升级 Vue3 时,如何减少打包体积的增加?
81 59
|
3天前
|
JavaScript
在vue3中(vite)引入unocss,安装配置unocss
在vue3中(vite)引入unocss,安装配置unocss
|
5天前
|
缓存 JavaScript 前端开发
「offer来了」从基础到进阶原理,从vue2到vue3,48个知识点保姆级带你巩固vuejs知识体系
该文章全面覆盖了Vue.js从基础知识到进阶原理的48个核心知识点,包括Vue CLI项目结构、组件生命周期、响应式原理、Composition API的使用等内容,并针对Vue 2与Vue 3的不同特性进行了详细对比与讲解。
「offer来了」从基础到进阶原理,从vue2到vue3,48个知识点保姆级带你巩固vuejs知识体系
|
4天前
|
API UED
如何实现Vue2项目升级Vue3?
如何实现Vue2项目升级Vue3?
11 1
|
4天前
|
API UED
升级 Vue3 后,项目的打包体积会有什么变化?
升级 Vue3 后,项目的打包体积会有什么变化?
9 0
|
5天前
|
JavaScript API
再不学vue3就没有人要你了!速来围观vue3
这篇技术文章介绍了作者从最初对学习 Vue3 抵触到最终决定投入学习的心路历程,展示了 Vue3 相较于 Vue2 的诸多改进和新特性,如更优的性能、更小的代码体积及更佳的 TypeScript 支持。文章重点阐述了 Vue3 中 createApp 的使用变化、emits 机制、多事件处理、Fragment 的引入等重要功能升级。此外,还深入探讨了 Composition API 和 Options API 的区别,强调 Composition API 在代码组织和逻辑复用方面的优势,并给出了在不同项目规模中选择合适 API 的建议。
15 0
|
5月前
|
JavaScript API
【vue实战项目】通用管理系统:api封装、404页
【vue实战项目】通用管理系统:api封装、404页
68 3
|
5月前
|
人工智能 JavaScript 前端开发
毕设项目-基于Springboot和Vue实现蛋糕商城系统(三)
毕设项目-基于Springboot和Vue实现蛋糕商城系统
|
5月前
|
JavaScript Java 关系型数据库
毕设项目-基于Springboot和Vue实现蛋糕商城系统(一)
毕设项目-基于Springboot和Vue实现蛋糕商城系统
153 0
|
5月前
|
JavaScript 前端开发 API
Vue3+Vite+TypeScript常用项目模块详解
现在无论gitee还是github,越来越多的前端开源项目采用Vue3+Vite+TypeScript+Pinia+Elementplus+axios+Sass(css预编译语言等),其中还有各种项目配置比如eslint 校验代码工具配置等等,而我们想要进行前端项目的二次开发,就必须了解会使用这些东西,所以作者写了这篇文章进行简单的介绍。
131 0
Vue3+Vite+TypeScript常用项目模块详解
下一篇
无影云桌面