“是男人就下一百层”h5游戏全网最详细教学、全代码,js操作

简介: “是男人就下一百层”h5游戏全网最详细教学、全代码,js操作

博主的话


  这里博主将展示此游戏的html和js部分的代码,主要是对这些代码的讲解,教大家如何编写这样一个简单的
h5小游戏。希望大家在认真看完博主的文章后,不但能编写“是男人就下一百层”,还可以发散思维,编写更多有
趣的小游戏。
  如果想要跑程序的话,还需要css代码和图片资源;在js里面还用到了jq和lufylegend框架,这是开源的,
大家可以到网上下载。

对于要css代码和img资源的,下载地址:

https://download.csdn.net/download/qq_43592352/12368545

游戏展示


看图说话

游戏初始界面:

image.png

游戏开始:

image.png

编程工具介绍


1’ Google浏览器。
  我是在Google上跑的游戏,如果大家拿我的文件参照的话,尽量用Google。我做的时候没有考虑兼容性
  ,觉得一个小游戏,没必要。
2’VS Code。
  这个没什么要求的,我用的是VS Code,只要可以编html、css、js,什么都可以,个人喜好。
3’JQuery和lufylegend插件。
  简单的说,它们两个也是js文件。只是被封装起来,方便各种功能的调用。
  用的话<script src="js/lufylegend-1.10.1.min.js"></script>
        <script src="js/jquery-3.3.1.js"></script>
    直接在相关的文件里引用就可以了。
4’JQuery介绍
  jq简单来说就是对原生js的简化,使js的使用更加方便快捷。
5’lufylegend介绍
  lufylegend是一种游戏开发引擎,它是通过html的canvas标签来操作的。里面有一些方法很好用,但是,
它的排版和监听和js一比实在是太麻烦,于是我就抛弃了lufylegend。我的js代码只用了lufylegend一点点的
游戏动作封装的函数。
  而且,用lufylegend只是身边正好有一本它的书。个人觉得lufylegend不是最好的游戏引擎。大家对游戏
感兴趣的话,不妨去网上找一些更大众的开源引擎。

游戏代码


<html>
        <link rel="stylesheet" type="text/css" href="css/index.css"/>
        <script src="js/lufylegend-1.10.1.min.js"></script>
        <script src="js/jquery-3.3.1.js"></script>
<body>
<div id="container">
    <div id="game">
        <audio id="player" src=""></audio>
        <div id="info">
            <div id="info_life"></div>
            <div id="info_score">
                <div class="info_score_num"><img src="css/img/0.png"></div>
                <div class="info_score_num"><img src="css/img/0.png"></div>
                <div class="info_score_num"><img src="css/img/0.png"></div>
                <div class="info_score_num"><img src="css/img/0.png"></div>
            </div>
        </div>
        <div id="main">
            <div id="menu">
                <div id="menu_title"><text>是男人就下100层</text></div>
                <div id="menu_hero">
                    <div id="menu_hero1"><img src="css/img/left.png"/></div>
                    <div id="menu_hero2"></div>
                    <div id="menu_hero3"><img src="css/img/right.png"/></div>
                </div>
                <div id="menu_button">
                    <button id="menu_button1">开始游戏</button><br/>
                    <button id="menu_button2">排行榜</button>
                </div>
            </div>
            <div id="gamemain">
                <div id="hero"></div>
                <div id="game_bg2"><img src="css/img/game_bg2.png"></div>
            </div>
            <div id="ranking">
                <text>排行榜</text>
                <div id="rank_table">
                    <dl>
                        <dt>排名</dt>
                        <dd>1</dd>
                        <dd>2</dd>
                        <dd>3</dd>
                        <dd>4</dd>
                        <dd>5</dd>
                    </dl>
                    <dl>
                        <dt>英雄大名</dt>
                        <dd></dd>
                        <dd></dd>
                        <dd></dd>
                        <dd></dd>
                        <dd></dd>
                    </dl>
                    <dl>
                        <dt>层数</dt>
                        <dd></dd>
                        <dd></dd>
                        <dd></dd>
                        <dd></dd>
                        <dd></dd>
                    </dl>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
