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>