Smoother sprite rotation in cocos2d? - ios

I have a simple program where when you hold the screen the sprite moves up and when you let go the sprite moves down. So in the ccTouchesBegan function I rotate the sprite:
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
player.rotation = -5;
}
And then in the ccTouchesEnded function I rotate it again:
-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
player.rotation = 20;
}
So I was wondering if there was a way to make the rotation a little slower and smoother? It looks very clunky when I run it and I want it to look more realistic. I am not using a physics engine (box2d, chipmunk, etc..)

You can use CCRotateBy or CCRotateTo Class functions to rotate it.
Ex. player->runAction(CCRotateTo::create(1.0f, -5)); // In C++
Here first parameter specifies duration to rotation (currently 1 sec) and 2nd one is for Angle.
But if you touch the screen too frequently this one also may look weird.

Below code is for cocos2d-IOS. But you can translate it for c++ also. its easy.
CCRotateBy *rotTouchBegin = [CCRotateBy actionWithDuration:1.0f angle:-5];
CCRotateBy *rotTouchEnd = [CCRotateBy actionWithDuration:1.0f angle:20];
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[player stopAllActions];
[player rotTouchBegin];
}
-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
[player stopAllActions];
[player rotTouchEnd];
}
If you dont want to stop all the actions running on the player then just tag your actions so that you can use
[player stopAction:[player getActionByTag:]];

Related

Move UIView in specific area

I use the following code to move an UIImageView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
paddle.center = CGPointMake(location.x, paddle.center.y);
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesBegan:touches withEvent:event];
}
It works great, moving from left to right. But i can't figure out how to avoid moving over the screen, i meant to move it but don't intersect right and left edges of my screen. let's say 10 pixels from left and 10 from right.
First of all, you are the one saying this:
paddle.center = CGPointMake(location.x, paddle.center.y);
So where paddle is, is entirely up to you. If you don't want it at a certain x value, don't set it to that x value.
Second, never never call touchesBegan from within touchesMoved.
Third, you'd be much happier and safer using a UIPanGestureRecognizer. Situations like this are exactly what it's for.

How to make the sprite move positions when the screen is tapped

I would like my sprite to move from one side of the screen to the other like this:
Before tapped:
http://imgur.com/wIFa3JL
And then after the screen has been tapped:
http://imgur.com/ZtWiE7b
Would it start with something like this:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
Thank you!
I am not quite sure if you want to get the position of your finger when you touch the screen and apply to the sprite's position or just to change the position of the sprite when you touch the screen.
If you want to get your finger's position inside touchesBegan and apply that position to the sprite:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
CGPoint location = [touch locationInView:self];
spriteNode.position = location;
}
}
If you want to just change the sprite's position to the opposite side of the tree every time you touch:
First you need to keep track of which side your sprite is currently. Let's create a BOOL to hold that info:
BOOL isRightSide;
Then, at the beginning, if your sprite start at the right side of the tree, just assign TRUE to the boolean.
Finally, in the touch event:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (isRightSide) {
//Change to sprite's position to the LEFT side
} else {
//Change to sprite's position to the RIGHT side
}
isRightSide = !isRightSide;
}
I hope this helps =)

How to make an animated button in Sprite Kit