<script>
    /**************************便捷函数**************************************/
    function getRandom(min,max){//获取在区间[min.max]内的int数
        var s;
        s=parseInt(Math.random()*max+1);
        while(s<min)
        {
        s=parseInt(Math.random()*max+1);
        }
        return s;
    }
    function onIt(hx,hy,fx,fy){
        if(hx<=fx+60&&hx>=fx-32&&hy>=fy-32&&hy<=fy-31)
            return 1;
        else 
            return 0;
    }
    var shansuoTimes=0;
    function shansuo(){//闪烁3次
        shansuoTimes++;
        $('#hero').fadeTo(200,0.1);
        $('#hero').fadeTo(200,1);
        if(shansuoTimes<=3) 
        setTimeout("shansuo()",400);
        else
            shansuoTimes=0;
      }
      function sleep(ms){//时间延迟函数
          return new Promise(resolve =>setTimeout(resolve,ms))
      }
      async function test() {
        console.log('Hello')
        await sleep(1000)
        console.log('world!')
        }
        test();
    /**************************基础页面操作设置**************************************/
    var hero_href=new Array(),hero_href_key=1;
    for(var i=1;i<=15;i++){
        hero_href[i]="css/hero/"+i+".png";
    }
    //js改变网页页面大小
    document.body.style.zoom=.8;
    //控制menu、gamemain、ranking的显示
    $("#menu_button1").click(function(){
        $("#menu").css('display','none');
        $("#gamemain").css('display','block');
        $("#ranking").css('display','none');
        heroDie();
        init(0,"hero",32,32,main);
        check();
        heroDown();
        myfloor();
        displayScore();
        displayLife();
    })
    $("#menu_button2").click(function(){
        $("#menu").css('display','none');
        $("#gamemain").css('display','none');
        $("#ranking").css('display','block');
    })
    //控制英雄的切换
    $("#menu_hero1 img").click(function(){
        if(hero_href_key>1) hero_href_key--;
        heroDie();
        main();
    })
    $("#menu_hero3 img").click(function(){
        if(hero_href_key<15) hero_href_key++;
        heroDie();
        main();
    })
   //分数显示
    var score_pic=new Array('css/img/0.png','css/img/1.png','css/img/2.png','css/img/3.png','css/img/4.png','css/img/5.png','css/img/6.png','css/img/7.png','css/img/8.png','css/img/9.png',);
    var score=0;
    function displayScore(){
        var s=score;
        var score0=s%10;
        var score1=parseInt(s/10)%10;
        var score2=parseInt(s/100)%10;
        var score3=parseInt(s/1000);
        $(".info_score_num img").eq(3).attr('src',score_pic[score0]);
        $(".info_score_num img").eq(2).attr('src',score_pic[score1]);
        $(".info_score_num img").eq(1).attr('src',score_pic[score2]);
        $(".info_score_num img").eq(0).attr('src',score_pic[score3]);
        setTimeout('displayScore()',50);
    }
    //生命条显示
    var deadflag=false;
    function displayLife(){
        isdie();
        $("#info_life").css('width',nowHP*8+'px');
        if(nowHP<=4&&nowHP>0) $("#info_life").css('background','red');
        if(nowHP==0&&deadflag==false) {playMusic(1);deadflag=true;}
        setTimeout('displayLife()',50);
    }
    function playMusic(i) {
        var player = $("#player")[0];
        if(i==1)
        {
            player.src='css/sound/dead.mp3';
            player.play();
        }
    }
    /**************************游戏设置**************************************/
    /***lufylegend框架封装英雄类*****/
    var loader,anime,layer;
    init(50,"menu_hero2",32,32,main);
    function main(){
        loader=new LLoader();
        loader.addEventListener(LEvent.COMPLETE,loadBItmapdata);
        loader.load(hero_href[hero_href_key],"bitmapData");
    }
    function loadBItmapdata(event){
        var bitmapdata=new LBitmapData(loader.content,0,0,64,64);
        var list=LGlobal.divideCoordinate(128,128,4,4);
        layer=new LSprite();
        addChild(layer);
        anime=new LAnimation(layer,bitmapdata,list);
        layer.addEventListener(LEvent.ENTER_FRAME,onframe);
    }
    function onframe(){
        $(document).keydown(function(event){
        if(event.which==39){
            anime.setAction(2);
        }
        else if(event.which==37){
            anime.setAction(1);
        }
        });
        $(document).keyup(function(event){
            anime.setAction(0);
        });
        anime.onframe();
    }
    function heroDie(){
        layer.die();
        layer.removeAllChild();
    }
    /***封装游戏背景类*****/
    var bgHeight=0;
    function background(){
        bgHeight+=2;
        $("#gamemain").css('background','url("css/img/gamemain_bg.png") 0px '+bgHeight+'px');
        if(bgHeight>=550) bgHeight=0;//防止bgHeight过大
        setTimeout('background()',50);
    }
    background();
    /*********封装地板****************/
    function floor(){
        var that=this;
        var img=$(new Image());
        var floorx=Math.random()*370;
        var floory=530;
        this.createFloor1=function(){//地板1类
            img.attr({
                'src':'css/img/floor1.png',
                'class':'floor',
                'relative':0,
                'type':1
            });
            img.css({
                'margin-left':floorx+'px',
                'margin-top':floory+'px',
            });
            $("#gamemain").append(img);
            this.run();
        }
        this.createFloor2=function(){//地板2类
            img.attr({
                'src':'css/img/floor2.png',
                'class':'floor',
                'relative':10,
                'type':1
            });
            img.css({
                'margin-left':floorx+'px',
                'margin-top':floory+'px',
            });
            $("#gamemain").append(img);
            this.run();
        }
        this.createFloor3=function(){//地板3类
            img.attr({
                'src':'css/img/floor3.png',
                'class':'floor',
                'relative':0,
                'type':1
            });
            img.css({
                'margin-left':floorx+'px',
                'margin-top':floory+'px',
            });
            $("#gamemain").append(img);
            this.run();
        }
        this.createFloor4=function(){//地板4类 会消失的地板
            img.attr({
                'src':'css/img/floor4in1.png',
                'class':'floor',
                'relative':0,
                'type':2
            });
            img.css({
                'margin-left':floorx+'px',
                'margin-top':floory+'px',
            });
            $("#gamemain").append(img);
            this.run();
        }
        this.createFloor5=function(){//地板5类 会滚动的地板
            img.attr({
                'src':'css/img/floor5.gif',
                'id':'floor5',
                'class':'floor',
                'relative':0,
                'type':3
            });
            img.css({
                'margin-left':floorx+'px',
                'margin-top':floory+'px',
            });
            $("#gamemain").append(img);
            this.run();
        }
        this.run=function(){
            if(floory>=-20)
            {
                floory-=2;
                img.css('margin-top',floory+'px');
                setTimeout(that.run,20);
            }
            else
            {
                img.css('display','none');
                img.remove();
                score++;
            }
        }
    }
    async function changefloor4($ppp) {//地板4类消失函数
        $ppp.attr('src','css/img/floor4in2.png')
        await sleep(300)
        $ppp.attr("src","css/img/floor4in3.png")
        await sleep(300)
        $ppp.css('display','none');
        $ppp.remove();
        score++;
        ontheFloor=false;heroDown();clearTimeout(up);
        }
    async function floor5Move1(fx){//地板5类左移英雄
        while(position[0]+20>fx){
        $('#hero').css('margin-left',position[0]+'px');
        position[0]-=2;
        await sleep(40);
        }
        ontheFloor=false;heroDown();clearTimeout(up);
    }
