Chris Handy
Chris Handy

Reputation: 23

Draw and move shapes across canvas with an interval

I'm trying to make my own "Flappy Bird" clone in my spare time, but I'm having trouble getting the "pipes" to draw and scroll at a set interval. I'm able to draw one set and move it, but having it repeatedly draw and move it in an interval is eluding me.

Any insight as to what I need to do would be appreciated.

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

Upvotes: 1

Views: 301

Answers (1)

Shomz
Shomz

Reputation: 37701

You were simply missing a notion of multiple pipes. I've modified your code, so pipes is now an array of pipes and their draw/move function work with each individual pipe. I've also added a newPipe function that gets called in the interval (which I've moved out of the render loop).

Since pipes pile up - I added a delete function which removes those pipes that pass the left canvas edge.

Here we go:

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

Upvotes: 1

Related Questions