Draw a frame in Spritekit - ios7

I want to draw a frame like in the picture below, where the white part inside the circle is clear(transparent) so that i can see the scene in the background, and the gray part is non-transparent.
I've looked into the CropNodes but I didn't find an answer. Everything should be added to the SKViewat the end.

this method works you can filter it more i am using shape node you can your texture shape node having some memory leaks in sprite kit
#import "milkhuntMyScene.h"
#implementation milkhuntMyScene
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
[self maskMe];
}
return self;
}
-(void)maskMe
{
//replace tomask to 1 pixel background and 778 width or acc to ur game
// SKSpriteNode *whiteArea = [SKSpriteNode spriteNodeWithImageNamed:#"pixel1.png"];
//[self addChild: whiteArea];
//whiteArea.xScale=1024;
SKSpriteNode *toMask = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size: CGSizeMake(2024, 778*2)];
SKSpriteNode *mask = [SKSpriteNode spriteNodeWithImageNamed:#"maskarea.png"];
mask.position=CGPointMake(400, 300);
//
CGRect circle = CGRectMake(0, 0,mask.frame.size.width,mask.frame.size.height);
SKShapeNode *shapeNode = [[SKShapeNode alloc] init];
shapeNode.path = [UIBezierPath bezierPathWithOvalInRect:circle].CGPath;
shapeNode.fillColor = SKColor.yellowColor;
shapeNode.strokeColor = [SKColor blueColor];
shapeNode.lineWidth=20;
shapeNode.position=CGPointMake(mask.position.x/2, 100);
[self addChild:shapeNode];
//
SKCropNode *cropNode = [SKCropNode node];
[cropNode addChild: toMask];
[cropNode setMaskNode: mask];
[self addChild: cropNode];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
}
-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
}
#end

Related

Sprite Kit SKLabel is not appearing when I initialize it in initWithSize:(CGSize)size