function myfloor(){//创建地板
    var ppp=new floor();
    if(getRandom(1,5)==1) ppp.createFloor1();
    else if(getRandom(1,5)==2) ppp.createFloor2();
    else if(getRandom(1,5)==3) ppp.createFloor3();
    else if(getRandom(1,5)==4) ppp.createFloor4();
    else if(getRandom(1,5)==5) ppp.createFloor5();
    setTimeout('myfloor()',500);
}
/*********封装英雄(未封装原因:lufylegend插件已经生成了英雄)****************/
    var position=new Array(0,10);//全局变量,hero的位置坐标
    var maxHP=12,nowHP=12;//全局变量,最大HP,现在HP
    var ontheFloor=false;//全局变量,是否在地板上
    var gspeed=2;//全局变量,英雄下落速度,可随游戏时间增加
    $(document).keydown(function(event){//对英雄移动的键盘操作
            if(event.which==37){
                ((position[0]-3)<0)?position[0]=0:position[0]-=3;
                $("#hero").css('margin-left',position[0]+'px');
            }
            else if(event.which==39){
                ((position[0]+3)>398)?position[0]=398:position[0]+=3;
                $("#hero").css('margin-left',position[0]+'px');
            }
    });
    var down,up,move;
    function heroDown(){//英雄自由下落
        position[1]+=gspeed;
        $("#hero").css('margin-top',position[1]+'px');
        down=setTimeout("heroDown()",20);
    }
    function heroUp(){//英雄随地板上升,此函数与floor类的run函数数值同步
        position[1]-=2;
        $("#hero").css('margin-top',position[1]+'px');
        up=setTimeout("heroUp()",20);
    }
    function isdie(){//对英雄向上触碰、向下掉底直接死亡,设置nowHP=0,然后交给‘生命条显示’函数来做英雄死亡后的事件
        var y=parseInt($("#hero").css('margin-top'));
        if(y>=520||y<=9) nowHP=0;
    }
