Moving a CCSprite and getting a callback - cocos2d-iphone

I move an instance of CCSprite in my Cocos2D-based iPhone game like this:
[mySprite runAction:[CCMoveBy actionWithDuration:1.0
position:ccp(10, 10)]];
How can I get a callback everytime the sprite moves?
I'd like to do something like this:
[self registerForCallbacksFrom:mySprite
selector:#selector(spriteMovedOneStep)];
So spriteMovedOneStep would be called everytime mySprite moves. Would be nice to specify the frequency of the callback too so minimize CPU usage.

One possible solution is to subclass CCMoveBy and call your callback from it's update method. You also can setup frequency and everything you want with this approach.

If I get your question right you would like to have a method called at times when the Sprite is moving, correct ?
How about scheduling an update method that performs what you want if a SpriteIsMoving BOOL is set to YES, I'm not sure on what your trying to achieve but this is my take on it.

Related

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 Forcefully Ending Touch

Is there a way to call upon the ccTouchEnd method?
Like, in my update, I want it write
If(situation occurs){
[self ccTouchEnd];
}
Or something like that. The reason I'm asking is because this thing happens for 2 different reason. one would be if the user ends the touch. The other would be if the sprite collides with another sprite.

How To Retrieve Actions From Sprite In cocos2d

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.

How to make sure Qt Widget.repaint has finished running?

I am currently having a problem with Qt graphics view framework namely, I want to clear my QGraphicScene background color and then run a function to take a webcam picture. So far when I use QWidget.repaint the screen only got repaint after about 1 second and by then the camera function has been called and the image captured is always off. Here is how my code currently look like.
//Scene is a QGraphicScene
//View is a QGraphicView
//Camera is a camera object
Scene.setBackgroundBrush(Qt::Blue)
View.repaint()
Camera.Capture()
I have tried wrapping the repaint() call with another function and use signal and slot call but it still fail. I want to know if there is a way to pause the program until the screen has been refreshed.
A QGraphicsView has a bit more going on than most QWidget subclasses and I'm not familiar enough with it to say what is going on for sure but I might venture a guess that your problem is related to the fact that the scene is actually rendered onto the view port widget. Perhaps calling viewport->repaint() will give you the results you are looking for?
Also, unless you really need to be using the webcam in this scenario, you could call ::render() on your scene and pass it a QImage which you could save directly to a file.

Handlings Game Loops in cocos2d

How does one handle multiple elements of a game at once?
In a scroller which the background/tilemap moves every gameloop how is the user input handled at the same time?
The map needs to be moved in the game loop and collision needs to be checked for the player object and parts of the map which it shouldnt hit, and there also needs to be code which takes the user input, moves the player on the map and checks for collisions too?
Should these be threaded or how are these done in cocos2d?
Are there any built in methods?
Register a step method with a specified interval.
[self schedule:#selector(step:) interval:1.0/60.0];
// Main loop of the application
-(void) step:(ccTime)delta
{
// do your step actions here
}
Try and avoid registering multiple step methods. You can do everything you need in one step method. You don't need to use threading.
It is prefer to register the update method
[self scheduleUpdate];
Then override the update method as you like
-(void) update:(ccTime)delta
{
//All steps happen here
}
this will be called in every frame of your game more accurately by the cocos2d than schedule a new one.
(Cocos2dx version: this->scheduleUdate(), void update(float delta);)