web版canvas做飞机大战游戏 总结
唠唠:两天的时间跟着做了个飞机大战的游戏,感觉做游戏挺好的。说是用html5做,发现全都是js。说js里一切皆为对象,写的最多的还是函数,都是函数调用。对这两天的代码做个总结,希望路过的大神指点一下,我对这个游戏的思路,可改进优化的代码。
先说一下游戏的基本内容: 打飞机(不要想歪了),有鼠标控制移动英雄机,子弹自动射击;敌机从上而下,有三种敌机;
先说下HTML代码(主要就是这一行):
<canvas id="canFly" width="480" height="650"></canvas>
一、对这个游戏的的基本数据状态做定义
主要包括:
游戏的状态: 开始状态 英雄机入场状态 游戏进行状态 暂停状态 gameOver;得分 英雄机的生命
var canvas = document.getElementById("canFly");//获取canvas元素
//创建画布对象
var context = canvas.getContext("2d");
//游戏的基本数据
var gameData = {
state : this.START,
//游戏状态
START : 0,//开始界面状态
STARTING : 1,//入场动画过渡状态
RUNNING : 2,//游戏运行状态
PAUSED : 3,//暂停
GAMEOVER : 4,//游戏结束
//英雄机生命
heroLife : 3,
//得分
score : 0,
//画布宽高
HEIGHT : canvas.height
}
二、对图片资源的加载及初始化相关数据
/*-- 加载游戏图片 -------------------------------------------------------------------*/
//背景图片
var bgImg = new Image();
bgImg.src="data:images/background.png";
//logo图片
var startLogo = new Image();
startLogo.src = "images/start.png";
//加载飞机入场动画
var loadings = [];
loadings[0] = new Image();
loadings[0].src="Images/game_loading1.png";
loadings[1] = new Image();
loadings[1].src="Images/game_loading2.png";
loadings[2] = new Image();
loadings[2].src="Images/game_loading3.png";
loadings[3] = new Image();
loadings[3].src="Images/game_loading4.png";
//加载英雄机图片
var heros = [];
heros[0] = new Image();
heros[0].src="data:images/hero1.png";
heros[1] = new Image();
heros[1].src="data:images/hero2.png";
//英雄机爆破动画图片
heros[2] = new Image();
heros[2].src="data:images/hero_blowup_n1.png";
heros[3] = new Image();
heros[3].src="data:images/hero_blowup_n2.png";
heros[4] = new Image();
heros[4].src="data:images/hero_blowup_n3.png";
heros[5] = new Image();
heros[5].src="data:images/hero_blowup_n4.png";
//加载子弹的图片
var bullet = [];
bullet[0] = new Image();
bullet[0].src = "images/bullet1.png";
...
/*-- 初始化游戏内容相关数据 --*/
//初始化游戏背景图片数据
var SKY = {
imgs : bgImg,//背景图片
width : 480,//图片宽度
height : 852 //图片高度
}
//初始化英雄机入场动画图片数据
var LOADING = {
imgs : loadings,
width : 186,//图片宽度
height : 38,//图片高度
sum : loadings.length //图片个数
}
//初始化英雄机的数据
var HERO = {
imgs : heros,
width : 99,
height : 124,
sum : heros.length,
length : 2//我方飞机正常图片个数
}
//初始化子弹的数据
var BULLET = {//默认子弹
imgs : bullet,
width : 9,
height : 21,
sum : bullet.length
}
.......
三、公用构造器及对象实例化
定义一个公用的构造器函数,这是我写这个游戏认最大的收获了,在这里体会到了面向对象的思想;相当于定义一个基础类,所有的构造器都用公用构造器函数进行初始化,提高代码的复用,然而在我的优化过程中仅仅只是节省了50多行的代码。
公共构造器函数:在这里定义了图片的宽高,图片对象是否执行爆破,是否删除,图片绘制坐标等一些公共的属性和方法
/*-- 通用构造器对象 前端代码尽量地使用通用代码 -------------------------------------------------------------------------------------------------------*/
function Compant(config){
//加载图片
this.imgs = config.imgs;
//图片的宽度和高度
this.width = config.width;
this.height = config.height;
this.sum = config.sum;
this.length = config.length;
// 敌方飞机具有以下属性
this.type = config.type;//敌机类型
this.life = config.life;//敌机声明值
this.score = config.score;//敌机分数
// 设置相对速度
this.time = 0;
// 设置图片的索引值
this.index = 0;
// 是否执行爆破动画的标识
this.down = false;
// 是否删除标识
this.canDelete = false;
//绘图坐标
this.x = 0;
this.y = 0;
// 绘制方法
this.paint = function(){
context.drawImage(this.imgs[this.index],this.x,this.y);
}
// 移动方法
this.step = function(){}
// 执行撞击后的逻辑方法
this.bang = function(){}
}
继承实例化:
//---背景
//创建背景图片的构造器
function BgSky(config){
//调用通用构造器初始化
Compant.call(this,config);
//图片绘制高度变量
this.y1 = -this.height;
this.y2 = 0;
//定义绘制方法
this.paint = function(){
context.drawImage(this.imgs,0,this.y1);//第一张图片
context.drawImage(this.imgs,0,this.y2);//第二张图片
}
//背景heigth运动方法
this.step = function(){
this.time++;
if (this.time%3==0)
{//控制背景图片height值的增加
this.y1++;//图片运动下一帧
this.y2++;
//图片移动处画布后将y坐标重置为-height 实现图片衔接滚动
this.y1>this.height&&(this.y1 = -this.height);
this.y2>this.height&&(this.y2 = -this.height);
this.time=1;//重置移动时间
}
}
}
//创建图片对象
var sky = new BgSky(SKY); //---英雄机入场动画构造器
function Loading(config){
Compant.call(this,config);
//定义绘制
this.paint = function(){
//绘制飞机入场动画图片
context.drawImage(this.imgs[this.index],0,gameData.HEIGHT-this.height);
}
//定义入场动画
this.step = function(){
this.time++;
if (this.time%20==0)
{//实现动画的播放速度
this.index++;//下一帧动画
if (this.index==this.sum)
{//判断动画结束后,更改游戏的状态,进入第三阶段游戏阶段
gameData.state=gameData.RUNNING;
this.time=0;//重置动画时间
}
}
}
}
//创建飞机入场动画的对象
var loading = new Loading(LOADING);
利用这种方式将所有的对象都进行实例化,并添加相应的方法
四、英雄机的子弹发射
英雄机的子弹发射是自动,就是说只要控制好装弹的频率就可以了;英雄机发射子弹就是向子弹数组中添加子弹
bullets[bullets.length] = new Bullet(BULLET);;//向子弹数组中添加子弹
子弹的移动,撞击,删除等功能在子弹的构造函数中定义,英雄机只管装弹的频率;
子弹的绘制:
function paintBullets(){
for (var i=0, length=bullets.length; i<length; i++)
{
bullets[i].paint();//绘制当前子弹
if (gameData.state==gameData.RUNNING)
{//游戏运行中时移动子弹
bullets[i].step();//移动子弹
}
}
}
删除子弹的判断:
function clearStep(){
for (var i = bullets.length-1; i>=0 ; i--)
{
if (bullets[i].y<=-bullets[i].height || (bullets[i].canDelete))
{
bullets.splice(i,1);//删除当前超出屏幕的子弹和撞机的子弹
}
}
}
//这个函数可以跟上边的合并到一起
五、敌机的相关设置
敌机的创建: 应为有三种类型的敌机,按照几率小的最多,中飞机的其次,打飞机满屏只能有一个
//创建用于创建敌方飞机的函数
function createEnemies(){
/*创建敌方飞机 - 小,中,大*/
var num = Math.floor(Math.random()*100);
if (num < 80)
{//小飞机
enemies[enemies.length] = new Enemy(ENEMY1);
}else if (num < 90)
{//中飞机
enemies[enemies.length] = new Enemy(ENEMY2);
}else {
//大飞机只能存在一个
if (enemies.length > 0 && enemies[0].type != 2)
{
enemies.unshift(new Enemy(ENEMY3));//将大飞机添加到数组开头,这样每次判断数组第一个就可以知道
}
}
}
对敌机的绘制,检测敌机是否超出屏幕,是否被打中,是否需要爆炸,是否和英雄机相撞等
function paintEnemiesAndCheckHit(){
for (var i=0; i<enemies.length; i++)
{//遍历敌机
//
var enemy = enemies[i];//敌机
//检测敌机和英雄机是否碰撞
if ((enemy.y > gameData.HEIGHT)||(enemy.canDelete))
{
enemies.splice(i,1);//删除当前超出屏幕的飞机
continue;
}
enemy.paint();//绘制飞机
if (gameData.state == gameData.RUNNING)
{//游戏运行中时才移动飞机
enemy.step();//移动飞机
}
//判断是否和我方飞机碰撞
if (enemy&&enemy.hit(hero))
{//敌机和我方飞机相撞
enemy.bang();
hero.bang();//飞机销毁
}
//判断子弹
for (var j=0; j<bullets.length; j++)
{//子弹遍历
var bullet = bullets[j];//子弹
if (enemy.hit(bullet))
{//子弹撞机敌方飞机
enemy.bang();//删除敌机
bullet.bang();//删除子弹
}
}
}
}
六、主体流程的控制
这里使用switch来控制在执行相应状态的操作,使用setTimeout来控制循环的进行,感觉setTimeout比setInterval更加的容易控制
//根据游戏状态执行相应操作
switch (gameData.state)
{
case gameData.START://游戏开始状态
context.drawImage(startLogo,30,0);//绘制开始logo
break;
case gameData.STARTING: //英雄机进场过渡状态
loading.paint();//绘制飞机入场动画
loading.step();//入场动画
break;
case gameData.RUNNING: //游戏进行状态
hero.paint();
hero.step();
hero.shoot();//飞机射击
paintBullets();//绘制所有子弹
clearStep();//清除超出的子弹 if (enemyTime%100 == 0)
{
createEnemies();//创建敌方飞机
}
paintEnemiesAndCheckHit();//绘制所有敌方飞机和碰撞检测
break;
case gameData.PAUSED: //游戏暂停状态
hero.paint();
paintBullets();//绘制所有子弹
paintEnemiesAndCheckHit();//绘制所有敌方飞机和碰撞检测
paintPaused();
break;
case gameData.GAMEOVER: //游戏结束状态
gameover();
break;
}
painText();//绘制得分 //定时器,画布刷新
setTimeout(function(){
gameExec();
},10);
七、响应事件的绑定
1.开始界面单击鼠标,开始游戏
canvas.onclick = function(){
if (gameData.state == gameData.START)
{//在游戏开始状态下单击,进入游戏过渡阶段
gameData.state = gameData.STARTING;//改变游戏状态
}
}
2.绑定鼠标的移动事件,英雄机是跟随鼠标移动的
canvas.onmousemove = function(event){
//获取鼠标当前相对于canvas画布的坐标
var x = event.offsetX;
var y = event.offsetY;
//我方飞机坐标设置
hero.x=x-hero.width/2;// x坐标
hero.y=y-hero.height/2;//y坐标
if (gameData.state == gameData.PAUSED)
{
gameData.state = gameData.RUNNING;
}
}
3.鼠标离开画布事件,鼠标离开则游戏暂停
canvas.onmouseout = function(){
if (gameData.state == gameData.RUNNING)
{
gameData.state = gameData.PAUSED;
}
}
八、后续的一些设想
现在的游戏不能重新开始,需要刷新才能重新开始,所以定义了 init() 函数用于游戏结束后重新开始(需要删除setTimeout事件):
function init(){
//设置游戏的初始状态
gameData.state = gameData.START;
gameData.score = 0;//分数重置
gameData.heroLife = 3;//声明值重置
//游戏运行
gameExec();
}
还有关于子弹的类型的设想: 可以设置 双列子弹,散花弹等子弹的类型,子弹可升级,设置子弹的威力等;可以设置速度的变更等
有路过的大神可以看下下边的源码,指点下(源码不长就10kb多点)
九、源码链接
web版canvas做飞机大战游戏 总结的更多相关文章
- Canvas:飞机大战 -- 游戏制作
Canvas:飞机大战 最开始我们要初始化信息,我们有五个状态:游戏封面,加载状态,运行状态,游戏暂停,游戏结束. 我们还需要 得分--score,生命--life. var START = 1;/ ...
- H5 canvas 实现飞机大战游戏
首先看几张效果图: 上面三张图分别对应游戏的三种状态 ready,play,pause.体验一下 先介绍一下canvas 画图的原理,在这个游戏中的背景,飞机,子弹以及飞机被击中爆炸的效果都是一张张的 ...
- 基于Cocos2d-x-1.0.1的飞机大战游戏开发实例(下)
在飞机大战游戏开发中遇到的问题和解决方法: 1.在添加菜单时,我要添加一个有背景的菜单,需要在菜单pMenu中添加一个图片精灵,结果编译过了但是运行出错,如下图: 查了很多资料,调试了很长时间,整个人 ...
- 基于Cocos2d-x-1.0.1的飞机大战游戏开发实例(中)
接<基于Cocos2d-x-1.0.1的飞机大战游戏开发实例(上)> 三.代码分析 1.界面初始化 bool PlaneWarGame::init() { bool bRet = fals ...
- 基于Cocos2d-x-1.0.1的飞机大战游戏开发实例(上)
最近接触过几个版本的cocos2dx,决定每个大变动的版本都尝试一下.本实例模仿微信5.0版本中的飞机大战游戏,如图: 一.工具 1.素材:飞机大战的素材(图片.声音等)来自于网络 2.引擎:coco ...
- 11.pygame飞机大战游戏整体代码
主程序 # -*- coding: utf-8 -*- # @Time: 2022/5/20 22:26 # @Author: LiQi # @Describe: 主程序 import pygame ...
- canvas绘制“飞机大战”小游戏,真香!
canvas是ArkUI开发框架里的画布组件,常用于自定义绘制图形.因为其轻量.灵活.高效等优点,被广泛应用于UI界面开发中. 本期,我们将为大家介绍canvas组件的使用. 一.canvas介绍 1 ...
- 一、利用Python编写飞机大战游戏-面向对象设计思想
相信大家看到过网上很多关于飞机大战的项目,但是对其中的模块方法,以及使用和游戏工作原理都不了解,看的也是一脸懵逼,根本看不下去.下面我做个详细讲解,在做此游戏需要用到pygame模块,所以这一章先进行 ...
- 用Javascript模拟微信飞机大战游戏
最近微信的飞机大战非常流行,下载量非常高. 利用JS进行模拟制作了一个简单的飞机大战[此源码有很多地方可以进行重构和优化] [此游戏中没有使用HTML5 任何浏览器都可以运行]. 效果图: 原理:利用 ...
随机推荐
- UML设计(团队作业)
UML设计 一.团队信息 1.队名 读完文章再睡觉 2.团队成员的学号与姓名 学号 姓名 211606381 吴伟华(队长) 211606369 蔺皓雯 211606340 杨池宇 211606372 ...
- maven把项目打包成jar包后找不到velocity模板的bug
使用springmvc 开发时候要实现发送velcotiy模板邮件,在配置正常后,在本地测试正常后,使用maven打包成jar包后,报以下错误, Caused by: org.apache.veloc ...
- css深入理解之 border
一 border-width不支持百分比值 1 不符合客观逻辑 2 w3成都一种约定吧 3 边框本身就像是一个包裹内容的界限 类似的还有outline,box-shadow text-shadow均不 ...
- dwarf是怎样处理的栈帧?
dwarf是如何处理的栈帧呢? 首先看下非dwarf的情况是如何处理栈帧的: 1 3623804982590 0x3e90 [0xb0]: PERF_RECORD_SAMPLE(IP, 0x1): 1 ...
- Android------去除标题栏
这里暂时只给出一种方法,在java代码中去除 1.继承Activity 在onCreate方法中 getWindow().setFlags(WindowManager.LayoutParams.FLA ...
- Android OCR文字识别 实时扫描手机号(极速扫描单行文本方案)
身份证识别:https://github.com/wenchaosong/OCR_identify 遇到一个需求,要用手机扫描纸质面单,获取面单上的手机号,最后决定用tesseract这个开源OCR库 ...
- iOS进阶--将项目的编译速度提高5倍
前言 作为开发团队的负责人,最近因为在快速迭代开发新功能,项目规模急速增长,单个端业务代码约23万行,私有库约6万行,第三方库代码约15万行,单个客户端的代码行数约60万.现在打包一次耗时需要11~1 ...
- 【bzoj1775】[Usaco2009 Dec]Vidgame 电视游戏问题 dp
题目描述 输入 * 第1行: 两个由空格隔开的整数: N和V * 第2到第N+1行: 第i+1行表示第i种游戏平台的价格和可以在这种游戏平台上面运行的游 戏.包含: P_i, G_i还有G_i对由空格 ...
- Android命名格式化详解
严格换行 一般情况下一个“:”一换行 建议函数的“{}”分别占一行 例:public void ooSomething() { …… } 不要用: 例:public void doSomething ...
- NetScaler SNIPs Bound To An Interface Without A VLAN
NetScaler SNIPs Bound To An Interface Without A VLAN https://www.citrix.com/blogs/2014/04/09/work-yo ...