/************************对是否落到地板上进行判断、处理****************************/
    var StandX;
    function check(){
        var allfloor=$(".floor");
        var n=allfloor.length;
        for(var i=0;i<=n;i++){
            var fx=parseInt(allfloor.eq(i).css("margin-left"));
            var fy=parseInt(allfloor.eq(i).css("margin-top"));
            var relativey=parseInt(allfloor.eq(i).attr("relative"));//将木板的relative值转化为int型
            var type=parseInt(allfloor.eq(i).attr("type"));//将木板的type值转化为int型
            var hx=position[0],hy=position[1];
            if(onIt(hx,hy,fx,fy)&&(ontheFloor==false))
                {
                    ontheFloor=true;
                    clearTimeout(down);
                    position[1]+=relativey;//每个地板加了一个属性relative,是人物相对于木板的距离,方便带刺木板人物位置摆放
                    if(relativey==10) {nowHP--;shansuo();}
                    if(type==2){
                        changefloor4(allfloor.eq(i));
                    }
                    else if(type==3){
                            floor5Move1(fx);
                    }
                    heroUp();
                    StandX=fx;
                }
            if((hx<StandX-32||hx>StandX+60)&&(ontheFloor==true))
                {ontheFloor=false;heroDown();clearTimeout(up);}
        }
        setTimeout("check()",.5);
    }
    /************************对排行榜相关数据处理****************************/
    /*var fso=new XMLHttpRequest(Scripting.FileSystemObject);
    var f=fso.createtextfile("data.txt",2,true);
    f.writeLine("wo shi di yi hang"); */
</script>
</html>

代码讲解


我尽量把讲解的重心放在游戏编程思想和js上面。

首先是html的节点结构。无论是编游戏,还是编网页,编程之前做好html节点的树结构是十分重要的事情。

如图:

image.png

dom结构大概是这样,方便大家搞清关系。

container

这是一个容器div,背景是截图中的那张山水图片。然后我把这个div居中,其他元素都写在container里面。

game

这也是一个容器div,背景如下:

image.png

让game居container的中。

info

这里面会显示生命条和分数。

main

main里面有三个div,这才是核心部分。第一个div是菜单,第二个是游戏主页,第三个是排行榜。

其次是js代码的编写,这是核心。

我们把main的宽高限制在#game(以后的div用#id替代)背景的第三个白色透明框。同样的,#menu,#gamemain,#ranking的宽高也是。

js 第一步 切换div的显示与隐藏


当我们刚开始打开游戏,出现的应该是菜单页面,在点击“开始游戏”“排行榜”之后,会切换到相应的div。即显示相应的div,隐藏其他的div。

//控制menu、gamemain、ranking的显示
    $("#menu_button1").click(function(){
        $("#menu").css('display','none');
        $("#gamemain").css('display','block');
        $("#ranking").css('display','none');
    })
    $("#menu_button2").click(function(){
        $("#menu").css('display','none');
        $("#gamemain").css('display','none');
        $("#ranking").css('display','block');
    })

对相应的按钮点击后,对不同的div进行显示和隐藏。

js 第二步 在菜单页面用lufylegend插件封装英雄


/***lufylegend框架封装英雄类*****/
    var loader,anime,layer;
    init(50,"menu_hero2",32,32,main);
    function main(){
        loader=new LLoader();
        loader.addEventListener(LEvent.COMPLETE,loadBItmapdata);
        loader.load(hero_href[hero_href_key],"bitmapData");
    }
    function loadBItmapdata(event){
        var bitmapdata=new LBitmapData(loader.content,0,0,64,64);
        var list=LGlobal.divideCoordinate(128,128,4,4);
        layer=new LSprite();
        addChild(layer);
        anime=new LAnimation(layer,bitmapdata,list);
        layer.addEventListener(LEvent.ENTER_FRAME,onframe);
    }
    function onframe(){
        $(document).keydown(function(event){
        if(event.which==39){
            anime.setAction(2);
        }
        else if(event.which==37){
            anime.setAction(1);
        }
        });
        $(document).keyup(function(event){
            anime.setAction(0);
        });
        anime.onframe();
    }
    function heroDie(){
        layer.die();
        layer.removeAllChild();
    }

这里值得注意的是:

init(50,"menu_hero2",32,32,main);

