Cocos2d Forcefully Ending Touch - cocos2d-iphone

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.

Related

how can i draw a sprite by left clicking?

i've tried to make a project, but i can't draw a sprite as i want. I mean that everything works when i just draw a sprite, but it stop working when i am trying to draw the sprite by clicking left mouse button. There's code i tried:
if(zdarzenie.type == Event::MouseButtonPressed && zdarzenie.mouseButton.button == Mouse::Left)
{
pocisk.setPosition(10, 10);
oknoAplikacji.draw(pocisk);
}
Btw, I am writing in Polish as if it would change something.
And yes, i have everything good besides that.
(and i am using 2.4.1 version of SFML)
I don't know what you are doing now because you didn't provide enough of your code and I actually don't understand your if statement but, it can just be :
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
sprite.setPosition(sf::Mouse::getPosition());
renderTarget.draw(sprite);
}
By the way I strongly suggest that you do not use the draw function here but organize your code to have a draw method called in a render loop, because depending on where your code is in your program, the sprite could be drawn for only one frame and then erased since it's not updated.
From what I understand in your code in Polish, you have the right code to do what you want, but the problem comes from the fact that you draw the sprite only once.
The draw method is called every frame and it will erase everything on screen and then redraw them. Doing it only once, like in your code, will only draw it a single time then delete it the very next frame.
At that point multiple solution can be used. If its a GameObject clicking can activate the object to then draw it or a simple bool could be used has a switch in your draw to make it appear.

Is it possible to "reset" any existing touches?

Cocos2d-iphone 1.0.1.
My main game scene requires the player to have a finger pressing the screen for the character to move.
While the character moves (thus the finger pressing the screen), a battle might occur. Such battle triggers a new CCScene which is pushed into the CCDirector (so the main game scene still exists within memory).
During the battle, naturally, the player will probably release his finger at some point.
When the battle is over, this CCScene is popped. Thus, the main game scene returns.
Now here is a problem: the main game scene still thinks that the finger that was initially pressing the screen before the battle is still pressing it at the same point, thus the joystick is still "functioning" and the player is still moving despite the fact that the finger is no longer pressing the screen.
Is there a way to "reset" the screen touches? I'd like to do so in the onEnter method of the main game scene. I tried something like
self.isTouchEnabled = NO;
self.isTouchEnabled = YES;
Hoping that such would re-register the touch dispatcher and thus causing some kind of reset. It did not work.
Basically, I need a way to tell the main game scene "dude, no one's touching the screen despite whatever you think".
Edit
Note that, if you press the screen again, it is fixed.
To make sure I understand the problem:
After you pop the battle scene, the character continues moving around as if the user never released his finger from the joystick?
My initial thought is that you have a deeper underlying design flaw somewhere in the code. It is my understanding that you want to use at least one layer to handle input. Try shifting everything in that 'game' CCScene to a 'game' CCLayer and add the layer as a child of the scene. Then register the layer to receive touch input.
If that doesn't work, you could always use a flag. Compare the scene you are in to the scene you want to be in, and if not, don't activate the joystick controller. Kind of hack-y but it works.
I've run into this kind of problem myself.
How i've fixed it:
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches){
[touchesOnScreen addObject:touch];
}
}
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches){
[touchesOnScreen removeObject:touch];
}}
- (void)ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[touchesOnScreen removeAllObjects];
}
So basically iOS keeps a pointer to every touch on the screen. What you do is manage those touches yourself with an NSSet. When you push the scene just set every UITouch from the set to nil. That is equivalent to UITouchPhaseCancelled. This will cancel all your touches on the screen. If the user still has his finger on the screen that touch wont be registered anymore...even if he moves it or something.
Note : you need to remove all objects in ccTouchesCancelled (it's called when the user has 6 or more touches on the screen) or else when he touches again the app crashes. If your app needs more than 5 touches you need to find a way around that.
Possibly the simplest solution is to have your CCDirector, on completion of popping your battle scene, call first resignFirstResponder then 'becomeFirstResponder` on the offending view; off the top of my head anyway it seems that ought to forward on the touches to another responder, hopefully letting it fizzle out when no one else handles it.
A more complicated dive into the UIView methods provides this private call cancelTouchTracking. Most likely it does something similar to what #skytz has put together. Warning: That last will mostly likely get you rejected in the app store process, but for your info there it is.
I'd opt for the simpler solution and hope it works. O_o

Moving a CCSprite and getting a callback

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.

Does replaceScene replace only the current scene or does it replace all scenes in Cocos2d

I have a game in Cocos2d with a main scene (game scene) and a button to go to a "Configuration" scene. When the user clicks on the Configuration button in the main scene I use pushScene to go tho the "Configuration" scene. The reason I use pushScene is to allow the user to resume the game where he was left off.
In the "Configuration" scene there are two options: "Cancel" and "Ok". If the user hits "Cancel" I use popScene and the game resumes where it was left of. If the user hits "Ok" I use replaceScene because I want the game to start from the beginning with the new configuration.
So, when the user hits "Ok" I know that the "Configuration" scene is replaced by the new game scene, but does the old game scene gets replaced too? Otherwise, am I doing things correctly or should I implement another way to let the game scene know whether it should resume or restart.
I want to make sure I am not leaking memory by accumulating unreplaced scenes.
The replaceScene method does what it says. It replaces the current scene. If you have 10 scenes pushed onto one another, it will replace the 10th scene and all previous scenes remain.
It's one of the reasons why I don't recommend using pushScene. It's too easy to forget a situation where scenes might get pushed more than they get popped. The other reason is that popScene can't be animated with a transition.
Btw, you can easily test this behavior if you do replaceScene after pushScene, then popScene in the newly replaced scene. You'll see the old scene popping up. Normally if you popScene with just a single scene in the stack it'll throw an assertion.

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.