javascript - HTML5 Canvas 游戏中的多个 setInterval

标签 javascript html canvas html5-canvas

我正在尝试在使用 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变量,无限粒子的问题得到解决,但现在它们仅在球与 Racket 碰撞时才会动画和出现。所以,我现在没有任何解决方案。

最佳答案

我在这里看到两个问题。

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

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

应该是

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

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

有一个要更新的粒子数组,并每帧更新一次该列表。当你制造新的粒子时,将额外的粒子插入其中。

关于javascript - HTML5 Canvas 游戏中的多个 setInterval,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11363576/

相关文章:

javascript - 将命名函数存储在具有不同名称的变量中

javascript - 模拟所有视口(viewport)大小的恒定页面大小

html - 单击按钮禁用文本选择

css - 努力应对响应式设计

javascript - onload 与 onLoad(区分大小写)

javascript - 在 HTML5 Canvas 中创建表格

javascript - 根据文本选择元素

javascript - Leaflet ReactJS Map 未完全显示图 block

html - 为什么我的容器显示白色背景?

javascript - 声明一个数据元素数组,以获得 Canvas 上的散点