Jump to content

CreateJS Noob - Problem with my Sprite class


ItsYaBoiWesley
 Share

Recommended Posts

Hi! I'm an experienced programmer with C++, but just getting started with JavaScript. I'm making a simple 2D game to get started. I'm using the CreateJS library to do my image/spritesheet manipulation.

Right now, I'm trying to create a Sprite class, which will set up a spritesheet in the constructor, and draw the sprite with coordinates in the draw() function. (a member of my Sprite class) Anyways, I'm doing some debugging now. My program stops in the constructor of my Sprite class, and I can't figure out why. To anyone with CreateJS experience, what is wrong with my constructor function?!?!?! Thanks!

 

class Sprite {
  constructor(src, frameWidth, frameHeight) {
    window.alert("DEBUG constructor. " + src + ", " + frameWidth + ", " + frameHeight); //Gets here
    this.spriteSheet = new createjs.SpriteSheet({
        images: [queue.getResult(src)],
        frames: {width: frameWidth, height: frameHeight},
        animations: { ani: [0,4] }
    });

    window.alert("DEBUG end constructor"); //Never gets here
  }
  draw(x, y) {
    animation = new createjs.Sprite(this.spriteSheet, "ani");
      animation.regX = 99;
      animation.regY = 58;
      animation.x = enemyXPos;
      animation.y = enemyYPos;
      animation.gotoAndPlay("ani");
      stage.addChildAt(animation,1);
  }
}

 

Link to comment
Share on other sites

1 hour ago, b10b said:

What does your dev-console tell you (F12)?  There are elements outside of the code shared that may be causing ''new createjs.SpriteSheet' to not return (e.g. queue), or perhaps the createjs functions may not be loaded etc.  @ItsYaBoiWesley feel free to share more (e.g. link to online demo).

Hi, I'm using "Atom" code editor for my code. I don't think there's a dev console. Where can I find an IDE that does have such a thing? I tried Visual Studio Code, but can't get it to work on 2 computers!

Without a dev-console, is there any way to find the desired information? I simply run my application with google chrome.

Link to comment
Share on other sites

13 minutes ago, ItsYaBoiWesley said:

I don't think there's a dev console

Sorry I wasn't clear, the dev-console is in the browser (e.g. Chrome).

IDE's like Atom aren't able to help too much with debugging for vanilla JS.  With your experience you may prefer to adopt Haxe or Typescript (to transpile your JS from a typed language) and gain a few more compile-time and IDE benefits :)

Link to comment
Share on other sites

Ah I see. I just checked out the console, thank you so much! This will be very helpful going forward! After correcting a series of other errors, here is the remaining error. (Which, again, runs in the constructor)

 

Uncaught TypeError: Cannot read property 'getContext' of undefined
    at a.b.initialize (createjs-2013.12.12.min.js:12)
    at new a (createjs-2013.12.12.min.js:12)
    at new Sprite (init.js:24)
    at init (init.js:79)
    at onload (index.html:9)

I searched up this error, and it seems to have something to do with the way my program is structured. Again, I'm a total newbie to JS, so the way a JS program is structured is still alien to me. The code you saw in my original post is in "init.js". Here is "index.html", my HTML file.

 

<!DOCTYPE html>
<html>
    <head>
        <title>Cat & Mouse EYESIGHT DEMO</title>
        <link href="normalize.css" type="text/css" rel="stylesheet" />
        <script language="javascript" type="text/javascript" src="http://code.createjs.com/createjs-2013.12.12.min.js" ></script>
        <script language="javascript" type="text/javascript" src="init.js" ></script>
    </head>
    <body onload="init();">
      <canvas id="demoCanvas" width="1000" height="1000"></canvas>
    </body>
</html>

 

Link to comment
Share on other sites

@ItsYaBoiWesley I am unsure if you've done this, but CreateJS needs to 'know' about your canvas ('demoCanvas').

So typically a 'new createjs.Stage()' is created, with the root canvas injected into the constructor.  Then additional displayObjects are attached to that Stage (as you're doing with your line 'stage.addChildAt(animation,1);').  Without this step Stage is not bound to a canvas, and so cannot 'getContext' - a term relating to the interface methods that sit atop a canvas that allow us to draw and transform (CreateJS uses this alot).

The getting started example shows this step:
https://createjs.com/getting-started

Link to comment
Share on other sites

This might be helpful. Here's what I'm doing in my JS initialization. (My HTML is unchanged)

window.alert("initialized");
  var canvas = document.getElementById('demoCanvas');
  context = canvas.getContext('2d');
  context.canvas.width = 1000;
  context.canvas.height = 1000;

  stage = new createjs.Stage("demoCanvas");

//QUEUE:
  queue = new createjs.LoadQueue(false);
  queue.installPlugin(createjs.Sound);
  queue.on("complete", queueLoaded, this);
  createjs.Sound.alternateExtensions = ["ogg"];

  window.alert("createJS did stuff");

  queue.loadManifest([
      {id: 'backgroundImage', src: 'assets/background.png'},
      {id: 'mouse', src: 'assets/mouse.png'},
  ]);
  queue.load();

  window.alert("manifest loaded");

These variables are defined globally

var stage;
var queue;
var context;

 

Link to comment
Share on other sites

@ItsYaBoiWesley hey, I suspect the issue is because your init.js is being run as soon as it loads (which is slightly ahead of body instantiating the canvas element, hence no getContext).  Given that you are calling 'init()' in the body.onLoad I suspect you intended to have all of init.js wrapped in a function?

So add:

function init()
{
  ... existing init.js code here
}

Then you'll encounter the issue 'queueLoaded is not defined' ... so add a function in for that and continue ...

Don't give up, getting any new project bootstrapped for that first build is always a challenge - often looking back later to see it was obvious :)

Link to comment
Share on other sites

Thanks for all the help. I don't have my entire init.js file wrapped in a function. Rather, Init() is the function I want to run first in the program.

I've made some changes, (to no avail) but here is my new index.html (I've removed that part in the onload)

