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 任何浏览器都可以运行]. 效果图: 原理:利用 ...
随机推荐
- 《梦断代码Dreaming In Code》阅读笔记(三)
最后这几章感觉上更多是从软件完成整体上来讲的.比如说技术.方法等. 在我看来,其实一个团队一直坚持一种好的.先进的方法是不可少的.如果一个优秀的团队刚愎自用,只随着成员们喜好发展,那不能长久.比如说, ...
- Alpha 冲刺(1/10)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作,对多个目标检测及文字识别模型进行评估.实验,选取较 ...
- iOS开发本地通知
/* 本地通知:不通过网络,在本地实现的通知,自己发给自己 远程通知:必须通过网络,使用推送技术(APNs),实现通知 本地通知: 1.要完成可以接收的通知形式的注册 2.具体通知的设置 3.发送通知 ...
- Swift-创建UIButton(其他UI组件雷同)
let button = UIButton.init(frame: CGRectMake(, , , )) button.setTitle("按钮", forState: UICo ...
- cURL和file_get_contents实现模拟post请求
以前面试时候,面试官问过我后端有没有跨域问题,但是不敢肯定,现在可以肯定的说没有. 不文用php的cURL和file_get_contents方法分别实现后端跨域.本文场景也是在tp5下实现的. 一, ...
- 最近面试js部分试题总结
二,JavaScript面试题总结 1,首先是数组去重算法:给一个数组,去掉重复值 (function() { var arr = [1, 2, 3, 3, 4, ]; function unique ...
- linux下清空文件全部内容,如log日志
在实际操作中经常需要清空log文件, 比如a.log, 有的人说, 直接删除不就行了, 但是, 直接删除后, 没法使用tail -f a.log了. 有的人说, 先rm再touch一个新文件不就可 ...
- [C/C++] C++抽象类
转自:http://www.cnblogs.com/dongsheng/p/3343939.html 一.纯虚函数定义 纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己 ...
- [NOIP2016]愤怒的小鸟 状态压缩dp
题目描述 Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可以用它向第一象限发射一只红色的小鸟,小鸟们的飞行轨迹均为形 ...
- Luogu1053 NOIP2005篝火晚会
首先造出所要求的得到的环.如果将位置一一对应上,答案就是不在所要求位置的人数.因为显然这是个下界,并且脑补一下能构造出方案达到这个下界. 剩下的问题是找到一种对应方案使错位数最少.可以暴力旋转这个环, ...