How To Retrieve Actions From Sprite In cocos2d - cocos2d-iphone

I have a CCSprite that I'm using in a scene and have created multiple CCAnimation actions to apply to it all using a single CCSpriteFrameCache sharedSpriteFrameCache. While everything is working and I'm able to switch between animations, I feel like I'm doing poorly and would like to simplify my code by retrieving the running action(s) on the CCSprite to stop them individually before running the next action on it.
To help create some context, lets assume the following situation:
We have a CCSprite called mySprite
We have 3 separate CCAnimation actions defined for walking to the right, walking to the left, and sitting looking forward called: actionAnimWalkRight, actionAnimWalkLeft, and actionAnimSitForward respectively.
We want to have the sprite walk to the right when someone touches the screen right of mySprite, walk left when someone touches the screen left of mySprite and sit when someone touches mySprite.
The approach I'm using to accomplish this is as follows:
Place CCSprite as a child in the scene.
Tell the sprite to run an action using: [self runAction:actionWalkRight];
When I want to change the action after someone touches, I have a method called stopAllAnimationActions which I call before I apply a new action that stops any animation action no matter what's running. Basically lists ALL the CCAnimation/CCActions I have defined and stops each one individually since I don't want to use stopAllActions. as follows: [self stopAction:actionWalkRight]; [self stopAction:actionWalkLeft]; [self stopAction:actionSitForward];
Then I apply the new animation after the above method fires using: [self runAction:actionWalkLeft];
While this works, it just seems like a poor design to stop items that I know aren't running just because I don't know exactly what is running. So just looking for advice and the best recommended practice to do something like this within very complex situations so tracking every possible situation is difficult. Any feedback would be appreciated.

When creating the actions set the tag of that action with a constant:
actionWalkRight.tag= kCurrentAction;
[self runAction:actionWalkRight];
Then, retrieve the running action by that tag and stop it.
[self stopActionByTag:kCurrentAction];

I recommend you simplify your process and take advantage of the native Cocos features, including stopAllActions. Don't re-use actions, always create them from scratch as it has been well discussed among Cocos developers that re-using actions can be buggy.
Cocos is well optimized and features like stopAllActions are not performance hogs. It would probably be faster than your approach, actually.

Related

Sprite does not jump when moving

I'm making a platform game, and everything was great. My sprite moved when i touched the left side of the screen, and jumped when i touched the right side. But then i decided to make it move by itself. so i added the ccmoveto function, but now it does not jump! I'm new to cocos2d but everything is working ok, except this, already searched but couldn't find the answer can someone please help me?
I tried everything, but it only jumps if i delete the ccmoveto action.
I'm using cocos2d 2.0
Thank you!!
CcMoveTo will override any manual position changes, inluding changes from other actions like CCJump. Your character is set to move to destination in a straight line, no matter what.
It's issues like these why I always recommend not to use actions for gameplay logic. Especially position, you need to retain full control over it. Use a direction vector and integrate position every update: and you're free to do everything you need.
my advice is to use one of the physics engines provided with cocos2d: Box2D and Chipmunk physics. Thanks to this engines you can define the characteristics of the world (i.e. gravity vector) a shape and a mass for your sprite (i.e. a rectangle with a weight). Then when you need it to jump you will just create a force vector with the characteristics you need (i.e. angle, etc.) and keep updated your sprite with its physical body. This will make your sprite jump and land quite realistically.

Replacing one long CCMoveTo to multiple CCMoveTo with update Cocos2D

Currently, I have a game where an object determines a point to go to. It then calculates a path to that point and constructs one long CCMoveTo animation to get to that point. With this method, the animation seems very smooth and continuous.
I am now trying to break this one long CCMoveTo to multiple CCMoveTo leveraging the update method that gets called periodically. I want to do this because at each node of the path that the objects passes through, there might be a distraction and I want my object to be able to act on that. So this is what I am doing:
- (void) update: (ccTime) dt
{
if(![self isWalking]){
CGPoint nextNode = [_path objectAtIndex:(_currentPathIndex%[_path count])];
_currentPathIndex++;
NSMutableArray *actions = [[NSMutableArray alloc] init];
[actions addObject:[CCCallBlockO actionWithBlock:^void(id obj) {
[(Monkey *) obj setIsWalking:NO];
} object:self]];
[self moveTo: nextNode withCallbacks: actions];
}
}
Note: that I set isWalking to NO as a callback when the object has completely reached the destination node. This will let it calculate the next node to go to and construct that animation. Without this, the object would try to runAction in the middle of an ongoing CCMoveTo action. The problem with this method is that the movement does not seem smooth and continuous anymore. There seems to be a lag at the end of each CCMoveTo animation
Anybody has any clue on how to fix this?
That's a side effect of cocos2d's CCAction system respectively the CCScheduler.
There will always be a 1-frame delay because when an action stops, it won't do any work in the current frame: it made the last position update in the previous frame, and in the current frame it does no longer exist as a running action.
If you now run another move action in a scheduled method, that action won't begin updating until the next frame because it will schedule itself to receive updates. And updates that are scheduled while cocos2d's CCScheduler performs updates will not be run until the next frame, due to the fact that you can't modify an array during enumeration.
My advise is always to avoid using CCMove* actions for gameplay purposes, and instead manually update position of game objects. It's easy enough to do, and if you need a code example, look inside the CCMoveTo class.
A workaround would be to extend the distance of the CCMoveTo and replace the action shortly before it completes. Though that'll be a hack and may actually be harder to implement correctly than manual position updates.
PS: That's an issue I have addressed in the action model of KoboldTouch. It implements its own action system, with more lightweight and reusable actions.

