Search code examples
javascriptjqueryhtmlhtml5-canvaskineticjs

Kinetic JS canvas game (Layering issue)(Javascript)


I am trying to recreate the game http://www.sinuousgame.com/ and studying html5 canvas and kineticJS.

This is my fiddle: http://jsfiddle.net/2WRwY/7/

My problem:

  1. The tail part of the player in the fiddle doesn't seem to retract back.
  2. The red ball objects should appear over the player objects.

(Try running the fiddle with layer.removeChildren(); and without it.)

Right now,I have commented "layer.removeChildren();" on the fiddle.. (basically which causes the problem for me)

Here's my html:

<!DOCTYPE html>
<html>
    <head>
        <title>Collision Detection-player</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta name="viewport" content="width=device-width">
        <link rel="stylesheet" href="../css/style.css"/>
    </head>
    <body>
        <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 src="../js/main_kinetic_combined.js"></script>
    </body>
</html>

Here's my javascript:

//The working player code
var LimitedArray = function(upperLimit) {
    var storage = [];

    // default limit on length if none/invalid supplied;
    upperLimit = +upperLimit > 0 ? upperLimit : 100;

    this.push = function(item) {
        storage.push(item);
        if (storage.length > upperLimit) {
            storage.shift();
        }
        return storage.length;
    };

    this.get = function(flag) {
        return storage[flag];
    };

    this.iterateItems = function(iterator) {
        var flag, l = storage.length;
        if (typeof iterator !== 'function') {
            return;
        }
        for (flag = 0; flag < l; flag++) {
            iterator(storage[flag]);
        }
    };
};

    var tail = new LimitedArray(50);

    var flag = 0, jincr = 0;
    var stage = new Kinetic.Stage({
        container: 'container',
        width: window.innerWidth,
        height: window.innerHeight,
        listening: true
    });
    var layer = new Kinetic.Layer({
        listening: true
    });
    stage.add(layer);
    var player = new Kinetic.Circle({
        x: 20,
        y: 20,
        radius: 6,
        fill: 'cyan',
        stroke: 'black',
        draggable: true
    });

    layer.add(player);

    // move the circle with the mouse
    stage.getContent().addEventListener('mousemove', function() {
        <!--layer.removeChildren();  -->
        layer.add(player);
        player.setPosition(stage.getPointerPosition());
        var obj = {
            x: stage.getPointerPosition().x,
            y: stage.getPointerPosition().y
        };

        tail.push(obj);
        var arr = [];
        tail.iterateItems(function(p) {
            arr.push(p.x, p.y);
        });
        var line = new Kinetic.Line({
            points: arr,
            stroke: 'white',
            strokeWidth: 2,
            lineCap: 'round',
            lineJoin: 'round'
        });
        layer.add(line);
//        layer.draw();
    });

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

    createEnemy();

    function createEnemy() {
        for (var i = 0; i < noOfEnemies; i++) {
            var enemy = new Kinetic.Circle({
                x: Math.random() * window.innerWidth,
                y: Math.random() * window.innerHeight,
                radius: 4.5 + 1.5 * Math.random(),
                fill: 'red',
                stroke: 'black',
            });
            enemy.speedX = enemy.speedY = (0.3 + Math.random() * 50);
            enemyArmada.push(enemy);
            layer.add(enemy);
        }
    }

    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 / 500,
                y: e.position().y + e.speedY * frame.timeDiff / 500
            });
            if (e.position().y < 0 || e.position().x < 0) {
                e.position({
                    x: (Math.random() * (window.innerWidth + 600)),
                    y: -(Math.random() * window.innerHeight)
                });
            }
        }
    }, layer);
    anim.start();

Any suggestions?


Solution

  • The problem is that after you've added the enemies, you're adding the player and the line to the layer again, so they'll be on top. Also, on each mouse move, you're creating the line over and over again. So, instead, you should just update the line points (and you don't need the layer.removeChildren(); line at all), like this:

    var line = new Kinetic.Line({
                points: [],
                stroke: 'white',
                strokeWidth: 2,
                lineCap: 'round',
                lineJoin: 'round'
            });
    layer.add(line);
    layer.add(player);
    
    // move the circle with the mouse
    stage.getContent().addEventListener('mousemove', function() {
        player.position(stage.getPointerPosition());
        var obj = {
            x: stage.getPointerPosition().x,
            y: stage.getPointerPosition().y
        };
    
        tail.push(obj);
        var arr = [];
        tail.iterateItems(function(p) {
            arr.push(p.x, p.y);
        });
        line.points(arr);
     });
    

    See fiddle: http://jsfiddle.net/Kunstmord/p9fnq/2/ This way, you're only creating the line once. This also seems to fix the non-disappearing trail.

    Also, please note: 1) use position instead of setPosition and getPosition (see KineticJS 5.0 docs) 2) adding <!-- --> does not comment out a line in Javascript (layer.removeChildren(); line).