SpriteKit - Rotate and Jump Both Ending at same Time - ios

New to Sprite Kit and Game Development i am learning by the Following tutorial # Raywenderlich.
WHAT I AM DOING ?
I have implemented the Continuous Motion on the map and Gravity on the Player and i know that the rotation action can be added to the SKSpriteNode like this.
SKAction *action = [SKAction rotateByAngle:M_PI duration:1];
[myPlayer runAction:[SKAction repeatActionForever:action]];
And my Player with gravity is as follows
MSPlayer.h
#import <SpriteKit/SpriteKit.h>
#interface MSPlayer : SKSpriteNode
#property (nonatomic, assign) CGPoint velocity;
- (void)update:(NSTimeInterval)delta;
#end
MSPlayer.m
#import "MSPlayer.h"
#import "SKTUtils.h"
#implementation MSPlayer
//2
- (instancetype)initWithImageNamed:(NSString *)name {
if (self == [super initWithImageNamed:name]) {
self.velocity = CGPointMake(0.0, 0.0);
}
return self;
}
- (void)update:(NSTimeInterval)delta {
//3
CGPoint gravity = CGPointMake(0.0, -10.0);
//4
CGPoint gravityStep = CGPointMultiplyScalar(gravity, delta);
//5
self.velocity = CGPointAdd(self.velocity, gravityStep);
CGPoint velocityStep = CGPointMultiplyScalar(self.velocity, delta);
//6
self.position = CGPointAdd(self.position, velocityStep);
}
-(CGRect)collisionBoundingBox {
return CGRectInset(self.frame, 2, 0);
}
#end
My Issue is
Now the issue is that i want the Node to be rotated and give make it jump with gravity and the rotation ends just before the Node is about to end its jump. What should be done to make both animations end at the same time?

Write another runAction for Jumping
[myPlayer runAction:[SKAction repeatActionForever:runAction]];
Define runAction here.

Related

How can I measure sprite's jump strength?

Hello,
I am new to spriteKit and I am trying to make a game. In the game I have a player that jumps from stair to stair, which comes from the top of the screen infinitely (Like in Doodle Jump, only the jump is controlled by the player's touch). I am trying to make a jump, by applying an impulse on the player, but I want to control the jump strength by the player's touch duration. How can I do so? The jump executes when the player STARTS touching the screen so I can't measure the jump intensity (By calculating the touch duration) ... Any ideas?
Thanks in advance!!! (:
Here's a simple demo to apply the impulse on a node with the duration of touch. The method is straightforward: set a BOOL variable YES when the touch began, and NO when the touch ended. When touching, it will apply a constant impulse in update method.
To make the game more natural, you might want to refine the impulse action, or scroll the background down as the node is ascending.
GameScene.m:
#import "GameScene.h"
#interface GameScene ()
#property (nonatomic) SKSpriteNode *node;
#property BOOL touchingScreen;
#property CGFloat jumpHeightMax;
#end
#implementation GameScene
- (void)didMoveToView:(SKView *)view
{
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
// Generate a square node
self.node = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(50.0, 50.0)];
self.node.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
self.node.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.node.size];
self.node.physicsBody.allowsRotation = NO;
[self addChild:self.node];
}
const CGFloat kJumpHeight = 150.0;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
self.touchingScreen = YES;
self.jumpHeightMax = self.node.position.y + kJumpHeight;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
self.touchingScreen = NO;
self.jumpHeightMax = 0;
}
- (void)update:(CFTimeInterval)currentTime
{
if (self.touchingScreen && self.node.position.y <= self.jumpHeightMax) {
self.node.physicsBody.velocity = CGVectorMake(0, 0);
[self.node.physicsBody applyImpulse:CGVectorMake(0, 50)];
} else {
self.jumpHeightMax = 0;
}
}
#end

ios 7 SKScene size vs visible area?

