
ホイールを高速回転させるiPhoneアプリのサンプルコードを描いてみます。
#import “ViewController.h”
#import <SpriteKit/SpriteKit.h>
@interface WheelScene : SKScene
@end
@implementation WheelScene
– (void)didMoveToView:(SKView *)view
{
self.backgroundColor = [SKColor colorWithRed:0.8 green:0 blue:0 alpha:1.0];
[self createShaft];
[self createWheel];
[self createSpeedMeter];
}
– (void)createShaft
{
SKSpriteNode *shaft = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(20, 20)];
shaft.position = CGPointMake(200, CGRectGetMidY(self.frame));
shaft.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:10];
shaft.physicsBody.dynamic = NO;
shaft.zPosition = 10;
shaft.physicsBody.restitution = 0.1;
shaft.physicsBody.friction = 0;
[self addChild:shaft];
}
– (void)createWheel
{
SKNode *wheel = [SKNode node];
wheel.name = @”wheel”;
wheel.position = CGPointMake(200, CGRectGetMidY(self.frame));
[self addChild:wheel];
float r = 100;
for (int i=0; i<5; i++) {
SKSpriteNode *spoke = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(20, r)];
spoke.anchorPoint = CGPointMake(0.5, 0.25);
spoke.zRotation = i * (2.0 * M_PI / 5.0);
[wheel addChild:spoke];
}
UIBezierPath *pathA = [UIBezierPath bezierPathWithArcCenter:CGPointZero radius:r startAngle:0 endAngle:2.0*M_PI clockwise:YES];
SKShapeNode *tire = [SKShapeNode node];
tire.path = pathA.CGPath;
tire.strokeColor = [SKColor colorWithWhite:0.2 alpha:1.0];
tire.lineWidth = 40;
[wheel addChild:tire];
NSMutableArray *bodies = [NSMutableArray array];
float dAngle = 2.0 * M_PI / 20.0;
for (int i=0; i<20; i++) {
float x = 20 * cos(dAngle * i);
float y = 20 * sin(dAngle * i);
SKPhysicsBody *b = [SKPhysicsBody bodyWithCircleOfRadius:1 center:CGPointMake(x, y)];
b.dynamic = NO;
[bodies addObject:b];
}
wheel.physicsBody = [SKPhysicsBody bodyWithBodies:bodies];
wheel.physicsBody.friction = 0;
wheel.physicsBody.restitution = 0;
SKSpriteNode *n = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(10, 10)];
n.position = CGPointMake(wheel.position.x + 100, wheel.position.y);
n.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:10];
[self addChild:n];
SKPhysicsJointPin *pin = [SKPhysicsJointPin jointWithBodyA:n.physicsBody bodyB:wheel.physicsBody anchor:n.position];
[self.physicsWorld addJoint:pin];
}
– (void)createSpeedMeter
{
SKSpriteNode *meter = [SKSpriteNode spriteNodeWithColor:[SKColor lightGrayColor] size:CGSizeMake(20, 160)];
meter.name = @”meter”;
meter.position = CGPointMake(CGRectGetMaxX(self.frame) – 50, CGRectGetMidY(self.frame));
[self addChild:meter];
SKSpriteNode *bar = [SKSpriteNode spriteNodeWithColor:[SKColor grayColor] size:CGSizeMake(40, 10)];
bar.name = @”bar”;
float speed = meter.position.y – 100;
bar.userData = [@{@”speed”: @(speed)} mutableCopy];
bar.position = meter.position;
[self addChild:bar];
}
– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
SKNode *meter = [self childNodeWithName:@”meter”];
SKNode *bar = [self childNodeWithName:@”bar”];
CGPoint p = [[touches anyObject] locationInNode:self];
if ([meter containsPoint:p]) {
bar.position = CGPointMake(bar.position.x, p.y);
float speed = p.y – 100;
[bar.userData setObject:@(speed) forKey:@”speed”];
}
SKNode *wheel = [self childNodeWithName:@”wheel”];
UIBezierPath *wheelPath = [UIBezierPath bezierPathWithArcCenter:wheel.position radius:100 startAngle:0 endAngle:2.0*M_PI clockwise:YES];
if ([wheelPath containsPoint:p]) {
SKSpriteNode *n = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(10, 10)];
n.position = p;
n.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:10];
[self addChild:n];
SKPhysicsJointPin *pin = [SKPhysicsJointPin jointWithBodyA:n.physicsBody bodyB:wheel.physicsBody anchor:n.position];
[self.physicsWorld addJoint:pin];
}
}
– (void)update:(NSTimeInterval)currentTime
{
SKNode *wheel = [self childNodeWithName:@”wheel”];
SKNode *bar = [self childNodeWithName:@”bar”];
NSNumber *speed = [bar valueForKeyPath:@”userData.speed”];
wheel.physicsBody.angularVelocity = speed.floatValue;
}
@end
@interface ViewController ()
@end
@implementation ViewController
– (void)viewDidAppear:(BOOL)animated
{
SKView *spriteView = [[SKView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:spriteView];
SKScene *scene = [[WheelScene alloc] initWithSize:spriteView.frame.size];
[spriteView presentScene:scene];
}
@end