Hi I'm trying to count my points in a game. I just started with javascript and working with CreateJS. My problem is that I don't know how I can use a Ticker and Click Event at the same time. It doesn't work...
function init(){
var stage = new createjs.Stage("myCanvas");
stage.mouseEventsEnabled = true;
createjs.Ticker.interval = 1500;
createjs.Ticker.addEventListener("tick", handleTick);
var statPoint = new createjs.Text("Punkte:", "bold 20px Arial", "#000000");
statPoint.x = 750;
var currentPoints = new createjs.Text("0", "20px Arial", "#000000");
currentPoints.x= 850;
var victim = new createjs.Bitmap("Opfer.png");
victim.scaleX = 0.4;
victim.scaleY = 0.4;
stage.addChild(statPoint);
stage.addChild(currentPoints);
stage.addChild(victim);
victim.addEventListener("click", handleClick);
function handleTick(event){
victim.x = 850*Math.random();
victim.y = 550*Math.random();
stage.update();
}
function handleClick(event){
currentPoints.text = parseInt(currentPoints.text + 1);
}
}
You are probably dealing with scope issues. You have defined your victim and currentPoints variables using var inside the init method, so it is only available there. This means your handleTick and handleClick methods can not access those variables. You likely have undefined errors in your console.
Change the variables to be declared outside of the init method, and they will be accessible in the handler methods.
var currentPoints, victim;
function init() {
// Other code
currentPoints = values;
victim = value;
}
Related
I'm building a game similar to the Chrome dinosaur in Vanilla JS. To animate the obstacles I have created a class Obstacle, which stores their position and size, and defines a method that changes the position.
var Obstacle = function (type, w, h, sprite) {
this.h = h; // Obstacle height
this.w = w; // Obstacle width
this.x = 600; // Starting horizontal position
this.y = GROUND - this.h; // Starting vertical position
this.type = type;
this.sprite = sprite;
this.speed = -4;
this.move = function () {
this.x += this.speed;
}
}
These are stored inside an array, defined as a property of a different class:
var ObstacleBuffer = function () {
this.bufferFront = [];
this.createObstacle = function () {
this.bufferFront.push(this.createBox());
}
// Obstacle creators
this.createBox = function () {
if (Math.random() < 0.5) return new Obstacle ("box1", OBSTACLES.box1.w, OBSTACLES.box1.h, OBSTACLES.box1.sprite);
return new Obstacle ("box2", OBSTACLES.box2.w, OBSTACLES.box2.h, OBSTACLES.box2.sprite);
}
//Obstacle animation
this.animateObstacle = function () {
this.bufferFront[0].move();
}
}
When running this an error pops up:
TypeError: Cannot read property 'move' of undefined.
I have logger the content of this.bufferFront[0] and it correctly show the Obstacle stored inside it.
I have also tried assigning this.bufferFront[0] locally to a variable and then tried to call the method from there. The data stored is correct but the error pops up whenever trying to access Obstacles methods or properties.
Any ideas ? Thank you very much.
EDIT - I have reviewed the code as per your suggestions and the problem seems to be at the point where I'm calling the function. Before generating the obstacles I am preloading a series of images and only generating obstacles once these have load:
this.loadWhenReady = function () {
if (self.resources.isLoadComplete()) {
self.sound.load(self.resources.list.sfx);
drawGround();
this.obstacles.createObstacle(); // <--
self.startGame();
return;
} else {
setTimeout(self.loadWhenReady, 300);
}
}
And this is called in:
setTimeout(self.loadWhenReady, 300);
Of course const self = this has been defined before.
Everything seems to move forward when the method is called outside the SetTimeout.
Why is this happening though ? And is there a way of solving this while calling the method in there ?
SOLVED - As #Bergi and #Jaime-Blandon mention it was a context problem. Calling the method from outside the setTimeout loop or using self.obstacle.createObstacle() instead of this.obstacle.createObstacle() did the trick and solved the issue.
Try this change on the ObstacleBuffer Class:
var ObstacleBuffer = function () {
this.bufferFront = [];
this.createObstacle = function () {
//this.bufferFront.push(this.createBox());
this.createBox();
}
// Obstacle creators
this.createBox = function () {
if (Math.random() < 0.5) this.bufferFront.push(new Obstacle ("box1", OBSTACLES.box1.w, OBSTACLES.box1.h, OBSTACLES.box1.sprite));
this.bufferFront.push(new Obstacle ("box2", OBSTACLES.box2.w, OBSTACLES.box2.h, OBSTACLES.box2.sprite));
}
//Obstacle animation
this.animateObstacle = function () {
this.bufferFront[0].move();
}
}
Best Regards!
I try to change a globally declared variable within a function. In Chrome developer tools I see that the variables change to the new values, but when the function is over and I use the variables later, the values are still the same.
Below I added my JavaScript code. The global variables are color, width, height and radius. In html there are input text-fields, in which the user enters the new values and fires the function "save" with a button onclick-event to change the global variables, which are used later (for drawing on Canvas).
Many thanks in advance for your help!! I really don't see the mistake :(
Please see below:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var color = "";
var width = 0;
var height = 0;
var radius = 0;
function save() {
color = document.getElementById("color").value;
width = document.getElementById("width").value;
height = document.getElementById("height").value;
radius = document.getElementById("radius").value;
}
function drawRectangle() {
ctx.fillStyle = color;
ctx.fillRect(20,20,width,height);
}
function drawCircle() {
ctx.beginPath();
ctx.arc(100,100,radius,0,2*Math.PI);
ctx.fillStyle = color;
ctx.stroke();
}
function showPicture() {
var imageObj = new Image();
imageObj.onload = function() {
ctx.drawImage(imageObj, 100, 100, 200, 200, 200,200, width, height);
};
imageObj.src = 'miami.jpg';
}
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var btn3 = document.getElementById("btn3");
btn1.addEventListener("click", drawRectangle, false);
btn2.addEventListener("click", drawCircle, false);
btn3.addEventListener("click", showPicture, false);
Thank you for your answers! I already figured it out. The problem was that I had the input-text fields in form tags, which expected an action post/get method for PHP for further handling. That's the reason why the variables didn't keep the changed values.
After deleting this form tags everything worked out fine.
As I already described above the save() function is being called from the html-file onclick="save();", when I click the button to save the values.
Many thanks for your help.
Hi I'm trying to learn how to use the EaselJS libraries, eventually combining with some of the EXTJS libs butt I'm having trouble putting all my code in the .Js files. My js file looks like this
var democanvas = document.createElement('canvas');
document.body.appendChild(democanvas);
democanvas.height = "400";
democanvas.width = "600";
function init() {
var canvas = document.getElementById("democanvas");
var stage = new createjs.Stage('canvas');
var im = new createjs.Bitmap("dbz.jpg");
// im.regX - im.image.width *.2;
// im.regY - im.image.height *.2;
stage.addChild(im);
stage.update();
im.addEventListener("click", function(){
var seed = new createjs.Bitmap("seed.jpg");
seed.alpha = 0.5;
seed.x = window.event.clientX;
seed.y = window.event.clientY;
stage.addChild(seed);
stage.update();
}); //end seed evenlistener */
} //end functin init()
this doesn't work, but if I comment out the whole document.createElement('canvas') section and I apply
<body onLoad="init();">
<canvas id="demoCanvas" width="1000" height="1000">
alternate content
</canvas>
to my index.html file It will start working :( I included the .js within the body tag of te index html
Edit:::::::::::::::::::::: this is my current code, still not showing anything unless I add the canvas to the html page :(
window.onload = function (){
var demoCanvas = document.createElement('canvas');
//document.body.appendChild(democanvas);
demoCanvas.height = "400";
demoCanvas.width = "600";
}
var stage;
function init() {
stage = new createjs.Stage("demoCanvas");
var text = new createjs.Text("Hello World", "bold 86px Arial", "#ff7700");
stage.addChild(text);
stage.update();
}
init();
Another thing - since you are using image paths, and not fully loaded images as Bitmaps sources, its possible the images are not ready when you update the stage. You can either put onload handlers on your image(s) to update the stage, or preload them first.
var image = new Image();
image.onload = handleLoad;
image.src = "src.jpg";
function handleLoad(event) { stage.update(); }
// You can also use the Bitmap
var bitmap = new createjs.Bitmap("src.jpg");
bitmap.image.onload = handleLoad;
You can also tick the stage to update it constantly. This is a quick way to see if thats the problem.
createjs.Ticker.addEventListener("tick", stage);
// OR
createjs.Ticker.on("tick", stage);
try the below :
document.body.onload = function(){
var democanvas = document.createElement('canvas');
document.body.appendChild(democanvas);
democanvas.height = "400";
democanvas.width = "600";
function init() {
var canvas = document.getElementById("democanvas");
var stage = new createjs.Stage('canvas');
var im = new createjs.Bitmap("dbz.jpg");
// im.regX - im.image.width *.2;
// im.regY - im.image.height *.2;
stage.addChild(im);
stage.update();
im.addEventListener("click", function(){
var seed = new createjs.Bitmap("seed.jpg");
seed.alpha = 0.5;
seed.x = window.event.clientX;
seed.y = window.event.clientY;
stage.addChild(seed);
stage.update();
}); //end seed evenlistener */
} //end functin init()
init();
}
Firstly you need to use the console of your navigator to see javascript's errors before any question.
You will see this error : Uncaught TypeError: Cannot call method 'appendChild' of null
That because you load document.body.appendChild(democanvas); before the html is load so your document.body is null.
This is the way:
function init() {
var democanvas = document.createElement('canvas');
document.body.appendChild(democanvas);
democanvas.height = "400";
democanvas.width = "600";
var canvas = document.getElementById("democanvas");
var stage = new createjs.Stage('canvas');
var im = new createjs.Bitmap("dbz.jpg");
// im.regX - im.image.width *.2;
// im.regY - im.image.height *.2;
stage.addChild(im);
stage.update();
im.addEventListener("click", function(){
var seed = new createjs.Bitmap("seed.jpg");
seed.alpha = 0.5;
seed.x = window.event.clientX;
seed.y = window.event.clientY;
stage.addChild(seed);
stage.update();
}); //end seed evenlistener */
} //end functin init()
I had the same problem and I solved it by using a preloader.
You can use the PreloadJS preloader like this:
var preloader = new createjs.LoadQueue(true);
preloader.addEventListener("complete",this.handleComplete.bind(this));
var manifest = [
{src:"./images/yourIMAGE.PNG"},
//another image
];
I have a class like:
function run(){
this.interval;
this.start = function(){
this.interval = setInterval('this.draw()',1000);
};
this.draw = function(){
//some code
};} var run = new run(); run.start();
however I can't seem to reference/call this.draw() within the setInterval, it says this.draw() is not a function, and if I remove the quotes it says useless setInterval call, what am I doing wrong?
The bind() method!
See the following example in ES6:
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="200" height="200" style="border: 1px solid black"></canvas>
<script>
class Circles {
constructor(canvas, r = 5, color = 'red') {
this.ctx = canvas.getContext('2d')
this.width = canvas.width
this.height = canvas.height
this.r = r
this.color = color
setInterval(
this.draw.bind(this),
1000
)
}
draw() {
this.ctx.fillStyle = this.color
this.ctx.beginPath()
this.ctx.arc(
Math.random() * this.width,
Math.random() * this.height,
this.r,
0,
2 * Math.PI
)
this.ctx.fill()
}
}
</script>
<script>
var canvas = document.querySelector('#canvas')
var circles = new Circles(canvas)
</script>
</body>
</html>
The value of this is set depending on how a function is called. When you call a function as a constructor using new then this will refer to the object being created. Similarly when you call a function with dot notation like run.start() then this will refer to run. But by the time the code run by the setInterval is called this doesn't mean what you think. What you can do is save a reference to this and then use that reference, like the following:
function Run(){
var self = this;
self.start = function(){
self.interval = setInterval(function() { self.draw(); },1000);
};
self.draw = function(){
//some code
};
}
var run = new Run();
run.start();
Note also that you've created a function called run and a variable called run - you need to give them different names. In my code (bearing in mind that JS is case sensitive) I've changed the function name to start with a capital "R" - which is the convention for functions intended to be run as constructors.
EDIT: OK, looking at the other answers I can see that just maybe I overcomplicated it and as long as draw() doesn't need to access this it would've been fine to just say:
this.interval = setInterval(this.draw, 1000);
But my point about not giving your constructor and later variable the same name still stands, and I'll leave all the self stuff in because it is a technique that you will need if draw() does need to access this. You would also need to do it that way if you were to add parameters to the draw() function.
function run(){
this.interval;
this.start = function(){
this.interval = setInterval(this.draw,1000);
};
this.draw = function(){
//some code
}
;}
var run = new run();
run.start();
I'm fairly new to object orientated stuff so this may very well be the wrong way to be going about getting this done.
This is a very slimmed down version of what I currently have, but the concept is essentially the same. When the user clicks on a canvas element on my page, I create 20 instances of the particle object below, append them to an array whilst at the same time updating the canvas at 30FPS and drawing circles based on the x property of the instances of each object. Once a particle is off the screen, it's removed from the array.
var particle = function()
{
var _this = this;
this.velocity = 1;
this.x = 0;
this.updateVelocity = function(newVelocity)
{
_this.multiplier = newVelocity;
}
var updateObject = function()
{
_this.x += velocity;
}
}
I would like the user to be able to control the velocity of new particles that are created using an input element on the page. When this is updated I have an event listener call
particle.updateVelocity(whateverTheUserEntered);
However I get the error "particle has no method updateVelocity". After a bit of reading up on the subject I understand that to call that function I need to create an instance of the object, but this will only update the velocity value of that instance which isn't going to work for me.
My question is, is there a way to achieve what I'm doing or have I approached this in completely the wrong way? As I said, I'm still getting to grips with OOP principles so I may have just answered my own question...
Try this:
var particle = new (function()
{
var _this = this;
this.velocity = 1;
this.x = 0;
this.updateVelocity = function(newVelocity)
{
_this.multiplier = newVelocity;
}
var updateObject = function()
{
_this.x += velocity;
}
})();
Your's is creating a function and then setting the variable particle to that value. particle will not have any special properties because of this. My example above, however, by using new and the function as a constructor assigns particle an instance of a (now anonymous) class.
I think what you want is:
// define a particle "class"
function Particle() {
var _this = {};
_this.velocity = 1;
_this.x = 0;
_this.multiplier = 1;
_this.updateVelocity = function(newVelocity)
{
_this.multiplier = newVelocity;
}
_this.updateObject = function()
{
_this.x += velocity;
}
return _this;
}
// make 1 particle
var myParticle = new Particle();
myParticle.updateVelocity(100);
// make a bunch of particles
var myParticles = [];
for (var i=0; i < 100; i++) {
var p = new Particle();
p.updateVelocity(Math.random * 100);
myParticles.push(p);
}
If you change it to
var particle = new function () {
}
The 'new' will cause creation of an instance.
So create a function that builds new particle instances for you.
Make velocity static and have a static method to update it. This way, you can still make instances of particle and update the velocity for all of them.
var particle = function() {
// particle stuff
}
particle.velocity = 1;
particle.updateVelocity = function(newVelocity) {
this.velocity = newVelocity
}