<!DOCTYPE html>
<html>
    <head>
        <title>Cat & Mouse EYESIGHT DEMO</title>
        <link href="normalize.css" type="text/css" rel="stylesheet" />
        <script language="javascript" type="text/javascript" src="http://code.createjs.com/createjs-2013.12.12.min.js" ></script>
        <script language="javascript" type="text/javascript" src="init.js" ></script>
    </head>

    <body>
      <canvas id="demoCanvas" width="1000" height="1000"></canvas>
    </body>
</html>

Here is what I want the program to run FIRST (in Init.js) In init.js, there are other functions and classes. But here is the function I want to run first.

window.onload = function() {

  window.alert("initialized");
  canvas = document.getElementById('demoCanvas');
  context = canvas.getContext('2d');
  context.canvas.width = WIDTH;
  context.canvas.height = HEIGHT;

  stage = new createjs.Stage("demoCanvas");

//QUEUE:
  queue = new createjs.LoadQueue(false);
  queue.installPlugin(createjs.Sound);
  queue.on("complete", queueLoaded, this);
  createjs.Sound.alternateExtensions = ["ogg"];

  window.alert("createJS did stuff");

  queue.loadManifest([
      {id: 'backgroundImage', src: 'assets/background.png'},
      {id: 'mouse', src: 'assets/mouse.png'},
  ]);
  queue.load();

  window.alert("manifest loaded");

AND SO ON...
});

Notice I'm doing window.onload, so I assume this function should load once everything is finished loading. If not, how do I make this function run once everything is finished loading?

Yes, I agree. Getting the first bootup is always the hard part. When I first learned C++, that was the case. From that point on, it was smooth sailing. (Well, not really. But you get the point. ?)

Link to comment
Share on other sites

@ItsYaBoiWesley I think you're almost there - and that code (with the exception of the missing globals (WIDTH, HEIGHT, queueLoaded) and the extraneous ');' at the end of the file - runs ok for me.  To answer your question of 

39 minutes ago, ItsYaBoiWesley said:

how do I make this function run once everything is finished loading?

There are various ways, each with pros and cons.  window.onload (or the equivalent body.onload) can vary from browser to browser, some waiting for all assets to load, some not.  I would suggest neither are what you want longer-term.  Best to launch your game when you need, and separate concerns from the DOM.  So the game should be a function in itself (like the init() method of the createjs example).  You can, optionally, call it directly and immediately on first load by adding the parenthesis on the end:

game = function()
{
  ... 
}();

Loading the js directly in the body (after any body dependencies have been established) is an easy way to manage load order:

<body>
  <canvas id="gameCanvas"></canvas>
  <script src="http://code.createjs.com/createjs-2013.12.12.min.js"/>
  <script src="game.js"/>
</body>

I often do things this way - obvious, simple and effective.  Only if I need conditional loads will I do anything more complex.

Link to comment
Share on other sites

Ok, I put all of my code in init.js into an init() function, which contains the classes and also the workflow in the original (small) init function. Now, how do I call that function from HTML? (Making sure everything was initialized)

The function is init() in init.js

<!DOCTYPE html>
<html>
    <head>
        <title>Cat & Mouse EYESIGHT DEMO</title>
    </head>

    <body>
      <link href="normalize.css" type="text/css" rel="stylesheet" />
      <canvas id="demoCanvas" width="1000" height="1000"></canvas>
      <script language="javascript" type="text/javascript" src="http://code.createjs.com/createjs-2013.12.12.min.js" ></script>
      <script src="init.js"></script>
    </body>
</html>

 

Link to comment
Share on other sites

Ok. Same error. Here are both of my files in full.

HTML:

<!DOCTYPE html>
<html>
    <head>
        <title>Cat & Mouse EYESIGHT DEMO</title>
    </head>

    <body>
      <link href="normalize.css" type="text/css" rel="stylesheet" />
      <canvas id="demoCanvas" width="1000" height="1000"></canvas>
      <script language="javascript" type="text/javascript" src="http://code.createjs.com/createjs-2013.12.12.min.js" ></script>
      <script src="init.js"></script>
    </body>
