how to draw many CCSprite without slow performance? - performance

I'm making such a arrow shooting game. Everything is good. but I realized if I draw line tracking my arrow, It will be great. so I put some code on my game in my Scheduler that is supposed to draw circle where arrow is going. But I had to draw so many circle, so game frame is not good when I shoot multi arrow.
Is there other better way? I use CCSpriteBatchNode, plist, CCSpriteFrameCache already. I did all I can do. I need help Thanks so much
this is my code
...............
[self schedule:#selector(CollisionDetection:)];
}
- (void)CollisionDetection:(ccTime)dt
{
for (CCSprite *arrow in arrows->arrowsArray)
{
CCSprite *track = [CCSprite spriteWithSpriteFrameName:#"WhiteCircle.png"];
[track setPosition:arrow.position];
[arrows->rootLayer->arrowsSheet addChild:track];
id delete = [CCFadeOut actionWithDuration:1.0];
id deleteAction= [CCSequence actions:delete ,[CCCallFuncN actionWithTarget:self selector:#selector(spriteActionFinished:)], nil];
[track runAction:deleteAction];
.......

The allocation of objects is a large overhead. If your game runs to slow you should consider creating a pool of arrows at the beginning of the game and only trigger the action on it as soon as you need it. If it is not visible anymore just set it to inactive and reuse it the next time you need an arrow.

Sounds like your problem isn't the arrows, but the circles, which I imagine are Cocos objects too. You'd be better off learning how to draw the circle texture directly to the screen using opengl commands instead of objects. That'll help a lot.

When have a time critical animation, i stay clear from CCCallFunc(N), as it can stall the scheduler for a noticeable amount of time. As I read your code, you have a CallFunc at every scheduled interval ... hmmmm. Have you tried running this without the scheduler, ie package and start all your animations at once, with a single CallFunc at the end ? Instead of changing the position as part of the scheduled interval, use a CCMoveTo that you will run at the same time as your tracking animation.

Related

SCNView overlay causes tearing on resize

I'm using SceneKit to display a 3D scene (so far, a single quad), and the overlaySKScene to display a 2D overlay (which so far is just a SKNode with no geometry, though I had previously used a single SKLabelNode). It's a pretty simple view inside a bunch of nested NSSplitView. And during normal use, it works brilliantly. The problem comes when I try to resize the window or split view — I get areas of red leaking through my nice background, which disappear shortly after.
I'm running this on a 2016 MBP with a Radeon Pro 460, and captured this frame using Quicktime's screen capture:
Disabling the overlay removes the red areas, which makes me think that it's the problem. Disabling the statistics bar or the scroller (a child view of the SCNView) do not have any impact. My most minimal SKScene subclass is defined as
#implementation TestOverlay
- (instancetype) initWithSize: (CGSize) size
{
if( self = [super initWithSize: size] )
{
// Setup the default state
self.scaleMode = SKSceneScaleModeResizeFill;
self.userInteractionEnabled = NO;
self.backgroundColor = [NSColor blackColor];
}
return self;
}
#end
Has anybody run into similar issues before? Annoyingly, the apple sample Fox2 doesn't have similar problems...
For true enlightenment, one needs to read the documentation carefully, then comment everything out and restore functionality one step at a time. And then read the documentation again.
In the discussion section of -[SCNSceneRendererDelegate renderer:willRenderScene:atTime:], the solution is obvious (emphasis mine):
You should only execute Metal or OpenGL drawing commands (and any setup required to perform them) in this method—the results of modifying SceneKit objects during this method are undefined.
Which is exactly what I was doing. I had misread this as modifying geometry, so thought that assigning textures would be reasonable to do here (after all, "will" render means it hadn't started rendering yet, right?), and would therefore pick the most recently created texture. And unfortunately, before I decided that I needed an overlay, this actually works perfectly well! As soon as the overlay was added, however, the tearing appeared.
The correct place to update material properties seems to be -[SCNSceneRendererDelegate renderer:updateAtTime]. Use that to avoid silly bugs like this one folks!
Try to reset SMC (System Management Controller). It helped me for solving a similar problem but with Autodesk Maya 2018 on MBP 2017 (Radeon 560).
So, shut down and unplug your MBP.
On the built-in keyboard, press and hold the Shift-Option-Control keys on the left side and press the Power Button and hold all of these down for 10 seconds, then release the keys.
Connect the power adapter and then turn the Mac on normally.
Hope this helps.
P.S. In case it doesn't help, try to check/uncheck Automatic graphics switching option in System Preferences–Energy Saver to see if there's a difference.

Unity 2D Animator, confusion on parameters and transitions for platform 2d character

I am new to designing games and have been having trouble for the past couple of days with the animator. I have downloaded a free asset off the Unity store that included a free sprite character and also its animations for idle, walk, run, and jump. My issue is when I go to use this asset pack in my game, I can not for the life of me figure out how to transition between idle->walk, and any state->jump. I believe it has to do with no parameters being set up, as I want the walk animation to occur when my character is moving. The issue is that it seems to be stuck in idle mode. In the animator the transitions are set up, but I can not figure out how to let the animator know when I am moving, and when I am actually idle. How can I connect my characters movement scripts to be used in conjunction with the animation? Do I need to write a new script, that uses new parameters I make in the animator, or am I completely missing something? Again I am very new at this, so I apologize if this is a dumb question but I cannot figure it out. All the videos I have watched only show how to build the animations and put them into the animator, and nothing about the scripts or parameters in specific. Thank you!
Look at the animation transition requirements, then set the required values. For example:
Animator anim = obj.GetComponent<Animator>();
anim.SetTrigger("running");
or
anim.SetFloat("speed", 2);
or
anim.SetBool("running", true);
One small thing that could be going wrong: If you somehow have a reference to the prefab instead of the instantiated object in your scene, it will not work. And to be sure it's not working, play the game, find the object with the Animator in the Hierarchy, click it, and open the Animator window. You can see which state is active.
If this doesn't help, can you describe the transitions in more detail?

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

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();

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.

Efficiently spawning sprites in Cocos2D

Just a quick question here; I have a background image in my game. Every time I spawn an sprite, I use the [self addChild:#""]; statement. Would it be more efficient to to call [backgroundImage addChild:#""]; instead? I have tested both ways and they both work, but I cannot tell which is more efficient, or if it even makes a difference.
Thanks,
Tate
If your object is CCLayer, calling [self addChild:img], the image will be added to the CCLayer.
I believe your background image is a CCSprite. [background addChild:img], will add the sprite to the background. If you adjust your background, like moving it up, all the sprites attached to background(child of background) would be moving together with the background image.
When you called [self removeChild:background], all the child attached to the background would be removed as well..
It depends on what are the requirements of the game.. =)

Resources