如何在HTML 5 JS Canvas足球点球游戏中每次拍摄后设置延迟

时间:2016-06-19 18:12:07

标签: javascript html5 canvas

我正在尝试使用HTML5 / JS Canvas制作一个简单的足球罚球游戏。目标是制作一个控制守门员的游戏,你有三次尝试拯救球。

我完成了大部分功能,我有一个分数系统和碰撞检测。

我的问题是,在球被击中后,反馈文本只会出现一瞬间,它会重置我的画布,为下一次点球尝试做好准备。

有什么建议吗?我尝试使用setTimeout()来延迟它,但它仍然不起作用。

由于

 <html>
<head>
    <meta charset="utf-8" />
    <title>Phantom football</title>
    <style>
        * { padding: 0; margin: 0; }
        #myCanvas { 
            background: url('http://i754.photobucket.com/albums/xx182/rache_R/Phantom-Football_Title-v1_zpsuj9jgu27.jpg');
            display: block; 
        }

    </style>
</head>
<body>

<canvas id="myCanvas" width="300" height="250"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.5/TweenMax.min.js"></script>
<script>



var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext("2d");

//Sets the original position of the ball
var x = canvas.width/2;
var y = 20;

// Defines  values that will be added to the position of x and y values
// List of possible values for the x position
var x_options = [2.4, 2, 1.4, 1, 0.4, 0, -0.5, -1, -1.5, -2, -2.5, -3, -2.4];

// Gets a random value from the x_options array
var dx = -2.4;
var dy = 5;

var ballRadius = 10;

// Defines the height and width of the goal
var goal_height = 40;
var goal_width = 200


// Defines the height, width and position of goalie
var goalieHeight = 20;
var goalieWidth = 40;
var goalieX = (canvas.width-goalieWidth)/2;
var goalieY = (canvas.height - goal_height) - 30;

// Set to false by default
var rightPressed = false;
var leftPressed = false;

// Set default values for score and number of attempts left
var goalkeeper_blocked = 0;
var goalkeeper_missed = 0;
var attempts_left = 3;


