Skip to content

Instantly share code, notes, and snippets.

@aclissold
Created May 4, 2014 04:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aclissold/6f90bf2f3deae8d65820 to your computer and use it in GitHub Desktop.
Save aclissold/6f90bf2f3deae8d65820 to your computer and use it in GitHub Desktop.
Simple SpriteKit Slingshot
//
// SlingScene.m
//
// Demonstrates a simple slingshot mechanism.
//
// Created by Andrew Clissold on 5/3/14.
// Copyright (c) 2014 Andrew Clissold. All rights reserved.
//
/* Contents of SlingScene.h:
#import <SpriteKit/SpriteKit.h>
@interface SlingScene : SKScene
@end */
#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 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
@aclissold
Copy link
Author

This can easily be played around with in an existing SpriteKit app:

SlingScene *slingScene = [[SlingScene alloc] initWithSize:self.view.bounds.size];
SKView *spriteView = (SKView *)self.view;
[spriteView presentScene:slingScene];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment