微信小程序 案例二 飞机大战

简介: 微信小程序 案例二 飞机大战

案例二 飞机大战

本案例主要使用 微信开发者工具内置的 小游戏 来开发

新建项目

要选择 微信小程序

精简代码

  1. 删除 js 文件夹
  2. 清空 game.js的代码

核心概念

canvas

提供了一个通过JavaScriptHTMLcanvas元素来绘制图形的方式。它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。

requestAnimationFrame

setTimeout 等 会重复让浏览器执行 回流 和重绘

告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新

  1. 屏幕刷新频率:屏幕每秒出现图像的次数。普通笔记本为60Hz
  2. 动画原理:计算机每16.7ms刷新一次,由于人眼的视觉停留,所以看起来是流畅的移动

代码解读

复制代码

requestAnimationFrame(callback);

核心API

函数名 作用
wx.createCanvas() 创建 canvas 的绘图上下文 CanvasContext 对象
canvas.getContext('2d') 该方法返回 Canvas 的绘图上下文
wx.createImage() 创建一个图片对象
CanvasContext.drawImage() 绘制图像到画布
wx.createInnerAudioContext() 创建内部 audio 上下文 InnerAudioContext 对象
InnerAudioContext.src 设置要播放的音频
InnerAudioContext.play() 播放音频
CanvasContext.clearRect() 清除画布上在该矩形区域内的内容

面向对象-编写游戏-高能预警

接下来使用 es6 + 面向对象对游戏代码进行简单的封装

搭建项目结构

在根目录下,新建 js 文件夹, 然后新建以下文件

+ /base/env.js 存放全局变量(height)和 引入资源(如图片等)
+ /background/music.js 音乐
+ /background/bg.js 背景图
+ /play/player.js 英雄
+ /play/enemy.js 敌机
+ /play/bullet.js 子弹
+ /databus.js 全局的状态管理对象

整体的关系图

编写环境类

js\base\env.js

  1. 在项目启动的时候先把需要用到的图片资源全部下载后,通过promise形势进行封装
  2. 把下载好的图片对象都存入到全局的window.imgs对象中,方便获取


window.canvas = wx.createCanvas()
window.ctx = canvas.getContext('2d');
window.width = wx.getSystemInfoSync().screenWidth;
window.height = wx.getSystemInfoSync().screenHeight;
window.imgs = [];
class env {
  init() {
    return new Promise((r, j) => {
      [
        "./images/bg.jpg",
        "./images/bullet.png",
        "./images/Common.png",
        "./images/enemy.png",
        "./images/explosion1.png",
        "./images/explosion10.png",
        "./images/explosion11.png",
        "./images/explosion12.png",
        "./images/explosion13.png",
        "./images/explosion14.png",
        "./images/explosion15.png",
        "./images/explosion16.png",
        "./images/explosion17.png",
        "./images/explosion18.png",
        "./images/explosion19.png",
        "./images/explosion2.png",
        "./images/explosion3.png",
        "./images/explosion4.png",
        "./images/explosion5.png",
        "./images/explosion6.png",
        "./images/explosion7.png",
        "./images/explosion8.png",
        "./images/explosion9.png",
        "./images/hero.png"
      ]
        .forEach((v, i, arr) => {
          const img = wx.createImage();
          img.src = v;
          window.imgs[v.match(/(\w+)\.[jpg|png|gif|jpeg|webp]+/)[1]] = img;
          img.onload = () => {
            if (i === arr.length - 1) {
              r();
            }
          }
        })
    })
  }
}
export default env;



编写 背景图片类

  1. 实现动态的显示图片

js\background\bgc.js


class bg {
  constructor() {
    this.img = imgs["bg"];
    this.top = 0;
    this.render();
  }
  render() {
    ctx.drawImage(this.img, 0, this.top, width, height);
    ctx.drawImage(this.img, 0, -height + this.top, width, height);
  }
  update() {
    this.top++;
    if (this.top === height) {
      this.top = 0;
    }
    this.render();
  }
}
export default bg;

编写全局状态管理类

  1. 负责控制其他类的状态
  2. 引入背景图片类,然后实例化

js\databus.js


import Bgc from "./background/bgc";
class databus {
  constructor() {
    this.bgc = null;
  }
  init() {
    this.bgc = new Bgc();
  }
  update() {
    this.bgc.update();
  }
}
export default databus

编写游戏入口文件

  1. 负责引入环境类和全局状态管理类
  2. 开始运行游戏

game.js


import Env from "./js/base/env";
import Databus from "./js/databus";
const env = new Env();
main();
async function main() {
  await env.init();
  const databus = new Databus();
  databus.init();
  loop();
  function loop() {
    ctx.clearRect(0, 0, width, height);
    databus.update();
    requestAnimationFrame(loop);
  }
}


编写背景音乐类

  1. 播放和控制背景音乐

js\background\music.js


