ボールを当ててZ軸回転させる板、とY軸回転のViewをシンクロさせて遊ぶiPhoneアプリのサンプルコードを描いてみます。
動かすとこんな感じです
サンプルコード
#import “ViewController.h”
#import <SpriteKit/SpriteKit.h>
@interface WheelScene : SKScene
@end
@implementation WheelScene
– (void)didMoveToView:(SKView *)view
{
[self createSceneContents];
}
– (void)createSceneContents
{
[self createWheel];
}
– (void)createWheel
{
SKSpriteNode *board = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(80, 80)];
board.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) + 100);
[self addChild:board];
board.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:board.size];
board.physicsBody.dynamic = NO;
board.physicsBody.categoryBitMask = 0x1 << 4;
board.physicsBody.collisionBitMask = 0x1 << 4;
SKNode *preBar = nil;
float angle = 0;
SKSpriteNode *bar = [SKSpriteNode spriteNodeWithColor:[SKColor lightGrayColor] size:CGSizeMake(80, 10)];
bar.name = @”bar”;
bar.position = board.position;
bar.zRotation = angle;
[self addChild:bar];
bar.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:bar.size];
bar.physicsBody.categoryBitMask = 0x1 << 2;
bar.physicsBody.collisionBitMask = 0x1 << 1;
bar.physicsBody.angularDamping = 1.0;
SKPhysicsJointPin *pin = [SKPhysicsJointPin jointWithBodyA:board.physicsBody bodyB:bar.physicsBody anchor:bar.position];
[self.physicsWorld addJoint:pin];
if (preBar) {
SKPhysicsJointFixed *fix = [SKPhysicsJointFixed jointWithBodyA:preBar.physicsBody bodyB:bar.physicsBody anchor:bar.position];
[self.physicsWorld addJoint:fix];
}
preBar = bar;
}
– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint p = [[touches anyObject] locationInNode:self];
UIBezierPath *ballPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-10, –10, 20, 20)];
SKShapeNode *ball = [SKShapeNode node];
ball.name = @”ball”;
ball.position = p;
ball.path = ballPath.CGPath;
ball.fillColor = [SKColor whiteColor];
[self addChild:ball];
}
– (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint p = [[touches anyObject] locationInNode:self];
SKNode *ball = [self childNodeWithName:@”ball”];
ball.name = @”released”;
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:10];
ball.physicsBody.categoryBitMask = 0x1 << 1;
ball.physicsBody.collisionBitMask = 0x1 << 2;
ball.physicsBody.density = 0.3;
float dx = ball.position.x – p.x;
float dy = ball.position.y – p.y;
CGVector v = CGVectorMake(dx * 10.0, dy * 10.0);
[ball.physicsBody applyForce:v];
}
– (void)didSimulatePhysics
{
SKNode *bar0 = [self childNodeWithName:@”bar”];
[[NSNotificationCenter defaultCenter] postNotificationName:@”update angle”
object:@(bar0.zRotation)];
[self enumerateChildNodesWithName:@”released” usingBlock:^(SKNode *node, BOOL *stop) {
if (node.position.y < 0) {
[node removeFromParent];
}
}];
}
@end
@interface ViewController ()
@property (nonatomic) float angel;
@end
@implementation ViewController
– (void)viewDidLoad
{
[super viewDidLoad];
[self createNumbers];
[self createWheelScene];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateAngle:) name:@”update angle” object:nil];
}
– (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
– (void)createNumbers
{
self.angel = 0;
for (int i=0; i<20; i++) {
float x = 160;
float y = 80;
UILabel *l = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 45, 45)];
l.tag = i + 1;
l.center = CGPointMake(x, y);
l.font = [UIFont systemFontOfSize:30];
l.text = [@(i) stringValue];
l.textAlignment = NSTextAlignmentCenter;
l.backgroundColor = [UIColor grayColor];
[self.view addSubview:l];
float r = 150;
float angle = (M_PI / 10.0) * (float)i;
CATransform3D t = CATransform3DIdentity;
t.m34 = 1.0 / –850;
t = CATransform3DRotate(t, angle, 0, 1, 0);
l.layer.transform = CATransform3DTranslate(t, 0, 0, r);
}
}
– (void)createWheelScene
{
SKView *spriteView = [[SKView alloc] initWithFrame:CGRectMake(0, 100, CGRectGetMaxX(self.view.frame), CGRectGetMaxY(self.view.frame) – 100)];
[self.view addSubview:spriteView];
SKScene *scene = [[WheelScene alloc] initWithSize:spriteView.frame.size];
[spriteView presentScene:scene];
}
– (void)setAngel:(float)angle
{
_angel = angle;
for (int i=0; i<20; i++) {
UIView *l = [self.view viewWithTag:i + 1];
float r = 150;
float a = (M_PI / 10.0) * (float)i + angle;
CATransform3D t = CATransform3DIdentity;
t.m34 = 1.0 / –850;
t = CATransform3DRotate(t, a, 0, 1, 0);
l.layer.transform = CATransform3DTranslate(t, 0, 0, r);
}
}
– (void)updateAngle:(NSNotification *)sender
{
if ([sender.name isEqualToString:@”update angle”]) {
float angle = [sender.object floatValue];
self.angel = angle;
}
}
@end