-
Html飞机大战(四):状态的切换(界面加载类的编辑)
好家伙,接着写
既然我们涉及到状态了,那么我们也会涉及到状态的切换
那么我们怎样切换状态呢?
想象一下,如果我玩的游戏暂停了,那么我们肯定是通过点击或者按下某个按键来让游戏继续
这里我们选择添加点击事件来切换游戏状态
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>
出处:https://www.cnblogs.com/FatTiger4399/p/16629003.html
栏目列表
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比
一款纯 JS 实现的轻量化图片编辑器
关于开发 VS Code 插件遇到的 workbench.scm.
前端设计模式——观察者模式
前端设计模式——中介者模式
创建型-原型模式