class music {
  constructor() {
    this.bgc = wx.createInnerAudioContext();
    this.bgc.src = "./audio/bgm.mp3";
    this.bgc.play();
  }
}
export default music;

然后修改全局状态管理类 js\databus.js

  1. 引入和播放音乐


import Bgc from "./background/bgc";
import Music from "./background/music"; // 新增代码
class databus {
  constructor() {
    this.bgc = null;
    this.music=null; // 新增代码
  }
  init() {
    this.bgc = new Bgc();
    this.music=new Music(); // 新增代码
  }
  update() {
    this.bgc.update();
  }
}
export default databus

新增英雄类

  1. 实现动态渲染飞机

js\play\hero.js


class hero {
  constructor() {
    this.width = 50;
    this.height = 50;
    this.img = imgs["hero"];
    this.x = (width - this.width) / 2;
    this.y = (height - this.height);
  }
  render() {
    ctx.drawImage(this.img, this.x, this.y, this.width, this.height);
  }
  update() {
    this.render();
  }
}
export default hero;

修改全局管理类 js\databus.js

  1. 引入飞机


import Bgc from "./background/bgc";
import Hero from "./play/hero";
import Music from "./background/music";
class databus {
  constructor() {
    this.hero = null;
    this.bgc = null;
    this.music=null;
  }
  init() {
    this.bgc = new Bgc();
    this.hero = new Hero();
    this.music=new Music();
  }
  update() {
    this.bgc.update();
    this.hero.update();
  }
}
export default databus

编写英雄跟随手指移动

  1. 通过给canvas绑定手指移动事件

js\play\hero.js


class hero {
  constructor() {
    this.width = 50;
    this.height = 50;
    this.img = imgs["hero"];
    this.x = (width - this.width) / 2;
    this.y = (height - this.height);
    this.addEventMove();
  }
  render() {
    ctx.drawImage(this.img, this.x, this.y, this.width, this.height);
  }
  addEventMove() {
    canvas.addEventListener("touchmove", (e) => {
      const { clientX, clientY } = e.changedTouches[0];
      this.x = clientX - this.width / 2;
      this.y = clientY - this.height / 2;
      this.render();
    })
  }
  update() {
    this.render();
  }
}
export default hero;

0. 新增子弹类

  1. 让英雄可以发射子弹

js\play\bullet.js


class bullet {
  constructor(x, y) {
    this.img = imgs["bullet"];
    this.width = 20;
    this.height = 20;
    this.x = x-this.width/2;
    this.y = y;
    this.top = 0;
    this.render();
  }
  render() {
    ctx.drawImage(this.img, this.x, this.y, this.width, this.height); 
  } 
  update() { 
    this.top++;
    this.y=this.y-this.top;
    this.render();
  }
}
export default bullet;

修改英雄类

js\play\hero.js

import Bullet from "./bullet";
class hero {
  constructor() {
    this.width = 50;
    this.height = 50;
    this.img = imgs["hero"];
    this.x = (width - this.width) / 2;
    this.y = (height - this.height);
    this.bulltes = [];
    this.times = 0;
    this.render();
    this.addEventMove();
    this.createBullets();
  }
  render() {
    ctx.drawImage(this.img, this.x, this.y, this.width, this.height);
  }
  addEventMove() {
    canvas.addEventListener("touchmove", (e) => {
      const { clientX, clientY } = e.changedTouches[0];
      this.x = clientX - this.width / 2;
      this.y = clientY - this.height / 2;
      this.render();
    })
  }
  update() {
    this.render();
    this.createBullets();
    this.shoot();
    
  }
  createBullets() {
    this.times++;
    if (this.times % 30 === 0) {
      this.bulltes.push(new Bullet(this.x+this.width/2, this.y));
      this.times = 0;
    }
  }
  shoot() {
    this.bulltes.forEach(v=>{
      v.update();
    })
  }
}
export default hero;

git地址

后续可以更新


https://github.com/itcastWsy/plane

目录
相关文章
|
2天前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1517 4
|
29天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
5天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
501 19
|
2天前
|
存储 SQL 关系型数据库
彻底搞懂InnoDB的MVCC多版本并发控制
本文详细介绍了InnoDB存储引擎中的两种并发控制方法:MVCC(多版本并发控制)和LBCC(基于锁的并发控制)。MVCC通过记录版本信息和使用快照读取机制,实现了高并发下的读写操作,而LBCC则通过加锁机制控制并发访问。文章深入探讨了MVCC的工作原理,包括插入、删除、修改流程及查询过程中的快照读取机制。通过多个案例演示了不同隔离级别下MVCC的具体表现,并解释了事务ID的分配和管理方式。最后,对比了四种隔离级别的性能特点,帮助读者理解如何根据具体需求选择合适的隔离级别以优化数据库性能。
179 1
|
8天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
21天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
9天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
451 5
|
7天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
314 2
|
23天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
25天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2608 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析