好家伙,接着写

 

既然我们涉及到状态了,那么我们也会涉及到状态的切换

 

那么我们怎样切换状态呢?

想象一下,如果我玩的游戏暂停了,那么我们肯定是通过点击或者按下某个按键来让游戏继续

 

这里我们选择添加点击事件来切换游戏状态

1.我们给canvas对象添加一个点击事件用于切换状态

canvas.addEventListener("click", () => {
if (state === START) {
state = STARTING;
}
});

 

然后我们去弄一点飞机加载图片

 

 (自己用PS画的,将就着用吧)

2.定义一个图片数组,用于存放图片

 const loading_frame = [];
loading_frame[0] = new Image()
loading_frame[0].src = "img/game_loading1.jpg"
loading_frame[1] = new Image()
loading_frame[1].src = "img/game_loading2.jpg"
loading_frame[2] = new Image()
loading_frame[2].src = "img/game_loading3.jpg"
loading_frame[3] = new Image()
loading_frame[3].src = "img/game_loading4.jpg"

我们会用一个变量的++来选择渲染哪一张图片

3.配置加载类Loading的配置项LOADING

//飞机加载界面类的配置项
const LOADING = {
//图片数组
frame: loading_frame,
//图片的宽
width: 480,
//图片的高
height: 100,
//图片的初始绘制x,y轴
x: 0,
//总高减去图片的高度
y: 650 - 100,
//速度单位为毫秒
speed: 1000,
};

(注释说的非常清楚了)

4.编辑Loading类:

class Loading {
constructor(config) {
this.frame = config.frame;
//加载哪张图片的下标
this.frameIndex = 0;
//图片宽度
this.width = config.width;
//图片高度
this.height = config.height;
this.x = config.x;
this.y = config.y;
this.speed = config.speed;
this.lastTime = new Date().getTime();
}
//一样的判断方法和绘图方法
judge() {
const currentTime = new Date().getTime();
if (currentTime - this.lastTime > this.speed) {
this.frameIndex++;
console.log(this.frameIndex);
if (this.frameIndex === 4) {
//更新状态
state = RUNNING;
}
//更新时间
this.lastTime = currentTime;
}
}
paint(context) {
context.drawImage(this.frame[this.frameIndex], this.x, this.y, this.width, this.height)
} }

方法说明:

4.1.judge方法

这里我们通过frameIndex的数字变化来对应不同的图片

和天空类相同,这里我们把(变量的控制/更新时机的判断)与绘制分开来

原理还是那条公式,    现在的时间-最后一次更新的时间 > 速度  =====>可以更新了

4.2.更新状态

if (this.frameIndex === 4) {
//更新状态
state = RUNNING;
          }

当四张图片都加载完以后,进入到下一个状态

4.3.paint图片绘制方法

paint(context) {
context.drawImage(this.frame[this.frameIndex], this.x, this.y, this.width, this.height)
}

还是那几个参数(忘了就去翻前两篇博客)

5.实例化

const loading = new Loading(LOADING);

6.方法的调用

在switch结构语句里加上方法调用

case STARTING:
sky.judge();
sky.paint(context);
//这里需要一个飞机加载的loading
loading.judge();
loading.paint(context);
break;

好了,让我们来看看看效果:

 (第一帧好像跳的有点快)

全部代码如下:

