I have the animation like below.
sit animation:
SKTexture *sit1 = [SKTexture textureWithImageNamed:#"sit_1_blur.png"];
SKTexture *sit2 = [SKTexture textureWithImageNamed:#"sit_2_blur.png"];
SKTexture *sit3 = [SKTexture textureWithImageNamed:#"sit_3_blur.png"];
SKTexture *sit4 = [SKTexture textureWithImageNamed:#"sit_4_blur.png"];
SKTexture *sit5 = [SKTexture textureWithImageNamed:#"sit_5_blur.png"];
NSArray *sitPng = #[sit1,sit2,sit3];
NSArray *drinkPng = #[sit3,sit4,sit5];
sitAnimation = [SKAction animateWithTextures:sitPng timePerFrame:0.2];
drinkAnimation = [SKAction animateWithTextures:drinkPng timePerFrame:1];
-(void) takeSit{
[self runAction:sitAnimation completion:^{
[self startDrink];
}];
}
How can I change value every second during startDrink animation? Like so:
someValue +=0.2;
You need to have this inside your startDrink Animation (I am assuming startDrink is another action defined somewhere),
+ (SKAction *)customActionWithDuration:(NSTimeInterval)seconds actionBlock:(void (^)(SKNode *node, CGFloat elapsedTime))block;
measure the the time passed and update someValue +=0.2; accordingly.
Hope this helps.
Related
For some odd reason textures from my texture atlas are not loading. I have no idea why.
Below is how I typically declare/code a texture
-(SKSpriteNode *)background {
SKSpriteNode *background;
NSArray *backgroundIpad;
background = [SKSpriteNode spriteNodeWithImageNamed:#"dodgR - main background"];
background.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
background.size = CGSizeMake(1136, 640);
NSArray *backgroundIphone = #[[SKTexture textureWithImageNamed:#"dodgR - animation 1.jpg"],
[SKTexture textureWithImageNamed:#"dodgR - animation 2.jpg"],
[SKTexture textureWithImageNamed:#"dodgR - animation 3.jpg"],
[SKTexture textureWithImageNamed:#"dodgR - animation 4.jpg"],
[SKTexture textureWithImageNamed:#"dodgR - animation 5.jpg"],
[SKTexture textureWithImageNamed:#"dodgR - animation 6.jpg"],
[SKTexture textureWithImageNamed:#"dodgR - animation 7.jpg"],
[SKTexture textureWithImageNamed:#"dodgR - animation 8.jpg"],
[SKTexture textureWithImageNamed:#"dodgR - animation 9.jpg"],
[SKTexture textureWithImageNamed:#"dodgR - animation 10.jpg"]];
SKAction *backgroundIphoneAnimation = [SKAction animateWithTextures:backgroundIphone timePerFrame:0.05];
SKAction *backgroundIphoneRepeat = [SKAction repeatActionForever:backgroundIphoneAnimation];
[background runAction:backgroundIphoneRepeat];
background.name = #"background";
return background;
}
The name of my texture atlas is sprites.atlas
Any help will be much appreciated, thanks
Your code above only works when using images not in a texture atlas because it doesn't actually make use of a texture atlas.
Images can't be pulled out of an Atlas (that i know of) without using SKTextureAtlas. So you can't grab those images directly.
SWIFT:
let atlas = SKTextureAtlas(named: "BackgroundImages") // atlas name
var backgroundFrames = [SKTexture]()
let imageCount = atlas.textureNames.count
for var i=1; i<= imageCount/2; i++ {
let textureName = "dodgR - animation \(i)"
backgroundFrames.append(atlas.textureNamed(textureName))
}
OBJECTIVE-C (not tested)
SKTextureAtlas *atlas = [SKTextureAtlas named:#"BackgroundImages"]; // atlas name
NSMutableArray *backgroundFrames = [NSMutableArray new];
int imageCount = atlas.textureNames.count;
for (int i = 1; i <= imageCount/2; i++) {
NSString *textureName = #"dodgR - animation \(i)";
[bacgroundFrames addObject:[atlas textureNamed:textureName]];
}
BONUS: Xcode 7 now allows you to create your sprite atlases right inside the assets folder.
How can I tell the walk cycle to continue animating until an NSNumber with bool flag stops it?
And also remove the SKSpriteNode with the SKTexture from the stage?
SKSpriteNode *walk = [SKSpriteNode spriteNodeWithTexture:[_walkTextures objectAtIndex:0]];
walk.zPosition = 100;
walk.scale = spliffScale;
walk.position = location;
[self addChild:walk];
SKAction *walkAction = [SKAction animateWithTextures:_walkTextures timePerFrame:0.03];
SKAction *remove = [SKAction removeFromParent];
[walk runAction:[SKAction sequence:#[walkAction, walkAction, remove]]];
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");
}
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];
}
I had a general SKScene where I created a SKSpriteNode, added it via
[self addChild:_charecter];
And all was well..
I tried making a new class for the SKSpriteNode so that I could add some custom methods to it. Here is it's init method:
- (instancetype)init
{
if (self = [super init]) {
SKTexture *run1 = [SKTexture textureWithImageNamed:#"run1"];
SKTexture *run2 = [SKTexture textureWithImageNamed:#"run2"];
SKTexture *run3 = [SKTexture textureWithImageNamed:#"run3"];
_charecterSprites = [NSArray arrayWithObjects:run1, run2, run3, nil];
self.texture = run1;
self.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:1.0]; //CHANGE THIS LATER
}
return self;
}
The problem is that now when I add the _charecter to the view, it doesn't appear. I'm adding him in the SKScene as follows:
_charecter = [[RUNPlayer alloc] init];
_charecter.position = CGPointMake(CGRectGetMidX(self.frame), CHARECTER_Y_AXIS);
self.physicsWorld.gravity = CGVectorMake(0, -10.0/150.0);
[self addChild:_charecter];
Any idea why my SKSpriteNode isn't visible?
Thanks
Trying using one of the SKSpriteNode initializers instead of init
- (instancetype)initWithImageNamed:(NSString *)name
{
if (self = [super initWithImageNamed:name]) {
SKTexture *run1 = [SKTexture textureWithImageNamed:#"run1"];
SKTexture *run2 = [SKTexture textureWithImageNamed:#"run2"];
SKTexture *run3 = [SKTexture textureWithImageNamed:#"run3"];
_charecterSprites = [NSArray arrayWithObjects:run1, run2, run3, nil];
self.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:1.0]; //CHANGE THIS LATER
}
return self;
}
From what I understand, when you use initWithImageNamed:, the sprite node's size is set to the texture's size. Your sprite could of been on screen but had a size of (0,0). Let us know if this works!
On a side note, check out Ray's tutorial on texture atlases to replace _characterSprites http://www.raywenderlich.com/45152/sprite-kit-tutorial-animations-and-texture-atlases
I'm trying to add a little animation based on two pngs, where I create two SKTextures with two images and create an SKAction, and have it run forever with [SKAction repeatActionForever] but nothing is happening, nothing is appearing on the screen.
Here's my code:
_planePropeller = [SKSpriteNode spriteNodeWithImageNamed:#"PLANE PROPELLER 1.png"];
_planePropeller.xScale = 0.2;
_planePropeller.yScale = 0.2;
_planePropeller.position = CGPointMake(screenWidth/2, _plane.size.height+10);
SKTexture *propeller1 = [SKTexture textureWithImageNamed:#"PLANE PROPELLER 1.png"];
SKTexture *propeller2 = [SKTexture textureWithImageNamed:#"PLANE PROPELLER 2.png"];
SKAction *spin = [SKAction animateWithTextures:#[propeller1, propeller2] timePerFrame:0.1];
SKAction *spinForever = [SKAction repeatActionForever:spin];
[_planePropeller runAction:spinForever];
[self addChild:_planePropeller];
Any ideas? Thanks a lot in advance!
could be your positioning details, are you sure they are correct? I've changed your code slightly (self.frame.size.width instead of screenWidth and the same for height, to position it in the centre of the view) and it works for me:
- (SKNode *)propellorNode
{
SKNode *planePropeller = [SKSpriteNode spriteNodeWithImageNamed:#"image1.png"];
planePropeller.xScale = 0.2;
planePropeller.yScale = 0.2;
planePropeller.position = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
SKTexture *propeller1 = [SKTexture textureWithImageNamed:#"image1.png"];
SKTexture *propeller2 = [SKTexture textureWithImageNamed:#"image2.png"];
SKAction *spin = [SKAction animateWithTextures:#[propeller1, propeller2] timePerFrame:0.1];
SKAction *spinForever = [SKAction repeatActionForever:spin];
[planePropeller runAction:spinForever];
return planePropeller;
}
So my problem was, actually, my own ignorance, since I first was adding my SKNodes, and the last, when the background should have been added the first, so it could be on the background :)
thanks a lot everybody for the answers!