var footBall = {

     // is a shot in progress
    isShooting:false,

    // time when next shot will run
    nextShotTime:0,

    // delay until next shot will run
    delayUntilNextShot:3000,

    // is the game currently running
    inGame : false,

    shapes : {
        ball: function (){
            ctx.beginPath();
            ctx.arc(x, y, ballRadius, 0, Math.PI*2, false);
            ctx.fillStyle = "red";
            ctx.fill();
            ctx.closePath();

        },

        goal : function (){
            ctx.beginPath();
            ctx.rect((canvas.width - goal_width) / 2 , canvas.height - goal_height, goal_width, goal_height);
            ctx.strokeStyle = "#000000";
            ctx.stroke();
            ctx.closePath();
        },

        goalie : function(){
            ctx.beginPath();
            ctx.rect(goalieX, goalieY, goalieWidth, goalieHeight);
            ctx.fillStyle = "#666666";
            ctx.fill();
            ctx.closePath();
        },

        score : function(){
            ctx.font = "16px Arial";
            ctx.fillStyle = "#ffffff";
            ctx.fillText("Saved: "+goalkeeper_blocked, 8, 20);
        },

        missedScore : function(){
            ctx.font = "16px Arial";
            ctx.fillStyle = "#ffffff";
            ctx.fillText("Missed: "+goalkeeper_missed, 8, 40);
        },

        attempts : function(){
            ctx.font = "16px Arial";
            ctx.fillStyle = "#ffffff";
            ctx.fillText("Attempts left: "+attempts_left, canvas.width-110, 20);
        },

        missedBallMessage : function(){
            ctx.font = "16px Arial";
            ctx.fillStyle = "#ffffff";
            ctx.fillText("You missed the ball! Attempts left : " +attempts_left, 20, canvas.height / 2);
        },

        savedBallMessage : function(){
            ctx.font = "16px Arial";
            ctx.fillStyle = "#ffffff";
            ctx.fillText("You saved the ball! Attempts left : " +attempts_left, 20, canvas.height / 2);

        },

        gameOverLoserMessage : function(){
            ctx.font = "16px Arial";
            ctx.fillStyle = "#ffffff";
            ctx.fillText("GAME OVER! You Lose!" , 20, canvas.height / 2);
        },

        gameOverWinnerMessage : function(){
            ctx.font = "16px Arial";
            ctx.fillStyle = "#ffffff";
            ctx.fillText("GAME OVER! You Win" , 20, canvas.height / 2);
        }

    },

    controls : {
        keyDownHandler : function (e){
            if(e.keyCode == 39) {
                rightPressed = true;
            }
            else if(e.keyCode == 37) {
                leftPressed = true;
            }

        },

        keyUpHandler : function(e){
            if(e.keyCode == 39) {
                rightPressed = false;
            }
            else if(e.keyCode == 37) {
                leftPressed = false;
            }

        },

        mouseMoveHandler : function(e){
            var relativeX = e.clientX - canvas.offsetLeft;
            if(relativeX > 0 && relativeX < canvas.width) {
                goalieX = relativeX - goalieWidth/2;
            }
        }

    },

    calculateScore : function(){
        if(goalkeeper_missed > goalkeeper_blocked){
            footBall.shapes.gameOverLoserMessage();
            document.location.reload();

        } else {
            footBall.shapes.gameOverWinnerMessage();
            document.location.reload();
        }
    },


    resetShapePositions : function(){
        //Sets the original position of the ball
        x = canvas.width/2;
        y = 20;

        // Sets a new shooting path
        dx = x_options[Math.floor(Math.random() * x_options.length)];
        dy = 5;

        // Resets the goalie to the middle
        goalieX = (canvas.width-goalieWidth)/2;

    },

    drawField: function(){
        // This ensures that the ball doesn't leave a trail
        // Clears the canvas of shapes each frame
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // Draws shapes on the canvas
        footBall.shapes.ball();
        footBall.shapes.goal();
        footBall.shapes.goalie();
        footBall.shapes.score();
        footBall.shapes.missedScore();
        footBall.shapes.attempts();
    },


    draw : function(currentTime){

        //   makes paddle move left and right and only within the canvas
        if(rightPressed && goalieX < canvas.width-goalieWidth) {
            goalieX += 7;
        }
        else if(leftPressed && goalieX > 0) {
          goalieX -= 7;
        }

        // draw the scene
        footBall.drawField();

        // delay until next shot time is due 
        if(!footBall.isShooting){
            // time has elapsed, let's shoot again
            if(currentTime>footBall.nextShotTime){
                console.log("Shot time delay " + footBall.nextShotTime);
                footBall.isShooting=true;
            }else{
                // time has not elapsed, just request another loop
                requestAnimationFrame(footBall.draw);
                return;
            }
        }

        // adds values to the balls  x and y position every frame
        x += dx;
        y += dy;



        // Ball hits the goal 
        if(y + dy > canvas.height - goal_height) {

            // end the shot
            footBall.isShooting=false;
            // delay the next shot
            footBall.nextShotTime=currentTime+footBall.delayUntilNextShot;


            attempts_left--;
            goalkeeper_missed++;
            if (!attempts_left){
                footBall.calculateScore();
            } 
            else {


                footBall.shapes.missedBallMessage();

                footBall.resetShapePositions();
            }



        } // Ball saved by goalie
        else if (x  > goalieX && x  < goalieX + goalieWidth && y + dy > goalieY - ballRadius){
            // end the shot
            footBall.isShooting=false;
            // delay the next shot
            footBall.nextShotTime=currentTime+footBall.delayUntilNextShot;

            attempts_left--;
            goalkeeper_blocked++;

            if (!attempts_left){
                footBall.calculateScore();
            } 
            else {
                footBall.shapes.savedBallMessage();
                footBall.resetShapePositions();

            }


        } 

        requestAnimationFrame(footBall.draw);       
    }


}

TweenMax.from("#myCanvas", 0.5, {opacity: 0, scale: 0, ease: Bounce.easeOut});



