SKCropNode Get Cropped Part As SKSpriteNode - ios

I applied a mask to SKCropNode And I see what i need now but
the cropped node has the size of the full image i just want to access the cropped part not the full image can i get that into SKSpriteNode??
Here is my code
SKSpriteNode *pic = [SKSpriteNode spriteNodeWithImageNamed:#"test.png"];
pic.name = #"PictureNode";
SKSpriteNode *mask = [SKSpriteNode spriteNodeWithImageNamed:#"2.png"];
mask.size=CGSizeMake(50, 50);
mask.position=CGPointMake(0, 50);
SKCropNode *cropNode = [SKCropNode node];
cropNode.position=CGPointMake(160, 70);
[cropNode addChild:pic];
[cropNode setMaskNode:mask];
[self addChild:cropNode];
and here are the images and result :
Thanks in advance

As far as I understood, you are trying to get cropped part as a SKSpriteNode, if it is the case, you can manage it as follows:
SKTexture *oldWholeTexture = [self.scene.view textureFromNode:cropNode];
SKTexture *newTexture = [SKTexture textureWithRect:CGRectMake(140.f/364.f,56.f/365.f,80.f/364.f,125.f/365.f) inTexture: oldWholeTexture];
SKSpriteNode *newNode = [SKSpriteNode spriteNodeWithTexture:newTexture];
CGRect parameter of textureWithRect takes unit values, so I normalized my values according my texture size. Bottom left is (0,0).

Related

Disable change of a spritenode

I'm creating a game where i'm creating an SKSpriteNode at the bottom. Cause i want to make a buttom higher than the actually bottom cause of grass as the background. The problem is after I've created the physics body and my moving SKSpriteNode makes contact with the bottom. the bottom SpriteNode that i've created will move.
How can i make the bottom sprite node which has the function as being the bottom edge, not move at all. By that i mean that it cant change position.
My code:
SKSpriteNode *bottom = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(self.frame.size.width*2, 98)];
bottom.physicsBody.dynamic = NO;
bottom.position = CGPointMake(0, 0);
[self addChild:bottom];
bottom.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:bottom.size];
You have to set the dynamic property of the physics body to NO. You are doing it before you actually create a physics body. That's why it does not have any effect. Change your code to:
SKSpriteNode *bottom = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor]
size:CGSizeMake(self.frame.size.width*2, 98)];
bottom.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:bottom.size];
bottom.physicsBody.dynamic = NO;
bottom.position = CGPointMake(0, 0);
[self addChild:bottom];
And it should work.

applying masks to SKEmitterNodes

May be some one can give me a hand… I’m trying to add a couple of SKEmitterNodes in their own SKCropNodes.
My code:
// left emitter node
NSString *path = [[NSBundle mainBundle] pathForResource:#"LeftParticle" ofType:#"sks"];
SKEmitterNode *lEmitterNode = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
// left crop node
SKSpriteNode *lMask = [SKSpriteNode spriteNodeWithColor:[UIColor blackColor] size:CGSizeMake(self.size.width/2, self.size.height)];
[lMask setAnchorPoint:CGPointZero];
SKCropNode *lCropNode = [SKCropNode node];
lCropNode.maskNode = lMask;
// move the left emitter under the mask
lEmitterNode.position = CGPointMake(CGRectGetMinX(lMask.frame) + lMask.size.width / 2, self.size.height);
[lCropNode addChild:lEmitterNode];
[self addChild:lCropNode];
// right emitter node
path = [[NSBundle mainBundle] pathForResource:#"RightParticle" ofType:#"sks"];
SKEmitterNode *rEmitterNode = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
// right crop node
SKSpriteNode *rMask = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake(self.size.width/2, self.size.height)];
[rMask setAnchorPoint:CGPointZero];
rMask.position = CGPointMake(rMask.size.width, 0);
SKCropNode *rCropNode = [SKCropNode node];
rCropNode.maskNode = rMask;
// move the right emitter under the mask
rEmitterNode.position = CGPointMake(CGRectGetMinX(rMask.frame) + rMask.size.width / 2, self.size.height);
[rCropNode addChild:rEmitterNode];
[self addChild:rCropNode];
And this is the result:
As you can see, my red particles render under the left mask... Why?
I’ve tried to reduce the size of mask with:
lMask.xScale = lMask.yScale = 0.9;
rMask.xScale = rMask.yScale = 0.9;
And this is the result:
I presume it’s a problem with render buffer, or may be it’s something about zPosition, or a bug, or may be I’m really lost.
Thnx

How to arc object with CGPathRef

In my iOS game, I am trying to move an object along a path (see below):
I want to move the triangle above around to the bottom of the box.
But I don't know how to use CGPathRefs very well. Here is what I am trying:
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddArc(path, NULL, 20, 0, 20, 0, M_PI/2, NO);
SKAction *moveTriangle = [SKAction followPath:path asOffset:YES orientToPath:YES duration:1.0];
[self.triangle runAction:moveTriangle];
And I keep getting odd results. Can anybody help me adjust my path to match the image above? Thanks!
Using prototypical's idea
// will arc around this sprite for demo
SKSpriteNode *boxOrange = [SKSpriteNode spriteNodeWithColor:[UIColor orangeColor] size:CGSizeMake(30, 30)];
boxOrange.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
[self addChild:boxOrange];
SKSpriteNode *heroSprite = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(70, 70)];
CGFloat offeset = 150; // change as required, ie bring hero closer to rotn point
heroSprite.position = CGPointMake(-offeset, heroSprite.position.y);
SKSpriteNode *guideContainer = [SKSpriteNode spriteNodeWithColor:[SKColor purpleColor] size:CGSizeMake(3, 3)];
// for full effect - change guide container to clearColor
// otherwise good for seeing where rotation point will occur
[guideContainer addChild:heroSprite];
[self addChild:guideContainer];
guideContainer.position = boxOrange.position;
[guideContainer runAction:[SKAction rotateToAngle:1.57 duration:3.0 shortestUnitArc:YES]];
// just found shortestUnitArc action .. this will be handy for at times

