视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
html5游戏开发-弹幕+仿雷电小游戏demo
2020-11-27 15:12:13 责编:小采
文档
 本游戏使用的是html5的canvas,运行游戏需要浏览器支持html5。

本篇文章详细讲解如何用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引擎,查看引擎包内源码

下载本文
显示全文
专题