var hideIntro = function (e) {
    if(e.keyCode == 32 && footBall.inGame == false) {
        document.getElementById('myCanvas').style.background = '#a5bd7b';
        console.log("hide");
        requestAnimationFrame(footBall.draw);
        footBall.nextShotTime = footBall.delayUntilNextShot;
        footBall.inGame = true;
    }
};



document.addEventListener("keydown", hideIntro, false);

// Defines what functions are fired when keydown or keyup event triggers
document.addEventListener("keydown", footBall.controls.keyDownHandler, false);
document.addEventListener("keyup", footBall.controls.keyUpHandler, false);
document.addEventListener("mousemove", footBall.controls.mouseMoveHandler, false);

</script>

</body>
</html>

1 个答案:

答案 0 :(得分:1)

以下是如何在下次尝试开始前向用户显示最后的结果。

提示:由于您已经运行了requestAnimationFrame循环,因此您可以使用rAF来处理上次结果通知的时间。

  • 创建一个footBall.lastResult属性,其中包含上次尝试的结果(&#34;目标&#34;或&#34;已阻止&#34;)。在第一次尝试之前设置football.lastResult=''以指示之前没有结果。

  • 添加仅在footBall.shapes.showLastResult为false时显示football.lastResult的{​​{1}}方法。

示例代码和演示:

&#13;
&#13;
football.isShooting
&#13;
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext("2d");

//Sets the original position of the ball
var x = canvas.width/2;
var y = 50;

// Defines  values that will be added to the position of x and y values
// List of possible values for the x position
var x_options = [3.5, 3, 2.5, 2, 1.5, 1, 0.5, 0, -0.5, -1, -1.5, -2, -2.5, -3, -3.5];

// Gets a random value from the x_options array
var dx = x_options[Math.floor(Math.random() * x_options.length)];
var dy = 5;

var ballRadius = 10;

// Defines the height and width of the goal
var goal_height = 40;
var goal_width = 200

// Defines the height, width and position of goalie
var goalieHeight = 20;
var goalieWidth = 40;
var goalieX = (canvas.width-goalieWidth)/2;
var goalieY = (canvas.height - goal_height) - 30;

// Set to false by default
var rightPressed = false;
var leftPressed = false;

var goalkeeper_blocked = 0;
var goalkeeper_missed = 0;
var attempts_left = 3;
var lastAttempt='';
var isGameOver=false;

var attempt1 = true;
var attempt2 = false;
var attempt3 = false;

var footBall = {

    // is a shot in progress
    isShooting:false,
    
    // time when next shot will run
    nextShotTime:0,
    
    // delay until next shot will run
    delayUntilNextShot:3000,
    
    shapes : {
        ball: function (){
            ctx.beginPath();
            ctx.arc(x, y, ballRadius, 0, Math.PI*2, false);
            ctx.fillStyle = "red";
            ctx.fill();
            ctx.closePath();
        },

        goal : function (){
            ctx.beginPath();
            ctx.rect((canvas.width - goal_width) / 2 , canvas.height - goal_height, goal_width, goal_height);
            ctx.strokeStyle = "#000000";
            ctx.stroke();
            ctx.closePath();
        },

        goalie : function(){
            ctx.beginPath();
            ctx.rect(goalieX, goalieY, goalieWidth, goalieHeight);
            ctx.fillStyle = "#666666";
            ctx.fill();
            ctx.closePath();
        },

        score : function(){
            ctx.font = "16px Arial";
            ctx.fillStyle = "#ffffff";
            ctx.fillText("Score: "+goalkeeper_blocked, 8, 20);
        },

        missed : function(){
            ctx.font = "16px Arial";
            ctx.fillStyle = "#ffffff";
            ctx.fillText("Missed: "+goalkeeper_missed, 8, 40);
        },

        attempts : function(){
            ctx.font = "16px Arial";
            ctx.fillStyle = "#ffffff";
            ctx.fillText("Attempts left: "+attempts_left, canvas.width-110, 20);
        },

        lastAttempt : function(){
            ctx.font = isGameOver?'18px Arial':'30px Arial';
            ctx.fillStyle = "#ff0000";
            ctx.textAlign='center';
            ctx.fillText(lastAttempt,canvas.width/2,canvas.height/2);
            ctx.textAlign='left';
        },

    },

    controls : {
        keyDownHandler : function (e){
            if(e.keyCode == 39) {
                rightPressed = true;
            }
            else if(e.keyCode == 37) {
                leftPressed = true;
            }

        },

        keyUpHandler : function(e){
            if(e.keyCode == 39) {
                rightPressed = false;
            }
            else if(e.keyCode == 37) {
                leftPressed = false;
            }

        }

    },

    calculateScore : function(){
        if(goalkeeper_missed > goalkeeper_blocked){
            lastAttempt="GAME OVER! YOU HAVE LOST!";
            isGameOver=true;
        } else {
            lastAttempt="GAME OVER! YOU HAVE WON!";
            isGameOver=true;
        }
        setTimeout(function(){
            document.location.reload();
            isGameOver=false;
        },3000);
    },

    resetShapePositions : function(){
        //Sets the original position of the ball
        x = canvas.width/2;
        y = 50;

        // Sets a new shooting path
        dx = x_options[Math.floor(Math.random() * x_options.length)];
        dy = 5;

        // Resets the goalie to the middle
        goalieX = (canvas.width-goalieWidth)/2;

    },

    drawField: function(){
        // This ensures that the ball doesn't leave a trail
        // Clears the canvas of this shape each frame
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // Draws shapes on the canvas
        footBall.shapes.ball();
        footBall.shapes.goal();
        footBall.shapes.goalie();
        footBall.shapes.score();
        footBall.shapes.missed();
        footBall.shapes.attempts();
        footBall.shapes.lastAttempt();
    },

    draw : function(currentTime){

        //   makes paddle move left and right and only within the canvas
        if(rightPressed && goalieX < canvas.width-goalieWidth) {
            goalieX += 7;
        }
        else if(leftPressed && goalieX > 0) {
          goalieX -= 7;
        }

        // draw the scene
        footBall.drawField();

        // delay until next shot time is due 
        if(!footBall.isShooting){
            // time has elapsed, let's shoot again
            if(currentTime>footBall.nextShotTime){
                footBall.isShooting=true;
                // clear the last attempt display while 
                // the shot is in progress
                lastAttempt='';
            }else{
                // time has not elapsed, just request another loop
                requestAnimationFrame(footBall.draw);
                return;
            }
        }

        // adds values to the balls  x and y position every frame
        x += dx;
        y += dy;

        // Ball hits the goal 
        if(y + dy > canvas.height - goal_height) {

            // end the shot
            footBall.isShooting=false;
            // delay the next shot
            footBall.nextShotTime=currentTime+footBall.delayUntilNextShot;
            // display shot result
            lastAttempt='Missed!';

            attempts_left--;
            goalkeeper_missed++;
            if (!attempts_left){
                footBall.calculateScore();
            } 
            else {
                footBall.resetShapePositions();
            }

        } // Ball saved by goalie
        else if (x  > goalieX && x  < goalieX + goalieWidth && y + dy > goalieY - ballRadius){

            // end the shot
            footBall.isShooting=false;
            // delay the next shot
            footBall.nextShotTime=currentTime+footBall.delayUntilNextShot;
            // display shot result
            lastAttempt='Saved!';

            attempts_left--;
            goalkeeper_blocked++;

            if (!attempts_left){
                footBall.calculateScore();
            } 
            else {
                footBall.resetShapePositions();

            }

        } 

        requestAnimationFrame(footBall.draw);
    }

}

footBall.drawField();
footBall.nextShotTime=footBall.delayUntilNextShot;
requestAnimationFrame(footBall.draw);

// Defines what functions are fired when keydown or keyup event triggers
document.addEventListener("keydown", footBall.controls.keyDownHandler, false);
document.addEventListener("keyup", footBall.controls.keyUpHandler, false);
&#13;
* { padding: 0; margin: 0; }
canvas { background: #a5bd7b; display: block; margin: 0 auto; }
&#13;
&#13;
&#13;