javascript - 以一定间隔在 Canvas 上绘制和移动形状

标签 javascript canvas

我正在尝试在业余时间制作自己的“Flappy Bird”克隆,但我无法让“管道”以设定的时间间隔绘制和滚动。我能够绘制一组并移动它,但让它在一定间隔内重复绘制和移动它却让我难以理解。

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

$(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 现在是一个管道数组,并且它们的绘制/移动函数适用于每个单独的管道。我还添加了一个在间隔中调用的 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>

关于javascript - 以一定间隔在 Canvas 上绘制和移动形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28077585/

相关文章:

Javascript如何从 map 返回数组

javascript - 预期在带有 if 语句的箭头函数末尾返回一个值

java - 投票系统增加票数

javascript - 作为 div 背景的 Canvas 动画 - EaselJS

javascript - getImageData - Web worker - 如何减少垃圾回收?

javascript - 使用无限滚动时 Canvas 最终太大而无法写入

javascript - YouTube onStateChange 未触发

javascript - 检查值是否包含字符串字符

javascript - Canvas 元素之后(之下)的 HTML 内容

javascript - Canvas - 清除矩形不起作用