做一个游戏引擎的Demo-弹幕大战
做一个游戏引擎的Demo-弹幕大战
还记得上次我们开发的那个游戏引擎吗?又经过几次更新维护,终于可以编写这游戏引擎的Demo啦!
注意:该游戏引擎已经过大换血,所以最好去查看一下我在GitHub上的README再看接下来的内容。
这次是要开发什么游戏呢?这次的游戏是结合弹幕与飞机大战于一身的游戏——弹幕大战。
这首先是什么玩法呢?先看看下面的演示:
游戏功能
功能操作 | 功能 |
---|---|
鼠标移动 | 控制飞机左右移动 |
按下空格 | 发射子弹 |
按下回车 | 创建子弹墙 |
根据以上内容,我们可以制定文件结构了:
首先咱需要准备几张图片与影片(都在GitHub上),然后编写基本html代码。
<!DOCTYPE html>
<html lang="cn">
<head>
<meta charset="UTF-8">
<title>弹幕大战</title>
<link rel="icon" href="img/logo.ico"/>
<link type="text/css" rel="stylesheet" href="css/index.css"/>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="webfire/js/jQuery-v3.3.1.js"></script>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="webfire/js/obj.js"></script>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="webfire/js/physics.js"></script>
</head>
<body>
<header>
<img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/logo.png" width="50">
<h1>弹幕大战</h1>
<h4>文字中的战斗机<br/>文字版飞机大战</h4>
<h1> </h1>
<h4><span>歼灭数:</span><span id="killNum">0</span><br/><span>剩余血量:</span><span id="bloodNum">20</span></h4>
</header>
<main id="main">
<video class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="movies/test.mp4" id="movie" loop="loop" autoplay="autoplay"></video>
</main>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="js/index.js"></script>
</body>
</html>
这样就完成了html结构。
都说如果html是名词,那么css就是形容词,一个漂亮的游戏总是需要css的帮助的,所以,可以编写index.css,让我们的网页更漂亮。
header{
background-color: crimson;
height: 50px;
width: 100%;
position: absolute;
top: 0;
left: 0;
color: #fff;
}
header *{
margin-right: 10px;
margin-top: 0;
float: left;
}
main{
overflow: hidden;
}
#movie{
position: absolute;
top: 50px;
left: 0;
z-index: -2;
}
这下子,再去浏览器查看一遍,是不是好多了?
接着,开始编写游戏主逻辑。
首先不管后面的视频,将用户飞机移动的逻辑做好。
// 创建对象
var posY = screen.height - 200;
var me = new role({
image: "img/me.png",
width: 100,
height: 50,
type: "img",
name: "me",
x: screen.width / 2 - 50,
y: posY,
pos: "main"
});
var blood = $("#bloodNum");
var kill = $("#killNum");
var bloodNum = 20;
var killNum = 0;
me.speed = 3;
// 添加事件监听
$(document).mousemove(function (e) {
me.move(e.pageX - 50,posY);
bullet.move(e.pageX - 50,posY - 5);
});
接着发射子弹的逻辑,可以首先定义一个子弹的游戏对象,然后不断克隆它:
var bullet = new role({
image: "webfire/img/outText.png",
width: 100,
height: 100,
type: "img",
name: "bullet",
x: me.x,
y: me.y - 5,
pos: "main"
});
bullet.setText({
text: "^",
size: 30,
color: "#f00"
});
bullet.webEntity.fadeOut(0);
$(document).keydown(function (e) {
switch (e.keyCode){
case 32:// space
var newBullet = bullet.copy();
newBullet.setText({
text: "^",
color: "#f00",
size: 30
});
var Interval = setInterval(function () {
if (newBullet.die){
clearInterval(Interval);
} else {
newBullet.run(270);
if (newBullet.y <= 60){
newBullet.del("none",0);
clearInterval(Interval);
}
}
},10);
window.moveTo(0,0);
break;
}
});
然后可以再实现创建子弹墙了:
var can = false;
$(document).keydown(function (e) {
switch (e.keyCode){
case 13:
can = false;
for (var i = 0 ; i < 15 ; i++){
for (var j = 0 ; j < 5 ; j++){
var newBullet = bullet.copy();
newBullet.setText({
text: "^",
color: "#f00",
size: 30
});
newBullet.move(i * 30 + me.x,j * 30 + 300);
}
}
setTimeout(function () {
can = true;
},10000);
break;
}
});
setTimeout(function () {
can = true;
},10000);
再将这两个语句合并,变为:
var can = false;
$(document).keydown(function (e) {
switch (e.keyCode){
case 32:// space
var newBullet = bullet.copy();
newBullet.setText({
text: "^",
color: "#f00",
size: 30
});
var Interval = setInterval(function () {
if (newBullet.die){
clearInterval(Interval);
} else {
newBullet.run(270);
if (newBullet.y <= 60){
newBullet.del("none",0);
clearInterval(Interval);
}
}
},10);
window.moveTo(0,0);
break;
case 13:
can = false;
for (var i = 0 ; i < 15 ; i++){
for (var j = 0 ; j < 5 ; j++){
var newBullet = bullet.copy();
newBullet.setText({
text: "^",
color: "#f00",
size: 30
});
newBullet.move(i * 30 + me.x,j * 30 + 300);
}
}
setTimeout(function () {
can = true;
},10000);
break;
}
});
setTimeout(function () {
can = true;
},10000);
阅读上面的源码后,细心的朋友可能发现了,剩下的敌人对象的名字是不是叫"em"呢?是的,正是如此,而且实现方法与子弹的创建实现方法也如出一辙,只不过需要一个数组来存储敌人弹幕的文字罢了与随机颜色罢了。
var em = new role({
image: "webfire/img/outText.png",
width: 50,
height: 50,
type: "img",
name: "em",
x: 0,
y: 50,
pos: "main"
});
var texts = ["emmm","哈哈","_","打call","尬聊","你的良心不会痛吗?","惊不惊喜,意不意外","皮皮虾,我们走","扎心了,老铁","还有这种操作?","怼","你有freestyle吗?","油腻"];
em.webEntity.fadeOut(0);
var gameLoop = setInterval(function () {
var newEm = em.copy();
newEm.move(Math.floor(Math.random() * screen.width - 100),newEm.y);
newEm.setText({
text: texts[Math.floor(Math.random() * texts.length)],
size: 10,
color: color.hex({
r: Math.floor(Math.random() * 255),
g: Math.floor(Math.random() * 255),
b: Math.floor(Math.random() * 255)
})
});
var interval = setInterval(function () {
newEm.run(90);
var collisionObjs = collisionObj(newEm);
if (collisionObjs.length){
for (var i = 0 ; i < collisionObjs.length ; i++){
if (collisionObjs[i].name == "bullet"){
newEm.del("none",0);
killNum++;
kill.html(killNum);
collisionObjs[i].del("none",0);
gameObjs.splice(collisionObjs[i].id,1);
clearInterval(interval);
break;
} else if (collisionObjs[i].name == "me"){
newEm.del("none",0);
clearInterval(interval);
bloodNum--;
blood.html(bloodNum);
if (bloodNum <= 0){
clearInterval(gameLoop);
for (var j in gameObjs){
gameObjs[j].del("none",0);
}
alert("游戏结束");
}
}
}
}
if (newEm.y >= (screen.height - 200)){
newEm.del("none",0);
clearInterval(interval);
}
},100);
},100);
现在实现完成后,大部分功能是实现了,只是还有一个小问题,就是子弹可能会在飞机上面,所以这还有一个小优化:
me.setCss({
"z-index": "1"
});
bullet.setCss({
"z-index": "0"
});
em.setCss({
"z-index": "-1"
});
最后,就到令人轻松的话题了,终于可以实现影片播放啦!html的dom结构已经组织好,只差js的点睛之笔了。
var movie = $("#movie");
movie.attr("width",screen.width + "px");
movie.attr("height",screen.height - 125 + "px");
现在代码编写完成,全部代码如下:
index.html
<!DOCTYPE html>
<html lang="cn">
<head>
<meta charset="UTF-8">
<title>弹幕大战</title>
<link rel="icon" href="img/logo.ico"/>
<link type="text/css" rel="stylesheet" href="css/index.css"/>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="webfire/js/jQuery-v3.3.1.js"></script>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="webfire/js/obj.js"></script>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="webfire/js/physics.js"></script>
</head>
<body>
<header>
<img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/logo.png" width="50">
<h1>弹幕大战</h1>
<h4>文字中的战斗机<br/>文字版飞机大战</h4>
<h1> </h1>
<h4><span>歼灭数:</span><span id="killNum">0</span><br/><span>剩余血量:</span><span id="bloodNum">20</span></h4>
</header>
<main id="main">
<video class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="movies/test.mp4" id="movie" loop="loop" autoplay="autoplay"></video>
</main>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="js/index.js"></script>
</body>
</html>
index.js
var posY = screen.height - 200;
var me = new role({
image: "img/me.png",
width: 100,
height: 50,
type: "img",
name: "me",
x: screen.width / 2 - 50,
y: posY,
pos: "main"
});
var bullet = new role({
image: "webfire/img/outText.png",
width: 100,
height: 100,
type: "img",
name: "bullet",
x: me.x,
y: me.y - 5,
pos: "main"
});
var em = new role({
image: "webfire/img/outText.png",
width: 50,
height: 50,
type: "img",
name: "em",
x: 0,
y: 50,
pos: "main"
});
var blood = $("#bloodNum");
var kill = $("#killNum");
var bloodNum = 20;
var killNum = 0;
var can = false;
var texts = ["emmm","哈哈","_","打call","尬聊","你的良心不会痛吗?","惊不惊喜,意不意外","皮皮虾,我们走","扎心了,老铁","还有这种操作?","怼","你有freestyle吗?","油腻"];
bullet.setText({
text: "^",
size: 30,
color: "#f00"
});
me.setCss({
"z-index": "1"
});
bullet.setCss({
"z-index": "0"
});
em.setCss({
"z-index": "-1"
});
bullet.webEntity.fadeOut(0);
em.webEntity.fadeOut(0);
me.speed = 3;
$(document).keydown(function (e) {
switch (e.keyCode){
case 32:// space
var newBullet = bullet.copy();
newBullet.setText({
text: "^",
color: "#f00",
size: 30
});
var Interval = setInterval(function () {
if (newBullet.die){
clearInterval(Interval);
} else {
newBullet.run(270);
if (newBullet.y <= 60){
newBullet.del("none",0);
clearInterval(Interval);
}
}
},10);
window.moveTo(0,0);
break;
case 13:
can = false;
for (var i = 0 ; i < 15 ; i++){
for (var j = 0 ; j < 5 ; j++){
var newBullet = bullet.copy();
newBullet.setText({
text: "^",
color: "#f00",
size: 30
});
newBullet.move(i * 30 + me.x,j * 30 + 300);
}
}
setTimeout(function () {
can = true;
},10000);
break;
}
});
var gameLoop = setInterval(function () {
var newEm = em.copy();
newEm.move(Math.floor(Math.random() * screen.width - 100),newEm.y);
newEm.setText({
text: texts[Math.floor(Math.random() * texts.length)],
size: 10,
color: color.hex({
r: Math.floor(Math.random() * 255),
g: Math.floor(Math.random() * 255),
b: Math.floor(Math.random() * 255)
})
});
var interval = setInterval(function () {
newEm.run(90);
var collisionObjs = collisionObj(newEm);
if (collisionObjs.length){
for (var i = 0 ; i < collisionObjs.length ; i++){
if (collisionObjs[i].name == "bullet"){
newEm.del("none",0);
killNum++;
kill.html(killNum);
collisionObjs[i].del("none",0);
gameObjs.splice(collisionObjs[i].id,1);
clearInterval(interval);
break;
} else if (collisionObjs[i].name == "me"){
newEm.del("none",0);
clearInterval(interval);
bloodNum--;
blood.html(bloodNum);
if (bloodNum <= 0){
clearInterval(gameLoop);
for (var j in gameObjs){
gameObjs[j].del("none",0);
}
alert("游戏结束");
}
}
}
}
if (newEm.y >= (screen.height - 200)){
newEm.del("none",0);
clearInterval(interval);
}
},100);
},100);
$(document).mousemove(function (e) {
me.move(e.pageX - 50,posY);
bullet.move(e.pageX - 50,posY - 5);
});
setTimeout(function () {
can = true;
},10000);
var movie = $("#movie");
movie.attr("width",screen.width + "px");
movie.attr("height",screen.height - 125 + "px");
index.css
header{
background-color: crimson;
height: 50px;
width: 100%;
position: absolute;
top: 0;
left: 0;
color: #fff;
}
header *{
margin-right: 10px;
margin-top: 0;
float: left;
}
main{
overflow: hidden;
}
#movie{
position: absolute;
top: 50px;
left: 0;
z-index: -2;
}
[完]
点击查看更多内容
7人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