EaselJS and multi layered canvas system: performance tuning, game developing, event handling - performance

I'm an engineer and we are currently porting our Red5 + Flash game into a Node.js + Easeljs html5 application.
Basicly: it's a board game, not an rpg. The layer system means we have multiple canvasses, based on functionally. For example there is a static background stage, with images. There is a layer for just the timers.
At default, all canvas size is 1920x1080, if needed we downscale to fit to the resolution.
The first approach used kinetic.js, but the performance fallen when the game got complex. Then we switched to easel, because it's abstraction level is lower, so we can decide how to implement some more function, not just use the provided robust one.
I was optimistic, but now it's starting to show slowness again, that's why I want to look deeper inside and do fine performance tuning. (Of course everything is fine in Chrome, Firefox is the problem, but the game must run smoothly on all modern browser).
The main layer (stage) is the map, contains ~30 containers, in each there is a complex custom shape, ~10 images. The containers are listening to mouse events, like mouseover, out, click. Currently, for example on mouseover I refill the shape with gradient.
Somehow, when I use cache, like the way in the tuts the performance get even worse, so I assume I'm messing up something.
I collected some advanced questions:
In the described situation when can I use cache and how? I've already tried cache on init, cacheUpdate after fill with other color or gradient, then stage.update(). No impact.
If I have a static, never changing stage cache doesn't make sense on that layer, right?
What stage.update() exactly do? Triggering the full layer redraw? The doc mentions some kind of intelligent if changed then redraw effect.
If I want to refill a custom shape with new color or gradient I have to completely redraw its graphics, not just use a setFill method, right?
In easel there is no possibility to redraw just a container for example, so how can I manage to not update the whole stage, but just the one container that changed? I thought I can achieve this with caching, cache all containers the just update the one that changed, but this way didn't work at all for me.
Does it make sense to cache bitmap images? If there are custom shapes and images in a container what is better? Cache the container or just the shape in container.
I found a strange bug, or at least an interesting clue. My canvas layers totally overlapping. On the inferior layers the mouseover listening is working well, but the click isn't on the very same container/object.
How can I produce a click event propagation to overlapped layers those have click listeners? I've tried it with simple DOM, jquery, but the event objects were far away from what canvas listeners wanted to get.
In brief, methods and props I've already played with bare success when tried tuning: cache(), updateCache(), update(), mouseEnabled, snapToPixel, clear(), autoClear, enableMouseOver, useRAF, setFPS().
Any answer, suggestion, starting point appreciated.
UPDATE:
This free board game is a strategy game, so you are facing a world map, with ~30 territories. The custom shapes are the territories and a container holds a territory shape and the icons that should be over the territory. This container overlapping is minimal.
An example mouse event is a hover effect. The player navigate over the territory shape then the shape is getting recolored, resized, etc and a bubble showing up with details about the place.
Basically, maximum amount of 1-3 container could change at once (except the init phase -> all at this time). Not just the animations and recoloring slow in FF, but the listener delay is high too.
I wrote a change handler, so I only stage.update() up on tick the modified stages and the stages where an animation is running (tweenjs).
In my first approach I put every image to the container that could be needed at least once during the game, so I only set visible flags on images (not vectors).

Regarding caching:
There are some strange caching-issues, somehow the performance can drop with certain sizes of the caching rectangle: CreateJS / EaselJS Strange Performance with certain size shapes
(2) Depending on how often you call stage.update();
(3)
Each time the update method is called, the stage will tick any
descendants exposing a tick method (ex. BitmapAnimation) and render
its entire display list to the canvas. Any parameters passed to update
will be passed on to any onTick handlers.
=> Afaik it rerenders everything if not cached
(4) Yes.
(5) No. (I don't know of any)
(6) If the content's of the container don't change often, I'd cache the whole container, otherwise the container will be reconstructed every frame.
I have a question though: Why do you use multiple canvases? How many do you use? I could imagine that using multiple canvases might slow down the game.
How many sprites do you use in total?

2: if your layer or stage doesn't change, don't call stage.update() for that layer (so it doesn't gets rerendered, gives me a much lower cpu!)
For example, keep a global "stagechanged" variable and set this to true when something has changed:
createjs.Ticker.addEventListener("tick",
function() {
if (stagechanged)
{
stagechanged = false;
stage.update();
}
});
(or do you already use this, as stated in your "update"?)
4: I found a way to update for example the fill color :)
contaier1.shape1.graphics._fillInstructions[0].params[1] = '#FFFFFF';
(use chrome debugger to look at the _fillInstructions array to see which array position contains your color)
5: I found a way to just paint one container :)
//manual draw 1 component (!)
var a = stage.canvas.getContext("2d");
a.save();
container1.updateContext(a); //set position(x,y) on context
container1.draw(a);
a.restore();