此init()方法表示在#menu_hero2为id的div里面建立一个宽高都为32px的canvas标签,整体速度是50ms一次,回调函数是main()。【建议大家去看一下lufylegend的官方API】

在main()函数中有如下代码:

loader.load(hero_href[hero_href_key],"bitmapData");

【划重点!!!】

这里hero_href[hero_href_key]是一个存放我本地英雄图片url的数组。

在main()函数中又调用了loadBItmapdata()函数。loadBItmapdata()函数里有如下代码:

javascriptvar list=LGlobal.divideCoordinate(128,128,4,4);

【划重点!!!】

这是对图片进行分割。长宽都为128px的图片,进行4x4的分割。如下图。这种RPG小游戏的人物图片都是这样的,经过插件封装后会自动循环播放(这里播放速度就和init()函数里面的参数有关啦)。

如果自己用js代码写的话,不一定可以写出来,而且也没有人家的好。

20190507185005530.png

好了,到这里,lufylegend的使命已经结束了,接下来都是js的功劳了。

js 第三步 在菜单页面实现挑选英雄


带大家理清思路。我们要实现的是#menu、#gamemain、#ranking三部分。现在我们已经把#gamemain、
#ranking的display设置为none了,它们消失了,只有#menu存在,所以我们专心做菜单的业务。

大家回到最上方看一下我菜单的样式,css我就不再说了,很简单的。在英雄两边设置了两个按钮来改变英雄的样式。

这个要怎么实现呢?

var hero_href=new Array(),hero_href_key=1;
    for(var i=1;i<=15;i++){
        hero_href[i]="css/hero/"+i+".png";
    }
     //控制英雄的切换
    $("#menu_hero1 img").click(function(){
        if(hero_href_key>1) hero_href_key--;
        heroDie();
        main();
    })
    $("#menu_hero3 img").click(function(){
        if(hero_href_key<15) hero_href_key++;
        heroDie();
        main();
    })

1’定义一个数组hero_href[]用来存放"css/hero/1.png",“css/hero/2.png”……这样的字符,注意我这里的字符就是我用js访问图片的路径,大家要设置好。

2’定义一个hero_href_key。当点击按钮的时候,hero_href_key会加一或者减一。

3’调用heroDie()函数把页面清空,然后再重新调用main(),但是此时的图片url已经改变,所以英雄会相应改变。

js 第四步 在游戏页面生成英雄


这时候菜单页面已经做完了,我们把#menu的display设为none,#gamemain的display设为block。方便调试,
不然每次都要点击一下“开始游戏”按钮。接下来,我们开始做游戏模块!

同样的,在点击“开始游戏”按钮后,插件会清除画布,并在#hero里面生成英雄。这时,init()的参数速度不能为>0,因为多次调用init,它的速度参数会叠加。

//控制menu、gamemain、ranking的显示
 $("#menu_button1").click(function(){
     $("#menu").css('display','none');
     $("#gamemain").css('display','block');
     $("#ranking").css('display','none');
     heroDie();
     init(0,"hero",32,32,main);
 })

定义全局变量,position[0]为英雄的x,position[1]为英雄的y;

监听键盘的左键和右键控制英雄左右移动,并且不可以移出#gamemain之外。

var position=new Array(0,10);//全局变量,hero的位置坐标
$(document).keydown(function(event){//对英雄移动的键盘操作
         if(event.which==37){
             ((position[0]-3)<0)?position[0]=0:position[0]-=3;
             $("#hero").css('margin-left',position[0]+'px');
         }
         else if(event.which==39){
             ((position[0]+3)>398)?position[0]=398:position[0]+=3;
             $("#hero").css('margin-left',position[0]+'px');
         }
 });

js 第五步 在游戏页面制作滚动的背景


/***封装游戏背景类*****/
 var bgHeight=0;
 function background(){
     bgHeight+=2;
     $("#gamemain").css('background','url("css/img/gamemain_bg.png") 0px '+bgHeight+'px');
     if(bgHeight>=550) bgHeight=0;//防止bgHeight过大
     setTimeout('background()',50);
 }
 background();

这里的技巧主要在css的background上,大家不妨去查一下background的参数。首先,我设置background是可以repeat的(没写默认可以),然后再定义y方向上的偏移量。最后每50ms执行一次其y上的偏移量加2。【值得注意的是,虽然背景图片是一张,但是拼接起来要看不出来分界线才行,要不然滚动也没意义】

js 第六步 在游戏页面添加地板!


