html5遊戲開發-彈幕+仿雷電小遊戲demo
阿新 • • 發佈:2019-01-03
本遊戲使用的是html5的canvas,運行遊戲需要瀏覽器支援html5。
本篇文章詳細講解如何用html5來開發一款射擊遊戲,雷電可以說是射擊遊戲中的經典,下面就來模仿一下。
先看一下游戲截圖
演示地址
遊戲開發,需要用到開源引擎:lufylegend.js
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> <div id="mylegend">loading……</div> </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引擎,檢視引擎包內原始碼
lufylegend.js引擎下載地址