Why I can't call to public function in a Javascript namespace - javascript

I want to call to method setupCanvas.Draw(); to draw rectangle.
And for some reason I can not call a function Draw(); from out the scop game.setupCanvas();
Demo jsfiddle
window.game = window.game|| {};
game.main = function() {};
game.setupCanvas = function(){
var w = $(window).outerWidth();
var h = $(window).outerHeight();
myCanvas = document.createElement('canvas');
document.body.appendChild(myCanvas);
myCanvas.id = "playground";
myCanvas.width = w * 0.8;
myCanvas.height = h * 0.8;
myCanvas.style.left= (w - myCanvas.width )/2 + 'px' ;
myCanvas.style.top= (h - myCanvas.height )/2 + 'px' ;
myCanvas.style.zIndex = 10;
myCanvas.style.position = "absolute";
myCanvas.style.border = "1px solid green ";
this.ctx= $('#playground').get(0).getContext('2d');
this.Draw = function(){
ctx.fillStyle="#0000FF";
ctx.fillRect(150,75,150,75);
ctx.fillStyle="#F0F0FF";
ctx.fillRect(0,0,150,75);
};
}();
game.setupCanvas.Draw();
​
Many thanks

You need to create a new instance:
var x = new game.setupCanvas();
x.Draw();
Also, this part is wrong:
};
}(); // <--
game.setupCanvas.Draw();
You're immediately-invoking the function, which you shouldn't be doing. It returns undefined to game.setupCanvas. Take it away and your code should work.
Moreover, when you reference a thectx property in your Draw method, you need to use this.ctx.
jsFiddle Demo

Your assignment of game.setupCanvas is invalid since the self invoking function doesn't return anything so game.setupCanvas will be undefined. Make sure to return an object with your public methods like this.
return {
Draw: function(){
ctx.fillStyle="#0000FF";
ctx.fillRect(150,75,150,75);
ctx.fillStyle="#F0F0FF";
ctx.fillRect(0,0,150,75);
},
DrawSomethingElse: function(){
ctx.fillStyle="#0000FF";
ctx.fillRect(150,75,150,75);
ctx.fillStyle="#F0F0FF";
ctx.fillRect(0,0,150,75);
}
};
Here is an update to your fiddle http://jsfiddle.net/dAvtS/11/

Related

Create and update CSS in two methods

How to update universe variable css using create and update methods below:
var gravity = {
universe: function (width, height, color) {
this._width = width;
this._height = height;
this._color = color;
var universe;
var create = function () {
universe = document.createElement("div");
universe.style.border = "5px solid #DDD";
universe.style.overflow = "hidden";
document.body.appendChild(universe);
};
var update = function () {
universe.style.width = this._width + "px";
universe.style.height = this._height + "px";
universe.style.backgroundColor = this._color;
};
create();
update();
}
}
Update method doesn't work.
your update method "doesnt work" because when you call it, this references the window object.
if you wanted it to work, one possible solution would be to set var that = this; outside of the update method and replace all references to this with that inside the method.
this should clear things up a bit

Need help understanding JavaScript objects

I am trying to understand objects in javascript. Here is the code:
var fn={};
var canvas;
var ctx;
fn.game=function(width,height,inSide,name){
this.canvas2=document.getElementById(inSide).innerHTML = "<canvas id="+name+" style='width:"+width+";height:"+height+";'>Your browser does not support the Canvas Element.</canvas>";
this.canvas=document.getElementById(name);
this.ctx=this.canvas.getContext("2d");
document.getElementById(inSide).style.width=width;
document.getElementById(inSide).style.height=height;
canvas=document.getElementById(name);
ctx=this.canvas.getContext("2d");
this.width=width;
this.height=height;
canvas.width=width;
canvas.height=height;
this.add={
};
this.add.state=function(name){
this[name]=3;
};
};
var game=new fn.game(640,480,"game","canvas");
game.addState("play");
when I am referencing this["name"] I am trying to refer this to fn.game, but that dous not work because this references the most local object. Any ideas on how to do this?
As you said, it references the most local object, to do what you explained :
...
fn.game=function(width,height,inSide,name){
var that = this;//expose this of fn.game to this scope
...
this.add={
};
this.add.state=function(name){
that[name]=3;//access this of fn.game
};
};
There are a couple of ways to do this, and it depends on the way you're doing it, although I think the biggest issue you've got is that your object has no declared function of addState() so when I tried to run your code it just gave me an error. In the code below I changed it, and it should work how you want it to currently.
var fn = {};
var canvas;
var ctx;
fn.game = function(width, height, inSide, name) {
this.canvas2 = document.getElementById(inSide).innerHTML = "<canvas id=" + name + " style='width:" + width + ";height:" + height + ";'>Your browser does not support the Canvas Element.</canvas>";
this.canvas = document.getElementById(name);
this.ctx = this.canvas.getContext("2d");
document.getElementById(inSide).style.width = width;
document.getElementById(inSide).style.height = height;
canvas = document.getElementById(name);
ctx = this.canvas.getContext("2d");
this.width = width;
this.height = height;
canvas.width = width;
canvas.height = height;
this.add = {
};
this.addState = function(name) {
this[name] = 3;
console.log(this);
};
};
var game = new fn.game(640, 480, "game", "canvas");
game.addState("play");
<div id="game"></div>
HOWEVER
If you'd like to have that same syntax as before, of game.add.state(), then something like either of the below examples should work:
Example 1
Link to Function.Prototype.Bind
//Rest of code
this.add={};
this.add.state = function(name){
this[name]=3;
}.bind(this)
//Rest of code
Example 2
Javascript Variables and Scope
//Rest of code
this.add={};
var self = this;
this.add.state = function(name){
self[name]=3;
}
//Rest of Code
every time you are inside a function() the meaning of this changes to the current function
all you need to do is save the reference to the object you want to access
fn.game=function(width,height,inSide,name){
var self = this;
this.add.state=function(name){
self[name]=3;
};
};
In order for this to mean mean fn.game, you would need to do something more like:
var doc = document, bod = doc.body;
function E(e){
return doc.getElementById(e);
}
function C(t){
return doc.createElement(t);
}
function FnGameAdd(){
this.state = function(popertyName){
this[propertyName] = 3;
}
}
function FnGame(canvasId, width, height, inside){
// style with CSS
inside.innerHTML = "<canvas id='"+canvasId+"'>Your browser does not support the Canvas Element.</canvas>";
var cv = this.canvas = E(canvasId);
cv.height = height; cv.width = width; this.ctx = cv.getContext('2d');
this.add = new FnGameAdd;
};
}
var fn = {};
fn.game = function(canvasId, width, height, inside){
// this.prop = 'belongs to fn';
return new FnGame(canvasId, width, height, inside);
}
new fn.game('canvas', 640, 480, E('game'));
/* keep this for fun of creating new Object literals, not needed here
Object.create = Object.create || function(obj){
function F(){}; F.prototype = obj;
return new F;
}
var newObj = Object.create(fn);*/