</html>

INIT.JS:

init = function() {

  var stage;
  var queue;
  var context;
  var canvas;
  var WIDTH = 1024;
  var HEIGHT = 768;

  class Circle {

    constructor() {
      //window.alert("constructor");
      this.circ = new createjs.Shape();
      //window.alert("E constructor");
    }
    draw(x, y, s) {
      //window.alert("drawing");
      this.circ.graphics.beginFill("DeepSkyBlue").drawCircle(0, 0, s);
      this.circ.x = x;
      this.circ.y = y;
      stage.addChild(this.circ);
    }
  }

  class Sprite {
    constructor(src, frameWidth, frameHeight) {
      window.alert("DEBUG constructor. " + src + ", " + frameWidth + ", " + frameHeight);
      // Create bat spritesheet
      this.spriteSheet = new createjs.SpriteSheet({
        "images": [queue.getResult(src)],
        "frames": {"width": frameWidth, "height": frameHeight},
        "animations": { "flap": [0,4] }
      });

      window.alert("DEBUG econstrucor");
    }
    draw(x, y) {
      var animation = new createjs.Sprite(this.spriteSheet, "ani");
      animation.regX = 99;
      animation.regY = 58;
      animation.x = enemyXPos;
      animation.y = enemyYPos;
      animation.gotoAndPlay("ani");
      stage.addChildAt(animation,1);
    }
  }

  function queueLoaded(event)
  {
    // Add background image
    var backgroundImage = new createjs.Bitmap(queue.getResult("backgroundImage"))
    stage.addChild(backgroundImage);
  }


  window.alert("initialized");
  canvas = document.getElementById('demoCanvas');
  context = canvas.getContext('2d');
  context.canvas.width = WIDTH;
  context.canvas.height = HEIGHT;

  stage = new createjs.Stage("demoCanvas");

  //QUEUE:
  queue = new createjs.LoadQueue(false);
  queue.installPlugin(createjs.Sound);
  queue.on("complete", queueLoaded, this);
  createjs.Sound.alternateExtensions = ["ogg"];

  window.alert("createJS did stuff");

  queue.loadManifest([
    {id: 'backgroundImage', src: 'assets/background.png'},
    {id: 'mouse', src: 'assets/mouse.png'},
  ]);
  queue.load();

  window.alert("manifest loaded");

  var objX = 100;
  var objY = 100;

  var Spi = new Sprite('mouse', 198, 148);

  window.alert("rdy");

  document.addEventListener('keydown', function(event) {
    if(event.keyCode == 37) {
      objX -= 10;
    }
    if(event.keyCode == 38) {
      objY -= 10;
    }
    else if(event.keyCode == 39) {
      objX += 10;
    }
    else if(event.keyCode == 40) {
      objY += 10;
    }
    Spi.draw(objX, objY);

    stage.update();
  });

  window.alert("done");
}()

As you can see, everything is in the function like you said. ?

Link to comment
Share on other sites

@ItsYaBoiWesley so close.  Welcome to async.  Your code after queue.load() is executing immediately, it's not waiting for the queue to complete loading.  Instead it should be called in (or by) the queueLoaded function (which is called when load is completed).  Moving it there, (and fixing the name of 'x','y' params) shows a spritesheet animating on keypress.

Link to comment
Share on other sites

Great! That issue has been solved. I also found those variables I needed to rename, thanks!

New problem. When I hit a key, these errors appear repeatedly as I hold down or press the key. Still no sprite. My thoughts are that it has to do with the Sprite.draw() function.

Uncaught RangeError: Maximum call stack size exceeded
    at a.b._normalizeFrame (createjs-2013.12.12.min.js:13)
    at a.b._normalizeFrame (createjs-2013.12.12.min.js:13)
    at a.b._normalizeFrame (createjs-2013.12.12.min.js:13)
    at a.b._normalizeFrame (createjs-2013.12.12.min.js:13)
    at a.b._normalizeFrame (createjs-2013.12.12.min.js:13)
    at a.b._normalizeFrame (createjs-2013.12.12.min.js:13)
    at a.b._normalizeFrame (createjs-2013.12.12.min.js:13)
    at a.b._normalizeFrame (createjs-2013.12.12.min.js:13)
    at a.b._normalizeFrame (createjs-2013.12.12.min.js:13)
    at a.b._normalizeFrame (createjs-2013.12.12.min.js:13)

Thank you SO MUCH for all of this help! It's so great that you're so willing to be helpful!

Link to comment
Share on other sites

Oh my god! Updating the version worked! Thank you so much, the sprite is now moving happily across the screen.

However, the sprite is not animated. It remains of frame 0 as it moves. (And yes, I fixed those names to be consistent in the class)

I'm gonna keep working on figuring out why the sprite doesn't animate, it's probably just some dumb bug. But any insight you could give might help.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...