好家伙,接着写

 

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

 

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

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

 

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

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

Html飞机大战(四):状态的切换(界面加载类的编辑)的更多相关文章

  1. ios单独的页面支持横竖屏的状态调整,HTML5加载下(更新2)

    单独的页面支持横竖屏的状态调整,HTML5加载下 工程中设置只支持竖屏状态,在加载HTML5的界面可以是横竖屏的,在不对工程其他界面/设置做调整的同时,可以这样去 #import "View ...

  2. 练习PopupWindow弹出框之实现界面加载的时候显示弹出框到指定的view下面--两种延迟方法

    今天在练习PopupWindow弹出框的时候,打算在界面加载的时候将弹出框展现出来并显示在指定的view下面. 初步方法是直接在OnResume方法里面直接执行showPopupWindows方法. ...

  3. vue 实现tab切换动态加载不同的组件

    vue 实现tab切换动态加载不同的组件 使用vue中的is特性来加载不同的组件.具体看如下代码:这个功能对于vue比较复杂的页面可以使用上,可以把一个页面的功能拆分出来,使代码更简单.使用方式具体看 ...

  4. 因为错误关闭Selinux导致CentOS7启动失败(进度条卡死,图形界面加载卡死)

    我在CentOS7上安装oracle,非常麻烦,搞半天终于安装完毕,当天我没有发现任何问题,第二天上班打开虚拟机CentOS7就进不去了. 我想起来之前关闭了Selinux,把系统名称改成了redha ...

  5. ionic js 加载动画 ionSpinner 提供了许多种旋转加载的动画图标。当你的界面加载时,你就可以呈现给用户相应的加载图标。 该图标采用的是SVG

    ionic 加载动画 ion-spinner ionSpinner 提供了许多种旋转加载的动画图标.当你的界面加载时,你就可以呈现给用户相应的加载图标. 该图标采用的是SVG. 用法 <ion- ...

  6. 飞机大战(1)--添加logo和加载动画

    注:以下代码都是用scratch 3.0版本编写 素材链接: 链接:https://pan.baidu.com/s/1sXqeZVuFgVTYT0OtqxXilw 提取码:1126 一.背景添加 导入 ...

  7. WPF 界面实现多语言支持 中英文切换 动态加载资源字典

    1.使用资源字典,首先新建两个字典文件en-us.xaml.zh-cn.xaml.定义中英文的字符串在这里面[注意:添加xmlns:s="clr-namespace:System;assem ...

  8. eclipse启动无响应,停留在Loading workbench状态,或老是加载不了revert resources

    做开发的同学们或多或少的都会遇到eclipse启动到一定程度时,就进入灰色无响应状态再也不动了.启动画面始终停留在Loading workbench状态.反复重启,状态依旧. 多数情况下,应该是非正常 ...

  9. iOS app应用界面加载卡顿的问题

    刚发布版本,忽然发现加载界面需要3-5秒延迟,那么问题来了. 首先,发现问题: 1.看代码,基于之前版本更新都没出问题,还是比较确信不是代码中的bug,以防万一,还是仔细看了下关于界面跳转部分的代码, ...

随机推荐

  1. ubuntu下连microsoft sql server解决方案

    shell for MSSQL: https://github.com/dbcli/mssql-cli mssql-cli -S 127.0.0.1,1433 -d testDB -U myuser ...

  2. 论文解读(MGAE)《MGAE: Masked Autoencoders for Self-Supervised Learning on Graphs》

    论文信息 论文标题:MGAE: Masked Autoencoders for Self-Supervised Learning on Graphs论文作者:Qiaoyu Tan, Ninghao L ...

  3. service继承baseService后无法注入dao的解决办法

    1.在set方法上加@Autowired 2.在set方法上加@Resource 这样子就可以拿到dao了

  4. 探索链路追踪在.NET6工业物联网项目的应用

    ExploringIoTDistributedTracingNet6 如果觉得有用,请留言学到了. 已经会了的老哥,请留言就这? 可能遇到的问题 工业物联网项目自上而下一般分为ERP.Mes.SCAD ...

  5. NC201605 Bits

    NC201605 Bits 题目 题目描述 Nancy喜欢做游戏! 汉诺塔是一个神奇的游戏,神奇在哪里呢? 给出 \(3\) 根柱子,最开始时 \(n\) 个盘子按照大小被置于最左的柱子. 如果盘子数 ...

  6. NC202498 货物种类

    NC202498 货物种类 题目 题目描述 某电商平台有 \(n\) 个仓库,编号从 \(1\) 到 \(n\) . 当购进某种货物的时候,商家会把货物分散的放在编号相邻的几个仓库中. 我们暂时不考虑 ...

  7. npm uninstall和rm直接删除的区别

    结论: 1. npm uninstall会备份包本身依赖的node_modules,rm -f会删除整个目录 2. npm uninstall不会删除被依赖的包.即使显式要删除这个包,但它被依赖不会删 ...

  8. Tapdata 在“疫”线:携手张家港市卫健委争分夺秒实时抗疫

      "抗疫两年以来最困难的时期,是漫长冬夜还是倒春寒?"--国家传染病医学中心主任张文宏 于3月14日凌晨   "等到疫情结束了,我一定要--",常怀这样的期许 ...

  9. Windows 远程连接后,自动断开,所有程序都自动关闭(待验证,待更新)

    win+r输入regedit打开注册表编辑SecurityLayer,将值改为2 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Ter ...

  10. 自己写雪花算法IdWorker

    package com.aiyusheng.shopping.util; import java.lang.management.ManagementFactory; import java.net. ...