Cocos2d scaling sprite causes artifact - ios

I am on the master branch so that it will work with ARC.
I have implemented a method whereby the sprite will scale by a factor of 1.1 when a user touches the sprite. Multiple touches will queue up multiple scaling actions, built on top of each other. Every now and then I get a strange artifact where the smaller version of the sprite shows up on top of the scaled version.
Here's a screenshot:
More background: I'm using a texture atlas so I use:
sprite = [super spriteWithSpriteFrameName:anObject.filename];
to initialize the sprite. Is this a bug in openGL/cocos2d? Any advice on how to stop this artifact?
EDIT:
I am subclassing CCSprite but as far as I can tell there is only one instance of the sprite (the call to super was in a class method). Basically the user will define a list of actions that the sprite will do. The action list can also be interrupted using:
[self stopAllActions]
I've had actions using subclasses of CCMoveBy and CCRotateBy with no issues. It's only the most recent subclass of CCScaleBy that is causing this artifact. In the subclasses of these actions I'm not changing anything in the actions, just tracking certain variables so that I can properly resume the action after the interrupt.

Are you perhaps subclassing CCSprite, and in your subclass did you add a CCSprite instance variable as well?
In that case you'll be showing two sprites. The super class sprite and the instance variable sprite. If the other sprite shows up only sometimes this may depend on the order of adding sprites as childs, or the zOrder property.

Related

Using SpriteKit inside UIKit

I am contemplating a simple app that has four characters that you can drag around on the screen. While dragging they "wiggle" — that's the animation. And they snap to a position if they get close enough to it... like in a puzzle. Without the animation, this is all simple in UIKit.
My first thought is to render each character in its own SKView inside a plain old UIView. I could attach UIGestureRecognizers to each SKView to track tapping and dragging. But I think this implies individual GameScenes for each character/SKView. That seems go go against the grain of SpriteKit.
The alternative is a single GameScene with the four sprites. But I would still need to track & drag them and I don't see how to do that within an all-SpriteKit app.
Is either approach better practice than the other?
You should implement the one that has a single scene and separate sprites for each character. The sprites will be SKSpriteNode instances which are SKNode instances, which descend from UIResponder and can, therefore, respond to touch events.
Look at the documentation for SKNode. It is a wealth of information that applies to sprites as well as to any other kind of node. In particular it says:
All nodes are responder objects that can respond directly to user interaction with the node onscreen…
And then later has a section on "The Hit-Test Order is the Reverse of Drawing Order" etc.

How to share Background SpriteNode among Multiple Scenes?

Well, the title says it all. If I am currently in a presented Scene of which I have initialized a Background SpriteNode to be a class constant, then how do I use the same Background SpriteNode in my next presented scene without having to create another SpriteNode that behaves and looks exactly the same as in the previous scene.
Will creating another SpriteNode be costly, assuming the background object loads its texture from a texture atlas?
And, I am using Swift.
Something like this should work.
backgroundSprite.removeFromParent()
nextScene.addChild(backgroundSprite)

cocos2d collision not detected in if((self=[super init]))

I used a CGRectIntersectsRect to detect the collision of a moving image (anvil) and an image (guy).
The "anvil" moves constantly in a CCRepeatForever and the "guy" moves in a ccTouchesBegan method by the control of the user.
Here it is, very simple:
if (CGRectIntersectsRect(guy.boundingBox, anvil1.boundingBox))
{
pancake = [CCSprite spriteWithFile:#"pancake.png"];
pancake.position = ccp(200,200);
[self addChild:pancake];
}
The problem is that the above lines of code do not work in the if((self=[super init])) and only in the ccTouchesBegan, where I have all of the actions for "guy." I do not want to have the image "pancake" appear only if the user taps exactly when the two images collide...if the images EVER collide, regardless of touch events, "pancake" should appear.
Any advice? Thanks in advance!
Not to criticize but your code doesn't make a lot of sense. Why would you be testing for interestion in an init method for two objects that are constantly in motion throughout your scene? Even if you wanted to show the pancake whenever the two intersected, why don't you load the pancake and make it invisible, then switch it to visible whenever the two objects intersect. This could be done simply by putting the condition in an update method and setting pancake's visible property to true if they intersect or false otherwise.
But to answer the question of "why" that code doesn't work in init is simply because at the point of calling this either one or both of your objects doesn't exist, they simply don't intersect, or their bounding box properties have not been set. I bet they simply don't intersect yet. But that doesn't matter much since there is no reason I can see to check for interestion in an init method. Schedule the update method, create the update method, and place this condition inside of it but rather than create the pancake sprite, you'd be setting the already existing pancake sprite's visibility to TRUE.

Creating a scrollview

Here's my current situation:
I created a CCScene named StoreScene.
Within that scene, I've initialized a CCLayer and just named it Store layer.
Now, I want a scrollable layer that contains content which the user can touch.
To do this, I created another CCLayer named Store Container.
I create an instance of this layer and add it as a child to StoreScene.
In StoreContainer, I've added multiple sprites, each with a unique tag.
The scrolling is done within the StoreScene and touches will move the entire Storecontainer layer up or down.
I have added 4 sprites to my scrolling layer (store container)
Initially,
sprite 1 is located at 0,10
sprite 2 is located at 0,20
sprite 3 is located at 0,30
sprite 4 is located at 0,40
Obviously, as the entire storecontainer layer shifts, the sprite positions shift as well.
However,
when I do this in the TouchesEnded method:
if (CGRectContainsPoint(sprite1.boundingBox, touchpoint)){
NSLog(#"TouchedSprite1");
}
... and so on for each sprite
The touch locations of each sprite remain in the same place!!!
Visually, the sprites are moving up and down nicely.
but their locations when receiving touches stay constant..
is there a reason for this?
Any other way for approaching a scrolling layer?
I've already looked at the UIKit's scrollview and I've looked at CCScrollLayer and both aren't good enough for me.
My way may be simpler but it doesn't work as planned.
Thanks in advance! ^_^
I'm guessing you've implemented touchesEnded in your StoreContainer. In that case the touches' coordinates will be relative to that layer, which explains why their coordinate system is following the layer around the screen. You could implement touchesEnded in the scene instead, or put the StoreContainer instance inside a new and immobile layer whose purpose is only to handle touches.
Alternatively you could keep your current setup and use your answer to this question to get the touch coordinates in the world... :)
Check out CCKit, there is a nice CCScrollLayer implementation included.

Cocos2D for First Game - Advice for Beginner

I never developed in Cocos2D. However, this animated app is not easy to make with regular UIView animation and CAAnimation.
I want a number of UIImageView's (from 1 to 30) to float around the screen with the certain path and I want them to be responsive for touch (they would do some animation when touched). I also need them to go back and forth the screen (new path would be calculated) when they are touched or reach the edge of screen. It's important to retrieve X and Y position of each element whenever needed.
Question is: what Cocos2D classes are best looking at (for a beginner) to make that happen? I've tried UIView animation and CAAnimation but I came across some difficulties so I have a feeling Cocos2D may bring better results. Thank you.
Yes, cocos2d makes it much easier. You want to create a CCSprite with the initWithFile: method. Example:
CCSprite *mySprite = [CCSprite initWithFile:#"fire.png"];
[self addChild:mySprite];
Where fire.png has been added to the project and self is the scene instance.

Resources