1
\$\begingroup\$

So I've been trying to draw sprites onto the world canvas. These sprites are held in a Group (aka object pool. They are meant to be bullets). They update properly, even go off bounds, but they never render!

The code below creates the engine, then after places a sprite onto the screen. This sprite will then 'shoot' out other sprites (That's where the issue is).

Engine:

var NE = (function() {
/* Public Variables */
var t = this;
this.images = {}; /* This is where all the loaded images are saved */
this.sprites = []; /* This is where are sprites are saved */
this.groups = []; /* This is where the groups are saved */
this.anim = ''; /* This is the main animation loop. Uses requestanimationframe to animate rooms */
this.canStart = false; /* Can the game start? Should be set to true when loading finishes */
this.rooms = {}; /* This is where all the rooms are saved. */
this.display = ''; /* Display canvas */
this.world = ''; /* This is the reference to the world canvas on which all the currrent running room's objects will live. */

var toBeLoaded = 0,
    /* Total number of images that need loading */
    isLoaded = 0,
    /* Images that have loaded */
    perLoadedDec = 0,
    /* Percentageloaded in decimal form */
    iDontDoAnything; /* Self explanatory, doesn't do anything */

this.Group = function(numEle, key, layer /*, obj*/ ) {
    /* Make sure theres an object value */
    /*if (obj === undefined) {
        obj = Sprite;
    }*/
    this.children = [];
    this.reloadTime = 0;
    this.isReload = false;
    /* Create array children with length numEle. The objects used will be obj */
    this.init = function() {
        for (var i = 0; i < numEle; i++) {
            this.children[i] = t.sprites[t.sprites.push(t.addSprite(key, 100, 100, false)) - 1];
            // this.chilldren[i].groupName =
        }
    };

    /* Create a getFirstAlive() that checks for the first 'alive' element in the children[] and returns it */
    this.getFirstAlive = function() {
        var l = this.children.length;
        for (var i = 0; i < l; i++) {
            if (this.children[i].alive) {
                console.log(this.children[i])
                return this.children[i];
            }
        }
    };

    this.getFirstDead = function() {
        var l = this.children.length;
        for (var i = 0; i < l; i++) {
            if (!this.children[i].alive) {
                return this.children[i];
                break;
            }
            if (i >= l - 1) {
                console.log('There are no more sprites');
                if (!this.isReload) {
                    // this.setAllAliveAfter();
                    // this.isReload = true;
                }
            }
        }
    };

    /* Create setAllAliveAfter(ms) which will set all children elements to alive after specified ms value. If none is given it happens immediately */
    this.setAllAliveAfter = function(ms) {
        var l = this.children.length;
        var ms = ms || this.reloadTime;
        console.log('Starting reloading')
        for (var i = 0; i < l; i++) {
            if (this.children.alive) {
                break;
            } else {
                if (i >= l - 1) {
                    setTimeout(function() {
                        for (var i = 0; i < l; i++) {
                            this.children[i].alive = true;
                            if (i >= l - 1) {
                                console.log("done reseting")
                                this.isReload = false;
                            }
                        }
                        console.log('reloaded!')
                    }, ms); /* END SetTimeout */
                } /* END if */
            } /* END else */
        } /* END forLoop */
    };

    /* Set attribute for all objects in group */
    // debugger;
    this.setAttr = function(attr, value) {
        for (var i = 0; i < this.children.length; i++) {
            this.children[i][attr] = value;
        }
    };

    t.groups.push(this);
    this.groupLength = (t.groups.length - 1 > 0) ? t.groups.length - 1 : 0;
    console.log(t.groups[this.groupLength]);
    return t.groups[this.groupLength];
}

this.Sprite = function(layer, key, x, y, isAlive) {
    /* Sprite Class */
    var spr = this;
    this.pos = t.Point(x, y);
    this.mass = 1;
    this.force = t.Vector();
    this.velocity = t.Vector();
    this.acceleration = t.Vector(this.force.x / this.mass, this.force.y / this.mass);
    // this.baseSpeed = t.Vector(170, 170);
    this.layer = layer || t.world; /* The layer onto which to draw this sprite */
    this.canvas = this.layer.canvas; /* The layer's canvas */
    this.ctx = this.layer.ctx; /* The layer canvas' drawing context */
    this.img = new Image(); /* The sprite's main image */
    this.img.src = t.images[key].src;
    this.group = undefined; /* This is the group to which this sprite controls */
    this.rotImg = undefined; /* The rotated version of the main image. To be used when rotating towards mouse/Vector */
    this.doIRotate = undefined;
    this.rotAngleRad = undefined; /* This is the angle between mouse and sprite */
    this.isClickable = false; /* Whether the sprite is clickable */
    this.acceptsClickEv = false; /* Whether the sprite accepts mouse click events or not*/
    this.mouse = t.Point();
    this.alive = isAlive || false; /* Whether the sprite should be drawn onto the world */
    this.checkOutOfBounds = false; /* Check if the out of bounds */
    this.killOutOfBounds = false; /* If out of bounds then kill the sprite */

    this.init = function() {
        /* Create the drawer canvas */
        // debugger
        this.drawer = undefined;
        this.cW = 0;
        this.cH = 0;
        this.imgW = this.img.width;
        this.imgH = this.img.height;
        // console.log('canvas width ' + this.cW + '. canvas height ' + this.cH + '. image width ' + this.imgW + '. image height ' + this.imgH + '.');
        /* Find dimensions for canvas */
        this.cW = (Math.sqrt(sqr(this.imgW / 2) + sqr(this.imgH / 2))) * 2;
        // console.log(this.cW + ' is hypotemus');
        this.cH = this.cW;
        this.imgOnDrawerX = 0 - (this.imgW / 2);
        this.imgOnDrawerY = 0 - (this.imgH / 2);
        // console.log('canvas width ' + this.cW + '. canvas height ' + this.cH)
        this.drawer = t.createCanvas(this.cW, this.cH, '0');
        this.drawer.ctx.translate(this.cW / 2, this.cH / 2);
        if (this.alive) {
            t.renderCanvas(this.drawer, this.img, this.imgOnDrawerX, this.imgOnDrawerY);
            t.renderWorld(this.drawer.canvas, this.pos.x, this.pos.y);
        }
        /* END Create the drawer canvas */

        /* Event Listeners */
        this.handleClick = function(m) {
            if (this.doIRotate) {
                this.setMouseToPointAngle(m);
                this.rotationInit(this.drawer);
            }
            this.customHandleClick(m);
        };
        this.handleSpriteClicked = function(m) {
            /* Handle collision between mouse and sprite */
        }
    };
    this.kill = function() {
        /* This will remove sprite from world canvas */
        if (this.alive) {
            this.alive = false;
            this.pos.x = 0;
            this.pos.y = 0;
            this.velocity = t.Vector(0, 0);
            this.acceleration = t.Vector(0, 0);
        }

    };
    this.outOfBounds = function() {
        if (this.checkOutOfBounds) {
            var x = this.pos.x,
                y = this.pos.y,
                cW = this.canvas.width,
                cH = this.canvas.height;
            if (x < 0 || y < 0 || x > cW || y > cH) {
                if (this.killOutOfBounds) {
                    this.kill();
                    console.log('Yay killed!')
                }
                return true;
            } else {
                return false;
            }
        }
    }
    this.render = function(a) {
        /* This will place sprite onto x,y position and then draw it */
        if (!this.outOfBounds()) {
            this.alive ? renderWorld(this.drawer.canvas, this.pos.x, this.pos.y) : 'a';
            // console.log(this.alive)
        }
        // console.log('Rendering!!' + this.group)
    }
    this.update = function(dt) {
        /* This is the update function */

        this.velocity.x += this.acceleration.x * dt;
        this.velocity.y += this.acceleration.y * dt;
        this.pos.x += this.velocity.x * dt;
        this.pos.y += this.velocity.y * dt;
        this.outOfBounds();

    };
    this.reset = function(x, y) {
        /* Bring a sprite back to life. Set alive to true */
        this.alive = true;
        this.pos.x = x;
        this.pos.y = y;
        console.log('Ive been reset!!')
    };

    if (this.alive) {
        this.init();
        this.render();
    } else {
        this.init();
    }
    t.sprites.push(this);
    return t.sprites[t.sprites.length - 1];
}
this.Sprite = Sprite;

function Room(obj) {
    this.create = obj.create;
    this.update = obj.update;
    return this;
}

this.mainGame = function(room) {
    var lastUpdate;
    room.create();
    var l = this.sprites.length;

    function loop() {
        stats.begin();
        var now = window.Date.now();

        if (lastUpdate) {
            var elapsed = (now - lastUpdate) / 1000;
            lastUpdate = now;

            // Update all game objects here.
            room.update();
            for (var i = 0; i < l; i++) {
                if (this.sprites[i].alive) {
                    this.sprites[i].update(elapsed);
                }
            }
            // ...and render them somehow.
            t.render();
        } else {
            // Skip first frame, so elapsed is not 0.
            lastUpdate = now;
        }
        stats.end();
        // This makes the `loop` function run 60 frames per second (or slower, depends on monitor's refresh rate).
        t.anim = window.requestAnimationFrame(loop);
    }
    loop();
};

this.renderCanvas = function(layer, img, x, y) {
    var canvas = layer.canvas,
        ctx = layer.canvas.getContext('2d');

    /* Draw image onto the canvas at position (x,y) */
    ctx.drawImage(img, x, y);
};
this.renderWorld = function(img, x, y) {
    renderCanvas(this.world, img, x, y);
};
this.clearCanvas = function(layer) {
    var c = layer.canvas,
        cx = layer.ctx; /* Get the canvas and context of the layer onto which we draw onto */
    cx.clearRect(0, 0, c.width, c.height); /* Clear the layer */
};
this.clearWorldCanvas = function() {
    clearCanvas(this.world);
};
this.render = function() {
    /* Render all the layers now */
    clearWorldCanvas();
    var l = this.sprites.length;
    for (var i = 0; i < l; i++) {
        this.sprites[i].render();
    }
};
this.addSprite = function( /*layer,*/ imgKey, x, y, isAlive) {
    return spr = new this.Sprite(this.world, imgKey, x, y, isAlive);
    // return spr;
};
this.addGroup = function(numEle, key, layer) {
    var grp = new this.Group(numEle, key, layer);
    grp.init();
    return grp;
};
/* ./Public Functions */

return this;
})();

main.js:

/* Thank YOU GOD for this code and may YOU Bless it
Col 3:23 "Whatever you do, work at it with all your heart, as working for the LORD, not for human masters" */

// All rights reserved by Kitanga Nday
var keyArray = [
    'box'
],
srcArray = [
    'img/box.png'
];

NE.init('displayCanvas', 700, 400, keyArray, srcArray);
NE.addRoom('room', {
    create: function() {
    var t = this;
    // debugger;
    this.spr = NE.addSprite('box', 10, 10, true);
    this.spr.doIRotate = true;
    this.spr.acceptsClickEv = true;
    this.bulletPool = NE.addGroup(40, 'box', NE.world);
    console.log(this.bulletPool);
    this.bulletPool.setAttr('checkOutOfBounds', true);
    this.bulletPool.setAttr('killOutOfBounds', true);
    this.bulletPool.setAttr('alive', false);
    this.bulletPool.reloadTime = 2000;
    this.spr.group = this.bulletPool;
    this.spr.customHandleClick = function(ev) {
        /* Take first alive element from bulletpool and reset on this sprite ==> spr. */
        var bullet = this.group.getFirstDead();
        // console.log(this.group);
        bullet.reset(this.pos.x + 20, this.pos.y + 20);
        bullet.applyImpulse(NE.Vector(10, 10));
        /* Give a speed relative to the normalized vector of mouse position. */

    }
},
update: function() {
    // this.spr.velocity = {x:0,y:0};
}
});
NE.startRoom('room');

The html code:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Blank</title>
<meta name="description" content="Game" />
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1" />
<link rel="stylesheet" href="main.css" />
</head>
<body>
<div id="displayCanvas"></div>
<script src="NDAY13ngine.js"></script>
<script src="main.js"></script>
</body>
</html>
\$\endgroup\$
  • 2
    \$\begingroup\$ And you expect someone to read trough all that? \$\endgroup\$ – Tyyppi_77 Sep 13 '16 at 9:10
  • \$\begingroup\$ @Tyyppi_77 All you need to do is look at the Group and Sprite Classes. Also check the main js if that's where the issue is. Otherwise I believe everything else should be fine. Ok maybe the render() might be off, but I can't tell. \$\endgroup\$ – Kitanga Nday Sep 13 '16 at 10:04
  • \$\begingroup\$ @Tyyppi_77 if you have any suggestions of what I should show, I'm all ears. \$\endgroup\$ – Kitanga Nday Sep 13 '16 at 10:05
  • 1
    \$\begingroup\$ Show only the parts that are relevant. Currently there is just too much. Cut everything unnecessary out. \$\endgroup\$ – Tyyppi_77 Sep 13 '16 at 10:15
  • \$\begingroup\$ @Tyyppi_77 so like this? \$\endgroup\$ – Kitanga Nday Sep 13 '16 at 10:47
0
\$\begingroup\$

The issue was in the sprite's init function.

Aparently, I started the drawing functions only if the sprite was alive. Since my sprite's image was drawn on a canvas, and fed to the main canvas, there was no image to draw.

To fix it, I had to set all children in the sprite to dead (aka this.alive = false).

if (this.alive) 
{
    t.renderCanvas(this.drawer, this.img, this.imgOnDrawerX, this.imgOnDrawerY);
    t.renderWorld(this.drawer.canvas, this.pos.x, this.pos.y);
}
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.