本篇文章详细讲解如何用html5来开发一款射击游戏,雷电可以说是射击游戏中的经典,下面就来模仿一下。
先看一下游戏截图
游戏开发,需要用到开源引擎:lufylegend.js
游戏预计用到下面几个文件
index.html
js文件夹|---main.js
|---plain.js//飞机
|---bullet.js//子弹
|---global.js//共通
images文件夹|--图片
我简单说一下制作过程,源代码在最下面
首先建立index.html文件,
<!doctype html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>弹幕</title> <!-- <meta name="viewport" content="width=480,initial-scale=0.5, minimum-scale=0.5, maximum-scale=1.0,user-scalable=no" /> --> <meta name="viewport" content="width=480,initial-scale=0.6" /> <script type="text/javascript" src="../legend/legend.js"></script> <script type="text/javascript" src="./js/global.js"></script> <script type="text/javascript" src="./js/bullet.js"></script> <script type="text/javascript" src="./js/plain.js"></script> <script type="text/javascript" src="./js/main.js"></script> </head> <body> <p id="mylegend">loading……</p> </body> </html>
打开main.js
在里面添加代码,先将图片全部读取,并显示进度条
以及,将一些可能会用到的变量添加进去
/** * main * */ //设定游戏速度,屏幕大小,回调函数 init(50,"mylegend",480,800,main); /**层变量*/ //显示进度条所用层 var loadinglayer; //游戏最底层 var backlayer; //控制层 var ctrllayer; /**int变量*/ //读取图片位置 var loadindex = 0; //贞数 var frames = 0; //boos start var boosstart = false; //game over var gameover = false; //game clear var gameclear = false; //得分 var point = 0; /**对象变量*/ //玩家 var player; //得分 var pointtext; /**数组变量*/ //图片path数组 var imgdata = new array(); //读取完的图片数组 var imglist = {}; //子弹数组 var barrage = new array(); //子弹速度数组 var barragespeed = [5,10]; //储存所有敌人飞机的数组 var enemys = new array(); function main(){ //准备读取图片 imgdata.push({name:"back",path:"./images/back.jpg"}); imgdata.push({name:"enemy",path:"./images/e.png"}); imgdata.push({name:"player",path:"./images/player.png"}); imgdata.push({name:"boss",path:"./images/boss.png"}); imgdata.push({name:"ctrl",path:"./images/ctrl.png"}); imgdata.push({name:"item1",path:"./images/1.png"}); //实例化进度条层 loadinglayer = new lsprite(); loadinglayer.graphics.drawrect(1,"black",[50, 200, 200, 20],true,"#ffffff"); addchild(loadinglayer); //开始读取图片 loadimage(); } function loadimage(){ //图片全部读取完成,开始初始化游戏 if(loadindex >= imgdata.length){ removechild(loadinglayer); legendloadover(); gameinit(); return; } //开始读取图片 loader = new lloader(); loader.addeventlistener(levent.complete,loadcomplete); loader.load(imgdata[loadindex].path,"bitmapdata"); } function loadcomplete(event){ //进度条显示 loadinglayer.graphics.clear(); loadinglayer.graphics.drawrect(1,"black",[50, 200, 200, 20],true,"#ffffff"); loadinglayer.graphics.drawrect(1,"black",[50, 203, 200*(loadindex/imgdata.length), 14],true,"#000000"); //储存图片数据 imglist[imgdata[loadindex].name] = loader.content; //读取下一张图片 loadindex++; loadimage(); }
现在,所用到的图片已经全部都加载完毕,先添加背景,显示一张图片
用legend库件显示图片非常简单
function gameinit(event){ //游戏底层实例化 backlayer = new lsprite(); addchild(backlayer); //添加游戏背景 bitmapdata = new lbitmapdata(imglist["back"]); bitmap = new lbitmap(bitmapdata); backlayer.addchild(bitmap);}
效果如下
射击游戏,子弹是亮点,如何添加多种子弹是游戏的关键
要使子弹有变化,必须要设定相应的角度,加速度,等多种变量
下面为了实现这些变化,我们来建立一个子弹类
/** * 子弹类 * */ function bullet(belong,x,y,angle,xspeed,yspeed,aspeed,speed){ base(this,lsprite,[]); var self = this; //子弹所属 self.belong = belong; //出现位置 self.x = x; self.y = y; //角度 self.angle = angle; //移动速度 self.speed = speed; //xy轴速度 self.xspeed = xspeed; self.yspeed = yspeed; //旋转角度加成 self.aspeed = aspeed; //子弹图片 var bitmapdata,bitmap; bitmapdata = new lbitmapdata(imglist["item1"]); bitmap = new lbitmap(bitmapdata); self.bitmap = bitmap; //显示 self.addchild(bitmap); }
然后,在子弹移动过程中,根据这些变量来实现多种变换
在共通类中,加入一个子弹数组,用来区分各种子弹
/** * 子弹类型数组 * 【开始角度,增加角度,子弹速度,角度加速度,子弹总数,发动频率,枪口旋转】 * */ global.bulletlist = new array( {startangle:0,angle:20,speed:5,aspeed:0,count:1,shootspeed:10,sspeed:0},//1发 );
游戏最基本的子弹,当然就是每次发一个子弹
在共通类里建一个发射子弹的函数
/** * 发射子弹 * @param 飞机 * */ global.setbullet = function(plainobject){ var i,j,obj,xspeed,yspeed,kaku; //获取子弹属性 var bullet = global.bulletlist[0]; //开始发射 for(i=0;i<bullet.count;i++){ //发射角度 kaku = i*bullet.angle + bullet.startangle; //子弹xy轴速度 xspeed = bullet.speed*math.sin(kaku * math.pi / 180); yspeed = barragespeed[0]*math.cos(kaku * math.pi / 180); //子弹实例化 obj = new bullet(0,210,300,kaku,xspeed,yspeed,bullet.aspeed,bullet.speed); //显示 backlayer.addchild(obj); barrage.push(obj); } };
这里,最终需要根据发射的飞机不同而不同,所以我加入了参数飞机
那现在建立飞机类,如下
/** * 飞机类 * */ function plain(name,belong,x,y,bullets){ base(this,lsprite,[]); var self = this; //飞机名称 self.name = name; //飞机位置 self.x = x; self.y = y; //飞机所属 self.belong = belong; //子弹数组 self.bullets = bullets; //初始子弹 self.bullet = self.bullets[math.floor(math.random()*self.bullets.length)]; self.shootspeed = global.bulletlist[self.bullet].shootspeed; //枪口旋转角度 self.sspeed = 0; //射击频率控制 self.shootctrl = 0; //获取飞机属性 self.list = global.getplainstatus(self); //飞机图片 self.bitmap = self.list[0]; //显示 self.addchild(self.bitmap); //枪口位置 self.shootx = self.list[1]; self.shooty = self.list[2]; //移动速度 self.speed = self.list[3]; //飞机hp self.hp = self.list[4]; //移动方向 self.move = [0,0]; //发射子弹数 self.shootcount = 0; //是否发射子弹 self.canshoot = true; if(name=="player")self.canshoot = false; } /** * 循环 * */ plain.prototype.onframe = function (){ var self = this; //移动 self.x += self.move[0]*self.speed; self.y += self.move[1]*self.speed; switch (self.name){ case "player": //自机移动位置限制 if(self.x < 0)self.x = 0; else if(self.x + self.bitmap.getwidth() > lglobal.width)self.x = lglobal.width-self.bitmap.getwidth(); if(self.y < 0)self.y = 0; else if(self.y + self.bitmap.getheight() > lglobal.height)self.y = lglobal.height-self.bitmap.getheight(); break; case "boss": //敌机boss移动 if(self.y < 0){ self.y = 0; self.move[1] = 1; }else if(self.y + self.bitmap.getheight() > lglobal.height){ self.y = lglobal.height-self.bitmap.getheight(); self.move[1] = -1; } //碰撞检测 self.hittest(); break; case "enemy": default: //碰撞检测 self.hittest(); } //射击 if(self.canshoot)self.shoot(); }; /** * 碰撞检测 * */ plain.prototype.hittest = function (){ var self = this; var disx,disy,sw,ew; sw = (self.bitmap.getwidth() + self.bitmap.getheight())/4; ew = (player.bitmap.getwidth() + player.bitmap.getheight())/4; disx = self.x+sw - (player.x + ew); disy = self.y+self.bitmap.getheight()/2 - (player.y + player.bitmap.getheight()/2); if(disx*disx + disy*disy < (sw+ew)*(sw+ew)){ player.visible = false; gameover = true; } }; /** * 射击 * */ plain.prototype.shoot = function (){ var self = this; if(self.shootctrl++ < self.shootspeed)return; self.shootctrl = 0; if(self.name == "boss"){ if(self.shootcount++ % 20 > 5)return; }else{ if(self.shootcount++ % 10 > 5)return; } global.setbullet(self); if(self.name == "boss"){ if(self.shootcount % 20 < 5)return; }else{ if(self.shootcount % 10 < 5)return; } if(self.bullets.length <= 1)return; self.bullet = self.bullets[math.floor(math.random()*self.bullets.length)]; self.shootspeed = global.bulletlist[self.bullet].shootspeed; };
代码已经加入了详细的注释,不难理解吧
完善子弹类如下
/** * 子弹类 * */ function bullet(belong,x,y,angle,xspeed,yspeed,aspeed,speed){ base(this,lsprite,[]); var self = this; //子弹所属 self.belong = belong; //出现位置 self.x = x; self.y = y; //角度 self.angle = angle; //移动速度 self.speed = speed; //xy轴速度 self.xspeed = xspeed; self.yspeed = yspeed; //旋转角度加成 self.aspeed = aspeed; //子弹图片 var bitmapdata,bitmap; bitmapdata = new lbitmapdata(imglist["item1"]); bitmap = new lbitmap(bitmapdata); self.bitmap = bitmap; //显示 self.addchild(bitmap); } /** * 循环 * @param 子弹序号 * */ bullet.prototype.onframe = function (index){ var self = this; //子弹移动 self.x += self.xspeed; self.y += self.yspeed; //子弹角度变更 if(self.aspeed != 0){ self.angle += self.aspeed; //子弹角度变更后,重新计算xy轴速度 self.xspeed = self.speed*math.sin(self.angle * math.pi / 180); self.yspeed = self.speed*math.cos(self.angle * math.pi / 180); } //子弹位置检测 if(self.x < 0 || self.x > lglobal.width || self.y < 0 || self.y > lglobal.height){ //从屏幕移除 backlayer.removechild(self); //从子弹数组移除 barrage.splice(index,1); }else{ self.hittest(index); } }; /** * 子弹碰撞检测 * @param 子弹序号 * */ bullet.prototype.hittest = function (index){ var self = this; var disx,disy,sw,ew,obj,i; if(self.belong == player.belong){ //自机子弹 for(i=0;i<enemys.length;i++){ obj = enemys[i]; sw = self.bitmap.getwidth()/2; ew = obj.bitmap.getwidth()/2; disx = self.x+sw - (obj.x + ew); disy = self.y+self.bitmap.getheight()/2 - (obj.y + obj.bitmap.getheight()/2); //距离检测 if(disx*disx + disy*disy < ew*ew){ obj.hp--; if(obj.hp == 0){ point += 1; pointtext.text = point; //从屏幕移除 backlayer.removechild(obj); //从敌机数组移除 enemys.splice(i,1); if(obj.name == "boss"){ gameclear = true; } } //从屏幕移除 backlayer.removechild(self); //从子弹数组移除 barrage.splice(index,1); } } }else{ //敌机子弹 obj = player; sw = self.bitmap.getwidth()/2; ew = obj.bitmap.getwidth()/2; disx = self.x+sw - (obj.x + ew); disy = self.y+self.bitmap.getheight()/2 - (obj.y + obj.bitmap.getheight()/2); //距离检测 if(disx*disx + disy*disy < ew*ew - 10){ obj.visible = false; gameover = true; //从屏幕移除 backlayer.removechild(self); //从子弹数组移除 barrage.splice(index,1); } } };
子弹发射函数,修改如下
/** * 发射子弹 * @param 飞机 * */ global.setbullet = function(plainobject){ var i,j,obj,xspeed,yspeed,kaku; //获取子弹属性 var bullet = global.bulletlist[plainobject.bullet]; //设定枪口旋转 plainobject.sspeed += bullet.sspeed; //开始发射 for(i=0;i<bullet.count;i++){ //发射角度 kaku = i*bullet.angle + bullet.startangle + plainobject.sspeed; //子弹xy轴速度 xspeed = bullet.speed*math.sin(kaku * math.pi / 180); yspeed = barragespeed[0]*math.cos(kaku * math.pi / 180); //子弹实例化 obj = new bullet(plainobject.belong,plainobject.x+plainobject.shootx,plainobject.y+plainobject. shooty,kaku,xspeed,yspeed,bullet.aspeed,bullet.speed); //显示 backlayer.addchild(obj); barrage.push(obj); } };
在main文件里添加循环
/** * 循环 * */ function onframe(){ var i; //循环子弹 for(i=0;i<barrage.length;i++){ barrage[i].onframe(i); } //循环敌机 for(i=0;i<enemys.length;i++){ enemys[i].onframe(); } }
现在,我只需要添加飞机,就可以发射子弹了
plain = new plain("enemy",1,200,300,[0]);
看效果
修改,子弹的相应参数,如下
/** * 子弹类型数组 * 【开始角度,增加角度,子弹速度,角度加速度,子弹总数,发动频率,枪口旋转】 * */ global.bulletlist = new array( {startangle:0,angle:20,speed:5,aspeed:0,count:1,shootspeed:10,sspeed:0},//1发 {startangle:-20,angle:20,speed:5,aspeed:0,count:3,shootspeed:10,sspeed:0},//3发 {startangle:0,angle:20,speed:5,aspeed:0,count:1,shootspeed:1,sspeed:20},//1发旋转 {startangle:0,angle:20,speed:5,aspeed:0,count:18,shootspeed:3,sspeed:0},//环发 {startangle:0,angle:20,speed:5,aspeed:1,count:18,shootspeed:3,sspeed:0},//环发旋转 {startangle:180,angle:20,speed:5,aspeed:0,count:1,shootspeed:5,sspeed:0},//1发 up {startangle:160,angle:20,speed:5,aspeed:0,count:3,shootspeed:5,sspeed:0}//3发 up );
效果分别为
lufylegend.js引擎包内包含这个demo,请直接下载lufylegend.js引擎,查看引擎包内源码
以上就是html5游戏开发-弹幕+仿雷电小游戏demo的内容。