I read up on other posts and changed view controller viewdidload to:
(void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
}
and I'm really not sure what the problem is. here is my code:
(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
world=SKNode.node;
[self addChild:world];
self.anchorPoint= CGPointMake(0.5, 0.5);
SKSpriteNode *ground = [SKSpriteNode spriteNodeWithColor:[UIColor yellowColor] size: CGSizeMake(self.frame.size.width, 150)];
ground.position= CGPointMake(0, -self.frame.size.height/2+ ground.frame.size.width/2);
ground.physicsBody= [SKPhysicsBody bodyWithRectangleOfSize:ground.size];
ground.physicsBody.dynamic=NO;
NSLog(#"ground position: %f" , -self.frame.size.height/2+ ground.frame.size.width/2);
[world addChild:ground];
generator = [WorldGenerator generatorWithWorld:world];
[self addChild:generator];
[generator populate];
hero = [MLHero hero];
[world addChild:hero];
pointsLabel =[SKLabelNode labelNodeWithFontNamed:#"ChalkDuster"];
if (pointsLabel)
NSLog(#"true");
pointsLabel.fontColor=[SKColor redColor];
pointsLabel.fontSize=40;
pointsLabel.text=#"0";
pointsLabel.position= CGPointMake(200,200); //I have tried many different values and none seem to work, including setting to the width and height etc.
[self addChild:pointsLabel];
}
return self;
}

SpriteKit SKCropNode Masks everything

I am trying to mask a node with SKCropNode class. I am doing it with my own init method in SKCropNode inherited class:
- (id)init {
self = [super init];
if (self) {
self.maskNode = [[SKSpriteNode alloc] initWithColor:[SKColor blackColor] size:(CGSize){50,50}];
SKSpriteNode *contentNode = [[SKSpriteNode alloc] initWithImageNamed:#"Spaceship"];
[self addChild: contentNode];
self.userInteractionEnabled = YES;
}
return self;
}
It works as expected:
Now, I want to add background to the scene and a cropped spaceship with following code:
-(void)didMoveToView:(SKView *)view {
/* Setup your scene here */
//
//background
//
SKSpriteNode * background = [SKSpriteNode spriteNodeWithImageNamed:#"background_game"];
background.position = CGPointMake(CGRectGetMidX(view.frame), CGRectGetMidY(view.frame) - CGRectGetMinY(view.frame));
[self addChild:background];
TurretCropNode * cropNode = [[TurretCropNode alloc] init];
cropNode.position = (CGPoint){view.frame.size.width/2,view.frame.size.height/2};
[self addChild:cropNode];
}
I have just added few lines with adding background at the beginning (cropped node lines remain the same)
Here what I got now:
Is it an expected behavior? Why cropped spaceship disappeared?
I am guessing that the image as shown below is your designated background. Have you checked your nodes zPosition?
If you want to show your spaceship infront of your background, you will have to adjust the zPosition to be higher than that of the background sprite.

SprikeKit physics - How can i make my character stand up after falling down?

I'm new to sprite kit and game physics in general. I want my character to stand up upright whenever he falls over or knocked down. A bit like a floor-mounted punch bag. Here's my current code:
#import "MyScene.h"
#interface MyScene () <SKPhysicsContactDelegate> {
SKSpriteNode *_body;
SKSpriteNode *_leg1;
SKSpriteNode *_leg2;
SKSpriteNode *_foot1;
SKSpriteNode *_foot2;
}
#end
#implementation MyScene
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
//self.backgroundColor = [SKColor greenColor];
self.physicsWorld.gravity = CGVectorMake(0, -2.0);
self.physicsWorld.contactDelegate = self;
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
SKSpriteNode *button = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(50, 50)];
button.position = CGPointMake(40, 40);
button.zPosition = 10;
button.name = #"button";
[self addChild: button];
[self createCharacter];
}
return self;
}
-(void)createCharacter {
// Add sprites
_body = [SKSpriteNode spriteNodeWithColor:[SKColor purpleColor] size:CGSizeMake(40, 60)];
_body.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
[self addChild: _body];
_leg1 = [SKSpriteNode spriteNodeWithColor:[SKColor purpleColor] size:CGSizeMake(14, 60)];
_leg1.position = CGPointMake(_body.position.x+20-7, _body.position.y-65);
[self addChild:_leg1];
_foot1 = [SKSpriteNode spriteNodeWithColor:[SKColor purpleColor] size:CGSizeMake(20, 10)];
_foot1.position = CGPointMake(_leg1.position.x-2.5, _leg1.position.y-40);
[self addChild:_foot1];
_leg2 = [SKSpriteNode spriteNodeWithColor:[SKColor purpleColor] size:CGSizeMake(14, 60)];
_leg2.position = CGPointMake(_body.position.x-20+7, _body.position.y-65);
[self addChild:_leg2];
_foot2 = [SKSpriteNode spriteNodeWithColor:[SKColor purpleColor] size:CGSizeMake(20, 10)];
_foot2.position = CGPointMake(_leg2.position.x-2.5, _leg2.position.y-40);
[self addChild:_foot2];
// Add physics bodies to sprites
_body.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_body.size];
_leg1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_leg1.size];
_foot1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_foot1.size];
_foot1.physicsBody.mass = 1;
_leg2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_leg2.size];
_foot2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_foot2.size];
_foot2.physicsBody.mass = 0.5;
// Add joints
SKPhysicsJoint *hipJoint = [SKPhysicsJointFixed jointWithBodyA:_body.physicsBody bodyB:_leg1.physicsBody anchor:_leg1.position];
SKPhysicsJoint *ankleJoint = [SKPhysicsJointFixed jointWithBodyA:_leg1.physicsBody bodyB:_foot1.physicsBody anchor:_foot1.position];
SKPhysicsJointPin *hipJoint2 = [SKPhysicsJointPin jointWithBodyA:_body.physicsBody bodyB:_leg2.physicsBody anchor:CGPointMake(_leg2.position.x, CGRectGetMaxY(_leg2.frame))];
[hipJoint2 setShouldEnableLimits:YES];
[hipJoint2 setLowerAngleLimit:-M_PI_2];
[hipJoint2 setUpperAngleLimit:0.0];
SKPhysicsJoint *ankleJoint2 = [SKPhysicsJointFixed jointWithBodyA:_leg2.physicsBody bodyB:_foot2.physicsBody anchor:_foot2.position];
[self.scene.physicsWorld addJoint:hipJoint];
[self.scene.physicsWorld addJoint:ankleJoint];
[self.scene.physicsWorld addJoint:hipJoint2];
[self.scene.physicsWorld addJoint:ankleJoint2];
}
-(void)characterJump {
CGFloat radianFactor = 0.0174532925;
CGFloat rotationInDegrees = _body.zRotation / radianFactor;
CGFloat newRotationDegrees = rotationInDegrees + 90;
CGFloat newRotationRadians = newRotationDegrees * radianFactor;
CGFloat r = 500;
CGFloat dx = r * cos(newRotationRadians);
CGFloat dy = r * sin(newRotationRadians);
[_body.physicsBody applyImpulse:CGVectorMake(dx, dy)];
NSLog(#"leg2 rotation: %f", _foot2.zRotation / radianFactor);
}
-(void)characterKick {
NSLog(#"Kick..");
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
if ([node.name isEqualToString:#"button"]) {
[self characterJump];
[self characterKick];
}
}
-(void)update:(CFTimeInterval)currentTime {
}
#end
Run the code and tap the button to make him jump and eventually fall over. Also, the joint limits don't work as it breaks through the limits sometimes.
Help would be really appreciated.
I resolved this issue by checking the _body SKSpriteNode's 'y' position in the scene's update method. If the 'y' position was below a certain limit, I applied an impulse to the body's physicsBody from below to stand it up again.
This worked as required/desired.
-(void)update:(CFTimeInterval)currentTime {
if(_body.position.y < 30) {
[self upOnYourFeet];
}
}
-(void)upOnYourFeet {
[_body.physicsBody applyImpulse:CGVectorMake(0, 80)];
}

How to display animated GIF in Objective C on top of the layered View?

I am trying to draw animated gif on my screen in mac OSX app .
I used this code to insert the gif: I can see the Gif as 1 picture it doesn't animates
only static picture :( what should I add to make it animated ?
#import <Cocoa/Cocoa.h>
#import <Quartz/Quartz.h>//for drawing circle
#import "sharedPrefferences.h"
#interface GenericFanSubView : NSView
{
NSColor * _backgroundColor;
NSImageView* imageView;
}
- (void)setBackgroundColor :(NSColor*)color;
- (void)insertGif1;
- (void)insertGif2;
- (void)insertGif3;
#end
#import "GenericFanSubView.h"
#define PI 3.14285714285714
#implementation GenericFanSubView
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
imageView = [[NSImageView alloc]initWithFrame:CGRectMake(0, 0,self.frame.size.width,self.frame.size.height)];
[imageView setAnimates: YES];
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];
// Drawing code here.
[self drawCircleInRect];
_backgroundColor = [NSColor whiteColor];
[self insertGif1];
}
-(void)drawCircleInRect
{
//draw colored circle here
CGContextRef context = [[NSGraphicsContext // 1
currentContext] graphicsPort];
// ********** Your drawing code here ********** // 2
CGContextSetFillColorWithColor(context,[self NSColorToCGColor:(_backgroundColor)]);
float radius1 = self.frame.size.height/2;
float startAngle = 0;
float endAngle = endAngle = PI*2;
CGPoint position = CGPointMake(self.frame.size.height/2,self.frame.size.height/2);//center of the view
CGContextBeginPath(context);
CGContextAddArc(context, position.x, position.y, radius1, startAngle, endAngle, 1);
CGContextDrawPath(context, kCGPathFill); // Or kCGPathFill
}
- (void)setBackgroundColor :(NSColor*)color
{
_backgroundColor = color;
[self setNeedsDisplay:YES];
}
- (CGColorRef)NSColorToCGColor:(NSColor *)color
{
NSInteger numberOfComponents = [color numberOfComponents];
CGFloat components[numberOfComponents];
CGColorSpaceRef colorSpace = [[color colorSpace] CGColorSpace];
[color getComponents:(CGFloat *)&components];
CGColorRef cgColor = CGColorCreate(colorSpace, components);
return cgColor;
}
//curentlly calling only this 1
- (void)insertGif1
{
[imageView removeFromSuperview];
[imageView setImageScaling:NSImageScaleNone];
[imageView setAnimates: YES];
imageView.image = [NSImage imageNamed:#"FanBlades11.gif"];
[self addSubview:imageView];
}
#end
Edit: I discovered the source of the problem:
I was adding my class (that represents gif inside the circle) on top of RMBlurredView
and the animations doesn't work when I adding it as subview ,However it works on all the other views I added.
Any ideas what could be the reason inside the RMBlurredView to stop my NSImageView from animating ?
Edit:
I think [self setWantsLayer:YES]; is the reason I am not getting animations
how can I still get the animation with this feature enabled?
Edit:
Here is a simple sample with my problem
http://snk.to/f-cdk3wmfn
my gif:This is my gif it is invisible on white background color
"You must disable the autoscaling feature of the NSImageView for the
animation playback to function. After you've done that, no extra
programming required. It works like a charm!"
--http://www.cocoabuilder.com/archive/cocoa/108530-nsimageview-and-animated-gifs.html
imageView.imageScaling = NSImageScaleNone;
imageView.animates = YES;
needed for layer backed views:
if the image view is in a layer backed view or is layer backed itself:
imageView.canDrawSubviewsIntoLayer = YES;
working example using the question's own gif:
NSImageView *view = [[NSImageView alloc] initWithFrame:CGRectMake(10, 10, 50, 50)];
view.imageScaling = NSImageScaleNone;
view.animates = YES;
view.image = [NSImage imageNamed:#"FanBlades2_42x42.gif"];
view.canDrawSubviewsIntoLayer = YES;
NSView *layerview = [[NSView alloc] initWithFrame:CGRectMake(0, 0, 60, 60)];
layerview.wantsLayer = YES;
[layerview addSubview:view];
[self.window.contentView addSubview:layerview];

SK Scene transition background

I've just started to learn how to program with xCode and more specifically with the new SpriteKit. So bare in mind I'm kind of new to this.
I've managed to move to a different scene by pressing on a label, but somehow the background of my scene has gone all wrong. the background should be like the first scene, but it gave me a background with two horizontal bars. I don't think I've done anything wrong since I've just copied the code needed to set the background to the second scene.
1st scene:
http://imageshack.us/photo/my-images/23/kyud.png/
2nd scene:
http://imageshack.us/photo/my-images/198/472h.png/
my code used to set up both backgrounds:
SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:#"background_start"];
background.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
background.xScale = 0.7;
background.yScale = 0.7;
[self addChild:background];
transition is done with:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
if([node.name isEqualToString:#"startgame"]){
Options_Scene *gs = [[Options_Scene alloc] initWithSize:self.size];
SKTransition *doors = [SKTransition doorsOpenVerticalWithDuration:0.5];
[self.view presentScene:gs transition:doors];
}
}
PS: I find it odd why I have to scale it to 0.7 when the background actually has the dimensions 480x320.
As you are using landscape I would swap the
viewWillAppear
With
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
SKView * skView = (SKView *)self.view;
if (!skView.scene) {
//skView.showsFPS = YES;
//skView.showsNodeCount = YES;
// Create and configure the scene.
SKScene * scene = [PMyScene sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
// Present the scene.
[skView presentScene:scene];
}
}