zoukankan      html  css  js  c++  java
  • js实现魂斗罗版的棍子英雄小游戏ContraHero

    一直想用canvas写一个魂斗罗游戏,但是发现自己水平和学习能力差太多,收集好素材之后发现一个棍子英雄的小游戏挺火,就产生了写本文这个游戏的想法。直接上demo,建议在chrome下:点我。

    简单说下写这个小游戏遇到的2个坑爹问题:

    1.之前下的素材music.mp3这个文件,其实是3段音频。最后几秒是魂斗罗结束时的音乐,我想在结束的时候直接从调用最后几秒的音频。查了一下audio,很容易找到了audio的currentTime这个属性可以设置音频的播放位置。但是我本地测试的过程中,这个属性是一直不起作用的。后来百度(百度根本不好用),谷歌了半天才在stackoverflow上找到了一段描述,大概的意思就是需要一个sever环境,然后把测试环境放到了服务器环境就可以正常使用currentTime这个属性设置音频的播放起始位置了,一个大坑。

    2.第二个大坑平时写transition的时候习惯的将transition-property写为all。比如transition:all 0s ease 0s;。在这个游戏中,当鼠标松开的时候棍子应该是以100% 100%的位置为远点进行旋转的。由于我写的是all,所以transfor-origin也产生了一个从默认的50% 50%到100% 100%的一个过渡过程,反应在页面上就是棍子开始明显转动的远点不是100% 100%的位置,但是动画完成到100%的时候原点是正确的。

     剩下的就是逻辑实现,本来是想做到自适应和重置游戏的,最后多少都有点不足,重置游戏直接用刷新页面的暴力方式来解决了。页面有很多bug,不行就刷一次,哈哈。

    直接上代码:

    html部分:

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>Child'sPlay</title>
        <link href="style/style.css" rel="stylesheet" type="text/css"/>
    </head>
    <body>
    <div class="main" id="main">
        <div id="score">当前得分<i class="current">0</i>分;最高得分<i class="top">0</i></div>
        <div class="bg">
            <div class="move" id="move">
                <div class="game-box" id="game_box">
                    <div class="contra" id="contra"></div>
                    <div class="item" style="left: 0;">
                        <div class="land"><div class="stick" id="stick"></div> </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="loading">
        <progress id="progress" value="0" max="8"></progress>
        <h3>游戏方法:按住鼠标让棍子变长,使其放下的时候正好落入下一块陆地时放开鼠标。</h3>
    </div>
    <div class="begin">
        <h3><i></i><i></i><i></i><i></i><i>J</i><i></i><i></i><i></i><i></i></h3>
    </div>
    <audio id="audio">
        <source src="audio/start.mp3" type="audio/mpeg"/>
    </audio>
    <audio id="audio2">
        <source src="audio/music.mp3" type="audio/mpeg"/>
    </audio>
    <audio id="audio3">
        <source src="audio/Game_Over.mp3" type="audio/mpeg"/>
    </audio>
    <script src="js/jquery-1.11.1.min.js"></script>
    <script src="js/contra.js"></script>
    <script src="js/source.js"></script>
    <script src="js/record.js"></script>
    </body>
    </html>

    css代码:

    *{ margin: 0; padding: 0;}
    body{ overflow: hidden;}
    .loading{ position: absolute; left: 0; top: 0; right: 0; bottom: 0; z-index: 2; background: #000;}
    #progress{  100%; height: 200px;border: 1px solid #0064B4;background-color:#e6e6e6;}
    progress::-webkit-progress-bar { background: #e6e6e6; }
    progress::-webkit-progress-value  { background: #0064B4; }
    .loading h3{ text-align: center; color: #fff;}
    
    .begin{ position: absolute;  100%; background: url("img/begin.jpg") 0 0 no-repeat; z-index: 3;}
    .begin h3{ display: none; position: absolute; left: 0; top: 20px;  100%; text-align: center; color: #fff;}
    .begin h3 i{
        -webkit-animation: slide_letters 1.8s linear 1s infinite;
        -moz-animation: slide_letters 1.8s linear 1s infinite;
        -ms-animation: slide_letters 1.8s linear 1s infinite;
        animation: slide_letters 1.8s linear 1s infinite}
    .main{ position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden;}
    #score{ position: absolute; left: 0; top: 50px;  100%; text-align: center; color: #fff;}
    #score i{ color: red;}
    .main .bg{ background: url("img/bg.png") 0 0 repeat-x;}
    .land{ position: relative; float: left; background: url("img/land.png") 0 0 no-repeat; background-size: 100% 100%;}
    .move{ position: relative; left: 0;}
    .game-box{ position: fixed; bottom: 5%;  99999px;}
    .game-box .item{ position: absolute; top: 0;}
    #audio{ display: none; position: fixed; right: 20px; top: 20px;}
    .contra{ background: url("img/contra.png");  97px; height: 109px; position: absolute; left: 0; bottom: 65%; z-index: 9;}
    .stick{ position: absolute; right: 0; bottom: 65%;  2px; background: gold; z-index: 99;}
    .rolling{ transition: transform 1s ease-in 0s;transform-origin:center bottom; -webkit-transform-origin:center bottom; -webkit-transform: rotate(90deg); transform: rotate(90deg); }
    
    .run{  87px; height: 110px; background: url("img/run.png") 0px center no-repeat; overflow: hidden;-webkit-animation:run 1s steps(8) infinite;animation:run 1s steps(8) infinite;}
    
    @-webkit-keyframes run{
        100%{background-position: -696px 0px;}
    }
    @keyframes run{
        100%{background-position: -696px 0px;}
    }
    
    .begin h3 i:nth-child(1) {
        -webkit-animation-delay: 0.2s;
        -moz-animation-delay: 0.2s;
        -ms-animation-delay: 0.2s;
        animation-delay: 0.2s;
    }
    
    .begin h3 i:nth-child(2) {
        -webkit-animation-delay: 0.4s;
        -moz-animation-delay: 0.4s;
        -ms-animation-delay: 0.4s;
        animation-delay: 0.4s;
    }
    
    .begin h3 i:nth-child(3) {
        -webkit-animation-delay: 0.6s;
        -moz-animation-delay: 0.6s;
        -ms-animation-delay: 0.6s;
        animation-delay: 0.6s;
    }
    .begin h3 i:nth-child(4) {
        -webkit-animation-delay: 0.8s;
        -moz-animation-delay: 0.8s;
        -ms-animation-delay: 0.8s;
        animation-delay: 0.8s;
    }
    .begin h3 i:nth-child(5) {
        -webkit-animation-delay: 1s;
        -moz-animation-delay: 1s;
        -ms-animation-delay: 1s;
        animation-delay: 1s;
    }
    .begin h3 i:nth-child(6) {
        -webkit-animation-delay: 1.2s;
        -moz-animation-delay: 1.2s;
        -ms-animation-delay: 1.2s;
        animation-delay: 1.2s;
    }
    .begin h3 i:nth-child(7) {
        -webkit-animation-delay: 1.4s;
        -moz-animation-delay: 1.4s;
        -ms-animation-delay: 1.4s;
        animation-delay: 1.4s;
    }
    .begin h3 i:nth-child(8) {
        -webkit-animation-delay: 1.6s;
        -moz-animation-delay: 1.6s;
        -ms-animation-delay: 1.6s;
        animation-delay: 1.6s;
    }
    .begin h3 i:nth-child(9) {
        -webkit-animation-delay: 1.8s;
        -moz-animation-delay: 1.8s;
        -ms-animation-delay: 1.8s;
        animation-delay: 1.8s;
    }
    @-webkit-keyframes slide_letters {
        0%,50% { color: #fff; }
        25% { color: red;}
    }
    @-moz-keyframes slide_letters {
        0%,50% { color: #fff; }
        25% { color: red;}
    }
    
    @-ms-keyframes slide_letters {
        0%,50% { color: #fff; }
        25% { color: red;}
    }
    @keyframes slide_letters {
        0%,50% { color: #fff; }
        25% { color: red;}
    }
    

     进度条加载source.js

    var gameSource = {
        "bg":"style/img/bg.png",
        "contra":"style/img/contra.png",
        "land":"style/img/land.png",
        "run":"style/img/run.png",
        "begin":"style/img/begin.jpg"
    };
    
    var loadNum = 0;
    
    function loading(){
        for(i in gameSource){
            var obj = new Image();
            obj.src = gameSource[i];
            //console.log(gameSource[i])
            obj.onload = function(){
                console.log(this.src+"   completed");
                //gameSource.splice(i,1);
                loadNum++;
                $("#progress").attr({"value":loadNum});
            };
        }
    }
    loading()
    
    var matchState = [1,1,1];
    function checkState(){
        var audioReadyState = [$("#audio")[0].readyState,$("#audio2")[0].readyState,$("#audio3")[0].readyState];
        if(loadNum==8){
            $("#progress").attr({"value":loadNum});
            clearInterval(checkStateTimer);
            contraHero.begin();
            $("#audio")[0].play();
        }
    
        for(var i=0; i<audioReadyState.length;i++){
            if(audioReadyState[i]==4 && matchState[i]){
                matchState[i] = 0;
                console.log("test",i,audioReadyState,matchState)
                loadNum++;
                console.log(audioReadyState);
            }
        }
    }
    var checkStateTimer = setInterval(checkState,1000);
    
    //var a = [];
    //alert(~a); // -1
    //alert(+a); // 0
    //alert(++a); // 1
    //alert(!a); // false
    

     localStorage保存得分记录

    if(localStorage.TopScore){
        $("#score .top").html(localStorage.TopScore);
    }
    function writeTopScore(score){
        if(!localStorage.TopScore || score > localStorage.TopScore){
            localStorage.TopScore = score;
            $("#score .top").html(localStorage.TopScore);
        }
    }
    

     contraHero主体逻辑代码

    var contraHero = {
        canPlay : false,
        isOn:false,//标记按住鼠标
        dom : {
            contra : $("#contra"),
            stick : $("#stick"),
            main : $("#main"),
            bg : $(".bg"),
            move : $("#move"),
            gameBox : $("#game_box"),
            audio : $("#audio"),
            audio2 : $("#audio2"),
            item : $("#game_box .item")
        },
        data : {
            landWidth : 0, //适配后一个陆地的宽度
            landHeight :0 , //适配后一个陆地的高度
            stickHeight:0, //棍子长度
            stickLong : "", //棍子边长定时器
            currentItem : 0, //魂斗罗当前所在的item索引
            itemPosition : [[0,1]]  //每片陆地的left值和对应的陆地数
        },
        init : function(){
            this.initEvent();
            this.initUnit();
            this.makeNextLand();
            this.mainTitle();
        },
        //getLastPositionLeft : function(){
        //    var n = contraHero.data.itemPosition.length-1;
        //    return contraHero.data.itemPosition[n][0] + contraHero.data.itemPosition[n][1]*contraHero.data.landWidth;
        //},
        makeNextLand : function(){
            var left = parseInt(Math.random()*500) + contraHero.data.itemPosition[contraHero.data.itemPosition.length-1][1] * contraHero.data.landWidth
                    + contraHero.data.itemPosition[contraHero.data.itemPosition.length-1][0];
    
            console.log(contraHero.data.itemPosition[contraHero.data.itemPosition.length-1][1] * contraHero.data.landWidth,contraHero.data.itemPosition[contraHero.data.itemPosition.length-1][0],left,"left")
            var landNo = parseInt(Math.random()*3)+1;
            contraHero.data.itemPosition.push([left,landNo]);
            var str = '';
            for(var i=0;i<contraHero.data.itemPosition[contraHero.data.itemPosition.length-1][1];i++){
                str +='<div class="land" style="'+contraHero.data.landWidth+'px;height:'+contraHero.data.landHeight+'px;">'+'</div>';
            };
            str ='<div class="item" style="left:'+contraHero.data.itemPosition[contraHero.data.itemPosition.length-1][0]+'px;height:'+contraHero.data.landHeight+'px;">'+str+'</div>';
            contraHero.dom.gameBox.append(str);
        },
        increase : function(){
            if(contraHero.isOn){
                contraHero.data.stickLong = setInterval(function(){
                    contraHero.data.stickHeight +=3;
                    $("#stick").css({"height":contraHero.data.stickHeight+"px"})
                },20)
            }
        },
        initEvent : function(){
            $(window).mousedown(function(){
                contraHero.isOn = true;
                contraHero.data.stickHeight = 0;
                contraHero.increase()
            });
            $(window).mouseup(function(){
                contraHero.isOn = false;
                contraHero.data.stickHeight = $("#stick").height();
                clearInterval(contraHero.data.stickLong);
                contraHero.putDownStick();
            });
            $(window).resize(function(){
                contraHero.initEvent();
                contraHero.initUnit();
            });
        },
        initUnit : function(){
            var screenHeight = contraHero.dom.main.height();
            var ratio = screenHeight/489;
            var bgSizeWidth = parseInt(1284*ratio);
            contraHero.data.landWidth = parseInt(34*ratio);
            contraHero.data.landHeight = parseInt(122*ratio);
            var gameBoxHeight = contraHero.dom.gameBox.height();
            contraHero.dom.bg.css({"background-size":bgSizeWidth+"px "+screenHeight+"px","height":screenHeight+"px"});
            $(".land").css({"width":contraHero.data.landWidth+"px","height":contraHero.data.landHeight+"px"});
            contraHero.dom.gameBox.css({"height":contraHero.data.landHeight+"px"});
            $(".begin").css({"background-size":"100% "+screenHeight+"px","height":screenHeight+"px","left":"100%"});
            contraHero.begin();
        },
        check : function(){
            var min = contraHero.data.itemPosition[contraHero.data.currentItem+1][0] - contraHero.data.itemPosition[contraHero.data.currentItem][0]
                    - contraHero.data.itemPosition[contraHero.data.currentItem][1] * contraHero.data.landWidth;
            var max = min + contraHero.data.itemPosition[contraHero.data.currentItem+1][1] * contraHero.data.landWidth;
            console.log(contraHero.data.currentItem,min,max,contraHero.data.stickHeight)
            if(contraHero.data.stickHeight >=min && contraHero.data.stickHeight <= max){
                return true;
            }else{
                return false;
            }
        },
        begin: function () {
            $(".begin").css({"background-size":"100% "+screen.height+"px","height":screen.height+"px","left":"100%"});
            $(".begin").animate({"left":"0"},6400,function(){
                $(".loading").remove();
                $(".begin h3").show();
                $(document).on("keyup",function(e){
                    e = e || window.e;
                    if(e.keyCode==74){
                        console.log("testet")
                        $(".begin").remove();
                        contraHero.init();
                        console.log("j")
                        $(document).off("keyup");
                    }
                })
            });
        },
        moveScreen : function(n){
            var distance = -contraHero.data.itemPosition[n][0]
            contraHero.dom.move.animate({"left":distance+"px"});
            contraHero.dom.bg.animate({backgroundPositionX:distance});
        },
        mainTitle:function(){
            contraHero.dom.audio2[0].play();
            contraHero.loopMainTitleTimer = setInterval(this.checkMainTitle,1000);
        },
        checkMainTitle:function(){
            var curTime = contraHero.dom.audio2[0].currentTime;
            contraHero.dom.audio2[0].play();
            if(curTime-64>=0){
                contraHero.dom.audio2[0].load();
            };
        },
        overMusic :function(){
            //contraHero.dom.audio2[0].pause();
            //contraHero.dom.audio2[0].currentTime = 140;
            //contraHero.dom.audio2[0].play();
            $("#audio3")[0].play();
        },
        putDownStick : function(){
            $("#stick").addClass("rolling");
            setTimeout(this.run,1000);
        },
        contraFixPosition : function(){
            contraHero.dom.contra.animate({"left":contraHero.data.itemPosition[contraHero.data.currentItem][0] + contraHero.data.itemPosition[contraHero.data.currentItem][1] * contraHero.data.landWidth -70 +"px"});
            console.log(contraHero.data.itemPosition[contraHero.data.currentItem][0],contraHero.data.itemPosition[contraHero.data.currentItem][1],"fix")
        },
        run : function(){
            contraHero.dom.contra.addClass("run");
            console.log(parseInt(contraHero.dom.contra.css("left")),contraHero.data.stickHeight,"wtf")
            contraHero.dom.contra.animate({"left":parseInt(contraHero.dom.contra.css("left"))+contraHero.data.stickHeight+"px"},5*contraHero.data.stickHeight,function(){
                if(contraHero.check()){
                    contraHero.data.currentItem++;
                    $("#score .current").html(contraHero.data.currentItem);
                    writeTopScore(contraHero.data.currentItem);
                    contraHero.contraFixPosition();
                    contraHero.moveScreen(contraHero.data.currentItem);
                    $("#stick").remove();
                    contraHero.dom.contra.removeClass("run");
                    contraHero.makeNextLand();
                    contraHero.dom.gameBox.find(".item").eq(contraHero.data.currentItem).find(".land:last").html('<div class="stick" id="stick"></div>');
                }else{
                    //contraHero.dom.contra.removeClass("run");
                    //
                    //contraHero.reset();
                    //contraHero.init();
                    contraHero.killMusic();
                    contraHero.overMusic();
                    $("#stick").css({"transform":"rotate(180deg)"});
                    $("#contra").animate({"top":"1000px"},7000,function(){
                        location.reload();
                    });
    
                }
    
            })
        },
        killMusic:function(){
            $("#audio")[0].pause();
            $("#audio2")[0].pause();
            $("#audio3")[0].pause();
            clearInterval(contraHero.loopMainTitleTimer);
        },
        reset : function(){
            contraHero.dom.contra.siblings(".item:gt(0)").remove();
            $("#stick").removeClass("rolling").removeAttr("style");
            contraHero.dom.contra.removeAttr("style");
            contraHero.dom.bg.css({"background-position-x":"0"});
            contraHero.dom.move.removeAttr("style");
            contraHero.data.stickHeight = 0;
            contraHero.data.itemPosition = [[0,1]];
    
        }
    }
    

    最后附上下载包,渣代码,见笑。ContraHero

  • 相关阅读:
    简单复利计算java板
    弹出提示框的方式——java
    实验一 命令解释程序
    简单复利计算c语言实现
    操作系统
    jsp 页面和 jsp标记
    对it行业的一些看法
    又穷自动机的构造
    复利计算——结对编程2.0
    汉堡包
  • 原文地址:https://www.cnblogs.com/childsplay/p/4184804.html
Copyright © 2011-2022 走看看