/*********封装地板****************/
 function floor(){
     var that=this;
     var img=$(new Image());
     var floorx=Math.random()*370;
     var floory=530;
     this.createFloor1=function(){//地板1类
         img.attr({
             'src':'css/img/floor1.png',
             'class':'floor',
             'relative':0,
             'type':1
         });
         img.css({
             'margin-left':floorx+'px',
             'margin-top':floory+'px',
         });
         $("#gamemain").append(img);
         this.run();
     }
     this.createFloor2=function(){//地板2类
         img.attr({
             'src':'css/img/floor2.png',
             'class':'floor',
             'relative':10,
             'type':1
         });
         img.css({
             'margin-left':floorx+'px',
             'margin-top':floory+'px',
         });
         $("#gamemain").append(img);
         this.run();
     }
     this.createFloor3=function(){//地板3类
         img.attr({
             'src':'css/img/floor3.png',
             'class':'floor',
             'relative':0,
             'type':1
         });
         img.css({
             'margin-left':floorx+'px',
             'margin-top':floory+'px',
         });
         $("#gamemain").append(img);
         this.run();
     }
     this.createFloor4=function(){//地板4类 会消失的地板
         img.attr({
             'src':'css/img/floor4in1.png',
             'class':'floor',
             'relative':0,
             'type':2
         });
         img.css({
             'margin-left':floorx+'px',
             'margin-top':floory+'px',
         });
         $("#gamemain").append(img);
         this.run();
     }
     this.createFloor5=function(){//地板5类 会滚动的地板
         img.attr({
             'src':'css/img/floor5.gif',
             'id':'floor5',
             'class':'floor',
             'relative':0,
             'type':3
         });
         img.css({
             'margin-left':floorx+'px',
             'margin-top':floory+'px',
         });
         $("#gamemain").append(img);
         this.run();
     }
     this.run=function(){
         if(floory>=-20)
         {
             floory-=2;
             img.css('margin-top',floory+'px');
             setTimeout(that.run,20);
         }
         else
         {
             img.css('display','none');
             img.remove();
             score++;
         }
     }
 }

首先,我们来封装个地板类。我们把地板的x坐标设为随机,y坐标固定在底部。

然后,不同的createfloor函数,它们的url不同(即图片的样式,是地板还是尖刺还是弹簧……),relative不同(针对尖刺地板,假设图片高是20px,对于一般木板,英雄可以直接站上去,但是带刺的木板,英雄要踩刺,得再往下站一些,所以定义relative相当于木板和英雄的相对距离),type不同(不同类型木板,英雄站上去之后有不同的函数去执行)。

最后,我们让每一个createfloor函数都去执行run函数,来控制木板上升,当木板上升到最上方时,把木板删去,分数+1。

function myfloor(){//创建地板
    var ppp=new floor();
    if(getRandom(1,5)==1) ppp.createFloor1();
    else if(getRandom(1,5)==2) ppp.createFloor2();
    else if(getRandom(1,5)==3) ppp.createFloor3();
    else if(getRandom(1,5)==4) ppp.createFloor4();
    else if(getRandom(1,5)==5) ppp.createFloor5();
    setTimeout('myfloor()',500);
}

每隔0.5秒随机创建五种木板里的一种出来。

js 第七步 定义英雄上升、下降、死亡函数


首先这里面的数值不是随便设置的,不然没有游戏体验的。

封装出英雄上升,下降,死亡函数。

在踩到地板时上升;脚下没有地板时下降,碰到上方的刺或者掉落判断死亡。

var down,up,move;
   function heroDown(){//英雄自由下落
       position[1]+=gspeed;
       $("#hero").css('margin-top',position[1]+'px');
       down=setTimeout("heroDown()",20);
   }
   function heroUp(){//英雄随地板上升,此函数与floor类的run函数数值同步
       position[1]-=2;
       $("#hero").css('margin-top',position[1]+'px');
       up=setTimeout("heroUp()",20);
   }
   function isdie(){//对英雄向上触碰、向下掉底直接死亡,设置nowHP=0,然后交给‘生命条显示’函数来做英雄死亡后的事件
       var y=parseInt($("#hero").css('margin-top'));
       if(y>=520||y<=9) nowHP=0;
   }

js 第八步 英雄与地板开始作用


