2016-06-19 1 views
0

Ich versuche, ein einfaches Fußball-Penalty-Spiel mit HTML5/JS Canvas zu machen. Ziel ist es, ein Spiel zu machen, in dem Sie den Torwart kontrollieren und drei Versuche haben, den Ball zu retten.Wie man eine Verzögerung nach jedem Schuss in HTML 5 JS Canvas Fußball Penalty-Spiel setzt

Ich habe die meisten Funktionen erledigt, ich habe ein Score-System und Kollisionserkennung.

Mein Problem ist, dass nachdem der Ball geschossen wurde, der Feedback-Text nur für einen Bruchteil einer Sekunde erscheint und meine Leinwand für den nächsten Penalty-Versuch bereit ist.

Irgendwelche Ratschläge? Ich habe versucht mit setTimeout() zu verzögern, aber es funktioniert immer noch nicht.

Dank

<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> 

Antwort

1

Hier ist, wie der Benutzer das letzte Ergebnis zu zeigen, bis der nächste Versuch gestartet wird.

Hinweis: Da Sie bereits eine requestAnimationFrame Schleife laufen, dann kann man auch verwenden, dass rAF für Sie den Zeitpunkt der letzten Ergebnis Ankündigung zu behandeln.

  • erstellen footBall.lastResult Eigenschaft, die das Ergebnis des letzten Versuchs („Tor“ oder „Blockiert“) hält. Stellen Sie vor dem ersten Versuch football.lastResult='' ein, um anzuzeigen, dass keine vorherigen Ergebnisse vorliegen.

  • eine footBall.shapes.showLastResult Methode hinzufügen, die football.lastResult nur anzeigt, wenn football.isShooting falsch ist.

Beispielcode und eine Demo:

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);
* { padding: 0; margin: 0; } 
 
canvas { background: #a5bd7b; display: block; margin: 0 auto; }
<canvas id="myCanvas" width="300" height="250"></canvas>

+0

Hey, Ich habe versucht, diese Umsetzung aber ohne Glück. Ich weiß nicht, ob ich mit meiner Frage einen Sinn hatte, aber mein Spiel geht sofort zum nächsten Versuch, ohne eine Pause einzulegen und den Text anzuzeigen, wenn er gespeichert oder verpasst wurde. http://codepen.io/geraldjtorres/pen/MejOaW – geraldjtorres

+0

Ich habe Beispielcode und eine Demo hinzugefügt. Der Code zeigt den "lastAttempt" -Wert von "Verpasst" oder "Blockiert" während der Verzögerung vor der nächsten Aufnahme an. – markE

+0

Prost! Du bist ein Glücksfall. Ich habe am Anfang des Spiels einen Splashscreen hinzugefügt, der das Spiel startet, wenn du die Leertaste drückst und den Splashscreen versteckst. Ich weiß nicht warum, aber es scheint den ersten Versuch zu beeinflussen und es wird sofort geschossen, wenn der Benutzer die Leertaste nicht vor drei Sekunden drückt. Ich dachte, die Verzögerung beginnt erst, wenn das Spiel begonnen hat, nicht vorher. Hier ist ein Beispiel. Warte länger als 3 Sekunden, dann drücke die Leertaste, der Ball wird sich nicht verzögern und er wird sofort schießen. die anderen Versuche verzögern gut. : http://codepen.io/geraldjtorres/pen/MejOaW – geraldjtorres