I'm starting to use Jasmine to run tests on my code. Most of the tests so far have been fairly primitive but I'm now facing a problem when checking to see if an array has been populated.
the test is:
describe("create grid of layers", function() {
var result = new Array(4);
it("returns an array of objects as a grid", function() {
result = randomQuadrants();
expect( result).toBeDefined();
});
});
I've also tried:
describe("create grid of layers", function() {
var result = new Array(4);
it("returns an array of objects as a grid", function() {
expect(result = randomQuadrants()).toBeDefined();
});
});
as well but am receiving an error of ReferenceError: fabric is not defined at this line var obj = new fabric.GeologicalObject({ in the following code.
function randomQuadrants() {
var posX, posY;
posY = 175;
for (var i=0; i<10; i++){
//declaring random num here makes each layer the same but random.
grid[i] = new Array(6);
posX = 100;
for(j=0; j<10; j++) {
//random num here makes each square a random layer
var randomNum = random_num(layerDetails.length);
var obj = new fabric.GeologicalObject({
strength: layerDetails[randomNum].strength,
minSpeed: layerDetails[randomNum].minSpeed ,
maxSpeed: layerDetails[randomNum].maxSpeed,
width: 200,
height: 75,
left: posX,
top: posY,
fill: 'red'
});
posX = parseInt(posX) + 200;
loadPattern(obj, layerDetails[randomNum].pattern);
grid[i][j] = obj;
}
posY+=75;
}
return grid;
}
Thanks for any help!
Related
So I'm using the Phaser framework to create a space invaders game but I have a problem with and array of game objects. The array enemies is normal and I can do console.log(enemies.length) fine inside the create method but it says that enemies is not defined when I run it.
var game = new Phaser.Game(800, 600);
var bgTile;
var speed = 200;
var dropCnt = 100;
var box = function(options) {
var bmd = game.add.bitmapData(options.length, options.width);
bmd.ctx.beginPath();
bmd.ctx.rect(0, 0, options.length, options.width);
bmd.ctx.fillStyle = options.color;
bmd.ctx.fill();
return bmd;
};
var mainState = {
preload: function(){
//var music;
//game.load.audio('sound1',['track01.mp3','track01.ogg']); // need to make this spce music
game.load.image('bgTile', 'bgtile.jpg');
},
create: function(){
lives = 3;
//music = game.add.audio('sound1');
//music.loopFull(1);
this.cursor = game.input.keyboard.createCursorKeys();
game.physics.startSystem(Phaser.Physics.ARCADE);
game.world.enableBody = true;
BGTile = starfield = game.add.tileSprite(0, 0, 800, 600, 'bgTile');
game.physics.startSystem(Phaser.Physics.ARCADE);
this.player = game.add.sprite(384, 550, box({
length: 32,
width: 32,
color: '#FFFFFF'
}));
this.enemy = game.add.group();
this.enemy.enableBody = true;
var enemies= [];
for(var i = 0; i < 8; i++){
for(var j = 0; j < 8; j++){
enemies.push(this.enemy.create(i*75+100,j*30+20, box({
length: 32,
width: 16,
color: '#FF0000'
})));
}
}
var bullets= [];
this.bullet = game.add.group();
this.bullet.enableBody = true;
this.player.body.immovable = true;
this.enemy.body.immovable = true;
},
update: function(){
console.log(enemies.length);
starfield.tilePosition.y += 2;
this.player.body.velocity.y = 0;
this.player.body.velocity.x = 0;
if (this.cursor.left.isDown) {
this.player.body.velocity.x -= speed;
} else if (this.cursor.right.isDown) {
this.player.body.velocity.x += speed;
}
dropCnt--;
if(dropCnt === 0){
dropCnt = 100;
for(var i = 0; i < enemies.length;i++){
this.enemies.body.x -= 8;
console.log("test");
}
}
}
};
game.state.add('main', mainState);
game.state.start('main');
Here DEMO
enemies array is defined inside mainState.create() so therefore it's not accessible to another function inside object mainState
In order to access you have to define enemies array as object member
var mainState = {
enemies:[],
....
...
}
So now to access enemies you have to do
mainState.enemies.push(....)
mainState.enemies.pop()
I am trying to change this paperscript:
<script type="text/paperscript" canvas="canvas-1">
tool.minDistance = 10;
tool.maxDistance = 45;
var path;
function onMouseDown(event) {
path = new Path();
path.fillColor = new Color({ hue: Math.random() * 360, saturation: 1, brightness: 1 });
path.add(event.point);
}
function onMouseDrag(event) {
var step = event.delta / 2;
step.angle += 90;
var top = event.middlePoint + step;
var bottom = event.middlePoint - step;
path.add(top);
path.insert(0, bottom);
path.smooth();
}
function onMouseUp(event) {
path.add(event.point);
path.closed = true;
path.smooth();
}
</script>
to a stand alone javascript like:
paper.install(window);
window.onload = function() {
paper.setup('myCanvas');
tool.minDistance = 10;
tool.maxDistance = 45;
var path;
function onMouseDown(event) {
path = new Path();
path.fillColor = {
hue: Math.random() * 360,
saturation: 1,
brightness: 1
};
path.add(event.point);
}
function onMouseDrag(event) {
var step = event.delta / 2;
step.angle += 90;
var top = event.middlePoint + step;
var bottom = event.middlePoint - step;
path.add(top);
path.insert(0, bottom);
path.smooth();
}
function onMouseUp(event) {
path.add(event.point);
path.closed = true;
path.smooth();
}
}
it give me an error:
TypeError: undefined is not an object (evaluating 'tool.minDistance =
10')
What is tool here? I understand that I might need to declare it before I can use it. Any idea how to resolve this?
You need to make the global scope as outlined in the documentation :
paper.install(window);
Then get on with global defs. :
window.onload = function() {
// Get a reference to the canvas object
paper.setup('myCanvas');
// In your case create tools
var tool = new Tool();
tool.minDistance = 10;
tool.maxDistance = 45;
Then continue as usual, this will set up your tools.. More can be found here.
Incidentally you've actually already done this correctly for Path(), so the same applies to Tool()
When I use Paper.js directly in javascript I prefer to create paper object this way:
var canvas = document.getElementById('canvas-line');
paper.setup(canvas);
// and then if you want to create some Paper.js object prefix it's name with paper
var myPath = new paper.Path();
If you want to use tool you need to decelerate it with new paper.Tool();
For example if you want to check whether path was clicked:
var tool1 = new paper.Tool();
var handle;
var myPath;
myPath.fullySelected = true;
tool1.onMouseDown = function(event) {
handle = null;
// Do a hit test on path for handles:
var hitResult = myPath.hitTest(event.point, {
handles: true,
fill: true,
stroke: true,
segments: true,
tolerance: 2
});
if (hitResult) {
if (hitResult.type == 'handle-in') {
handle = hitResult.segment.handleIn;
} else if (hitResult.type == 'segment') {
handle = hitResult.segment.point;
} else if (hitResult.type == 'handle-out') {
handle = hitResult.segment.handleOut;
}
}
}
You can find more informations about tools in here http://paperjs.org/reference/tool/
I have a canvas animation that has been created with createjs. The entire animation script including init() function is loaded via jquery: $.getScript() on page load.
The init() and handlecomplete() function included below is then run which attaches the animation to a html canvas element on the page.
var canvas, stage, exportRoot, audio;
var tweens = [];
function init() {
canvas = document.getElementById("canvas");
images = images||{};
if (stage) {
stage.enableDOMEvents(false);
stage.removeAllChildren();
createjs.Ticker.removeAllEventListeners()
stage.enableDOMEvents(true);
}
if (audio ) {
audio.stop();
}
removeTweens();
exportRoot = null;
audio = null;
stage = null;
var loader = new createjs.LoadQueue(false);
loader.installPlugin(createjs.Sound);
loader.addEventListener("fileload", handleFileLoad);
loader.addEventListener("complete", handleComplete);
loader.loadManifest(lib.properties.manifest);
}
function handleComplete() {
exportRoot = new lib.animation2();
stage = new createjs.Stage(canvas);
stage.addChild(exportRoot);
stage.update();
stage.canvas.width = 1280;
stage.canvas.height = 720;
resizeToFit();
stage.update();
createjs.Ticker.setFPS(lib.properties.fps);
createjs.Ticker.addEventListener("tick", stage);
createjs.Ticker.addEventListener("tick", updateTimer);
if (lib.properties.audiovolume) {
audio = createjs.Sound.play("audio", createjs.Sound.INTERRUPT_EARLY, 0, 0, -1, lib.properties.audiovolume);
}
exportRoot.gotoAndPlay(startFrame );
}
My issue is when the user makes a change, we load the script a second time using the same jquery method which returns the updated script. The init() function then executes properly and the new animation plays correctly, but our animated text (using the animateText below) does not appear on the canvas. This function is also loaded dynamically with other functions.
Checking the tween arrays, they are being created and removed as required, but they are not visible.
They are either layered behind the new animation, or not being attached to the new canvas or something else?
Simply refreshing the page will then load the new script and text properly. So clearly something in the dynamic loading of the script?
var animateText = function(localString, startX, startY, letterClip, endObject, font, color) {
var waitAmount = 0;
var offSetAmount = 20;
for(var i = 0; i < localString.length; i++){
var fl_MyInstance = new letterClip();
fl_MyInstance.localName.text = localString[i];
if(font != null){
fl_MyInstance.localName.font = font;
}
if(color != null){
fl_MyInstance.localName.color = color;
}
var localX = startX;
var localY = startY;
fl_MyInstance.x = startX + offSetAmount;
var beginX = startX + offSetAmount
offSetAmount = offSetAmount - 4
fl_MyInstance.y = startY;
fl_MyInstance.alpha = 0;
fl_MyInstance.scaleX = 0.1;
fl_MyInstance.scaleY = 0.1;
var bounds = fl_MyInstance.getBounds();
startX += bounds.width + 0;
var target = fl_MyInstance;
var tween = createjs.Tween.get(target, {
loop: false
}).wait(waitAmount)
.to({
x: localX,
y: localY,
alpha: 1,
scaleX: 1,
scaleY: 1
}, 400, createjs.Ease.circOut);
tween.waitAmount = waitAmount;
if(endObject == null){
tween.endObject = {
x: localX,
y: localY,
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}
} else {
tween.endObject = {
x: localX - endObject.x,
y: localY - endObject.y,
alpha: endObject.alpha,
scaleX: endObject.scaleX,
scaleY: endObject.scaleY
}
}
tween.targetClip = fl_MyInstance;
tween.arrayIndex = tweens.length;
tweens.push(tween);
waitAmount += 20;
stage.addChild(fl_MyInstance);
}
}
var removeTweens = function(){
for(var i = 0; i<tweens.length; i++){
if(tweens[i] != null){
var tween = tweens[i];
stage.removeChild(tween.targetClip);
tweens[tween.arrayIndex] = null;
}
}
}
var closeTweens = function(){
for(var i = 0; i<tweens.length; i++){
if(tweens[i] != null){
var tween = tweens[i];
createjs.Tween.get(tween.targetClip, {
loop: false
}).wait(tween.waitAmount).to(tween.endObject, 400, createjs.Ease.circOut).call(function(){
stage.removeChild(tween.targetClip);
tweens[tween.arrayIndex] = null;
});
}
}
}
var finalTweens = function(){
for(var i = 0; i<tweens.length; i++){
if(tweens[i] != null){
var tween = tweens[i];
createjs.Tween.get(tween.targetClip, {
loop: false
}).to(tween.endObject, 400, createjs.Ease.circOut);
}
}
}
Since the rest of the animation works perfectly using this method of dynamic loading, I don't think it is something in the loading. But there must be something missing in animateText and reloading functions that causes the issue.
I am trying to load multiple images in a loop but no idea why it ain't working.
LoadCharactersImages2:function(Layer,roomObject)
{
var imgs = Array(5);
var ImgBanners = Array(5);
var sources = Array(5);
var locationX = 100; //x coordinate location of image
var self = this;
self.ImgloadCount = 0;
sources[0] = "images/pacman/pacman_right.png";
sources[1] = "images/pacman/pinkdown.png";
sources[2] = "images/pacman/redleft.png";
sources[3] = "images/pacman/yellowup.png";
sources[4] = "images/pacman/blueright.png";
for(var i = 0 ; i < 5;i++)
{
imgs[i] = new Image();
imgs[i].src = sources[i];
imgs[i].onload = function() {
ImgBanners[i] = new Kinetic.Image({
x: locationX,
y: 100,
image: imgs[i],
});
Layer.add(ImgBanners[i]);
self.ImgloadCount++;
self.AddtoStage(Layer,self);
self.LoadUsersImages(self,roomObject,Layer);
}
locationX = locationX + 100;
}
},
AddtoStage:function(layer,self)
{
if(self.ImgloadCount == 5)
self.stage.add(layer);
},
AddtoStage will add layer to stage when all the images are loaded. Now why it is not showing images on the canvas whats the problem ?
EDIT:
Now i edited the code to work it with closures as #zeta suggested but still no success.Here's the edited code.
imgs[i].onload = (function(index){
return function() {
ImgBanners[index] = new Kinetic.Image({
x: locationX,
y: 100,
image: imgs[index],
});
Layer.add(ImgBanners[index]);
self.ImgloadCount++;
self.AddtoStage(Layer,self);
self.LoadUsersImages(self,roomObject,Layer);
Layer.draw();
}
})(i);
You need a closure:
imgs[i].onload = (function(index){
return function() {
ImgBanners[index] = new Kinetic.Image({
x: locationX,
y: 100,
image: imgs[index],
});
})(i);
See also:
How do JavaScript closures work?
Please have a look at that link. Loads images in a loop of coffeescript
https://gist.github.com/4589644
I solved the problem by removing return function from the statement.
ctx is predefined along with other canvas properties. I didn't want to bombard the page with a huge chunk of code.
I'm building an array of literal objects and they have one method. When I try to call the method it says that It's undefined, like this:
var enemiesArray = [];
function createEnemy(ene) {
for (e = 0; e <= ene; e++) {
var t = Math.floor(Math.random() * 291)
var p = Math.floor(Math.random() * 101)
var enemies = {
x: t,
y: p,
hp: 20,
dir: 0,
damageImage: function () {
return "bomber4.png";
}
}
enemiesArray.push(enemies);
}
}
//an interval is set to call the following function:
function drawEnemey() {
for (zdp in enemiesArray) {
img = new Image();
img.src = "Images/" + enemiesArray[zdp].damageImage(); //this is where I get the error.
img.style.width = "20px";
ctx.drawImage(img, enemiesArray[zdp].x, enemiesArray[zdp].y);
//move from side to side
if (enemiesArray[zdp].dir == 0) {
//move left
enemiesArray[zdp].x -= 1;
if (enemiesArray[zdp].x <= 0) enemiesArray[zdp].dir = 1;
} else {
//move right
enemiesArray[zdp].x += 1;
if (enemiesArray[zdp].x >= 290) enemiesArray[zdp].dir = 0;
}
//check if they are hit
}
}
What I don't understand is when I run the code as is,enemiesArray[zdp].x through enemiesArray[zdp].dir are defined, but enemiesArray[zdp].damageImage() isn't.