3

我第一次做一个小游戏,只是为了练习。正如你在我的小提琴中看到的那样,当屏幕上有很多子弹和/或敌人时,它会在一段时间后开始掉帧。有没有办法通过以某种方式缓存它来减少这种情况?

我读过一些关于预渲染的东西。但由于我使用的是 Kinetic 库,所以我认为这不是我能做的。是否有一些提示和技巧来减少它的丢帧?还是一种使用 KineticJS 进行预渲染的方法?

这是我的小提琴:http: //jsfiddle.net/3nEUv/3/

我认为子弹的绘制是一个真正的交易破坏者:(小提琴中的第 713 行)

function Enemybullet(destinationX, destinationY, enemySprite) {
    this.id = 'enemyBullet';
    this.x = enemySprite.getX()+(enemySprite.getWidth()/2);
    this.y = enemySprite.getY()+(enemySprite.getHeight()/2);

    this.damage = enemy.damage;

    //The targetX and Y are compensated by the player width and height. Subtract or add the halve of the player accordingly
    if (this.x > player.sprite.x) {
        var targetX = (destinationX - this.x)-(player.sprite.getWidth()/2);
        targetY = (destinationY - this.y)-(player.sprite.getHeight()/2);
    } else {
        var targetX = (destinationX - this.x)+(player.sprite.getWidth()/2);
        targetY = (destinationY - this.y)+(player.sprite.getHeight()/2);
    }


    var distance = Math.sqrt(targetX * targetX + targetY * targetY);

    this.velX = (targetX / distance) * enemyAttackSpeed;
    this.velY = (targetY / distance) * enemyAttackSpeed;

    this.finished = false;

    this.sprite = new Kinetic.Circle({
        x: this.x,
        y: this.y, 
        radius: 2,
        fill: 'black',
        name: 'enemyProjectile'
    });

    this.draw = function(indexEnemy, indexBullet) {

        var mayDelete = false;

        this.x += this.velX;
        this.y += this.velY;

        this.sprite.setAbsolutePosition(this.x, this.y);
        //console.log(this.sprite.getX());


        if(collisionDetection(this, player) == true) {
            player.collide(this);
            mayDelete = true;
        }

        if (bulletLeftField(this.sprite) == true) {
            mayDelete = true;
        }

        if (mayDelete == true) {
            delete this;
            this.sprite.remove();
            //console.log(enemies[indexEnemy].bullets);
            if (enemies[indexEnemy]) {
                enemies[indexEnemy].bullets.splice(indexBullet, 1);
            }
        }

        ammoLayer.draw();
    }

}

提前致谢!

4

2 回答 2

1

一些想法并没有真正上升到答案的水平

我注意到你以 5 发子弹的方式发射子弹。发火速度如此之快,以至于所有 5 发子弹都或多或少地朝着目标直线移动。我的建议是只对领先的子弹进行碰撞测试。如果领先的子弹击中,尾随的子弹最终会击中您的静止目标。

KineticJS 形状非常智能,因此非常占用处理器资源。因此,您可以使用缓存的子弹图像,而不是创建智能子弹。Eric Drowell(KineticJS 的创建者)说,使用“愚蠢”图像而不是“智能”形状可以将性能提升 4 倍。您可以缓存 5 种子弹图像模式(1-子弹、2-子弹、3-子弹、4-子弹、5-子弹)。在发射时,您遍历 1-5 个子弹图像,直到获得 5 个子弹。然后,您只需沿着射击线的斜面移动 5 子弹图像。

最后,从屏幕外缓冲区画布进行 blitting确实很有帮助,但不可能,因为 KineticJS 拒绝放弃对其画布的可写引用。Eric Drowlell,如果你在听……爱你的作品,但是给我们一个缓冲画布怎么样!

于 2013-03-25T18:44:11.780 回答
1

我能想到的几件事会有所作为。


1/对象池

这是回收对象的技术。创建新的(并通过垃圾收集删除旧的)是浪费的。

这是通过在不再需要时将子弹移动到临时阵列来完成的。就像它离开屏幕或击中敌人一样。然后,当您需要新的子弹时,您从临时数组中取出对象并重新初始化子弹。

查看此链接(搜索标题“回收鱼”)


2/四叉树碰撞检测

这是一个很好的碰撞优化技术。而不是检查你的子弹是否在每个滴答声中都与每个敌人发生碰撞,你只检查那些与你的子弹在同一个“四边形”中的敌人。

这是一个很好的教程


3/缓冲

使用屏幕外画布。我会有一个用于背景、用户界面、玩家/敌人/子弹。这有一些变化,但根据我的经验,最有效的是将所有元素绘制到屏幕外层;然后每次打勾时,如果该图层已更改,则仅重绘(到屏幕外图层)图像。完成后,您将每个屏幕外图层编译为一个可见图层。我已经在我的手机游戏中成功使用了这种技术,它一次在屏幕上显示超过 90 个对象,在 iPhone4s 上以 60fps 的速度运行。


编辑:刚刚看到这个有趣的演示,展示了 3 个不同框架的性能,包括 Kinetic。Kinetic 在我的台式机和移动设备上对我来说最糟糕。

互动演示在这里

于 2013-03-25T20:21:14.980 回答