I have been trying to implement a method where the user can press down the play button, it then changes the texture to the pressed down image. Then, if the user decides not to continue with their action. Such as starting the game. They can then simply drag out of the sprite's frame/body which will then no longer detect the touch as one which will start the action.
The problem with this implementation is that I can't make the touch on the button cancel if the user drags outside of the play button's sprite frame.
The code you will see below doesn't have the transition between the scenes, as I'd like to test the button's usability before having to always quit the application to try the button.
Also, I have declared the majority of objects in the .h file.
Code from MenuScene.m:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//Touch detection declaration
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInNode:self];
touchNode = [self nodeAtPoint:touchLocation];
if([touchNode.name isEqualToString:#"playButton"]){
[playButtonSprite runAction:changePlayButtonTextureON];
}else{}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
if ([touchNode.name isEqualToString:#"playButton"]) {
[playButtonSprite runAction:changePlayButtonTextureOFF];
}
}
I would also like to know if there is an alternative method to detecting if the touch is on the play button sprite node. Though, this may be solved when a solution is found for the previous issue I have mentioned.
The best way to handle this would be to subclass SKSpriteNode to handle touches on it's own. You can see such an implementation in this project on GitHub. It cancels the touch when the touch goes out of the node's bounds.
The existing code you have posted is good as the code will not get called when the touch ends out of the play button's bounds.
In your case, since you are handling the touches from the scene itself, you can explicitly set the playButton's texture whenever the touch is detected outside the node's bounds.
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInNode:self];
touchNode = [self nodeAtPoint:touchLocation];
if(![touchNode.name isEqualToString:#"playButton"]){
[playButtonSprite runAction:changePlayButtonTextureOFF];
}
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//Touch detection declaration
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInNode:self];
touchNode = [self nodeAtPoint:touchLocation];
if([touchNode.name isEqualToString:#"playButton"]){
[playButtonSprite runAction:changePlayButtonTextureON];
playButtonSprite.isON = YES;
}else{}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (playButtonSprite.isON) {
if ([touchNode.name isEqualToString:#"playButton"]) { // The user really wants to play!
[self startPlaying];
}
[playButtonSprite runAction:changePlayButtonTextureOFF];
playButtonSprite.isON = NO;
}
}
Where changePlayButtonTextureON also sets playButtonSprite.isON to YES, and vise versa.
You will want to make a subclass of SKSpriteNode for playButtonSprite, and add that boolean property isON there.

COCOS2d Creating movement when button is held

I am working on making an iPhone game involving a spaceship moving from left to right on the screen. I want to make it such that the ship only moves if the buttons are pressed. Here is my current code that creates movement, but it doesnt stop when the button is no longer pressed.
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGSize winSize = [CCDirector sharedDirector].winSize;
NSSet *allTouches = [event allTouches];
UITouch *touch = [allTouches anyObject];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
if (CGRectContainsPoint([_paddle2 boundingBox], location)){
int bottomOfScreenX = 0 + _Paddle1.contentSize.width/2;
id action = [CCMoveTo actionWithDuration:5 position:ccp(bottomOfScreenX,winSize.height/3) ];
[_starShip runAction:action];
[action setTag:1];
}
}
-(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
[_starShip stopActionByTag:1];
}
I believe it has to do with your use of "ccTouchesBegan" along with "ccTouchEnded". Notice "touches" versus "touch". They need to be consistent. ccTouchesBegan handles multiple touch events, while ccTouchBegan is meant for a single touch event. So since it appears you are dealing with a single touch event, you really do not need to use ccTouchesBegan. Switch it to ccTouchBegan and you should be fine.
THe problem with this code is that the TouchHasEnded and TouchHasBegan are each using different argument setters. THe Touch began is using an NSSet while the TouchEnded is suing a UITouch. Set the TouchHasEnded as a
-(void)ccTouchEnded:(NSSet *)Touches withEvent:(UIEvent *)event;
or
have the touch began
-(void)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event.
The second method will require a slight tweak to the logic.

Get all touches on screen

I'm having a small issue. I'd like to receive all touches on the screen and for each one spawn a new video. The problem is that once a video is placed then it intercepts the touch points. I tried various values to go in locationInView but without any luck so far. Am I looking in the right place?
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint pointOnScreen = [[touches anyObject] locationInView:self.view];
C4Movie *player = [C4Movie movieNamed:#"inception.mov"];
player.shouldAutoplay = YES;
player.loops = YES;
player.center = pointOnScreen;
[self.canvas addMovie:player];
}
#end
Try setting the userInteractionEnabled property of each video screen (assuming it is held in some sort of UIView) to NO - that way, touch events will pass through it and continue to be received by your handler.
Yes, you're looking in the right place, and Chris has it right about user interaction. You should try:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint pointOnScreen = [[touches anyObject] locationInView:self.view];
C4Movie *player = [C4Movie movieNamed:#"inception.mov"];
player.shouldAutoplay = YES;
player.loops = YES;
player.center = pointOnScreen;
player.userInteractionEnabled = NO;
[self.canvas addMovie:player];
}
However you're going to run into an issue with adding videos. Unfortunately, iOS / hardware only lets you have 4 video pipelines running at one time so you'll hit that pretty quickly.
If you want to add things to the screen as you touch and drag your finger, then you could also do the above code inside of the following method:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
//work your magic here
}

Resources