欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

html5游戏开发-弹幕+仿雷电小游戏demo

程序员文章站 2022-04-19 18:45:55
    本游戏使用的是html5的canvas,运行游戏需要浏览器支持html5。   本篇文章详细讲解如何用h...

 

 

本游戏使用的是html5的canvas,运行游戏需要浏览器支持html5。

 

本篇文章详细讲解如何用html5来开发一款射击游戏,雷电可以说是射击游戏中的经典,下面就来模仿一下。

 

先看一下游戏截图

 

 

html5游戏开发-弹幕+仿雷电小游戏demo

演示地址

 

 

http://fsanguo.comoj.com/html5/barrage/index.html

 

 

 

游戏开发,需要用到开源库件:LegendForHtml5Programming。

 

 

 

LegendForHtml5Programming1.1下载地址:

 

http://legendforhtml5programming.googlecode.com/files/LegendForHtml5Programming1.1.zip

 

 

游戏预计用到下面几个文件

 

 

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);}   

 

效果如下

 

html5游戏开发-弹幕+仿雷电小游戏demo

射击游戏,子弹是亮点,如何添加多种子弹是游戏的关键

要使子弹有变化,必须要设定相应的角度,加速度,等多种变量

下面为了实现这些变化,我们来建立一个子弹类

 

 

 

/**

 * 子弹类 

 * */ 

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]); 

           

 

 

看效果

 

html5游戏开发-弹幕+仿雷电小游戏demo

修改,子弹的相应参数,如下

 

 

/**

 * 子弹类型数组

 * 【开始角度,增加角度,子弹速度,角度加速度,子弹总数,发动频率,枪口旋转】

 * */ 

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 

); 

 

效果分别为

html5游戏开发-弹幕+仿雷电小游戏demo

html5游戏开发-弹幕+仿雷电小游戏demo

html5游戏开发-弹幕+仿雷电小游戏demo

html5游戏开发-弹幕+仿雷电小游戏demo

 

 

最后附上所有源码下载

http://legend-demo.googlecode.com/files/barrage.zip