Related

Gamemaker Studio2, Draw GUI layer conflict

I would like to preface this by saying I am still quite new to gameMakerstudio and I do not know all there is to know about how the software works and this is probably the root cause of my problem as I do not know why I am having this current layering issue.
I have been having an issue where I have TWO DrawGUI events in separate objects within the same room.
The first object is a Fog Of War that draws a GUI and reveals the map as the player moves, and keeps explored places visible but not in view.
The second object is the joystick where a player will use their thumb to drag the stick to move the player.
Ever since I have implemented the Fog of War. I have been unable to view the joystick. It appears that the fog of war draws overtop of it and I am unable to use it.
I understand there are other draw events where I can do this.
Draw
Draw GUI
Draw Begin
Draw End
Draw GUI BEGIN
Draw GUI END
After changing where I have the code drawing.
Example: At first the joystick and the fog were both in Draw GUI, After moving one from Draw GUI to Draw GUI Begin, the same issue appears.
I have made sure to place the joystick at the top most level in the room and the fog of war at the bottom most layer.
I have tried to apply depth the object
oJoystick_Stick.depth = -100;
this does not achieve anything.
Is there another way to force two objects on the GUI layer to be on top of the other?
To my understanding, DrawGUI always prioritises the objects drawn there above anything in Draw, including Begin Draw and End Draw. This is because DrawGUI is for an interface (like the stats you see about your character like health, ammo ect.), and objects drawn there aren't part of the room itself. You may also have noticed that the objects drawn in DrawGUI also follows the camera/Viewpoint.
So, to clear up the draw priority:
First is the DrawGUI layer that places objects in front of everything, like an interface.
After that, the depth variable and layers inside the room has priority, each layer has also given a depth value, with an interval of 100.
If the depth is also the same (for example when they're in the same layer), then the order of the objects and code loaded decides the order drawn.
The latter is not always reliable when multiple objects are overlapping at the same depth, because if the objects are redrawn in-game again (e.g. a persistent object been loaded into a new room, or pause and unpause using instance_activate_all), then the order of objects drawn may differ. Keep in mind when overlapping objects, that they are placed in different layers to prevent mixed priorities.
I've however not used a Fog of War system myself, so I don't know if it's build-in or not, but I wouldn't recommend placing them in the DrawGUI, as that should be reserved for the interface layout. With the default Draw options, you'll have more flexibility to the layers inside the room.
Some advice about DrawGUI
DrawGUI Begin --> call the event before every drawGUI in that moment
DrawGUI --------> the event is called sync with the screen refresh rate
DrawGUI End ----> call the event after every drawGUI in that moment
so GM-Studio "pipeline" for the DrawGUI is like the step event, we have a BEGIN, a CURRENT, an END.
To prioritize the object render, GM-Studio use the depth in-build variabile. Take the 0 as the reference value. Object with depth value > 0 are rendering as last. Object with depth value < 0 are rendering infront everything.
Check the depth during the calling of the instance_create_depth() function, check where the depth variabile is changing, check in the room editor for each instance layer the depth value. and z-order.

JavaFX DragView Image has lowered opacity compared to actual image... Can that be changed?

I have been working on using Drag and Drop with JavaFX, and one thing I notice is that items are given lowered opacity compared to their actual images, as well as the larger the image the made "Faded/transparent" the image gets. I am working on am application that can drag fairly large items which end up almost invisible when dragging, which defeats the purpose of using a DragView Image in the first place, and makes this unusable for larger items (the way I'm using the DragView I want the images to be a certain size compared to the scene in which I'm dragging onto).
My application essentially has 2 Windows (Stages) where the data is in one Stage and I get the item from a list and drag it onto the scene. The DragView image is a representation of the object going onto the scene, so when I drop the DragView Image, it gets dropped exactly into place on the scene, so the DragView is important to my overall application.
Just a NOTE: There is also backing data in my transfer in order to recreate the box, as well as additional data that gets transferred with the Drag and Drop.
I tried looking at the FX DragView Internal code but didn't find anything that sets the Opacity or anything like that, so one of my assumptions of "it's built into the OS" is something I keep thinking about, as lowered opacity is something I remember being built in, and when trying it it does happen, but very very slight, and not as bad as what I'm experiencing (Also possible that since the icons are much smaller they don't run into the "larger image opacity issue."
I am running Windows 7 64-Bit for those who are wondering.
My question is, is it possible to change the opacity settings of the Drag and Drop ImageView either via JavaFX or possibly Native with using something along the lines of JNI?
I don't have any example code at the moment, but can add if someone is interested, but I'm sure for those who know about Drag and Drop ImageViews should already know about the opacity.
Thank you all.

hiding movieclip, rendering performance

I'm developing a rendering engine for a game i am currently building..
I have a main camera (rectangle) that determines what needs to be rendered (thing within it's boundaires)
I am using a bitmap rendering method for the background and that all works fine.
but for the character i am using a movieclip over the top.
when the character goes out of the camera's view is it 100% neccesary to set visible=false?
atm the game is running at 30 FPS (as intended) and everything is sweet, i just wanted to ask out of curiosity.
Is flash clever enough to not bother with movieclip outside of the scene boundaires?
Thanks in advance,
Rory
According to http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7e3e.html Flash won't render if an object is outside of Stage boundaries:
Display list
The hierarchy of display objects that will be rendered as visible
screen content by Flash Player and AIR. The Stage is the root of the
display list, and all the display objects that are attached to the
Stage or one of its children form the display list (even if the object
isn’t actually rendered, for example if it’s outside the boundaries of
the Stage).
In my experience display objects added to the stage cause a performance hit even if they are not rendered.
Setting visible to false causes a much lower performance hit, but still a small hit.
Removing unnecessary display objects from the display list is a documented performance tip from adobe as well.
Of course, if you only have a few dislay objects it might not be worth the effort, but if we talk about large amounts of display objects I strongly recommend removing them from the display list.

Cocoa drawing issues

I'm working on an application that does some drawing on the screen based on information received over the network. 
My problem is that sometimes those events come in at a rate higher than I can draw and I'm experiencing a delay. Now the problem isn't with the delay it's with the type of delay that builds up. 
If I would draw based on events such as clicking with the mouse and dragging this doesn't happen and I assume it's because of the way events are delivered. How could I find out when the view is "ready" to draw again because then I could discard some of the events received over the network and draw just the most recent ones. 
Right now I have a transparent window that is on "top" of the window hierarchy. 
Im drawing on an NSImage that is the size of the screen an after each drawing operation I make a setneedsdisplayinrect call to the view in which the drawing happens. When I receive the drawrect call I draw the portion of the image which is included in the dirty rect. 
My attempt of solving this is a bit of a hack since I don't know another way to do it. I set a Boolean to true after each setneedsdisplayinrect and I set it to false in drawrect. If I get a subsequent event to draw on the image I just ignore it of the Boolean is set to true. 
What other alternatives of doing this do I have? 
I thought of using cashapelayers and modifying their path but I'm not sure how efficient shape layers are once the path gets big. I also thought of using multiple shape layers for different portions of the path that are separated (not continuous) but if I want to clear the drawing and i remove the layers if there are many I noticed a bit of a performance hog. 
The only other way I could think of is drawing with open gl but considering the nature of the OpenGL view (screen size and transparent) I'm not sure how much of a performance issue will this be. 
Any tips would be greatly appreciated. 
Thanks. 
I figured it out :)
From the object that managed the network connection I was sending events out using the main dispatch queue. Which from what I understand - I might be wrong about this - can span across multiple iterations of the runloop. What I needed was to dispatch events during each iteration of the run loop and by creating a custom run loop source that would signal the main runloop every time I get a new event over the network connection it greatly improved my performance.

How does CATransition work?

CATransition is quite unusual. Consider the following code.
CATransition* trans=[CATransition animation];
trans.duration=0.5;
trans.type=kCATransitionFade;
[self.holdingView.layer addAnimation:trans forKey:nil];
self.loadingView.hidden=YES;
self.displayView.hidden=NO;
Notice that nowhere did I tell the transition that I wanted to display the displayView rather than loadingView, so the views must somehow access the transition themselves. Can anyone explain in more detail how this works?
When you add the transition as an animation, an implicit CATransaction is begun. From that point on, all modifications to layer properties are going to be animated rather than immediately applied. The way the CATransition performs this animation to to take a snapshot of the view before the layer properties are changed, and a snapshot of what the view will look like after the layer properties are changed. It then uses a filter (on Mac this is Core Image, but on iPhone I'm guessing it's just hard-coded math) to iterate between those two images over time.
This is a key feature of Core Animation. Your draw logic doesn't generally need to deal with the animation. You're given a graphics context, you draw into it, you're done. The system handles compositing that with other images over time (or rotating it in space, or whatever). So in the case of changing the hidden state, the initial-state fully composited image is blended with the final-state composted image. Very fast on a GPU, and it doesn't really matter what change you made to the view.

Resources