For a simple game, I have 4 different platforms (all on one spritesheet). I initially add 5 of each to a CCSpriteBatchNode, and set them all as not visible. When I set my platforms I want to take a platform of a certain type from my CCSpriteBatchNode and change it to make it visible and position it.
I am having trouble finding platforms of a specific type that aren't visible. Or vice-versa?
I know you can use [batchnode getchildbytag:tag] but as far as I know that only returns one sprite. Is there any way I can put pointers to each platform of a specific type into an array, so that I can iterate through the array and find all the not visible sprites?
Thanks!
As suggested by Drama, you will have no choice than to 'iterate' the children. As for identifying which sprite corresponds to which platform, a few ways exist. A simple one would be to use the 'tag' property of the sprite -- assuming you do not use it for any other purpose.
// some constants
static int _tagForIcyPlatform = 101;
static int _tagForRedHotPlatform = 102;
... etc
// where you create the platforms
CCSptiteBatchNode *platforms= [CCSpriteBatchNode batchNodeWithFile:#"mapItems_playObjects.pvr.gz"];
CCSprite *sp = [CCSprite striteWithSpriteFrameName:#"platform_icy.png"];
sp.tag = _tagForIcyPlatform;
[platforms addChild:sp];
sp = [CCSprite striteWithSpriteFrameName:#"platform_redHot.png"];
sp.tag = _tagForRedNotPlatform;
[platforms addChild:sp];
// ... etc
// where you want to change properties of
-(void) setVisibilityOf:(int) aPlatformTag to:(BOOL) aVisibility {
for (CCNode *child in platforms.children) {
if (child.tag != aPlatformTag) continue;
child.visible = aVisibility;
}
}
once again, this works if you are not using tags of platform's children for another purpose. If you need the tags for some other purpose, consider using an NSMutableArray in the class, one per platform type, and store in that array the pointer to your sprites of the appropriate type.
There's not a super straightforward way to do that. You'll need to iterate through the children and inspect each child individually.
For coding efficiency, consider adding a category to CCSpriteBatchNode that performs this function for you. That way you can easily replicate it as needed.
Related
I have just started unity. I have 4 Images(sprites) aligned in a grid.
As soon as i touch the particular chocolate, its texture changes[I wrote a code for that]. There is a button on screen.After pressing the button, I want to move only those chocolates whose texture has been changed.
I know the following move code but i don't know how to use it here.
void Update () {
float step=speed*Time.deltaTime;
transform.position=Vector3.MoveTowards(transform.position,target.position,step);
}
I just don't know to move that particular sprite whose texture is changed. Thanks
Do you want to be moving the sprites over the course of a duration or instantly?
If it's over the course of a duration I suggest you use Lerp. You can Lerp between two Vector.3's in a time scale. Much cleaner and once learned a very useful function.
Code examples below:
http://docs.unity3d.com/ScriptReference/Vector3.Lerp.html
http://www.blueraja.com/blog/404/how-to-use-unity-3ds-linear-interpolation-vector3-lerp-correctly
However if you want to move it instantly. This can be done very easily using the built in localPosition properties which you can set in or outside the object.
Set your changed sprites Bool moved property (create this) to true on click (if you're using Unity 4.6 UI canvas then look at the IClick interfaces available for registering mouse activity in canvas elements) and then when you press the button, loop through a list in a handler file which contains all your button texture objects and move those that the moved property is set to true for.
foreach(GameObject chocolate in chocolateList)
{
if (chocolate.moved == true)
{
gameObject.transform.localPosition.x = Insert your new x position.
gameObject.transform.localPosition.y = Insert your new y position.
}
}
However please do clarify your intentions so I can help further.
EDIT 1:
I highly suggest you make your sprites an object in the canvas for absolute work clarity. This makes a lot of sense as your canvas can handle these type of things much better. Use Image and assign your image the sprite object (your chocolate piece), define it's width and height and add a script to it called "ChocolatePiece", in this script create two public variables, bool moved and int ID, nothing else is required from this script. Save this new object as your new prefab.
Once you've done this in a handler script attached to an empty gameobject in your canvas make a list of gameobjects:
List<GameObject> chocolatePieces = new List<GameObject>();
You'll want to at the top of your handler script define GameObject chocolatePiece and attach in your inspector the prefab we defined earlier. Then in Start(), loop the size of how many chocolate pieces you want, for your example lets use 4. Instantiate 4 of the prefabs you defined earlier as gameobjects and for each define their properties just like this:
Example variables:
int x = -200;
int y = 200;
int amountToMoveInX = 200;
int amountToMoveInY = 100;
Example instantiation code:
GameObject newPiece = (GameObject)Instantiate(chocolatePiece);
chocolatePieces.Add(newPiece);
newPiece.GetComponent<ChocolatePiece>().ID = i;
newPiece.transform.SetParent(gameObject.transform, false);
newPiece.name = ("ChocolatePiece" + i);
newPiece.GetComponent<RectTransform>().localPosition = new Vector3(x, y, 0);
From this point add to your positions (x by amountToMoveInX and y by amountToMoveInY) for the next loop count;
(For the transform.position, each count of your loop add an amount on to a default x and default y value (the position of your first piece most likely))
Now because you have all your gameobjects in a list with their properties properly set you can then access these gameobjects through your handler script.
In my game, I'm trying to determine what points to dole out depending on where an arrow hits a target. I've got the physics and collisions worked out and I've decided to draw several nested circular SKShapeNodes to represent the different rings of the target.
I'm just having issues working out the logic involved in checking if the contact point coordinates are in one of the circle nodes...
Is it even possible?
The easiest solution specific to Sprite Kit is to use the SKPhysicsWorld method bodyAtPoint:, assuming all of the SKShapeNode also have an appropriate SKPhysicsBody.
For example:
SKPhysicsBody* body = [self.scene.physicsWorld bodyAtPoint:CGPointMake(100, 200)];
if (body != nil)
{
// your cat content here ...
}
If there could be overlapping bodies at the same point you can enumerate them with enumerateBodiesAtPoint:usingBlock:
You can also compare the SKShapeNode's path with your CGPoint.
SKShapeNode node; // let there be your node
CGPoint point; // let there be your point
if (CGPathContainsPoint(node.path, NULL, point, NO)) {
// yepp, that point is inside of that shape
}
What do you recommend me if I have two layers (which are added to a parallaxNode) and on each layers I've added sprites which I want to restrict the order that the player won't be able to remove sprite5 until it removes first the previous ones: sprite1, sprite2, sprite3 and sprite4 and so one.
I'm using Juan's example for dynamically touch detection
What will be the dynamical option for this?
UPDATE:
if([sprite tag] == tag_collection_1 && [sprite GetCanTrack]) {
//Set others to NO & call remove sprite method
[[TSprite FindByTag:tag_collection_number] SetCanTrack:NO];
[self removeSpriteMethod:touchLocation];
} else if ([sprite tag] == tag_collection_number && [sprite GetCanTrack]) {
// and so on
}
Use a fifo stack implementation. If you want to remove the sprite, you first check if it's at the bottom of the stack and when you do remove it, you pop it from the stack as well. Practically you will have an NSMutableArray and look at the first item if the object is in that position before you remove it. If you have added 1,2,3,4,5 in that order and want only to be able to remove them in the same order you check if the object you are trying to remove is at index 0 in the array first.
I am looking for a way to find the filename of the CGSprite variable, then use it in an IF statement. Like this:
if(target.spritefilename?? == #"Car1.png")
{
target = [CCSprite spriteWithFile:#"Car1_dead.png" rect:CGRectMake(0, 0, 37, 76)];
}
I am not sure why you want to do this. But as far as I am guessing your purpose I would like to suggest an alternative and proper way to identify your different sprites.
There is a "userData" property in the sprite (inherited from parent) which you can use to store your custom data. So when you create your sprites you should also assign the identified to the userData property.
Like in your case when you first create your "target" sprite, you can then set, "target.userData = "
Later you can check if target.userData is equal to your required file name.
This is the proper way to store custom data in your sprites.
I hope it helps.
if([target.spritefilename isEqualtoString:#"Car1.png"])
is what i guess you are looking for.
You can use isEqualtoString for string comparison.
if([target.spritefilename isEqualtoString:#"Car1.png"])
For NSString.
store the sprite names in an array and check the current sprite name matches the name in an array.
if([image_array containsObject:#"car.png"])
{
NSLog(#"Image Found");
}
Hope this helps!!!
If([sprite.userData hasPrefix#"Car1"])
...
if([(NSString*)sprite.userData hasPrefix#"Car1"])
...
If the purpose of this to just identifying the sprite you can simply do it by using tag property of sprite.
Like set a taf for sprite while initialing or creating the sprite as
CCSprite *spr1=[CCSprite spriteWithFile:#"1.png"];
spr1.tag=1;
CCSprite *spr2=[CCSprite spriteWithFile:#"2.png"];
spr2.tag=2;
and while getting the sprite on particular event use to get tag value as
if([(CCSprite*)tagetSprite tag]==1)
{
}
else if([(CCSprite*)tagetSprite tag]==2)
{
}
I was wondering if anyone could help me with my program,
I have randomised my sprites into a specific set of co-ordinates.
I want one of the sprites that is at that specific co-ordinate, to be able to make them do something when they are at this random co-ordinate. The problem i am having is that i have to make a long list of if statements saying if this sprite is here do this if another sprite is here do the exact same thing.
if (red1.position.y>=0 && red1.position.y<=63) {
id r1animation = [CCMoveTo actionWithDuration:0.2 position:ccp(red1.position.x,33)];
[red1 runAction:r1animation];
}
if (red2.position.y>=0 && red2.position.y<=63) {
id r2animation = [CCMoveTo actionWithDuration:0.2 position:ccp(red2.position.x,33)];
[red2 runAction:r2animation];
}
i want to be able to say if any of the sprites are at that exact co-ordinate then move them to a point, in a short amount of code as possible. so basically grouping the sprites or something i'm not sure.
Thanks
i want to be able to say if any of the sprites are at that exact co-ordinate then move them to a point
Firstly, specify the 'hotspot' programatically:
CGPoint hotspot = ccp(32,32); // convenience macro,
//creates a CGPoint with x = 32, y = 32
You should store a reference to all your sprites in an array when you create them (you can use cocos2d's 'tagging' also, but I usually like to use an array for simplicity)
-(void)init {
//.. misc
// creating sprite returns a reference so keep it in an array
CCSprite* curSprite = [CCSprite spriteWithFile: //...etc]
[self.spriteArray addObject: curSprite];
// add all sprite references to your array
}
Now you can iterate over this array to see if any of the sprite's frames overlap the hotspot:
-(BOOL) checkAllSpritesForCollision
{
for (CCSprite *sp in self.spriteArray)
{
CGRect spriteRect = sp.frame;
if (CGRectContainsPoint(spriteRect,hotspot))
{
// run your action on sp...
}
}
// you might like to return YES if a collision happened?
}
This is a brute force method of checking whether every sprites frame contains a given point. There are many ways to skin this cat of course, but hopefully this will set you on a better path.
What you can do is to calculate the distance:
float pointX = thePoint.position.x;
float pointY = thePoint.position.y;
float pointDeltax = sprite.position.x-pointX;
float pointDeltay = sprite.position.y-pointY;
float pointDist = sqrt(pointDeltax*pointDeltax+pointDeltay*pointDeltay);
But maybe davbryns solution suits your purpose better.