Search code examples
iossprite-kitskaction

SpriteKit change Image after swipe gesture


I am trying to code a game. I got an object, that can jump and slide. I want to hold the animation of 'run' while jumping, but while sliding, I want to change the image. My problem: the image won't show off , if I just change the image to 'slide7'. Nothing happens. The slide animation should appear only for about 4 seconds, than go again into the run animation. Any suggestions?

My Code :

-(void)Mensch{

SKTexture * MenschTexture1 = [SKTexture textureWithImageNamed:@"Mensch1"];
MenschTexture1.filteringMode = SKTextureFilteringNearest;
SKTexture * MenschTexture2 = [SKTexture textureWithImageNamed:@"Mensch2"];
MenschTexture2.filteringMode = SKTextureFilteringNearest;

SKAction * Run = [SKAction repeatActionForever:[SKAction animateWithTextures:@[MenschTexture1, MenschTexture2] timePerFrame:0.4]];

Mensch = [SKSpriteNode spriteNodeWithTexture:MenschTexture1];
Mensch.size = CGSizeMake(45, 45);
Mensch.position = CGPointMake(self.frame.size.width / 5, Boden.position.y + 73);
Mensch.zPosition = 2;

Mensch.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:Mensch.size];
Mensch.physicsBody.dynamic = YES;
Mensch.physicsBody.allowsRotation = NO;
Mensch.physicsBody.usesPreciseCollisionDetection = YES;
Mensch.physicsBody.restitution = 0;
Mensch.physicsBody.velocity = CGVectorMake(0, 0);

[Mensch runAction:Run];
[self addChild:Mensch];

}


- (void)didMoveToView:(SKView *)view
{
UISwipeGestureRecognizer *recognizerDown = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeDown:)];
recognizerDown.direction = UISwipeGestureRecognizerDirectionDown;
[[self view] addGestureRecognizer:recognizerDown];
}


-(void)handleSwipeDown:(UISwipeGestureRecognizer *)sender
{

[Mensch removeAllActions];

Mensch = [SKSpriteNode spriteNodeWithImageNamed:@"slide7.png"];

NSLog(@"Slide");

}

Solution

  • You are replacing the Mensch object. More specifically, you are replacing the pointer you have to the object, but that doesn't stop it from being displayed in the scene.

    You can either:

    • Replace the SKTexture inside the sprite, which should be displayed immediately. This means Mensch.texture = [SKTexture textureWithImageNamed:@"slide7.png"];
    • Replace the Sprite. This entails removing the current sprite ([sprite removeFromParent]) and adding the new one ([self addChild:newSprite]).

    I think you want the first one, since you don't have to recreate the Mensch object.

    Might I add that you are performing a lot of Mensch-specific logic in this object? It would be better (from an Object Oriented standpoint) to move this creation code to an SKSpriteNode subclass Mensch.

    @interface Mensch : SKSpriteNode
    
    - (void) displayRunAnimation;
    - (void) displaySlideAnimation;
    
    @end
    
    @implementation : Mensch 
    
    - (instancetype) init {
      self = [super init];
      if (self) {
        // your initialization code here, including physics body setup
    
        [self displayRunAnimation];
      }
      return self;
    }
    
    - (void) displayRunAnimation {
      SKTexture * MenschTexture1 = [SKTexture textureWithImageNamed:@"Mensch1"];
      MenschTexture1.filteringMode = SKTextureFilteringNearest;
      SKTexture * MenschTexture2 = [SKTexture textureWithImageNamed:@"Mensch2"];
      MenschTexture2.filteringMode = SKTextureFilteringNearest;
    
      SKAction * Run = [SKAction repeatActionForever:[SKAction animateWithTextures:@[MenschTexture1, MenschTexture2] timePerFrame:0.4]];
      // if you plan to call this often, you want to cache this SKAction, since creating it over and over is a waste of resources
    
      [self runAction:Run];
    }
    
    - (void) displaySlideAnimation {
      [self removeAllActions];
      self.texture  = [SKTexture textureWithImageNamed:@"slide7.png"];
      NSLog(@"Slide");
    
      // re-start the runAnimation after a time interval
      [self performSelector:@selector(displayRunAnimation) withObject:nil afterDelay:4.0];
    }