Dan
Dan

Reputation: 345

Spawn a node at random coordinates in SpriteKit

I'm trying to spawn a node I've created at random coordinates. So far, I've made the attempt by doing the following:

- (SKShapeNode *)createTargetNode
{

  int maxXCoord = CGRectGetMaxX(self.frame);
  int maxYCoord = CGRectGetMaxY(self.frame);

  int x = arc4random()% maxXCoord + 40;
  int y = arc4random()% maxYCoord + 40;

  SKShapeNode *target = [SKShapeNode new];
  CGMutablePathRef circle = CGPathCreateMutable();
  CGPathAddArc(circle, NULL, x, y, 5, 0, M_PI*2, YES);
  target.path = circle;
  target.fillColor = [SKColor redColor];
  target.strokeColor = [SKColor redColor];
  NSLog(@"%d, %d", x, y);
  return target;
}

Sometimes the node appears on the screen, sometimes it doesn't. I guess it's going out of bounds. How can I fix that? The orientation of the phone is landscape, so do the coordinates change?

Thanks!

Edit 1:

Here are some coordinates that have been plotted:

2014-02-14 17:54:09.629 reactions[16096:70b] 221, 402
2014-02-14 17:54:10.990 reactions[16096:70b] 273, 542
2014-02-14 17:54:11.586 reactions[16096:70b] 88, 299
2014-02-14 17:54:14.660 reactions[16096:70b] 69, 306

Only (88, 299) and (69, 306) are actually plotted. Here's the link to the image (I can't post it yet, I don't have enough reputation):

Edit 2:

Here's my main view controller. Pretty standard, just loading the SKScene.

#import "DKViewController.h"
#import "DKPlayScene.h"

@implementation DKViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    SKView * skView = (SKView *)self.view;
    skView.showsFPS = YES;
    skView.showsNodeCount = YES;

    SKScene * scene = [DKPlayScene sceneWithSize:skView.bounds.size];
    scene.scaleMode = SKSceneScaleModeAspectFill;

    [skView presentScene:scene];
}

- (BOOL)shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        return UIInterfaceOrientationMaskAllButUpsideDown;
    } else {
        return UIInterfaceOrientationMaskAll;
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

@end

And here's the implementation file for the SKScene:

#import "DKPlayScene.h"
#include <stdlib.h>


@interface DKPlayScene ()

@property (nonatomic, strong) SKLabelNode *scoreLabel;
@property bool *gameHasStarted;
@property int  *score;

@end

@implementation DKPlayScene

- (id)initWithSize:(CGSize)size
{
  if (self = [super initWithSize:size]) {

    self.gameHasStarted = NO;
    self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
    self.scoreLabel = [SKLabelNode new];

    self.scoreLabel.text = @"High Score:";
    self.scoreLabel.fontSize = 10;
    self.scoreLabel.position = (CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) + 70));
    [self createTargetNode];
    [self addChild:self.scoreLabel];
  }
  return self;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
  [self addChild:[self createTargetNode]];
}

-(void)update:(CFTimeInterval)currentTime {

}

#pragma mark - Private

- (SKShapeNode *)createTargetNode
{

  int maxXCoord = self.frame.size.width;
  int maxYCoord = self.frame.size.height;

  int circleWidth = 6;

  int x = arc4random() % (maxXCoord - (circleWidth / 2));
  int y = arc4random() % (maxYCoord - (circleWidth / 2));

  SKShapeNode *target = [SKShapeNode new];
  CGMutablePathRef circle = CGPathCreateMutable();
  CGPathAddArc(circle, NULL, x, y, circleWidth, 0, M_PI*2, YES);
  target.path = circle;
  target.fillColor = [SKColor redColor];
  target.strokeColor = [SKColor redColor];
  NSLog(@"%d, %d", x, y);
  return target;
}

Upvotes: 2

Views: 1276

Answers (1)

novalagung
novalagung

Reputation: 11502

Sometimes the node appears on the screen, sometimes it doesn't. I guess it's going out of bounds. How can I fix that? The orientation of the phone is landscape, so do the coordinates change?

It's because the height and width used are wrong.

In your code, [MyScene sceneWithSize:skView.bounds.size] will always return size in portrait orientation, even though it's landscape on the device / emulator, it's happen because you put it on viewDidLoad.

If you want to get the size of current orientation (landscape), place the code in viewDidLayoutSubviews, not in viewDidLoad.

Go to "ViewController.m", replace the viewDidLoad to viewDidLayoutSubviews.

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    SKView * skView = (SKView *)self.view;
    skView.showsFPS = YES;
    skView.showsNodeCount = YES;

    SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];
    scene.scaleMode = SKSceneScaleModeAspectFill;

    [skView presentScene:scene];
}

Documentation link: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instm/UIViewController/viewDidLayoutSubviews

Upvotes: 2

Related Questions