<!DOCTYPE html>
<html lang="zh-CN"> <head>
<meta charset="UTF-8">
<meta name="viewprot" content="width-devic-width,initial-scale=1.0">
<title>飞机大战</title>
<style>
* {
padding: 0;
margin: 0;
} canvas {
border: 1px solid red;
margin: auto;
} #stage {
width: 480px;
height: 650px;
margin: auto;
}
</style>
</head> <body>
<div id="stage">
<canvas id="canvas" width="480" height="650"></canvas>
</div>
<script>
// 1.让画笔能够绘制图片
// 1.1找到这个画布
const canvas = document.querySelector("#canvas");
// 1.2.利用这个画布初始换一个2D的画框
const context = canvas.getContext("2d");
/* canvas画布绘制bg对象时的坐标 */
let x1 = 0;
let y1 = 0;
let x2 = 0;
let y2 = -650;
// 2.加载这张图片
const bg = new Image();
bg.src = "img/4.jpg";
//定义游戏状态
const START = 0;
const STARTING = 1;
const RUNNING = 2;
const PAUSE = 3
const END = 4; //初始化一个加载图片logo
const copyright = new Image();
copyright.src = "img/START.jpg" //初始化飞机大战的加载图片
const loading_frame = [];
loading_frame[0] = new Image()
loading_frame[0].src = "img/game_loading1.jpg"
loading_frame[1] = new Image()
loading_frame[1].src = "img/game_loading2.jpg"
loading_frame[2] = new Image()
loading_frame[2].src = "img/game_loading3.jpg"
loading_frame[3] = new Image()
loading_frame[3].src = "img/game_loading4.jpg"
/*
image 加载的图片对象
dX为图片开始绘制的左上角横坐标
dY为图片开始绘制的左上角横坐标
dWidth为图片在canvas绘制的宽度
dHeight为图片在canvas绘制的宽度
*/
/*
首参为事件名
二参为一个回调函数,表示加载完毕后执行的代码
*/ //已经是Java的形状了
class Sky {
constructor(config) {
//图片资源
this.bg = config.bg;
this.width = config.width;
this.height = config.height;
this.x1 = 0;
this.y1 = 0;
this.x2 = 0;
this.y2 = -this.height;
this.speed = config.speed;
//最后更新时间
this.lasttime = new Date().getTime(); }
//判断方法
judge() {
let currentTime = new Date().getTime();
//在此处增加一个判断
if (currentTime - this.lasttime > this.speed) {
this.y1++;
this.y2++;
this.lasttime = currentTime; }
//渲染完毕,重置y1,y2
if (this.y2 === 0) {
this.y1 = 0;
this.y2 = -this.height;
}
}
//绘图方法
paint(context) {
context.drawImage(this.bg, this.x1, this.y1++, this.width, this.height);
context.drawImage(this.bg, this.x2, this.y2++, this.width, this.height);
if (this.y2 === 0) {
this.y1 = 0;
this.y2 = -650;
}
} }
//天空类的配置项
const SKY = {
bg: bg,
width: 480,
height: 650,
speed: 10,
/* 速度 */
}
//初始化一个飞机加载界面类
class Loading {
constructor(config) {
this.frame = config.frame;
//加载哪张图片的下标
this.frameIndex = 0;
//图片宽度
this.width = config.width;
//图片高度
this.height = config.height;
this.x = config.x;
this.y = config.y;
this.speed = config.speed;
this.lastTime = new Date().getTime();
}
//一样的判断方法和绘图方法
judge() {
const currentTime = new Date().getTime();
if (currentTime - this.lastTime > this.speed) {
this.frameIndex++;
console.log(this.frameIndex);
if (this.frameIndex === 4) {
//更新状态
state = RUNNING;
}
//更新时间
this.lastTime = currentTime;
}
}
paint(context) {
context.drawImage(this.frame[this.frameIndex], this.x, this.y, this.width, this.height)
} }
//飞机加载界面类的配置项
const LOADING = {
//图片数组
frame: loading_frame,
//图片的宽
width: 480,
//图片的高
height: 100,
//图片的初始绘制x,y轴
x: 0,
//总高减去图片的高度
y: 650 - 100,
//速度单位为毫秒
speed: 1000,
};
//初始化一个天空实例
const sky = new Sky(SKY);
//初始化一个飞机界面加载实例
const loading = new Loading(LOADING);
//state表示游戏状态 取值必须是以上的五种状态
let state = START;
//为canvas绑定一个点击事件,且如果是START状态的时候需要修改成
//STARING状态 canvas.addEventListener("click", () => {
if (state === START) {
state = STARTING;
}
});
//开始加载图片了:
bg.addEventListener("load", () => {
/*
callback: Function 表示回调函数
timeout: Number 表示每次调用函数所间隔的时间段
*/
setInterval(() => {
switch (state) {
case START:
sky.judge();
sky.paint(context);
//渲染飞机大战LOGO
//图片原始宽高
let logo_x = (480 - copyright.naturalWidth) / 2;
let logo_y = (650 - copyright.naturalHeight) / 2;
context.drawImage(copyright, logo_x, logo_y)
break;
case STARTING:
sky.judge();
sky.paint(context);
//这里需要一个飞机加载的loading
loading.judge();
loading.paint(context);
break;
case RUNNING:
sky.judge();
sky.paint(context);
//加载敌机
break;
case PAUSE:
sky.judge();
sky.paint(context);
//加载暂停页面
break;
case END:
sky.judge();
sky.paint(context);
//加载游戏结束字样
break;
} }, 10);
})
</script>
</body> </html>

Html飞机大战Demo

最新文章

  1. iOS获取网络图片大小
  2. composer &quot;Illegal offset type in isset or empty&quot;报错解决方案
  3. JAVA实现 springMVC方式的微信接入、实现消息自动回复
  4. supervisor centos安装
  5. Cosh.2
  6. Linux如何学习
  7. 【图解】Eclipse下JRebel6.2.0热部署插件安装、破解及配置【转】
  8. svn merge和branch
  9. Ubuntu安装ARM架构GCC工具链(ubuntu install ARM toolchain)最简单办法
  10. linux 套接字编程入门--Hello World
  11. mysql pdo数据库连接
  12. 使用Qt开发绘制多个设备的流量曲线图(附带项目图)
  13. [C++基础]队列&lt;queue&gt;中的常用函数
  14. 《机器学习实践》程序清单3-7 plotTree函数
  15. uva 10618 Tango Tango Insurrection 解题报告
  16. php-config 介绍
  17. PL/SQL中decode函数简介
  18. faked 一个用于 mock 后端 API 的轻量工具
  19. eclipse插件开发常见的问题及解决办法
  20. [luogu5176] 公约数

热门文章

  1. Python参数传递中的 args, kwargs
  2. 表达式的动态解析和计算,Flee用起来真香
  3. Torch的索引与形变
  4. linux-python安装pip
  5. Vue之封装二次axios
  6. mybatis查询mysql 数据库中 BLOB字段,结果出现乱码
  7. CentOS中实现基于Docker部署BI数据分析
  8. Python Excel 操作
  9. Unity-A-Star寻路算法
  10. vue Blob 下载附件报错