Cocos2D - Large Image

Is it possible to use a large image in Cocos2D, and allow, via swiping or pinching, for the user to zoom in and out?
I see from this post, that the max res for a Cocos2D image is 2048x2048. That is obviously larger than a device viewport, so I want the user to be able to move around the image.
I'm not creating a game, I'm making a sort of interactive biological cell, that will allow the user to tap arbitrary organelles, and see a popup of information about them.
Here is an idea of what the image will be, and obviously cramming the whole thing into a device viewport is not possible:
So really, before I delve too deep into this project, I'm just curious as to whether it is possible to use a large image, that allows the user the ability to arbitrarily move it around, and, if I can detect organelle touches, perhaps via CCSprites?
I recommend subclassing CCSprite and using your large image as the class's image. CCSprites certainly can detect touches by simply adding the basic CCTouchDispatcher delegate to the sprite's class:
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:-1 swallowsTouches:YES];
Then also add this method to your CCSprite subclass:
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
You can do anything you want with the touches at this point, scroll or whatever suits your needs.
You could break up your image into many multiple sprites and use a CCLayer to manage touches instead, it just depends on whether you really need your image to be that large, or if the limitations for a single image are enough for you to work with, considering they are pretty large too. My method here is a lot less complicated than that.
The max texture size is limited by OpenGL ES not just coscos2d and it changes by device. However, you can load the image into more than one texture and then position and move those textures around the screen. So really you could have the appearance of an image any size you would like but programmatically you will have to manage the different sprites (tiles) of the image.
CCSptites don't detect touches. CCLayers have will get the touch events you can then do a hit test to see if it hits a givcen CCSprite.

Can a CCSprite switch between multiple animations?

Is it possible to make a CCSprite switch between two different animations? (both are CCRepeatForever)
I try to use stopAction: and runAction: but it crashes the app.
I can only use pauseSchedulerAndActions: and resumeSchedulerAndActions: with one animation.
To answer your question: Yes. If switching animations troubles you, use one sprite for each animation and keep them all updated to the same position, and only set the one to visible whose animation should be played.
The crash is certainly unrelated.

What is the best way to set up menus with cocos2d?

I'm new to development and I have played around with a few tutorials. I wonder what the best way to set up a menu for a game with cocos2d?
I want a MainMenu with a Startbutton, SettingsButton, HighScoresButton and a little info/creditsButton in the corner.
How should I set this up?
Should I have the MainMenu as a Scene and the others as layers or just make all of them as separate Scenes?
The buttons that I add, should they be a plain button and then I add the textLabel on top or should I make them complete with textLabel?
I would like the buttons to "wiggle" like it is made of jello when i tap them, how do I do that?
As I said, I am new to this but I wanna learn as much as I can before school starts. I'm currently taking a summer class in iphone development so I get a head start for the next semester. I would like to see experienced game developers to help me out with this since i want to work with that when I get older, if they could also show me how to structure a game and the design.
Thank you so much.
David H
You've got several questions buried in there, so I'll address them in order...
First, to save on memory, you should break sections of your game, including menus, into separate scenes and switch between them using:
[[CCDirector sharedDirector] replaceScene: yourScene];
Alternatively you can use pushScene: and popScene, but these hold pushed scenes in memory and can be very costly depending on what you've got in the scene.
As for how to design your buttons, that's completely up to you and what fits best with the game. Some games look fine with text buttons. Others need a more stylized button that is best created with images. Remember, a CCMenuItem (button) is just a CCNode, so you can layer images and text in almost any way you wish.
Animating buttons is going to be a manual thing. I suggest subclassing the CCMenuItem, or CCMenuItemImage and overriding the selected and unselected methods to animate the underlying images.
We used cocos2d for our game The Selfish Birdbreeder. You can find the game and source here and dig around. I'm pretty certain we have a main menu.
http://pyweek.org/e/BirdBreeder/