这次是一个网页小游戏
通过点击 使小鸟飞过水管,然后积分。
下面放出代码
1.界面
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="css/reset.css"/>
<link rel="stylesheet" type="text/css" href="css/main.css"/>
<title></title>
</head>
<body>
<div id="flyWrap">
<ul id="pipeWrap">
</ul>
<div id="score">
<img src="img/0.jpg" alt="" />
</div>
<div id="head">
<img src="img/head.jpg" alt="" />
<div>
<img src="img/bird0.png" alt="" />
</div>
</div>
<div id="start">
<img src="img/start.jpg" alt="" />
</div>
<div id="slide"></div>
<img src="img/bird0.png" id="flyBird"/>
<img src="img/game_over.jpg" alt="" id="gameOver"/>
<img src="img/ok.jpg" alt="" id="ok"/>
<audio src="source/game_music.mp3"></audio>
<audio src="source/bullet.mp3"></audio>
<audio src="source/die.mp3"></audio>
<audio src="source/money.mp3"></audio>
</div>
</body>
</html>
<script src="js/main.js" type="text/javascript" charset="utf-8"></script>
2.css
记得这里还有一个reset.css
#flyWrap{
width: 343px;
height: 480px;
border: 1ps solid black;
position: relative;
margin: 100px auto;
background: url(../img/bg.jpg)no-repeat;
-webkit-user-select: none;
overflow: hidden;
}
#score{
width: 100%;
position: absolute;
top: 50px;
text-align: center;
}
@keyframes head{
from{top: 100px;}
50%{top:130px}
to{top:100px}
}
#head{
position: absolute;
top: 100px;
width: 100%;
animation: head 2s linear infinite;
}
#head>img{
position: absolute;
left: 40px;
}
#head>div{
position: absolute;
right: 50px;
top: 30px;
background: url(../img/bird1.png);
}
@keyframes bird{
from{opacity: 1;}
to{opacity: 0;}
}
#head>div>img{
animation: bird 0.7s linear infinite;
}
#start{
width: 85px;
margin: 0 auto;
position: relative;
top: 300px;
cursor: pointer;
}
@keyframes slide{
from{left: 0;}
to{left: -343px;}
}
#slide{
width: 700px;
height: 14px;
background: url(../img/slider.jpg);
position: absolute;
top: 422px;
animation: slide 4s linear infinite;
}
#flyBird{
position: absolute;
left: 60px;
top: 130px;
display: none;
}
#pipeWrap{width: 100%;height: 422px;position: absolute;top: 0;left: 0;}
#pipeWrap>.pipe{width: 62px;height: 422px;position: absolute;left: 400px;top: 0;}
#pipeWrap .pipeTop{position: absolute;top: 0;background:url(../img/up_mod.png);width: 100%;}
#pipeWrap .pipeTop>img{position: absolute;bottom: 0;}
#pipeWrap .pipeBottom{position: absolute;bottom: 0;background: url(../img/down_mod.png);width: 100%;}
#pipeWrap .pipeBottom>img{position: absolute;top: 0;}
#gameOver{
position: absolute;top: 150px;left: 60px;
animation: gameOver 0.5 linear; display: none;
}
@keyframes gameOver{
from{top:50px;}
to{top:150px}
}
#ok{
position: absolute;top: 320px;left: 120px;display: none;
animation: ok 0.5 linear;
}
@keyframes ok{
from{left: -100px;}
to{left: 120px;}
}
3.JavaScript
!function Game(){
var start =document.getElementById("start");
var head=document.getElementById("head");
var flyBird=document.getElementById("flyBird")
var audios=document.getElementsByTagName("audio");
var flyWrap=document.getElementById("flyWrap");
var pipeWrap=document.getElementById("pipeWrap");
var scoreScreen = document.getElementById("score");
var over=document.getElementById("gameOver");
var ok=document.getElementById("ok");
var maxspeed=8;
var downTimer=null;
var crashTimer=null;
var upTimer=null;
var speed=0;
var scoreNum = 0;
var pipeTimer = null;
function birdDown(){
flyBird.src="img/down_bird0.png";
speed+=0.3;
if(speed>=maxspeed){
speed=maxspeed;
}
flyBird.style.top=flyBird.offsetTop+speed+"px";
}
function randNumber(min,max){
return parseInt((max-min)*Math.random()+min)
}
function addScore(){
scoreNum++;
var scoreNumStr = String(scoreNum);
scoreScreen.innerHTML = "";
for(var i = 0; i < scoreNumStr.length; i++) {
var num = scoreNumStr[i];
var img = document.createElement("img");
img.src = "img/" + num + ".jpg";
scoreScreen.appendChild(img);
}
}
function createPipe(){
var li=document.createElement("li");
li.className="pipe";
pipeWrap.appendChild(li);
var topHeight=randNumber(50,200);
var bottomHeight=300-topHeight;
li.innerHTML = "<div class='pipeTop'style='height:" + topHeight + "px'><img src='img/up_pipe.png'></div><div class='pipeBottom' style='height:" + bottomHeight + "px'><img src='img/down_pipe.png'></div>";
li.lock=false;
li.appearTimer = setInterval(function(){
var lileft= li.offsetLeft-3;
if(lileft<=-70){
clearInterval(li.appearTimer);
pipeWrap.removeChild(li);
}
li.style.left=lileft+"px";
if(li.offsetLeft+li.offsetWidth<=flyBird.offsetLeft && li.lock ==false){
addScore();
li.lock=true;
}
},30)
}
function gameOver(){
audios[0].pause();
audios[1].pause();
audios[2].play();
clearInterval(downTimer);
clearInterval(upTimer);
clearInterval(crashTimer);
clearInterval(pipeTimer);
var lis =pipeWrap.getElementsByClassName("pipe");
for (var i=0;i<lis.length;i++){
clearInterval(lis[i].appearTimer);
}
start.onclick=null;
flyWrap.onclick=null;
over.style.display="block";
ok.style.display="block";
}
function isCrash(obj1,obj2){
var a = obj1.offsetTop > obj2.offsetTop + obj2.offsetHeight;
var b = obj2.offsetTop > obj1.offsetTop + obj1.offsetHeight;
var c = obj1.offsetLeft > obj2.parentNode.offsetLeft + obj2.offsetWidth;
var d = obj2.parentNode.offsetLeft > obj1.offsetLeft + obj1.offsetWidth;
if(a||b||c||d){
return false;
}
return true;
}
function crashCheck(){
//检测是否和天花板或地板碰撞
if(flyBird.offsetTop<=0 || flyBird.offsetTop+flyBird.offsetHeight>=422){
gameOver();
}
//或管道碰撞
var lis = pipeWrap.getElementsByClassName("pipe");
for(var i=0;i<lis.length;i++){
var a=isCrash(flyBird,lis[i].children[0]);
var b=isCrash(flyBird,lis[i].children[1]);
if(a||b){
gameOver();
}
}
}
function gamestart(){
head.style.display="none";
start.style.display="none";
flyBird.style.display="block";
audios[0].play();
downTimer=setInterval(birdDown,30);
pipeTimer=setInterval(createPipe,3000);
crashTimer=setInterval(crashCheck,30);
}
function birdup(){
audios[1].pause();
audios[1].play();
clearInterval(upTimer);
clearInterval(downTimer);
flyBird.src="img/up_bird0.png";
speed=maxspeed;
upTimer=setInterval(function(){
speed-=0.7;
if(speed<=0){
clearInterval(upTimer);
downTimer=setInterval(birdDown,30)
}
flyBird.style.top=flyBird.offsetTop-speed+"px";
},30)
}
!function inti(){
start.onclick=function(event){
var ev=event||window.event;
if(ev.stopPropagation){
ev.stopPropagation();
}else{
ev.cancelBubble=true;
}
gamestart();
flyWrap.onclick=function(){
birdup();
}
ok.onclick=function(){
window.location.reload()
}
}
}()
}()
这里是我当时写完后总结的一些逻辑思路:
1.html+css布局
2.布局完成后,点击start开始游戏
3.从接口函数inti开始(132),对start创建一个点击事件,当点击时,先阻止冒泡(作用是防止用户点击过快出现bug),然后调用gamestart函数(105),先清除掉head标题,和start按钮,然后将小鸟(flybird)显形,并开始播放音乐,然后设置三个定时器(downtimer下降定时器(18),creatpipe创建管道的定时器(40),crashcheck碰撞检测的定时器(89))
a.downtimer定时器 触发时,先改变小鸟标志的朝向,即换图,然后为小鸟设置初速度为0,速度每次+0.3,最大速度为8,然后使小鸟的top值等于小鸟当前的top值+速度大小,实现小鸟下降。其中该定时器每30ms执行一次
b.creatpipe定时器 触发时,创建一个li,并放在pipiwrap中作为其子代。设定上下管道的长度,上管道为随机数生成,调用randnumber函数(26),然后给中间通过的口预留122px的空间,则下管道的长度为300-上管道的长度,然后在html文件的li中写入上下管道这两个div。当管道移动到屏幕以为时,就需要消除,防止创建的li过大,使游戏缓存变大卡顿,设定一个判断的定时器,每30ms判断li的lift的值是否超过屏幕,而且同时,要进行加分判定,当没通过一个管道时,便加一分,设置lock属性,防止重复判断。加分时调用addscore函数(29)
(1) addscore函数 ,每触发一次,使scorenum加一,然后将scorenum转换成字符串,然后以字符串你的长度判断循环次数,如9就for循环一次,12就for循环两次。加分就是改变img或者增加一张img。
c.crashcheck定时器 触发时,开始进行碰撞判断 若判断撞上,则调用gameover函数(61)。判断分两点,对上下天花板的判断,和对管道碰撞的判断。对上下天花板的判断用小鸟当前的top值与天花板的top值比较即可。对管道的判断则要调用iscrash函数(79)判断,若碰上,则调用gameOver函数。
(1)iscrash函数,4种情况,鸟的top值大于管道的top+管道height,管道的top值大于鸟的top+鸟height,鸟的left值大于管道的left值+width,管道的left值大于鸟的left+鸟width。除了这四种情况外,都将碰上,返回true,若没碰上,返回false
d.游戏时,点击一个游戏界面,小鸟就会向上飞,所以在flywrap上创建一个点击事件,调用birdup函数(114),点击一下,会响一下,然后清除掉downtimer定时器,更换小鸟上升的图片,为小鸟设置一个初速度,设置uptimer定时器,使速度每30ms降低0.7,当速度小于等于0时,清除此uptimer定时器,开启下降定时器。每次调用birdup函数时,需要先清除上一次的uptimer定时器和音乐,以免出现问题。
e.gameover函数 调用时,暂定背景音乐和upbird点击时的音乐,然后播放死亡音乐。清除所有定时器,然后清除鸟的模型,出现游戏结束的提示以及ok按钮,为ok按钮设置一个鼠标事件,点击时,刷新页面,即可重新开始。
通过这次游戏的设计,让我感受到了编程的乐趣,也是第一次设计这种游戏,虽然很简单,但是很有意思,也将学到的js知识得到了应用,虽然还不太熟练,仍然得多加练习!