以一定间隔在 canvas 范围内绘制和移动形状

Draw and move shapes across canvas with an interval

我试图在业余时间制作自己的 "Flappy Bird" 克隆,但我无法让 "pipes" 以设定的时间间隔进行绘制和滚动。我能够绘制一组并移动它,但是让它在一定间隔内重复绘制和移动它让我难以接受。

任何关于我需要做什么的见解都将不胜感激。

$(document).ready(function(){
    //global vars   
    var world = document.getElementById('gameWorld');
    var startScreen = document.getElementById('startScreen');
    var context = world.getContext('2d');

    window.requestAnimFrame = (function(callback) {
        return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
        function(callback) {
            window.setTimeout(callback, 1000 / 60);
    };
    })()


    //bord constructor  
    function bordBuilder(){
        this.radius = 10;
        this.x = world.width / 2;
        this.y = world.height / 2;
        this.vy = -20;
        this.gravity = 0.8;
    }

    function pipesBuilder(){
        this.width = 50;
        this.x = world.width;

    }
    // draw the Bord on the stage
    function drawBord(bord, context){
        context.beginPath();
        context.arc(bord.x, bord.y, bord.radius, 0, 2 * Math.PI, false);
        context.fillStyle = 'blue';
        context.fill();
        context.lineWidth = 1;
        context.strokeStyle = 'navyblue';
        context.stroke();
    }

    //function to check whether or not the bord is hitting the top or bottom of the stage
    function fallingBord(bord){
        bord.y += bord.gravity;
        if(bord.y < 0 + bord.radius){
            bord.y = bord.radius;
        }else if(bord.y + bord.radius > world.height){
            bord.y = world.height - bord.radius;
        }
    }

    //animation function always running
    function startAnimation(bord, context, pipes){
        context.clearRect(0, 0, world.width, world.height);
        drawBord(bord, context);
        fallingBord(bord);
        setInterval(function(){ 
            drawPipes(pipes, context);
        }, 3000);

        movePipes(pipes);
        requestAnimFrame(function(){
            startAnimation(bord, context, pipes);
        });
    }

    //make the bird fly higher every click
    function flyHigher(bord){
        console.log('higher');
        bord.y += bord.vy;
    }

    //pipe function/hitboxes
    function drawPipes(pipes, context){
        context.beginPath();
        context.rect(pipes.x, world.height-50, pipes.width,50);
        context.fillStyle = 'green';
        context.fill();

        context.beginPath();
        context.rect(pipes.x, 0, pipes.width, 50);
        context.fillStyle = 'green';
        context.fill();
    }

    //function to move the pipes from the left to right
    function movePipes(pipes){
        pipes.x -= 1;
    }


    var pipes = new pipesBuilder();
    var bord = new bordBuilder();

    //add the fly event listener to the stage
    world.addEventListener("click", function(){
        flyHigher(bord);
    }, false);
    startScreen.addEventListener("click", function(){
        startScreen.style.display = 'none';
        startAnimation(bord, context, pipes);
    }, false);
});
#gameWorld{
    height: 50%;
    width: 50%;
    border: 1px solid black;
}
#startScreen{
    position: absolute;
    z-index: 5;
    top: 0;
    left: 0;
    height: 50%;
    width: 50%;
}
#startScreen h1{
    text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="startScreen"><h1>START</h1></div>
<canvas id="gameWorld"></canvas>

您只是错过了多个管道的概念。我已经修改了你的代码,所以 pipes 现在是一个管道数组,它们的 draw/move 函数适用于每个单独的管道。我还添加了一个在间隔中调用的 newPipe 函数(我已将其移出渲染循环)。

由于管道堆积 - 我添加了一个删除功能,用于删除那些通过左 canvas 边缘的管道。

开始吧:

$(document).ready(function(){
    //global vars   
    var world = document.getElementById('gameWorld');
    var startScreen = document.getElementById('startScreen');
    var context = world.getContext('2d');

    window.requestAnimFrame = (function(callback) {
        return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
        function(callback) {
            window.setTimeout(callback, 1000 / 60);
    };
    })()


    //bord constructor  
    function bordBuilder(){
        this.radius = 10;
        this.x = world.width / 2;
        this.y = world.height / 2;
        this.vy = -20;
        this.gravity = 0.8;
    }

    function pipesBuilder(){
        this.width = 50;
        this.x = world.width;

    }
    // draw the Bord on the stage
    function drawBord(bord, context){
        context.beginPath();
        context.arc(bord.x, bord.y, bord.radius, 0, 2 * Math.PI, false);
        context.fillStyle = 'blue';
        context.fill();
        context.lineWidth = 1;
        context.strokeStyle = 'navyblue';
        context.stroke();
    }

    //function to check whether or not the bord is hitting the top or bottom of the stage
    function fallingBord(bord){
        bord.y += bord.gravity;
        if(bord.y < 0 + bord.radius){
            bord.y = bord.radius;
        }else if(bord.y + bord.radius > world.height){
            bord.y = world.height - bord.radius;
        }
    }

    //animation function always running
    function startAnimation(bord, context, pipes){
        context.clearRect(0, 0, world.width, world.height);
        drawBord(bord, context);
        fallingBord(bord);
        
        drawPipes(pipes, context);
        movePipes(pipes);
        requestAnimFrame(function(){
            startAnimation(bord, context, pipes);
        });
    }

    //make the bird fly higher every click
    function flyHigher(bord){
        console.log('higher');
        bord.y += bord.vy;
    }

    //pipe function/hitboxes
    function drawPipes(pipes, context){
      for(var i = 0; i < pipes.length; i++){
        context.beginPath();
        context.rect(pipes[i].x, world.height-50, pipes[i].width,50);
        context.fillStyle = 'green';
        context.fill();

        context.beginPath();
        context.rect(pipes[i].x, 0, pipes[i].width, 50);
        context.fillStyle = 'green';
        context.fill();
      }
    }

    //function to move the pipes from the left to right
    function movePipes(pipes){
      for(var i = 0; i < pipes.length; i++){
        pipes[i].x -= 1;
        if (i == 0 && pipes[i].x < -pipes[i].width) {
          console.log('deleting pipe');
          pipes.splice(i, 1);
          }
        }
    }
  
  function newPipe(pipes){
    pipes.push(new pipesBuilder());
    }


    var pipes = [new pipesBuilder()];
    var bord = new bordBuilder();

    //add the fly event listener to the stage
    world.addEventListener("click", function(){
        flyHigher(bord);
      drawPipes(pipes, context);
    }, false);
    startScreen.addEventListener("click", function(){
        startScreen.style.display = 'none';
        startAnimation(bord, context, pipes);
        setInterval(function(){ 
          console.log('new pipe', pipes);
            newPipe(pipes);
        }, 3000);
    }, false);
});
#gameWorld{
    height: 50%;
    width: 50%;
    border: 1px solid black;
}
#startScreen{
    position: absolute;
    z-index: 5;
    top: 0;
    left: 0;
    height: 50%;
    width: 50%;
}
#startScreen h1{
    text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="startScreen"><h1>START</h1></div>
<canvas id="gameWorld"></canvas>