I'm trying to graph some trigonometric functions on an SKScene.. I'm using an SKShapeNode for each point in the screen so when it reaches the left side I remove if from the parent.
The problem is that, for some reason it only draws on a portion of the screen as if it were contained by a smaller view.. The position on the screen is not matching the real screen... for example if I place it at 100 it is actually at a different place.. Plus the size of the area where it graphs is reduced...
There is some code at the bottom
I hope someone could help me! Thank you very much!
Anything else that might help ask and I'll re-edit the post.
Thank you!
Here is some code:
- (void) createTrigonometricFunction
{
[self calculateFunction];
CGMutablePathRef pathToDraw = CGPathCreateMutable();
CGPathMoveToPoint(pathToDraw, NULL, groundOriginLocation.x,groundOriginLocation.y + groundPointPrevious.y);
CGPathAddLineToPoint(pathToDraw, NULL, groundOriginLocation.x + 1,groundOriginLocation.y + groundPointCurrent.y);
SKShapeNode * currentLine = [SKShapeNode node];
currentLine.position = CGPointMake(groundOriginLocation.x,groundOriginLocation.y);
currentLine.path = pathToDraw;
CGPathRelease(pathToDraw);
[currentLine setStrokeColor:[UIColor whiteColor]];
currentLine.name = #"terrainLine";
currentLine.lineWidth = 1;
[currentScene addChild: currentLine];
groundPointPrevious = groundPointCurrent;
//NSLog(#"%f - %f",currentLine.position.x,currentLine.position.y);
}
- (void) calculateFunction
{
groundDominio += 1;
groundPointCurrent.x = groundOriginLocation.x;
groundPointCurrent.y = 2*(sin(degreesToRadian(groundDominio)*2)/5*degreesToRadian(180))*cos(degreesToRadian(150) + degreesToRadian(groundDominio)*5)*sin(degreesToRadian(groundPointCurrent.x));
groundPointCurrent.y = radianToDegrees(groundPointCurrent.y);
}
//The view controller:: (This is how I load it)
- (void)viewDidLoad
{
[super viewDidLoad];
// Configure the view.
SKView * skView = (SKView *)self.view;
//skView.showsFPS = YES;
skView.showsNodeCount = YES;
// Create and configure the scene.
SKScene * scene = [MainGame sceneWithSize: skView.bounds.size];
//scene.scaleMode = SKSceneScaleModeAspectFill;
NSLog(#"%f $$ %f",self.view.frame.size.height,self.view.frame.size.width);
// Present the scene.
[skView presentScene:scene];
}
Do you draw on the scene or on another node?
If you are drawing on another node, your drawing will be off since the default anchor point for node is 0.5, 0.5 (it is pinned to scene with its center) but the actual 0.0 position inside the node is not its center.
Related
Spent a whole day on this. I don't find this in the iOS docs or on SO.
I have a SKShapeNode* that is like a window in my app, and I add a background that is an SKSpriteNode, and the background has another 10 SKSpriteNode as its children. So the node tree is like this:
SKScene -> window -> background -> (child1, ..., child10)
The dimensions are such that the background matches the size of the window, and all the background's children fit inside the background.
I want to zoom when I click inside the window (have the background & 10 children all zoom together). I accomplish this by setting the background's xScale & yScale, and the children inherit this scaling. But I also don't want to spill outside the window's boundaries, so I made a SKCropNode, and added the background as its child. Now the background doesn't spill out:
SKScene -> window -> SKCropNode -> background -> (child1, ..., child10)
Problem is, the background's children spill out when zooming. This is counter-intuitive to me. I tried searching online and looking in docs, "does SKCropNode crop its children & all descendants"? Since the answer appears to be no, I thought to change all 10 children's parent from background to SKCropNode:
SKScene -> window -> SKCropNode -> (background, child1, ..., child10)
Now I scale the SKCropNode. This scales background and all children, but now it spills to outside the window again. (Later in the game, the number of children may increase from 10 to 300, and I don't want to do a for loop on 300 items. So I want to be able to set scale on just one parent.)
I finally decided to try something a bit "hacky". This I did not find anywhere online, so I'm wondering if I'm in "undefined behavior" territory.
SKScene -> window -> SKCropNode1 -> SKCropNode2 -> (background, child1, ..., child10)
I added another SKCropNode on top of my original SKCropNode. Now, I only scale SKCropNode2. This works. However, now I'm getting very strange behavior. My SKShapeNode buttons (completely outside the window) will disappear one by one, then come back, and cycle like this. Further, the "nodes: 10, 60.0 fps" in the lower right will disappear too and return in the cycle. By cycle I mean me clicking inside the window zooming. It seems I've hit a bug in SpriteKit? I set the zPosition of the buttons to 20, way higher than anything else (5 and below). I also set skview.ignoresSiblingOrder = false; Appreciate any help or advice on how to accomplish this!
Edit: In reply to the comments, I did not use a simulator. I tested this on my iPad Pro and iPhone 6+, both running iOS 9.2. Below is my code that compiles & reproduces the behavior. I also took out the zooming code, but it's still reproducible. Please try to tap on the spaceship (Apple's sample image) about 30 times, you will start to see it then.
MainScene.h
#import <UIKit/UIKit.h>
#import <SpriteKit/SpriteKit.h>
#interface MainScene : SKScene<NSStreamDelegate>
#property (strong, nonatomic) SKCropNode* skcrop;
#end
MainScene.m
#import "MainScene.h"
#implementation MainScene
- (void)didMoveToView: (SKView*)view { }
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if ((int)[touches count] != 1) return;
UITouch* touch = [touches anyObject];
const CGPoint location = [touch locationInNode:self];
{ // without the 6 lines below, the disappearing-sprites behavior is gone
SKShapeNode* newshape = [SKShapeNode shapeNodeWithRectOfSize:
CGSizeMake(10.0, 10.0) cornerRadius:1.0];
newshape.position = location;
newshape.zPosition = 5;
newshape.fillColor = [UIColor purpleColor];
[self.skcrop addChild:newshape];
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { }
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { }
#end
GameViewController.m:
#import "GameViewController.h"
#import "MainScene.h"
#import <CoreFoundation/CoreFoundation.h>
#implementation GameViewController
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscapeLeft
| UIInterfaceOrientationMaskLandscapeRight;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Configure SKView
SKView* skview = (SKView*)self.view;
skview.showsFPS = true;
skview.showsNodeCount = true;
skview.ignoresSiblingOrder = false;
skview.multipleTouchEnabled = false;
// Get Screen Size
// IPad Pro prints: screen size 768 1024
// IPhone 6+ prints: screen size 375 667
const int screenWidth = floor(0.5+skview.bounds.size.width);
const int screenHeight = floor(0.5+skview.bounds.size.height);
NSLog(#"screen size %d %d", screenWidth, screenHeight);
const double width = (screenWidth < 375) ? 360 : 720;
// Configure SKScene
MainScene *skscene = [[MainScene alloc]
initWithSize:CGSizeMake(screenWidth, screenHeight)];
skscene.scaleMode = SKSceneScaleModeFill;
skscene.backgroundColor = [UIColor whiteColor];
[skview presentScene:skscene];
// Set up window's crop mask
const CGSize winSurface = CGSizeMake(width, width);
const CGPoint winPosition = CGPointMake(
CGRectGetMidX(skscene.frame), CGRectGetMidY(skscene.frame));
NSLog(#"pos %f %f", winPosition.x, winPosition.y);
SKSpriteNode* winMaskParent = [[SKSpriteNode alloc]
initWithColor:[UIColor redColor] size:winSurface];
[winMaskParent retain];
winMaskParent.position = winPosition;
SKCropNode* scnParent = [SKCropNode node];
scnParent.zPosition = 1;
scnParent.maskNode = winMaskParent;
[skscene addChild:scnParent];
SKSpriteNode* winMask = [[SKSpriteNode alloc]
initWithColor:[UIColor blueColor] size:winSurface];
[winMask retain];
winMask.position = winPosition;
SKCropNode* scn = [SKCropNode node];
scn.zPosition = 1;
scn.maskNode = winMask;
[scnParent addChild:scn];
// Add window sprite
SKSpriteNode* win =
[SKSpriteNode spriteNodeWithImageNamed:#"Spaceship.png"];
win.zPosition = 2;
win.position = winPosition;
[scn addChild:win];
for (int i = 0; i < 5; ++i) {
const double height = 30.0;
const double width = 50.0;
const double posY = screenHeight - (1+i)*100.0;
const double posX = screenWidth - width - 10.0;
SKShapeNode* button = [SKShapeNode shapeNodeWithRectOfSize:
CGSizeMake(width, height) cornerRadius:1.0];
button.position = CGPointMake(posX, posY);
button.zPosition = 15;
button.fillColor = [UIColor greenColor];
button.lineWidth = 1.0;
button.glowWidth = 0.0;
[skscene addChild:button];
}
skscene.skcrop = scn;
return;
}
#end
Edit 2: I removed the nested SKCropNode so that there is only 1 layer of SKCropNode. The button sprites disappear after a few clicks on the spaceship.
I am trying to (learn how to) build a game using SpriteKit and i ran into a problem that has been bugging me for hours.
I have a class named Tank with the following constructor:
+ (instancetype)tankAtPosition:(CGPoint)position {
Tank *tank = [self spriteNodeWithImageNamed:#"tank_base_1"];
tank.position = position;
tank.anchorPoint = CGPointMake(0.5, 0.5);
return tank;
}
In my scene i have the following constructor:
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:#"level_bg_1"];
background.xScale = 0.40f;
background.yScale = 0.40f;
background.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
[self addChild:background];
Tank *tank = [Tank tankAtPosition:CGPointMake(CGRectGetMidX(self.frame), 512)];
[self addChild:tank];
}
return self;
}
which compiled results in the following render:
Everything ok for now, however, if i change the y of the tank to 256:
Tank *tank = [Tank tankAtPosition:CGPointMake(CGRectGetMidX(self.frame), 256)];
I get this:
As far as i know, the bottom is y = 0 and and the middle point y = 512, so when i specify a y = 256 it should be centered in the bottom half of the screen. Why is is near the edge?
The testing device is a ipad retina mini and in the Deployment Info > Devices i specified iPad.
What am i missing? Thank you.
i figured it out. the frame size was all messed up because i set my game to run in landscape only. solution: initialize the scene in viewDidLayoutSubviews instend of viewDidLoad
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
// Configure the view.
SKView * skView = (SKView *)self.view;
skView.showsFPS = YES;
skView.showsNodeCount = YES;
// Create and configure the scene.
SKScene * scene = [Level sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
// Present the scene.
[skView presentScene:scene];
}
I'm working on a game where I have a line across the bottom of the screen that I use to launch things up into the air. It should behave like a rubber band or a slingshot. I have hacked together something that works, but it's kind of a bad solution and I'm hoping someone can suggest another way. My way basically involved redrawing a mutablepath by repeated calls to the draw method during the touchesMoved method. Again, I know this is a bad way of doing it, so sorry for the horrible code.
-(void)drawLine:(CGPoint)location
{
[_powerLine removeFromParent];
CGPoint pointTL = CGPointMake(19, 131);
CGPoint pointTR = CGPointMake(308, 131);
CGPoint pointBL = CGPointMake(location.x-10, location.y);
CGPoint pointBR = CGPointMake(location.x+10, location.y);
UIBezierPath *lineShape = [UIBezierPath bezierPath];
[lineShape moveToPoint:pointTL];
[lineShape addLineToPoint:pointBL];
[lineShape addLineToPoint:pointBR];
[lineShape addLineToPoint:pointTR];
_powerLine = [SKShapeNode node];
_powerLine.path = lineShape.CGPath;
_powerLine.lineWidth = 2.0;
_powerLine.strokeColor = [SKColor colorWithRed:0.0 green:0 blue:0 alpha:1];
[self addChild:_powerLine];
CGMutablePathRef powerLinePath = CGPathCreateMutable();
CGPathMoveToPoint(powerLinePath, nil, pointTL.x, pointTL.y);
CGPathAddLineToPoint(powerLinePath, nil, pointBL.x, pointBL.y);
CGPathAddLineToPoint(powerLinePath, nil, pointBR.x, pointBR.y);
CGPathAddLineToPoint(powerLinePath, nil, pointTR.x, pointTR.y);
_powerLine.physicsBody = [SKPhysicsBody bodyWithEdgeChainFromPath:powerLinePath];
_powerLine.physicsBody.categoryBitMask = WFPhysicsCategoryPowerline;
_lastBR = pointBR;
_lastBL = pointBL;
}
I'm hoping there is a better way to do this other than constantly redrawing it when the person pulls the line down to shot the object up in the air. I looked into spring joints but couldn't convince them to work. The other problem I had with spring joints was how to get the image to stretch to match where the line should be. This approach solves trying to stretch an image by simply eliminating the image. It would be nice to use springs so that I could avoid having to hand code the physics of this.
Anyone have thoughts on how to do this?
I'm not sure if you're concerned about how to draw a convincing elastic band onscreen, or how to emulate the physics of one. If it's the former I can't help you much, but if it's the latter you could try something like this! You should be able to copy and paste it into an existing sprite kit app to play around with it, just initialize it and call SKView's presentScene: with it.
(header file)
#import <SpriteKit/SpriteKit.h>
#interface SlingScene : SKScene
#end
(implementation file)
#import "SlingScene.h"
#interface SlingScene ()
#property (nonatomic, strong) SKAction *slingAction;
#end
#implementation SlingScene
- (instancetype)initWithSize:(CGSize)size {
self = [super initWithSize:size];
if (self) {
CGPoint center = CGPointMake(self.size.width/2.0, self.size.height/2.0);
self.slingAction = [SKAction sequence:
#[[SKAction waitForDuration:0.1],
[SKAction runBlock:
^{
[self.physicsWorld removeAllJoints];
}
]]];
// Create a square, which will be slung by the spring
SKSpriteNode *square =
[SKSpriteNode spriteNodeWithColor:[SKColor whiteColor]
size:CGSizeMake(60.0, 60.0)];
square.position = CGPointMake(center.x, center.y - 2*square.size.height);
square.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:square.size];
square.physicsBody.collisionBitMask = 0;
square.name = #"square";
// Create a post to anchor the square to
SKShapeNode *post = [SKShapeNode node];
post.path = CGPathCreateWithEllipseInRect(
CGRectMake(0.0, 0.0, 60.0, 60.0), NULL);
post.fillColor = [SKColor brownColor];
post.strokeColor = [SKColor brownColor];
post.position = CGPointMake(center.x-30.0, center.y-30.0);
post.physicsBody =
[SKPhysicsBody bodyWithCircleOfRadius:60.0 center:center];
// Give the post a near-infinite mass so the square won't tug at it
// and move it around
post.physicsBody.mass = 1000000;
post.physicsBody.affectedByGravity = NO;
// Set their collision bit masks to the same value to allow them to pass
// through each other
post.physicsBody.collisionBitMask = 0;
square.physicsBody.collisionBitMask = 0;
// Add them to the scene
[self addChild:post];
[self addChild:square];
// Connect them via a spring
SKPhysicsJointSpring *spring =
[SKPhysicsJointSpring jointWithBodyA:post.physicsBody
bodyB:square.physicsBody
anchorA:center
anchorB:square.position];
spring.damping = 0.4;
spring.frequency = 1.0;
[self.physicsWorld addJoint:spring];
// Lower gravity from the default {0.0, -9.8} to allow the
// square to be slung farther
self.physicsWorld.gravity = CGVectorMake(0.0, -4.0);
}
return self;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
// Move the square to the touch position
SKSpriteNode *square = (SKSpriteNode *)[self childNodeWithName:#"square"];
CGPoint location = [[touches anyObject] locationInNode:self];
[square runAction:[SKAction moveTo:location duration:0.1]];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// Sling the square by
// 1. allowing the spring to accelerate it, and
// 2. removing the spring altogether
[self runAction:self.slingAction];
}
#end
Another method might be to compute the x and y positions relative to a specific point, and apply an impulse in the opposite direction. For example, if you find dx = -100.0 and dy = -100.0, you could use applyImpulse:CGVectorMake(-dx, -dy) to launch it up and right. Using the spring joint gives you some acceleration, however.
I've seen the Trailer of "Third Eye Crime".
How can you realise the blue field of view cone so that it's shape changes depending on obstacles?
My attempt was to cast rays till an obstacle occurs and then I take the end points of the rays to draw the cone shape.
The problem with my method is that the precision of the cone depends on the number of rays. Besides the more rays are casted the worse the performance.
Here you can see the rays:
Here you can see the cone shape drawn with the end points of the rays:
Are there better solutions?
Your question has been bugging me all day but I can't find a fully working answer. My work notes are too much for me to write it as a comment so I am adding it as an answer.
My first issue was to test for a contact between a field of view line and any obstruction object. Unfortunately SpriteKit only has the contactBitMask which can do this job AND provide contact coordinates.
I looked at SKNode's intersectsNode: but its return value is only a BOOL and we need coordinates.
I also looked at Apple's Sprite Kit Programming Guide's section Searching for Physics Bodies. This deals with line of sight, obstacles, etc... The command used here is bodyAlongRayStart:end:. The return is the first physics body it intersects with but without providing the coordinates for the actual contact point.
The code I ended up with first draws the complete line of sight cone. Next any lines found contacting an object got the contact point using contact.contactPoint and then deleted the offending line. So far so good. But I ran into trouble trying to draw the deleted line to the new end point (contact point). For some inexplicable reason only some of the deleted lines are being redrawn and not all.
Keep in mind this is rough code so slap it, pull it and throw it against the wall a couple of times. You don't really need the array for example. I hope this will steer you in the right direction or you can spot something I am too blind to see.
Side note: I ran this in simulator iPhone (4 inch) landscape.
#import "MyScene.h"
typedef NS_OPTIONS(uint32_t, CNPhysicsCategory)
{
Category1 = 1 << 0,
Category2 = 1 << 1,
Category3 = 1 << 2,
};
#interface MyScene()<SKPhysicsContactDelegate>
#end
#implementation MyScene
{
SKSpriteNode *player;
SKSpriteNode *obstacle1;
SKSpriteNode *obstacle2;
SKSpriteNode *obstacle3;
SKSpriteNode *obstacle4;
NSMutableArray *beamArray;
int beamCounter;
}
-(id)initWithSize:(CGSize)size
{
if (self = [super initWithSize:size])
{
self.physicsWorld.contactDelegate = self;
beamArray = [[NSMutableArray alloc] init];
beamCounter = 0;
player = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(20, 20)];
player.position = CGPointMake(100, 150);
[self addChild:player];
obstacle1 = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size:CGSizeMake(200, 20)];
obstacle1.name = #"obstacle1";
obstacle1.position = CGPointMake(250, 100);
obstacle1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:obstacle1.size];
obstacle1.physicsBody.affectedByGravity = NO;
obstacle1.physicsBody.categoryBitMask = Category2;
obstacle1.physicsBody.collisionBitMask = 0x00000000;
[self addChild:obstacle1];
obstacle2 = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size:CGSizeMake(40, 40)];
obstacle2.name = #"obstacle2";
obstacle2.position = CGPointMake(400, 200);
obstacle2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:obstacle2.size];
obstacle2.physicsBody.affectedByGravity = NO;
obstacle2.physicsBody.categoryBitMask = Category2;
obstacle2.physicsBody.collisionBitMask = 0x00000000;
[self addChild:obstacle2];
obstacle3 = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size:CGSizeMake(50, 20)];
obstacle3.name = #"obstacle3";
obstacle3.position = CGPointMake(530, 130);
obstacle3.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:obstacle3.size];
obstacle3.physicsBody.affectedByGravity = NO;
obstacle3.physicsBody.categoryBitMask = Category2;
obstacle3.physicsBody.collisionBitMask = 0x00000000;
[self addChild:obstacle3];
for (int y = 0; y <= 320; y++)
{
SKShapeNode *beam1 = [SKShapeNode node];
beam1.name = [NSString stringWithFormat:#"%i",beamCounter++];
CGMutablePathRef pathToDraw = CGPathCreateMutable();
CGPathMoveToPoint(pathToDraw, NULL, player.position.x, player.position.y);
CGPathAddLineToPoint(pathToDraw, NULL, 600, y);
beam1.path = pathToDraw;
[beam1 setStrokeColor:[UIColor yellowColor]];
[beam1 setLineWidth:2.0];
beam1.physicsBody = [SKPhysicsBody bodyWithEdgeFromPoint:CGPointMake(player.position.x, player.position.y) toPoint:CGPointMake(600, y)];
beam1.physicsBody.affectedByGravity = NO;
beam1.physicsBody.categoryBitMask = Category1;
beam1.physicsBody.contactTestBitMask = Category2;
[self addChild:beam1];
[beamArray addObject:beam1];
}
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//
}
-(void)update:(CFTimeInterval)currentTime
{
//
}
- (void)didBeginContact:(SKPhysicsContact *)contact
{
NSLog(#"bodyA:%# bodyB:%#",contact.bodyA.node.name, contact.bodyB.node.name);
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision == (Category1 | Category2))
{
CGPoint newEndPoint = contact.contactPoint;
[beamArray removeObject:contact.bodyA.node.name];
[contact.bodyA.node removeFromParent];
SKShapeNode *beam1 = [SKShapeNode node];
beam1.name = [NSString stringWithFormat:#"%i",beamCounter++];
CGMutablePathRef pathToDraw = CGPathCreateMutable();
CGPathMoveToPoint(pathToDraw, NULL, player.position.x, player.position.y);
CGPathAddLineToPoint(pathToDraw, NULL, newEndPoint.x, newEndPoint.y);
beam1.path = pathToDraw;
[beam1 setStrokeColor:[UIColor greenColor]];
[beam1 setLineWidth:2.0];
[self addChild:beam1];
}
}
#end
Removing the touching lines:
Removing the touching lines and replacing the removed lines:
How I would do it is send out a ray at the edges of view and make note of the points that they hit. Then find points that are important(corners of objects for example), form rays with those points and use those rays to find collisions past those points and finally fill triangles with the points and the "source" of the light.
I might get a chance to make pictures to help demonstrate my algorithm later but this is what I have now.
I think the efficient way to do this is to use Bresenham's Algorithm. There are lots of references and example code in the Wikipedia references section.
http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
Here I've found several answers:
https://code.google.com/p/straightedge/
http://www.redblobgames.com/articles/visibility/
I have created my SKScene subclass which sets the anchorpoint and then adds one SKSpriteNode for the world, the world has multiple SKSpriteNodes for the obstacles, player etc. I am also centering on the
The problem I am having is that as I have set the anchorpoint of the scene to (0.5, 0.5), the position of any child node that I add to the world starts at the center of the world. How do I fix the postion of the nodes so that position = (0,0) will be at the bottom left of the world node and any child nodes added to it, instead of the center?
#implementation LevelScene
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
NSLog(#"width:%f height:%f", self.view.bounds.size.width, self.view.bounds.size.height);
// set the physics body
self.physicsWorld.gravity = CGVectorMake(0,-5);
self.physicsWorld.contactDelegate = self;
self.anchorPoint = CGPointMake(0.5, 0.5);
NSMutableDictionary *plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"LevelScene" ofType:#"plist"]];
NSString *backgroundImage = [plistDict objectForKey:#"background"];
// add a node that holds the background
background = [SKSpriteNode spriteNodeWithTexture:[SKTexture textureWithImageNamed:backgroundImage] size:CGSizeMake(1024, 768)];
background.position = CGPointMake(0, 0);
[self addChild:background];
world = [SKSpriteNode spriteNodeWithColor:[SKColor brownColor] size:CGSizeMake(1024, 768)];
world.position = CGPointMake(0, 0); // this should be bottom-left
world.size = CGSizeMake(1024, 768);
world.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:world.frame];
world.physicsBody.categoryBitMask = worldCategory;
[self addChild:world];
// load in the game tiles (these are non-dynamic tiles the player can use)
[self loadInTiles];
// add in game object to the world skspritenode - this just creates a subclass of skspritenode and sets position to 0,0
[self addGameObject:CGPointMake(0, 0)];
...
}
// ...setup functions, input handling, etc
-(void)didSimulatePhysics {
// setup the player to move depending on their direction
[player updatePosition];
[self centreOnNode:player];
}
-(void)centreOnNode: (SKSpriteNode *)node {
CGPoint cameraPositionInScene = [node.scene convertPoint:node.position fromNode:node.parent];
CGFloat x = node.parent.position.x - cameraPositionInScene.x;
CGFloat y = node.parent.position.y - cameraPositionInScene.y;
NSLog(#"camera x:%f y:%f", x, y);
NSLog(#"world frame origin x:%f y:%f", world.frame.origin.x, world.frame.origin.y);
node.parent.position = CGPointMake(x, y);
}
If you want to set the world sprite's origin to the bottom left side, just set it's anchor point.
world.anchorPoint = CGPointMake(0,0);
With this, the world sprite's coordinate system will be just like that of the scene's default.
Make sure to remove the line:
self.anchorPoint = CGPointMake(0.5, 0.5);
Replace this row:
world.position = CGPointMake(0, 0);
by this:
world.position = CGPointMake(-CGRectGetMidX(self.frame), -CGRectGetMidY(self.frame));
(0,0) is the center of the scene, since you set anchor point of the SKScene to (0.5,0.5)