IOS Spritekit: Circle outline not showing - sprite-kit

In the below the yellow circle does not show in the IOS emulator. If I add the setFillColor which is currently commented out, then I get a red circle.
Why does the outline of the shape not show?
Is there a way to trigger the outline?
-(void)addTargetNode2 {
float radius=90;
SKShapeNode *targetOuter = [SKShapeNode shapeNodeWithCircleOfRadius:radius];
//[targetOuter setFillColor:[UIColor redColor]];
[targetOuter setStrokeColor:[UIColor yellowColor]];
[targetOuter setLineWidth:1];
//Position the node.
targetOuter.position = CGPointMake(CGRectGetMidX(self.frame),
CGRectGetMidY(self.frame));
[self addChild:targetOuter];
}
I did find this article - but no answer.
Edit:
I've got a working work-around... but not particularly fond of it. Drawing a circle the color of the background over the top of a filled in circle:
-(void)addTarget {
float radius=50;
CGFloat borderWidth=3;
//Draw the Circle.
SKShapeNode *targetOuter = [SKShapeNode shapeNodeWithCircleOfRadius:radius];
[targetOuter setName:#"targetOuter"];
[targetOuter setFillColor:[UIColor yellowColor]];
//Following line should set the outline color but isn't working.
//[targetOuter setStrokeColor:[UIColor yellowColor]];
[targetOuter setLineWidth:1];
targetOuter.position = CGPointMake(CGRectGetMidX(self.frame),
CGRectGetMidY(self.frame));
[self addChild:targetOuter];
/* Work around
Add a circle the color of the background to emulate an outline.
Can be removed in targetOuter outline works.
*/
SKShapeNode *targetInner = [SKShapeNode shapeNodeWithCircleOfRadius:radius-borderWidth];
[targetInner setFillColor:self.backgroundColor];
targetInner.position = targetOuter.position;
[self addChild:targetInner];
}

It seems there is a bug with the iOS simulator and SKShapeNode. I've been able to replicate this problem on simulator but never on device so you shouldn't worry to add a workaround.
iOS Simulator is good to test low framerate conditions and different screen sizes but, aside from that, not very reliable to test SpriteKit games overall.

Related

SpriteKit bodyWithTexture gap between sprites when colliding

I'm new to SpriteKit and I'm trying to create a game, where blocks would fall from top of the screen and land on the bottom of the screen or on top of another block. Here is the sample code from GameScene.m:
- (void)didMoveToView:(SKView *)view
{
self.size = CGSizeMake(view.frame.size.width, view.frame.size.height);
self.backgroundColor = [UIColor whiteColor];
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
SKSpriteNode *redRect = [SKSpriteNode spriteNodeWithImageNamed:#"RedRect"];
redRect.position = CGPointMake(CGRectGetMidX(self.frame), self.frame.size.height);
redRect.physicsBody = [SKPhysicsBody bodyWithTexture:redRect.texture size:redRect.texture.size];
redRect.physicsBody.affectedByGravity = YES;
SKSpriteNode *blueRect = [SKSpriteNode spriteNodeWithImageNamed:#"BlueRect"];
blueRect.position = CGPointMake(CGRectGetMidX(self.frame), self.frame.size.height);
blueRect.physicsBody = [SKPhysicsBody bodyWithTexture:blueRect.texture size:blueRect.texture.size];
blueRect.physicsBody.affectedByGravity = YES;
[self addChild:redRect];
[self addChild:blueRect];
}
As you can see on the screenshot, there is a gap between the two blocks and between the red block and the ground. This only happens when rects collide with each other or with the ground. For instance, if I use the SKAction moveToY: which moves the block to the bottom of the screen, the gap disappears. How can I get rid of these gaps when the nodes collide?
I am totally sure that the problem is about your texture images, They are not precisely cropped or even created.
Spritekit engine never creates gaps between nodes.

Rotating UIImageView Moves the Image Off Screen

I have a simple rotation gesture implemented in my code, but the problem is when I rotate the image it goes off the screen/out of the view always to the right.
The image view that is being rotated center X gets off or increases (hence it going right off the screen out of the view).
I would like it to rotate around the current center, but it's changing for some reason. Any ideas what is causing this?
Code Below:
- (void)viewDidLoad
{
[super viewDidLoad];
CALayer *l = [self.viewCase layer];
[l setMasksToBounds:YES];
[l setCornerRadius:30.0];
self.imgUserPhoto.userInteractionEnabled = YES;
[self.imgUserPhoto setClipsToBounds:NO];
UIRotationGestureRecognizer *rotationRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotationDetected:)];
[self.view addGestureRecognizer:rotationRecognizer];
rotationRecognizer.delegate = self;
}
- (void)rotationDetected:(UIRotationGestureRecognizer *)rotationRecognizer
{
CGFloat angle = rotationRecognizer.rotation;
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, angle);
rotationRecognizer.rotation = 0.0;
}
You want to rotate the image around it's center, but that's not what it is actually happening. Rotation transforms take place around the origin. So what you have to do is to apply a translate transform first to map the origin to the center of the image, and then apply the rotation transform, like so:
self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, self.imageView.bounds.size.width/2, self.imageView.bounds.size.height/2);
Please note that after rotating you'll probably have to undo the translate transform in order to correctly draw the image.
Hope this helps
Edit:
To quickly answer your question, what you have to do to undo the Translate Transform is to subtract the same difference you add to it in the first place, for example:
// The next line will add a translate transform
self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, 10, 10);
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, radians);
// The next line will undo the translate transform
self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, -10, -10);
However, after creating this quick project I realized that when you apply a rotation transform using UIKit (like the way you're apparently doing it) the rotation actually takes place around the center. It is only when using CoreGraphics that the rotation happens around the origin. So now I'm not sure why your image goes off the screen. Anyway, take a look at the project and see if any code there helps you.
Let me know if you have any more questions.
The 'Firefox' image is drawn using UIKit. The blue rect is drawn using CoreGraphics
You aren't rotating the image around its centre. You'll need correct this manually by translating it back to the correct position

Cocos2d, Weird position offset when using CCParallaxNode

I'm using cocos2d for iOS. Not sure if I'm doing something wrong here or if CCParallaxNode does something strange that I just don't understand.
I'm trying to create a few layers of parallax scrolling in the background of my game, at the moment I just have one layer added to the parallax node till I can figure out what's going wrong. When the game loads the layer it's always offset down and left by about 30% of the image size. I've uploaded an image demonstrating the difference in position here http://oi42.tinypic.com/29dz1av.jpg.
Here is my code:
background = [CCParallaxNode node];
background.anchorPoint = ccp(0,0);
background.position = ccp(0,0);
[self addChild: background];
background_image = [CCSprite spriteWithFile: #"layer01.png"
rect: CGRectMake(0, 0, 100, 100)];
background_image.anchorPoint = ccp(0,0);
background_image.position = ccp(0,0);
[background addChild: background_image z:0 parallaxRatio: ccp(0,0) positionOffset:ccp(0,0)];
The cocos2d icon is attached to the same layer as the parallax node and it's position and anchor point are set to 0,0 so the bottom left of the icon should be in the same location as the bottom left of the blue background image.
I have tested this using a basic sprite in place of the parallax node and everything lines up as it should so it's not the image itself.
Any help with this would be appreciated.
First, I don't suggest you to set parallax node & its children's anchor point & position directly because it will cause some unexpected results. You should add the parallax node to a layer as its child, and set the layer's anchor point & position to place your parallax.
Second, CCParallaxNode also provides a positionOffset that you can place your picture in parallax at first. This can help if you want to align several layers of pictures' view center.
So I think you should do something like this(Since I'm using cocos2d-x, I'm not sure its right with obj-C):
layer = [[CCLayer alloc]init];
background = [CCParallaxNode node];
[layer addChild: background];
[self addChild: layer];
Then you just have to add the picture sprite in background, and set layer's position & anchor point.
Hope it can help.
Make sure the background image size is 480x320.
Why did you write CGRectMake(0, 0, 100, 100) ? Why 100 and 100 ? You're limiting your 'CGRect', that's probably wrong..

Add a magnifier in cocos2d games

i want to add a magnifier in cocos2d game. here is what i found online:
http://coffeeshopped.com/2010/03/a-simpler-magnifying-glass-loupe-view-for-the-iphone
I've changed the code a bit:(since i don't want to let the loupe follow our touch)
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:magnifier_rect])) {
// make the circle-shape outline with a nice border.
self.layer.borderColor = [[UIColor lightGrayColor] CGColor];
self.layer.borderWidth = 3;
self.layer.cornerRadius = 250;
self.layer.masksToBounds = YES;
touchPoint = CGPointMake(CGRectGetMidX(magnifier_rect), CGRectGetMidY(magnifier_rect));
}
return self;
}
Then i want to add it in one of my scene init method:
loop = [[MagnifierView alloc] init];
[loop setNeedsDisplay];
loop.viewToMagnify = [CCDirector sharedDirector].openGLView;
[[CCDirector sharedDirector].openGLView.superview addSubview:loop];
But the result is: the area inside the loupe is black.
Also this loupe just magnify images with the same scale, how can i change it to magnify more near the center and less near the edge? (just like real magnifier)
Thank you !!!
Here I assume that you want to magnify the center of the screen.
You have to change dynamically size attribute to your wishes according to your app needs.
CGSize size = [[CCDirector sharedDirector] winSize];
id lens = [CCLens3D actionWithPosition:ccp(size.width/2,size.height/2) radius:240 grid:ccg(15,10) duration:0.0f];
[self runAction:lens];
Cocos2d draws using OpenGL, not CoreAnimation/Quartz. The CALayer you are drawing is empty, so you see nothing. You will either have to use OpenGL graphics code to perform the loupe effect or sample the pixels and alter them appropriately to achieve the magnification effect, as was done in the Christmann article referenced from the article you linked to. That code also relies on CoreAnimation/Quartz, so you will need to work out another way to get your hands on the image data you wish to magnify.