Refactor Help> For loop mapping CGPoints, and SKSpriteNodes

Hi I am new to programming and I have been learning SpriteKit. (although this is a general purpose programming question.) I have hard coded values, and reused the same image over and over. A coding no no from what I understand. Can someone help me learn this by refactoring with loops I assume.
I am creating a row of 20 dashed empty card spots and placing 4 at a time to a screen size centered at the bottom of the screen. I have added these empty spots (just one card image used over and over) as a "child" to the rack.
Side Note: Since this is a general programming question if you are not familiar with SpriteKit my CGPoints are mapped to the racks coordinate system and not to the screen coordinates... if that confused you..
I have attempted to create the refactored code at the bottom but I am stuck because the node.positions are tied to SKSpriteNodes and looping that seems to be puzzling me.
Here is what I have:
-(SKSpriteNode*)createBottomRack
{
self.rack = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(10240.0, 200)];
self.rack.position = CGPointMake(0.0,150.0);
self.rack.zPosition = 0;
self.rack.name = #"bottomRack";
// Screen 1
SKSpriteNode *number0 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
SKSpriteNode *number1 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
SKSpriteNode *number2 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
SKSpriteNode *number3 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
// Screen 1 positions
number0.position = CGPointMake(212, 0.0);
number1.position = CGPointMake(412, 0.0);
number2.position = CGPointMake(612, 0.0);
number3.position = CGPointMake(812, 0.0);
// Screen 2
SKSpriteNode *number4 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
SKSpriteNode *number5 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
SKSpriteNode *number6 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
SKSpriteNode *number7 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
// Screen 2 positions
number4.position =CGPointMake(1236.0, 0.0);
number5.position =CGPointMake(1436.0, 0.0);
number6.position =CGPointMake(1636.0, 0.0);
number7.position =CGPointMake(1836.0, 0.0);
// Screen 3
SKSpriteNode *number8 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
SKSpriteNode *number9 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
SKSpriteNode *number10 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
SKSpriteNode *number11 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
// Screen 3 positions
number8.position =CGPointMake(2260.0, 0.0);
number9.position =CGPointMake(2460.0, 0.0);
number10.position =CGPointMake(2660.0, 0.0);
number11.position =CGPointMake(2860.0, 0.0);
// Screen 4
SKSpriteNode *number12 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
SKSpriteNode *number13 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
SKSpriteNode *number14 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
SKSpriteNode *number15 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
// Screen 4 positions
number12.position =CGPointMake(3284.0, 0.0);
number13.position =CGPointMake(3484.0, 0.0);
number14.position =CGPointMake(3684.0, 0.0);
number15.position =CGPointMake(3884.0, 0.0);
// Screen 5
SKSpriteNode *number16 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
SKSpriteNode *number17 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
SKSpriteNode *number18 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
SKSpriteNode *number19 = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
// Screen 5 positions
number16.position =CGPointMake(4308.0, 0.0);
number17.position =CGPointMake(4508.0, 0.0);
number18.position =CGPointMake(4708.0, 0.0);
number19.position =CGPointMake(4908.0, 0.0);
// Add dashedCards in position on screen
[self.rack addChild:number0];
[self.rack addChild:number1];
[self.rack addChild:number2];
[self.rack addChild:number3];
[self.rack addChild:number4];
[self.rack addChild:number5];
[self.rack addChild:number6];
[self.rack addChild:number7];
[self.rack addChild:number8];
[self.rack addChild:number9];
[self.rack addChild:number10];
[self.rack addChild:number11];
[self.rack addChild:number12];
[self.rack addChild:number13];
[self.rack addChild:number14];
[self.rack addChild:number15];
[self.rack addChild:number16];
[self.rack addChild:number17];
[self.rack addChild:number18];
[self.rack addChild:number19];
return self.rack;
}
Here is where I currently am in refactoring...
NSMutableArray *dashesArray = [NSMutableArray arrayWithCapacity:20];
for (int i = 0; i<=20; i++) {
SKSpriteNode *dash = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
[dashesArray addObject:dash];
}
This is it because if I make a loop holding generically numbered SKSpriteNodes I don't see how I map those to the positions....?
Calculating the x coordinate for the position of each node is pretty straightforward:
x starts at 212
Subsequent nodes are 200px to the right of the previous node
Every 5th node is 424px (instead of 200px) to the right of the previous node
The code for that looks like this:
- (SKSpriteNode *)createBottomRack
{
self.rack = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(10240.0, 200)];
self.rack.position = CGPointMake(0.0,150.0);
self.rack.zPosition = 0;
self.rack.name = #"bottomRack";
float x = 212.0, y = 0.0;
for (NSUInteger i = 0; i < 20; i++) {
SKSpriteNode *dash = [SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
dash.position = CGPointMake(x, y);
[self.rack addChild:dash];
// Calculate the next x coordinate
x += (i % 4 == 3) ? 424.0 : 200;
}
return self.rack;
}
Since you are new to programming, I suggest you spend some time learning how arrays work, and how they are used:
http://en.wikipedia.org/wiki/Array_data_structure
and their iOS implementation:
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html
For starters, you can declare two arrays, one containing the SKSpriteNodes, and the other containing the position points:
//Declare these in #interface
#property (nonatomic) NSMutableArray *sprites;
#property (nonatomic) NSMutableArray *points;
//This will contain the SKSpriteNodes
self.sprites =[[NSMutableArray alloc] init];
//This will contain the points, we initialise it with the hard-coded values.
//You have to wrap the values in an object type of NSValue of the array to accept it
self.points = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithCGPoint:CGPointMake(212, 0.0)],
[NSValue valueWithCGPoint:CGPointMake(412, 0.0)],
[NSValue valueWithCGPoint:CGPointMake(612, 0.0)],
[NSValue valueWithCGPoint:CGPointMake(812, 0.0)],
//Put the rest of the values here... for the moment it will do
nil];
//Now for each declared point, we create a SKSpriteNode, insert it into the array and add it to "rack"
//for will loop over eacg point you have defined.
for (NSValue *point in self.points){
//This will be a temporary object we create to add it into the array.
SKSpriteNode *node =[SKSpriteNode spriteNodeWithImageNamed:#"dashedCard"];
node.position = [point CGPointValue];
[self.sprites addObject:node];
[self.rack addChild:node];
}
As you get more experience you will find many other ways to improve the code, but take your time studying the code and basic data structures. Good luck!

How do you scale SKSpirteNode without anti aliasing

I am trying to scale an SKSpriteNode object without smoothing/anti-aliasing (I'm using pixel-art so it looks better pixelated).
Is there a property I need to set to do this? This is the code I am using to render the sprite:
SKTextureAtlas *atlas = [SKTextureAtlas atlasNamed:#"objects"];
SKTexture *f1 = [atlas textureNamed:#"hero_1.png"];
SKSpriteNode *hero = [SKSpriteNode spriteNodeWithTexture:f1];
[self addChild: hero];
hero.scale = 6.0f;
The image is scaled correctly but blurry/smoothed out. This is hero_1.png .
Try,
SKTexture *texture = [SKTexture textureWithImageNamed:#"Fak4o"];
texture.filteringMode = SKTextureFilteringNearest;
SKSpriteNode *newHero = [SKSpriteNode spriteNodeWithTexture:texture];
newHero.position = CGPointMake(200, 200);
[newHero setScale:50];
[self addChild:newHero];
SKTextureFilteringNearest
Each pixel is drawn using the nearest point in the texture. This mode
is faster, but the results are often pixelated.
Swift:
sprite.texture!.filteringMode = .Nearest
Just a note, if you create a SKSpriteNode instead of SKTexture, you can set the SKTextureFilteringNearest like in the following example:
SKSpriteNode *asteroid = [SKSpriteNode spriteNodeWithImageNamed:#"o1"];
asteroid.size = CGSizeMake(36, 24);
asteroid.position = CGPointMake(startX, startY);
asteroid.name = #"obstacle";
// >>>
asteroid.texture.filteringMode = SKTextureFilteringNearest;
// <<<
[self addChild:asteroid];
try this:
hero.xscale = 6.0f;
hero.yscale = 6.0f;

Resources