Kineticjs output lags

I am trying to recreate the sinuous game.(http://www.sinuousgame.com/) I created the red enemies,but it lags(slows down) after some time.

My code is given below: Javascript as follows:

var x = 0;
var y = 0;
var noOfEnemies = 10;
var enemyArmada = new Array();

var stage = new Kinetic.Stage({
    container: 'container',
    width: window.innerWidth,
    height: window.innerHeight,
    listening: true
});
var layer = new Kinetic.Layer({
    listening: true
});

createEnemy();

function createEnemy() {
    for (var i = 0; i < noOfEnemies; i++) {
        var enemy = new Kinetic.Circle({
            x: Math.random() * 1200,
            y: Math.random() * 50,
            radius: 6,
            fill: 'red',
            stroke: 'black',
            speed: 3 + Math.random() * 5
        });
        enemyArmada.push(enemy);

    }
    setInterval(draw, 60);
}

function draw() {
    for (var i = 0; i < noOfEnemies; i++)
    {
        enemyArmada[i].setPosition({
            x: enemyArmada[i].getPosition().x + 5,
            y: enemyArmada[i].getPosition().y + 5
        });
        layer.add(enemyArmada[i]);
    }
    layer.draw();
    stage.add(layer);
}

html:

<!DOCTYPE html>
<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
        <link rel="stylesheet" href="../css/style.css"/>
    </head>
    <body>
        <!--<canvas id="canvasRegn" width="600" height="450" style="margin:100px;"></canvas>-->
        <div id="container" style="width: auto; height: auto; background:#000; margin:auto; float:left;"></div>
        <script src="../js/jquery.min.js"></script>
        <script src="../js/kinetic-v5.0.0.min.js"></script>
        <script type="text/javascript" src="../js/rain2.js"></script>
    </body>
</html>

Fiddle: http://jsfiddle.net/jfGL6/3/

Answers


I suggest using Kinetic.Animation class instead of setInterval.

They move slower since their is speed is in px/s now.

http://jsfiddle.net/Kunstmord/cP9GR/1/

All you do is start the animation (anim.start();), and update the positions:

var anim = new Kinetic.Animation(function(frame) {
        for (var i = 0; i < noOfEnemies; i++) {
        var e=enemyArmada[i];
        e.position({
            x: e.position().x + e.speedX * frame.timeDiff / 1000,
            y: e.position().y + e.speedY * frame.timeDiff / 1000
        });
    }
      }, layer);
anim.start();

Where frame timeDiff is the time difference between two consecutive frames, measured in ms. Learning to use animations will help you in the long run, since you can time what is happening pretty exactly (frame.time, frame.timeDiff).


A few glitches in your code:

  • Add the layer to the stage right after the layer is created.
  • In createEnemy: add each new enemy to the layer: layer.add(enemy);
  • In draw: don't add the enemies there (you are adding the same enemy many times)
  • In draw: don't add the layer to the stage
  • setInterval with an interval of 1 is too fast for the processor to handle. The min delay should be 16 which corresponds to 60 frames per second.

Some suggestions:

  • Use requestAnimationFrame (RAF) instead of setInterval because RAF efficiently coordinates draws between screen refreshes.
  • You set a speed in your enemy object but you use a constant velocity of 2. Maybe increment by the speed in your enemy object.

Demo: http://jsfiddle.net/m1erickson/2WRwY/

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Prototype</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.1.min.js"></script>

<style>
body{padding:20px;}
#container{
  border:solid 1px #ccc;
  margin-top: 10px;
  width:350px;
  height:350px;
}
</style>        
<script>
$(function(){

var stage = new Kinetic.Stage({
    container: 'container',
    width: 350,
    height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);

var x = 0;
var y = 0;
var noOfEnemies = 120;
var enemyArmada = new Array();

createEnemy();

function createEnemy() {
    for (var i = 0; i < noOfEnemies; i++) {
        var enemy = new Kinetic.Circle({
            x: Math.random() * 350,
            y: Math.random() * 50,
            radius: 6,
            fill: 'red',
            stroke: 'black',
            speed: 3 + Math.random() * 5
        });
        enemyArmada.push(enemy);
        layer.add(enemy);
    }
    setInterval(draw,20);
}

function draw() {
    for (var i = 0; i < noOfEnemies; i++)
    {
        enemyArmada[i].setPosition({
            x: enemyArmada[i].getPosition().x + 2,
            y: enemyArmada[i].getPosition().y + 2
        });
    }
    layer.draw();
}





    $("#myButton").click(function(){});



}); // end $(function(){});

</script>       
</head>

<body>
    <button id="myButton">Button</button>
    <div id="container"></div>
</body>
</html>

Use requestAnimationFrame instead of setInterval. I also recreated the the sinuous game. play. Here is my open source code


Need Your Help

unable to start a aplication with tmux at startup

linux shell raspberry-pi tmux

I'm trying to start an application (newsbeuter) at boot but I can't.

Omitting big objects when pickling in python

python pickle

In the object I have reference to some other, big object.