var StandX;
 function check(){
     var allfloor=$(".floor");
     var n=allfloor.length;
     for(var i=0;i<=n;i++){
         var fx=parseInt(allfloor.eq(i).css("margin-left"));
         var fy=parseInt(allfloor.eq(i).css("margin-top"));
         var relativey=parseInt(allfloor.eq(i).attr("relative"));//将木板的relative值转化为int型
         var type=parseInt(allfloor.eq(i).attr("type"));//将木板的type值转化为int型
         var hx=position[0],hy=position[1];
         if(onIt(hx,hy,fx,fy)&&(ontheFloor==false))
             {
                 ontheFloor=true;
                 clearTimeout(down);
                 position[1]+=relativey;//每个地板加了一个属性relative,是人物相对于木板的距离,方便带刺木板人物位置摆放
                 if(relativey==10) {nowHP--;shansuo();}
                 if(type==2){
                     changefloor4(allfloor.eq(i));
                 }
                 else if(type==3){
                         floor5Move1(fx);
                 }
                 heroUp();
                 StandX=fx;
             }
         if((hx<StandX-32||hx>StandX+60)&&(ontheFloor==true))
             {ontheFloor=false;heroDown();clearTimeout(up);}
     }
     setTimeout("check()",.5);
 }

这算是核心代码了。

解释如下:

1,定义一个check函数,每0.5ms执行一次,一秒2000次。
2,每次都干什么事情呢?
   每次都获取当前页面存在的地板对象,放在一个数组里面。然后用for循环遍历(暴力方式,所以是小游戏,大游戏
   得考虑算法和数据结构优化的)每个对象是不是碰到英雄了,并且ontheFloor这个flag也很重要。
   onIt(hx,hy,fx,fy)函数是我刚开始封装的,判断英雄有没有站在地板上。
3,如果在地板上了,调用heroup函数,控制英雄与地板同步上升。之后开始判断是哪个地板。如果relative==10(带
  刺木板),那么英雄life-1,并且闪烁三次,并且再向下移动10px才行。如果是type==2(会消失的地板),那
  么英雄站上去之后,每隔300ms此地板换一个样式,三次之后木板消失,英雄继续下落。如果是type==3(水平传
  送带),那么……
4,如果英雄脚下没有地板了,那么停止heroup函数,执行herodown。

js 第九步 添加生命条、分数、声音显示


//分数显示
 var score_pic=new Array('css/img/0.png','css/img/1.png','css/img/2.png','css/img/3.png','css/img/4.png','css/img/5.png','css/img/6.png','css/img/7.png','css/img/8.png','css/img/9.png',);
 var score=0;
 function displayScore(){
     var s=score;
     var score0=s%10;
     var score1=parseInt(s/10)%10;
     var score2=parseInt(s/100)%10;
     var score3=parseInt(s/1000);
     $(".info_score_num img").eq(3).attr('src',score_pic[score0]);
     $(".info_score_num img").eq(2).attr('src',score_pic[score1]);
     $(".info_score_num img").eq(1).attr('src',score_pic[score2]);
     $(".info_score_num img").eq(0).attr('src',score_pic[score3]);
     setTimeout('displayScore()',50);
 }
 //生命条显示
 var deadflag=false;
 function displayLife(){
     isdie();
     $("#info_life").css('width',nowHP*8+'px');
     if(nowHP<=4&&nowHP>0) $("#info_life").css('background','red');
     if(nowHP==0&&deadflag==false) {playMusic(1);deadflag=true;}
     setTimeout('displayLife()',50);
 }
 function playMusic(i) {
     var player = $("#player")[0];
     if(i==1)
     {
         player.src='css/sound/dead.mp3';
         player.play();
     }
 }

分数显示:

我的分数是用图片显示的。就是获取score后,得到个、十、百、千位的值,然后对应我的数字(艺术字样式)的图片显示出来。和之前英雄的显示类似。

生命条显示:

我把生命分成12份,每少1,生命条的宽度小8.3%,当nowHP小于4,设置生命条颜色为红色。

声音:

当nowHP为0,执行声音函数,播放死亡的音效。

js 第十步 排行榜


排行榜,我有三种方法去实现。但是我这个游戏也不是多人玩的,不想做排行榜。

方法介绍给大家:

1,运用php+mysql。

用php写好之后,把获取的值转递给页面,页面来显示。

但是,php文件必须在xampp目录下才可以运行,意味着,我要把html、js文件都移过去。麻烦。

2,运用txt文本。

大家学c的时候,一定操作过用c来对txt流进行读和写吧。

就是这种思想。

第一,每次游戏结束后,你要对玩家的姓名和分数进行写入。

第二,每次打开排行榜,你要读取txt文本,获取值。因为txt文本的特性,所以读取之后你要进行数据提取稍微麻烦一点点(相信大家领会我的意思)。

3,用js/json文件,存数据。

但是好像只能读不能写。