Apple's documentation has me a bit confused.
According to the documentation page : https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Nodes/Nodes.html the relationship between the visible area of the scene in points and the size of the scene should be the same according to the sentence :
"The size of the scene specifies the size of the visible portion of
the scene in points".
I created a custom scene that gets its size from the size of the device's screen (in my case I've been testing this for the iPad in portrait mode so the size should be 768 wide by 1024 high).
The following line which is being called in the scene's createContent method
NSLog(#"self.size : %f %f", self.size.width, self.size.height);
Returns
2014-07-15 14:53:28.844 SpriteWalkthrough[15888:90b] self.size : 768.000000 1024.000000
as expected.
However when I try to draw a SKSpriteNode at the position(self.size.width/2,self.size.height/2) the node is drawn in the upper right hand corner of the screen, not in the middle.
Why is this happening?
For other people who may be making similar mistakes drawing SpriteNodes to a scene, take a look at my source code for the scene, and in particular pay attention to the //self.sCar.car.position = self.sCar.position;line.
FoolAroundScene.h
#import <SpriteKit/SpriteKit.h>
#interface FoolAroundScene : SKScene
#end
FoolAroundScene.m
#import "FoolAroundScene.h"
#import "ScrollingBackground.h"
#import "SpriteCar.h"
#define BACKGROUND_NAME #"clouds.jpg"
#interface FoolAroundScene ()
#property BOOL contentCreated;
#property (strong, nonatomic) ScrollingBackground * sbg;
#property (strong, nonatomic) SpriteCar * sCar;
#end
#implementation FoolAroundScene
-(void) didMoveToView:(SKView *)view
{
if (!self.contentCreated) {
[self createContent];
self.contentCreated = !self.contentCreated;
}
}
-(void)createContent
{
self.sbg = [[ScrollingBackground alloc] initWithBackgroundImage:BACKGROUND_NAME size:self.size speed:2.0];
self.sCar = [[SpriteCar alloc] init];
[self addChild:self.sbg];
[self addChild:self.sCar];
self.sCar.position = CGPointMake(self.size.width/2, self.size.height/2);
//self.sCar.car.position = self.sCar.position;
SKSpriteNode * spriteCar = [self.sCar makeCarSprite];
spriteCar.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
NSLog(#"anchor point : %f %f", self.anchorPoint.x, self.anchorPoint.y);
NSLog(#"self.size : %f %f", self.size.width, self.size.height);
NSLog(#"self.scalemode : %d", self.scaleMode);
}
-(void) update:(NSTimeInterval)currentTime
{
[self.sbg update:currentTime];
}
#end
Even though I had set the sCar's position property to the middle of the scene, by setting its child node (the sCar's car property) position to the same value, the child's position will not be the same as its parent's. This is because the child's position is relative to its parent's.
Explained another way : the parent's position in the context of the scene was (384,512) and the child's position in the context of its parent was (384,512). However this means that the child's position in the context of the scene was actually (768,1024), which is why the car was being drawn in the upper right hand corner of the screen.
Also, in case anyone wants the implementation for the sprite car, here it is. A crappily drawn car that can be used to get a grip on how the Sprite Kit works.
SpriteCar.h
#import <SpriteKit/SpriteKit.h>
#interface SpriteCar : SKNode
-(id)init;
-(SKSpriteNode *)makeCarSprite;
#end
SpriteCar.m
#import "SpriteCar.h"
#interface SpriteCar ()
#property (nonatomic, strong) SKSpriteNode * car;
#end
#implementation SpriteCar
-(id) init
{
self = [super init];
if (self) {
self.car = [self makeCarSprite];
[self addChild:self.car];
}
return self;
}
-(SKSpriteNode *) makeCarSprite
{
SKSpriteNode * carBody1 = [[SKSpriteNode alloc] initWithColor:[SKColor redColor] size:CGSizeMake(64.0, 24.0)];
SKSpriteNode * carBody2 = [[SKSpriteNode alloc] initWithColor:[SKColor redColor] size:CGSizeMake(32.0, 32.0)];
SKSpriteNode * wheel1 = [[SKSpriteNode alloc] initWithColor:[SKColor blackColor] size:CGSizeMake(8.0, 8.0)];
SKSpriteNode * wheel2 = [wheel1 copy];
SKSpriteNode * light = [[SKSpriteNode alloc] initWithColor:[SKColor yellowColor] size:CGSizeMake(6.0, 6.0)];
carBody2.position = carBody1.position;
wheel1.position = CGPointMake(30.0, -30);
wheel2.position = CGPointMake(-30.0, -30.0);
light.position = CGPointMake(32.0, 11.0);
[carBody1 addChild:carBody2];
[carBody1 addChild:wheel1];
[carBody1 addChild:wheel2];
[carBody1 addChild:light];
SKAction * hover = [SKAction sequence:#[[SKAction moveByX:0.0 y:5.0 duration:0.1],
[SKAction waitForDuration:0.05],
[SKAction moveByX:0.0 y:-5.0 duration:0.1],
[SKAction waitForDuration:0.05]]];
[carBody1 runAction:[SKAction repeatActionForever:hover]];
return carBody1;
}
#end

SpriteKit: Change texture based on direction

I'm using an on-screen DPAD to move my character but I'm having trouble with passing in my sprites based on direction. Basically what I need is if the character is moving up, use the walking up animation. Moving down, use down. Left, use left, and right, use right animations. The angles are what I'm really having trouble with. This is the code that I'm using to move my character.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//if control pad touched
if ([node.name isEqualToString:#"controlPadNode"]) {
touchX = location.x +100; //adjust for anchor
touchY = location.y +43;
controlButtonDown = YES;
}
-(void)update:(CFTimeInterval)currentTime {
if (controlButtonDown == YES) {
//the node I want to move
SKNode *character = (CSCharacter*)node;
//compute the angle between parameters pad and the horizontal
float angle = atan2f (touchY - controlPadY, touchX - controlPadX) ;
//move the character
SKAction *moveCharacter = [SKAction moveByX: 1*cosf(angle) y:1*sinf(angle) duration:0.005];
[character runAction: moveCharacter];
//add h and m file in your project
#import <SpriteKit/SpriteKit.h>
//spriteSequence
#interface spriteSheet : SKSpriteNode
{
//private variable no one
}
#property SKTexture *startingFrame;
#property SKSpriteNode *animatedsprite;
#property SKAction *Animation;
#property SKAction *currentAction;
#property NSMutableArray *spritesArray;
#property NSMutableArray *frameRateArray;
#property NSMutableArray *actionKeys;
#property NSString *previousAction;
//public mehods
-(id) initSpritesheet:(NSString*)firstFrame;
-(void)addAnimation:(NSMutableArray*)frames frameRate:(float)time withKey:(NSString*)Key;
-(void)gotoAndPlay:(int)animationindex label:(NSString*)framelabel;
-(void)removeThisAction:(int)index;
//for ground hero
#property float totalWidth;
//for zipline
#property float Hspeed;
//
#end
#import "spriteSheet.h"
#implementation spriteSheet
-(id) initSpritesheet:(SKTexture*)firstFrame{
self=[super init];
if(self)
{
//passing rect to rectangle
_startingFrame=firstFrame;
[self addRefernce];
}
return self;
}
-(void) addRefernce
{
//adding a reference
_animatedsprite=[SKSpriteNode spriteNodeWithTexture:_startingFrame];
_animatedsprite.anchorPoint=CGPointMake(0.5, 0.5);
[self addChild:_animatedsprite];
_spritesArray=[[NSMutableArray alloc] init];
_frameRateArray=[[NSMutableArray alloc] init];
_actionKeys=[[NSMutableArray alloc] init];
}
//
-(void)addAnimation:(NSMutableArray*)frames frameRate:(float)time withKey:(NSString*)Key
{
[_spritesArray addObject:frames];
[_frameRateArray addObject:[NSNumber numberWithFloat:time]];
[_actionKeys addObject:Key];
}
-(void)gotoAndPlay:(int)animationindex label:(NSString*)framelabel;
{
// [self removeAllActions];
NSMutableArray *frames=_spritesArray[animationindex];
float time=[_frameRateArray[animationindex] floatValue];
NSString *key=_actionKeys[animationindex];
_Animation = [SKAction animateWithTextures:frames timePerFrame:time resize:TRUE restore:TRUE];
if([framelabel isEqualToString:#"loop"])
{
_currentAction = [SKAction repeatActionForever:_Animation ];
}
else if([framelabel isEqualToString:#"playonce"])
{
_currentAction=_Animation;
}
[_animatedsprite runAction:_currentAction withKey:key];
}
-(void)removeThisAction:(int)index
{
[_animatedsprite removeActionForKey:_actionKeys[index]];
}
#end
adding all animation
NSString *frame =gameViewController.commanDataHolder.heroRunning[0];//add first frame
_gameHero=[[herospriteSheet alloc] initSpritesheet:frame];
//adding animation
[_gameHero addAnimation:gameViewController.commanDataHolder.heroRunning frameRate:1 withKey:#“up”]; //index 0
[_gameHero addAnimation:gameViewController.commanDataHolder.heroJumpUp frameRate:6 withKey:#“down]; //index 1
[_gameHero addAnimation:gameViewController.commanDataHolder.heroFallDown frameRate:1 withKey:#“left”];//index 2
[_gameHero addAnimation:gameViewController.commanDataHolder.heroJumpDown frameRate:0.5 withKey:#“right”];//index 3
[self addObject:_gameHero];
at any action degree of rotation or swipe etc
//play first animation in loop
[_gameHero gotoAndPlay:0 label:#"loop"];
//play first animation in loop
[_gameHero gotoAndPlay:0 label:#“playonce”];
at any action degree of rotation or swipe etc
//play second animation in loop
[_gameHero gotoAndPlay:1 label:#"loop"];
//play first animation in loop
[_gameHero gotoAndPlay:1 label:#“playonce”];
I've got the animations working but I'm not sure how to pass them in according to which direction the character is moving. I have up and down working with this:
if (touchY > 1 ) {
[leader runWalkBackTextures]; //character moving up animations
}else{
[leader runWalkFrontTextures]; //character moving down animations
}
but my issue comes in with the angles, like if someone were to press between up and right on the control pad. If they press more to the right then up I'd like it to pass in my moving right animation but if they press more to the top of the DPAD I want to pass in the move up animation. Not sure exactly how to do this.

Throwing ball in SpriteKit

Last days, I experimented some time with spriteKit and (amongst other things) tried to solve the problem to "throw" a sprite by touching it and dragging.
The same question is on Stackexchange, but they told me to first remove the bug and then let the code be reviewed.
I have tackled the major hurdles, and the code is working fine, but there consist one little problem.
(Additionally, I'd be interested if somebody has a more polished or better working solution for this. I'd also love to hear suggestions about how to perfect the feeling of realism in this interaction.)
Sometimes, the ball just gets stuck.
If you want to reproduce that, just swipe the ball really fast and short. I suspect the gestureRecognizer to make "touchesMoved" and "touchesEnded" callback asynchronous and through that some impossible state occurs in the physics simulation.
Can anybody provide a more reliable way to reproduce the issue, and what could be the solution for that?
The project is called ballThrow and BT is the class prefix.
#import "BTMyScene.h"
#import "BTBall.h"
#interface BTMyScene()
#property (strong, nonatomic) NSMutableArray *balls;
#property (nonatomic) CGFloat yPosition;
#property (nonatomic) CGFloat xCenter;
#property (nonatomic) BOOL updated;
#end
#implementation BTMyScene
const CGFloat BALLDISTANCE = 80;
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
_balls = [NSMutableArray arrayWithCapacity:5];
//define the region where the balls will spawn
_yPosition = size.height/2.0;
_xCenter = size.width/2.0;
/* Setup your scene here */
self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
}
return self;
}
-(void)didMoveToView:(SKView *)view {
//Make an invisible border
//this seems to be offset... Why the heck is this?
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:view.frame];
[self createBalls:2];
//move balls with pan gesture
//could be improved by combining with touchesBegan for first locating the touch
[self.view addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(moveBall:)]];
}
-(void)moveBall:(UIPanGestureRecognizer *)pgr {
//depending on the touch phase do different things to the ball
if (pgr.state == UIGestureRecognizerStateBegan) {
[self attachBallToTouch:pgr];
}
else if (pgr.state == UIGestureRecognizerStateChanged) {
[self moveBallToTouch:pgr];
}
else if (pgr.state == UIGestureRecognizerStateEnded) {
[self stopMovingTouch:pgr];
}
else if (pgr.state == UIGestureRecognizerStateCancelled) {
[self stopMovingTouch:pgr];
}
}
-(void)attachBallToTouch:(UIPanGestureRecognizer *)touch {
//determine the ball to move
for (BTBall *ball in self.balls) {
if ([self isMovingBall:ball forGestureRecognizer:touch])
{
//stop ball movement
[ball.physicsBody setAffectedByGravity:NO];
[ball.physicsBody setVelocity:CGVectorMake(0, 0)];
//the ball might not be touched right in its center, so save the relative location
ball.touchLocation = [self convertPoint:[self convertPointFromView:[touch locationInView:self.view]] toNode:ball];
//update location once, just in case...
[self setBallPosition:ball toTouch:touch];
if (_updated) {
_updated = NO;
[touch setTranslation:CGPointZero inView:self.view];
}
}
}
}
-(void)moveBallToTouch:(UIPanGestureRecognizer *)touch {
for (BTBall *ball in self.balls) {
if ([self isMovingBall:ball forGestureRecognizer:touch])
{
//update the position of the ball and reset translation
[self setBallPosition:ball toTouch:touch];
if (_updated) {
_updated = NO;
[touch setTranslation:CGPointZero inView:self.view];
}
break;
}
}
}
-(void)setBallPosition:(BTBall *)ball toTouch:(UIPanGestureRecognizer *)touch {
//gesture recognizers only deliver locations in views, thus convert to node
CGPoint touchPosition = [self convertPointFromView:[touch locationInView:self.view]];
//update the location to the touche´s location, offset by touch position in ball
[ball setNewPosition:CGPointApplyAffineTransform(touchPosition,
CGAffineTransformMakeTranslation(-ball.touchLocation.x,
-ball.touchLocation.y))];
//save the velocity between the last two touch records for later release
CGPoint velocity = [touch velocityInView:self.view];
//why the hell is the y coordinate inverted??
[ball setLastVelocity:CGVectorMake(velocity.x, -velocity.y)];
}
-(void)stopMovingTouch:(UIPanGestureRecognizer *)touch {
for (BTBall *ball in self.balls) {
if ([self isMovingBall:ball forGestureRecognizer:touch]) {
//release the ball: enable gravity impact and make it move
[ball.physicsBody setAffectedByGravity:YES];
[ball.physicsBody setVelocity:CGVectorMake(ball.lastVelocity.dx, ball.lastVelocity.dy)];
break;
}
}
}
-(BOOL)isMovingBall:(BTBall *)ball forGestureRecognizer:(UIPanGestureRecognizer *)touch {
//latest location of touch
CGPoint touchPosition = [touch locationInView:self.view];
//distance covered since the last call
CGPoint touchTranslation = [touch translationInView:self.view];
//position, where the ball must be, if it is the one
CGPoint translatedPosition = CGPointApplyAffineTransform(touchPosition,
CGAffineTransformMakeTranslation(-touchTranslation.x,
-touchTranslation.y));
CGPoint inScene = [self convertPointFromView:translatedPosition];
//determine weather the last touch location was on the ball
//if last touch location was on the ball, return true
return [[self nodesAtPoint:inScene] containsObject:ball];
}
-(void)update:(CFTimeInterval)currentTime {
//updating the ball position here improved performance dramatically
for (BTBall *ball in self.balls) {
//balls that move are not gravity affected
//easiest way to determine movement
if ([ball.physicsBody affectedByGravity] == NO) {
[ball setPosition:ball.newPosition];
}
}
//ball positions are refreshed
_updated = YES;
}
-(void)createBalls:(int)numberOfBalls {
for (int i = 0; i<numberOfBalls; i++) {
BTBall *ball;
//reuse balls (not necessary yet, but imagine balls spawning)
if(i<[self.balls count]) {
ball = self.balls[i];
}
else {
ball = [BTBall newBall];
}
[ball.physicsBody setAffectedByGravity:NO];
//calculate ballposition
CGPoint ballPosition = CGPointMake(self.xCenter-BALLSIZE/2+(i-(numberOfBalls-1)/2.0)*BALLDISTANCE, self.yPosition);
[ball setNewPosition:ballPosition];
[self.balls addObject:ball];
[self addChild:ball];
}
}
#end
The BTBall (subclass of SKShapeNode, because of the custom properties needed)
#import <SpriteKit/SpriteKit.h>
#interface BTBall : SKShapeNode
const extern CGFloat BALLSIZE;
//some properties for the throw animation
#property (nonatomic) CGPoint touchLocation;
#property (nonatomic) CGPoint newPosition;
#property (nonatomic) CGVector lastVelocity;
//create a standard ball
+(BTBall *)newBall;
#end
The BTBall.m with a class method to create new balls
#import "BTBall.h"
#implementation BTBall
const CGFloat BALLSIZE = 80;
+(BTBall *)newBall {
BTBall *ball = [BTBall node];
//look
[ball setPath:CGPathCreateWithEllipseInRect(CGRectMake(-BALLSIZE/2,-BALLSIZE/2,BALLSIZE,BALLSIZE), nil)];
[ball setFillColor:[UIColor redColor]];
[ball setStrokeColor:[UIColor clearColor]];
//physics
SKPhysicsBody *ballBody = [SKPhysicsBody bodyWithCircleOfRadius:BALLSIZE/2.0];
[ball setPhysicsBody:ballBody];
[ball.physicsBody setAllowsRotation:NO];
//ball is not moving at the beginning
ball.lastVelocity = CGVectorMake(0, 0);
return ball;
}
#end
1. A couple of problems (see comments in code) are related to the spriteKit coordinate system. I just do not get the border of the scene align with its actual frame, though I make it with the exact same code that Apple gives us in the programming guide. I have moved it from initWithSize to didMoveToView due to a suggestion here on Stackoverflow, but that did not help. It is possible to manually offset the border with hardcoded values, but that does not satisfy me.
2. Does anybody know a debugging tool, which colors the physics body of a sprite, in order to see its size and whether it is at the same position as the sprite?
Update: Problems above solved by using YMC Physics Debugger:
This lines of code are correct:
[ball setPath:CGPathCreateWithEllipseInRect(CGRectMake(-BALLSIZE/2,-BALLSIZE/2,BALLSIZE,BALLSIZE), nil)];
SKPhysicsBody *ballBody = [SKPhysicsBody bodyWithCircleOfRadius:BALLSIZE/2.0];
Because 0,0 is the center of the physics body, the origin of the path must be translated.

Why isn't this SKAction moveByX: y: duration: moving this sprite at all?

I'm trying to respond to Swipe Gestures in a scene and move a sprite in response. The sprite is displaying on the left side of the screen. The logging statement in the handleSwipeRight is going to the log. But the sprite isn't moving at all. Surely I'm just missing something basic on the SKAction?
Here's my Scene code :
MFFMyScene.h :
#import <SpriteKit/SpriteKit.h>
#interface MFFMyScene : SKScene <UIGestureRecognizerDelegate>
#property (nonatomic) SKSpriteNode *player;
#property (nonatomic) UISwipeGestureRecognizer * swipeRightGesture;
#property (nonatomic) UISwipeGestureRecognizer * swipeLeftGesture;
#property (nonatomic) UISwipeGestureRecognizer * swipeUpGesture;
#property (nonatomic) UISwipeGestureRecognizer * swipeDownGesture;
#end
Relevant bits from MFFMyScene.m :
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
NSLog(#"Size: %#", NSStringFromCGSize(size));
self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
SKTextureAtlas *atlas = [SKTextureAtlas atlasNamed:#"dungeon"];
SKTexture *texture = [atlas textureNamed:#"hero_trans.png"];
_player = [SKSpriteNode spriteNodeWithTexture:texture];
_player.position = CGPointMake(10, 150);
[self addChild:_player];
}
return self;
}
-(void) didMoveToView:(SKView *)view {
_swipeRightGesture = [[UISwipeGestureRecognizer alloc]
initWithTarget:self
action:#selector(handleSwipeRight:)];
_swipeRightGesture.direction = UISwipeGestureRecognizerDirectionRight;
[view addGestureRecognizer:_swipeRightGesture];
}
- (void)handleSwipeRight:(UISwipeGestureRecognizer *)sender {
if(sender.direction == UISwipeGestureRecognizerDirectionRight) {
NSLog(#"scene: SWIPE RIGHT");
SKAction *movePlayerRight = [SKAction moveByX:10.0
y:0.0
duration:100.0];
[_player runAction:movePlayerRight];
}
}
Make your properties strong, use setters to let system do right memory management for you, for instance
#property (nonatomic, strong) UISwipeGestureRecognizer *rightSwipe;
self.rightSwipe = /* init code here */
check for swipe gesture state:
- (void)swipeHandled:(UISwipeGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateRecognized) {
if (sender.direction == UISwipeGestureRecognizerDirectionRight) {
/* moving code here */
}
}
}
I was using this SKAction wrong. I was looking for an SKAction that would do 'move x/y every z seconds' or 'move x/y every frame for z seconds'. The way I originally had it written, the SKAction will move the sprite 10 points total over a period of 100 seconds.
So I think the sprite was moving after all, but my X/Y/duration values were such that the movement was so small that it looked like it wasn't moving. With x=10 and duration=100 seconds, it was moving 10 points over 100 seconds. I don't even understand point vs pixel, but that was slow movement.
I changed it to x=100, y=50, duration=1.0, and it moved just fine.

Resources