Issue with scoping, when calling a function in a callback

when clicking inside the canvas it will generate a ball and move to the clicked location
when the ball get's to its location I want it to remove itself. But i think i have a problem
with the scope when calling the removeBall() function.
You can find a working example her: jsfiddle
/*
* Main app logic
*/
function Main() {
this.canvas = "canvas";
this.stage = null;
this.WIDTH = 0;
this.HEIGHT = 0;
this.init();
}
Main.prototype.init = function() {
console.clear();
this.stage = new createjs.Stage(this.canvas);
this.resize();
//start game loop
createjs.Ticker.setFPS(30);
createjs.Ticker.addEventListener("tick", this.gameLoop);
//click event handler
this.stage.on("stagemousedown", function(evt) {
main.fireBall(evt);
});
};
Main.prototype.fireBall = function(evt) {
var bal = new Bal(evt.stageX, evt.stageY);
};
Main.prototype.resize = function() {
//resize the canvas to take max width
this.WIDTH = window.innerWidth;
this.HEIGHT = Math.floor(window.innerWidth * 9 / 16);
this.stage.canvas.width = this.WIDTH;
this.stage.canvas.height = this.HEIGHT;
};
Main.prototype.gameLoop = function() {
//game loop
main.stage.update();
};
/*
* Ball logic
*/
function Bal(toX, toY) {
this.toX = toX ;
this.toY = toY;
this.widthPerc = 8;
this.init();
}
Bal.prototype.width = function() {
return Math.floor(main.stage.canvas.width / 100 * this.widthPerc);
};
Bal.prototype.init = function() {
//create a new ball
this.ball = new createjs.Shape();
this.ball.graphics.beginFill("green").drawCircle(0, 0, this.width());
this.ball.x = (main.stage.canvas.width / 2) - (this.width() / 2);
this.ball.y = main.stage.canvas.height - 20;
main.stage.addChild(this.ball);
this.move();
};
Bal.prototype.move = function() {
//create a tween to cliked coordinates
createjs.Tween.get(this.ball).to({
x: this.toX ,
y: this.toY ,
scaleX:0.4,scaleY:0.4,
rotation: 180
},
750, //speed
createjs.Ease.none
).call(this.removeBall); // <---- How can i pass the correct scope to the called function?
};
Bal.prototype.removeBall = function() {
//try to remove the ball
main.stage.removeChild(this.ball);
};
var main = new Main();
The solution above using bind works, however there is a much better solution. Bind is not available in all browsers (most notably Safari 5.1, which is a modern browser). http://kangax.github.io/es5-compat-table/#Function.prototype.bind
TweenJS has built-in support for scoping functions when using call(). Just pass the scope as the 3rd argument.
Ball.prototype.move = function() {
console.log(this.toX +","+this.toY);
createjs.Tween.get(this.ball).to({
x: this.toX ,
y: this.toY ,
scaleX:0.4,scaleY:0.4,
rotation: 180
},
750, //speed
createjs.Ease.none
).call(this.removeBall, null, this);
};
You can also pass an array of function arguments as the second parameter.
Tween.call(this.removeBall, [this.ball], this);
Ok found a solution! using the bind() functionality.
Bal.prototype.move = function() {
console.log(this.toX +","+this.toY);
createjs.Tween.get(this.ball).to({
x: this.toX ,
y: this.toY ,
scaleX:0.4,scaleY:0.4,
rotation: 180
},
750, //speed
createjs.Ease.none
).call(this.removeBall.bind(this));
};

