【问题标题】:Multiple setInterval in a HTML5 Canvas gameHTML5 Canvas 游戏中的多个 setInterval
【发布时间】:2017-01-14 10:07:14
【问题描述】:

我正在尝试在使用 Canvas 创建的游戏中实现多个动画(这是一个简单的乒乓球游戏)。这是我的第一个游戏,我是 canvas 新手,但之前做过一些实验,所以我对 canvas 的工作原理有很好的了解。

首先,看看游戏here。 问题是,当球击中桨时,我想要在接触点爆发 n 个粒子,但这并不正确。即使我将粒子数设置为 1,它们也只是不断地从接触点而来,然后在一段时间后自动隐藏。

另外,我想在每次碰撞时都有爆发,但它只发生在第一次碰撞时。我在这里粘贴代码:

//Initialize canvas
var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    W = window.innerWidth, 
    H = window.innerHeight,
    particles = [],
    ball = {},
    paddles = [2],
    mouse = {},
    points = 0,
    fps = 60,
    particlesCount = 50,
    flag = 0,
    particlePos = {}; 

canvas.addEventListener("mousemove", trackPosition, true);

//Set it's height and width to full screen
canvas.width = W;
canvas.height = H;

//Function to paint canvas
function paintCanvas() {
    ctx.globalCompositeOperation = "source-over";
    ctx.fillStyle = "black";
    ctx.fillRect(0, 0, W, H);
}

//Create two paddles
function createPaddle(pos) {
    //Height and width
    this.h = 10;
    this.w = 100;

    this.x = W/2 - this.w/2;
    this.y = (pos == "top") ? 0 : H - this.h;

}

//Push two paddles into the paddles array
paddles.push(new createPaddle("bottom"));
paddles.push(new createPaddle("top"));

//Setting up the parameters of ball
ball = {
    x: 2,
    y: 2,
    r: 5,
    c: "white",
    vx: 4,
    vy: 8,
    draw: function() {
        ctx.beginPath();
        ctx.fillStyle = this.c;
        ctx.arc(this.x, this.y, this.r, 0, Math.PI*2, false);
        ctx.fill();
    }
};

//Function for creating particles
function createParticles(x, y) {
    this.x = x || 0;
    this.y = y || 0;

    this.radius = 0.8;

    this.vx = -1.5 + Math.random()*3;
    this.vy = -1.5 + Math.random()*3;
}

//Draw everything on canvas
function draw() {
    paintCanvas();
    for(var i = 0; i < paddles.length; i++) {
        p = paddles[i];

        ctx.fillStyle = "white";
        ctx.fillRect(p.x, p.y, p.w, p.h);
    }

    ball.draw();
    update();
}

//Mouse Position track
function trackPosition(e) {
    mouse.x = e.pageX;
    mouse.y = e.pageY;
}

//function to increase speed after every 5 points
function increaseSpd() {
    if(points % 4 == 0) {
        ball.vx += (ball.vx < 0) ? -1 : 1;
        ball.vy += (ball.vy < 0) ? -2 : 2;
    }
}

//function to update positions
function update() {

    //Move the paddles on mouse move
    if(mouse.x && mouse.y) {
        for(var i = 1; i < paddles.length; i++) {
            p = paddles[i];
            p.x = mouse.x - p.w/2;
        }       
    }

    //Move the ball
    ball.x += ball.vx;
    ball.y += ball.vy;

    //Collision with paddles
    p1 = paddles[1];
    p2 = paddles[2];

    if(ball.y >= p1.y - p1.h) {
        if(ball.x >= p1.x && ball.x <= (p1.x - 2) + (p1.w + 2)){ 
            ball.vy = -ball.vy;
            points++;
            increaseSpd();

            particlePos.x = ball.x,
            particlePos.y = ball.y;
            flag = 1;
        }
    }

    else if(ball.y <= p2.y + 2*p2.h) {
        if(ball.x >= p2.x && ball.x <= (p2.x - 2) + (p2.w + 2)){ 
            ball.vy = -ball.vy;
            points++;
            increaseSpd();

            particlePos.x = ball.x,
            particlePos.y = ball.y;
            flag = 1;
        }
    }

    //Collide with walls
    if(ball.x >= W || ball.x <= 0)
        ball.vx = -ball.vx;

    if(ball.y > H || ball.y < 0) {
        clearInterval(int);
    }

    if(flag == 1) {
        setInterval(emitParticles(particlePos.x, particlePos.y), 1000/fps);
    }

}

function emitParticles(x, y) {

    for(var k = 0; k < particlesCount; k++) {
        particles.push(new createParticles(x, y));
    }

    counter = particles.length;

    for(var j = 0; j < particles.length; j++) {
        par = particles[j];

        ctx.beginPath(); 
        ctx.fillStyle = "white";
        ctx.arc(par.x, par.y, par.radius, 0, Math.PI*2, false);
        ctx.fill();  

        par.x += par.vx; 
        par.y += par.vy;

        par.radius -= 0.02; 

        if(par.radius < 0) {
            counter--;
            if(counter < 0) particles = [];
        }

    } 
}

var int = setInterval(draw, 1000/fps);

现在,我的发射粒子函数在第 156 行,我在第 151 行调用了这个函数。这里的问题可能是因为我没有重置 flag 变量,但我尝试这样做并且变得更奇怪结果。您可以查看here。

通过重置flag 变量,无限粒子的问题得到解决,但现在它们只会在球与桨碰撞时出现动画和出现。所以,我现在没有任何解决方案。

【问题讨论】:

标签: javascript html canvas html5-canvas


【解决方案1】:

我可以在这里看到 2 个问题。

您的主要短期问题是您对 setinterval 的使用不正确,它的第一个参数是一个函数。

setInterval(emitParticles(particlePos.x, particlePos.y), 1000/fps);

应该是

setInterval(function() {
    emitParticles(particlePos.x, particlePos.y);
}, 1000/fps);

其次,一旦你开始一个间隔,它就会永远运行 - 你不希望每个碰撞事件都让后台计时器像这样运行。

有一个要更新的粒子数组,每帧更新一次这个列表。当您制作新粒子时,将其他粒子推入其中。

【讨论】:

    猜你喜欢
    • 2015-08-05
    • 1970-01-01
    • 2012-07-04
    • 2013-11-07
    • 1970-01-01
    • 1970-01-01
    • 2014-11-27
    • 2013-06-10
    • 2022-01-13
    相关资源
    最近更新 更多