iphone - Focus effect (just like UIAlertView)

I know title of my question is so bad, but I don't know how to describe it.
When an UIAlertView pops up, anything else on the screen (except the UIAlertView) becomes a bit darker but can be seen. I call this as Focus effect, because you will know clearly and directly that now the UIAlertView is the focus.
So how can I implement such a focus effect?
thanks
Just add a translucent view below the view you want to "focus" on.
Simple example:
UIView *shieldView = [[[UIView alloc] initWithFrame:myView.bounds] autorelease];
shieldView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.7];
[myView.superview insertSubview:shieldView belowSubview:myView];
UIAlertView actually uses an image with a radial gradient instead of a simple color, in order to highlight the center of the view.
I know this post is a bit old but I thought it might help someone.
Use this code to generate the radial gradient background:
- (UIImage *)radialGradientImage:(CGSize)size start:(float)start end:(float)end centre:(CGPoint)centre radius:(float)radius{
UIGraphicsBeginImageContextWithOptions(size, YES, 1);
size_t count = 2;
CGFloat locations[2] = {0.0, 1.0};
CGFloat components[8] = {start, start, start, 1.0, end, end, end, 1.0};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef grad = CGGradientCreateWithColorComponents (colorSpace, components, locations, count);
CGColorSpaceRelease(colorSpace);
CGContextDrawRadialGradient (UIGraphicsGetCurrentContext(), grad, centre, 0, centre, radius, kCGGradientDrawsAfterEndLocation);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
CGGradientRelease(grad);
UIGraphicsEndImageContext();
return image;}
Define gradient in the .h file like so:
UIImageView *gradient;
Call your gradient like so:
- (void)addGradient{
CGSize size = self.view.bounds.size;
CGPoint centre = CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2);
float startColor = 1.0f;
float endColor = 0.0f;
float radius = MIN(self.view.bounds.size.width/4, self.view.bounds.size.height/4);
gradient = [[UIImageView alloc] initWithImage:[self radialGradientImage:size
start:startColor
end:endColor
centre:centre
radius:radius]];
[gradient setBackgroundColor:[UIColor clearColor]];
[gradient setUserInteractionEnabled:YES];
[gradient setAlpha:0.6f];
[self.view addSubview:gradient];}
UIAlertView works like this. It fades in an alpha mask image to dim out the background. Once that animation is finished it starts the "bounce in" animation of the dialog.
So to reproduce it you need first to generate an alpha mask with a "bright spot" where your dialog will end up and fade that in. Then use a (few) frame animation(s) to get the bounce effect.
More info here: Creating a Pop animation similar to the presentation of UIAlertView
To make it better than "not good" you could ...
create a UIView in a nib (easiest if the part of your code where you need the effect is already utilising a nib) and then add a translucent graphic (with a 'focus' effect) to that view.
connect the UIView in the nib to an IBOutlet
fade in the graphic using an animation into view hierarchy (omz example shows this)

Categories