Javascript - random images error

I have the following problem I have 21 little pictures, and I want them positioned randomly in a the window in defined time intervals.
I have the following code, and I know what causes the problem, but I can't solve it.
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function () {
if (oldonload) {
oldonload();
}
func();
}
}
}
addLoadEvent(Prep6);
addLoadEvent(Prep7);
function Prep6() {
window_Height = window.innerHeight;
window_Width = window.innerWidth;
image_Element = document.getElementById("loader06");
image_Height = image_Element.clientHeight;
image_Width = image_Element.clientWidth;
availSpace_V = window_Height - image_Height;
availSpace_H = window_Width - image_Width;
moveImage7();
var changeInterval = 300;
setInterval(moveImage7, changeInterval);
}
function moveImage6() {
var randNum_V = Math.round(Math.random() * availSpace_V);
var randNum_H = Math.round(Math.random() * availSpace_H);
image_Element.style.top = randNum_V + "px";
image_Element.style.left = randNum_H + "px";
}
function Prep7() {
window_Height = window.innerHeight;
window_Width = window.innerWidth;
image_Element = document.getElementById("loader07");
image_Height = image_Element.clientHeight;
image_Width = image_Element.clientWidth;
availSpace_V = window_Height7 - image_Height;
availSpace_H = window_Width - image_Width;
moveImage7();
var changeInterval = 300;
setInterval(moveImage7, changeInterval);
}
function moveImage7() {
var randNum_V = Math.round(Math.random() * availSpace_V);
var randNum_H = Math.round(Math.random() * availSpace_H);
image_Element.style.top = randNum_V + "px";
image_Element.style.left = randNum_H + "px";
}
And the problem is:
moveImage7();
function moveImage6()
How can I solve it?
I believe you are having some scope issues. In other words, the variables used in your moveImage6() and moveImage7() function are not seen because they are local to your other functions. To fix this you must pass those variables to your moveImage functions. Your moveImage functions are called periodically via the setInterval function, so pass parameters as follows:
setInterval(function(){
moveImage6(availSpace_V, availSpace_H, image_Element);
}, changeInterval);
This would also require you to update your moveImage6() and moveImage7() functions to accept those parameters as well.
Passing parameters with setInterval
jsfiddle: simplified in action
Hope this helps!
PS: you may want to change window_Height7 in prep7() to window_Height

I need help finding errors in my JavaScript mini-game (Three error that i don't get)

This is my first time making a mini-game from complete scratch.
Google chrome gives me these errors at runtime:
Uncaught TypeError: Cannot call method 'draw' of undefined Logic.js:28
loop Logic.js:28
startLoop Logic.js:35
init Logic.js:19
It was working fine when i used "setInterval" but i want the newest stuff.
I don't think that requestAnimationFrame has anything to do with it.
But i don't see what's wrong! Please help.
// Create the canvas
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
canvas.addEventListener('click', canvasClick, false);
//Declarations
var isPlaying = false;
var animeFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame;
var Pair1;
var Pair2;
//init
function init(){
startLoop();
Pair1 = new Pair();
Pair2 = new Pair();
alert('init called');
}
//Draw
function loop(){
if(isPlaying){
Pair1.draw();
Pair2.draw();
animeFrame(loop);
}
}
function startLoop(){
isPlaying = true;
loop();
}
function stopLoop(){
isPlaying = false;
}
//Interface
function canvasClick(){
var X = event.x;
var Y = event.y;
X -= canvas.offsetLeft;
Y -= canvas.offsetTop;
if(X > Pair1.X && X < Pair1.X + 64){
if(Y > Pair1.Y && Y < Pair1.Y + 96){
alert('Clicked Pair1');
};
};
}
//Create Images
var pairImg = new Image();
pairImg.src = "images/Gold_Pair.png";
pairImg.addEventListener('load',init,false)
//Pair
function Pair(){
var X = Math.floor(Math.random() * (canvas.width - 64));
var Y = Math.floor(Math.random() * (canvas.height - 96));
}
//Draw
Pair.prototype.draw = function(){
ctx.drawImage(pairImg, this.X, this.Y, 64, 96);
};
Thanks for you replys!!!
Your "init" function calls "startLoop", which calls "loop", which expects that "Pair1" and "Pair2" have been initialized. However, "init" doesn't initialize them until after calling "startLoop".
Try changing "init":
function init(){
Pair1 = new Pair();
Pair2 = new Pair();
startLoop();
alert('init called');
}
I think the problem is that your function loop requires Pair1 and Pair2 to exist, but init doesn’t do that until after loop has been called (via startloop).
Maybe this version of init would work?
//init
function init(){
Pair1 = new Pair();
Pair2 = new Pair();
startLoop();
alert('init called');
}

Categories