进行下一个游戏的开发!


飞机大战h5小游戏开发

指尖大冒险、跳一跳升级版html5游戏全代码

总结


虽然引用了一些框架,但是都是浅尝辄止。而且对英雄和地板的判断那一块,都是靠for循环,和时间函数来暴力执行(一秒2000次,我都害怕)。所以多看点算法,数据结构,框架还是很重要的,可以进行代码的优化,使其效率更高、更准确。

继承也是一个很重要的地方。比如地板,我本可以定义一个父类,然后对每种类型的地板进行继承父类,然后重写函数,不但节约代码,效率也高。但是我看了找js的书,也没有找到一种好的办法来继承(因为floor里面还有一个Image对象,我其实操作的是Image对象,但是Image对象是不可以编写定义的),所以只好把所有的地板都放在一个类中,用不同的函数名来区分。


相关文章
|
25天前
|
JavaScript
短小精悍的js代码
【10月更文挑战第17天】
120 58
|
1月前
|
JavaScript 前端开发 开发者
如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 来检查代码规范并自动格式化 Vue.js 代码。
【10月更文挑战第7天】随着前端开发技术的快速发展,代码规范和格式化工具变得尤为重要。本文介绍了如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 来检查代码规范并自动格式化 Vue.js 代码。通过安装和配置这两个工具,可以确保代码风格一致,提升团队协作效率和代码质量。
221 2
|
12天前
|
JavaScript
原生js炫酷随机抽奖中奖效果代码
原生js随机抽奖是一个炫酷的根据数据随机抽奖的代码,该网页可进行随机抽取一个数据,页面动画高科技、炫酷感觉的随机抽奖效果,简单好用,欢迎下载!
29 3
原生js炫酷随机抽奖中奖效果代码
|
10天前
|
移动开发 前端开发 JavaScript
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
于辰在大学期间带领团队参考网易游戏官网的部分游戏页面,开发了一系列前端实训作品。项目包括首页、2021校园招聘页面和明日之后游戏页面,涉及多种特效实现,如动态图片切换和人物聚合效果。作品源码已上传至CSDN,视频效果可在CSDN预览。
17 0
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
|
17天前
|
JavaScript 前端开发 开发者
如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查代码规范并自动格式化 Vue.js 代码,包括安装插件、配置 ESLint 和 Prettier 以及 VSCode 设置的具体步骤
随着前端开发技术的快速发展,代码规范和格式化工具变得尤为重要。本文介绍了如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查代码规范并自动格式化 Vue.js 代码,包括安装插件、配置 ESLint 和 Prettier 以及 VSCode 设置的具体步骤。通过这些工具,可以显著提升编码效率和代码质量。
174 4
|
19天前
|
JSON 移动开发 数据格式
html5+css3+js移动端带歌词音乐播放器代码
音乐播放器特效是一款html5+css3+js制作的手机移动端音乐播放器代码,带歌词显示。包括支持单曲循环,歌词显示,歌曲搜索,音量控制,列表循环等功能。利用json获取音乐歌单和歌词,基于html5 audio属性手机音乐播放器代码。
69 6
|
15天前
|
JavaScript 前端开发 开发者
如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查代码规范并自动格式化 Vue.js 代码
随着前端开发技术的快速发展,代码规范和格式化工具变得尤为重要。本文介绍如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查代码规范并自动格式化 Vue.js 代码。通过安装和配置这些工具,可以确保代码风格一致,提高代码质量和可读性。
45 1
|
1月前
|
JavaScript 前端开发 开发者
如何在 VSCode 中使用 ESLint 和 Prettier 检查并自动格式化 Vue.js 代码,提升团队协作效率和代码质量。
【10月更文挑战第9天】随着前端开发技术的发展,代码规范和格式化工具变得至关重要。本文介绍如何在 VSCode 中使用 ESLint 和 Prettier 检查并自动格式化 Vue.js 代码,提升团队协作效率和代码质量。通过安装插件、配置 ESLint 和 Prettier,以及设置 VSCode,实现代码实时检查和格式化,确保代码风格一致。
27 2
|
1月前
|
JavaScript 前端开发 开发者
如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查并自动格式化 Vue.js 代码,提升代码质量和团队协作效率。
【10月更文挑战第8天】本文介绍了如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查并自动格式化 Vue.js 代码,提升代码质量和团队协作效率。通过安装 VSCode 插件、配置 ESLint 和 Prettier,实现代码规范检查和自动格式化,确保代码风格一致,提高可读性和维护性。
68 2