Passing Canvas Display

I’m trying to render a sprite from a class/object that I’ve created, its saying “addchild” is not a method when I do this:

tilesheetCanvas = new Sprite();
addChild(tilesheetCanvas);

Is there a way I can pass in a reference to the canvas, so I can do canvas.addChild?

Does your custom class need to extend Sprite? :wink:

Ah dang, I did extend sprite. I am getting an error which means my problem must be somewhere else.

Thanks for the help. :relieved:

I’ve actually narrowed it down, I’ve created an object in a separate file which draw graphics, however its not being allowed access to my images:

var tilesBitmapData:BitmapData = Assets.getBitmapData(“img/tiles.png”);
tilesheetCanvas = new Sprite();
addChild(tilesheetCanvas);
tilesheet = new Tilesheet(tilesBitmapData);
//Split tilesheet up into blocks
for (y in 0…40){
for (x in 0…8){
tilesheet.addTileRect(new Rectangle(x90, y30, 90, 30));
}
}

It throws an error:

DefaultAssetLibrary.hx:727: Warning: Could not load asset manifest (Invalid call)
Assets.hx:310: [Assets] There is no Image asset with an ID of “img/tiles.png”

Anyone have any ideas? Do I have to declare my assets differently for objects, I have it importing with: import openfl.Assets; inside the file.

Do you have the following in your XML file?

<assets path="assets/img" rename="img" />

And is that where the image is located?

When you build it also, Haxe will generate hx source object files (not actual object files for C++, configuration files) located in “bin/windows/bin/obj” which would include things like ApplicationMain.hx. That’s used to map resources into the application if you were to consider embedding them instead of making them separate resources. Regardless, the mapping needs to be done, so if you have an image that has not be output to the application’s build path, you may need to rebuild your game.

You may find that in your callstack there will be a line reference to ApplicationMain.hx because the ID is missing, meaning that the reference to the image was not mapped correctly or detected by the OpenFL build command.

Thanks for the suggestions, however I know its taking the assets as the code was working before I tried to turn it into an object. I also do see it under the bin file. It seems to simply take issue with handing the assets over to an object.

Perhaps I have a problem somewhere else, kind of a peculiar error though. I will try moving just the rendering to the main class.

Actually does anybody know if its possible to split code up between different files without using objects/classes? I am only putting it in an object to organize the code, if I could put it as an “include” like in php that would be awesome.

Why are you trying to avoid using multiple classes? Haxe is an object-oriented language; go ahead and take advantage of it.

Well its a loop to draw tiles, so I was hoping for it to be as fast as possible without being unreadable. As far as I know objects incur an overhead to performance.

You’re probably looking for static functions, which don’t require instantiating anything.

But first, you should also consider the “rules” of optimization:

  1. Don’t.
  2. Don’t… yet.
  3. Profile before optimizing.

In other words, worry about code structure first, and don’t worry about performance until you actually find a performance issue.

If you’re storing data for a bunch of tiles, why don’t you have a Tile class? It’s about as efficient as any other way you could store that data, but it’s easier to understand and modify.

1 Like

Okay I finally got it solved. Apparently I have to use the “addchild(tilesheetCanvas)” from the main class, which means I have to create a function to pass the tilesheetCanvas back to the main class, then call addchild on it; then it worked normally from my render object using:

tilesheet.drawTiles(tilesheetCanvas.graphics, tileData,true);

So everything can be done from the created object, except the addchild part.

Thanks for the help.

Or add a parameter to Tilesheet's constructor:

public function new(main:Main) {
    //...
    
    tilesheetCanvas = new Shape();
    main.addChild(tilesheetCanvas);
}

Calling main.addChild(tilesheetCanvas); in your Tilesheet class is the same as calling addChild(tilesheet.tilesheetCanvas); from Main.


Another option is to make Main a singleton:

public static var instance(default, null):Main;

public function new() {
    instance = this;
    
    //...
}

With that done, you can call Main.instance.addChild() from anywhere.


You can also add children to Lib.current, but that’ll make it slightly harder to keep track of what order things are in.

Oh cool thanks, that top one seems to be what I want to do. What do I pass in when I create the function though, the arguement for “main”? I’m guessing its self, or something similar, but nothing I’ve tried is working.

The keyword you’re looking for is “this.”

1 Like