SpriteKit入門 -25-


今回は、シーンのdidSimulatePhysicsメソッドを試してみます。
[ぴぽや](http://piposozai.blog76.fc2.com/ "ぴぽや")さんの画像素材を使っています。

1フレームで行われるシーンの処理は次のような流れになります。

1. シーンの更新
2. アクションの更新
3. didEvaluateActionsメソッド呼び出し
4. 物理シミュレーション処理
5. didSimulatePhysicsメソッド呼び出し
6. シーンの描画

didSimulatePhysicsメソッドを使う例として、あるNodeをシーンの真ん中に持ってくる処理を作ってみます。

使用する画像は、こちらです。

マップ用。
![pipo-map001.png](https://qiita-image-store.s3.amazonaws.com/0/30731/8f5ceae5-3cf4-0990-2bfd-d51fe6f14703.png "pipo-map001.png")

キャラクタ用。
![pipo-charachip001.png](https://qiita-image-store.s3.amazonaws.com/0/30731/c8404bee-b081-a34f-4a3b-02c600f12f00.png "pipo-charachip001.png")

シーンの構成はこのようになっています。
キャラクタはシーンの真ん中でアニメーションするだけなので、WorldではなくSceneの子にしておきました。
CameraをSceneの真ん中に移動することにより、マップスクロールを実現します。

![spritekit_25_01.png](https://qiita-image-store.s3.amazonaws.com/0/30731/5a0075f0-baa5-3729-f0a3-6c2601d8ae82.png "spritekit_25_01.png")

ソースコードはこのようになります。

```objectivec:HelloScene.m
@interface HelloScene()
{
	SKNode *_world;
	SKNode *_camera;
}
@property BOOL contentCreated;
@end

@implementation HelloScene

- (void)didMoveToView:(SKView *)view
{
    if (! self.contentCreated) {
        [self createSceneContents];
        self.contentCreated = YES;
    }
}

- (void)createSceneContents
{
    self.backgroundColor = [SKColor blackColor];
    self.scaleMode = SKSceneScaleModeAspectFit;
	self.anchorPoint = CGPointMake(0.5, 0.5);
	
	_world = [SKNode node];
	[self addChild:_world];
	
	_camera = [SKNode node];
	_camera.name = @"camera";
	[_world addChild:_camera];
	
	_camera.position = CGPointMake(1000, 1000);
	
	int x = 10;
	int y = 10;
	SKTexture *mapTexture = [SKTexture textureWithImageNamed:@"pipo-map001.png"];
	SKTexture *mapchipTextureBase = [SKTexture textureWithRect:CGRectMake(0.0/MAPFILE_WIDTH, (MAPFILE_HEIGHT-MAPCHIP_HEIGHT-0.0)/MAPFILE_HEIGHT, MAPCHIP_WIDTH/MAPFILE_WIDTH, MAPCHIP_HEIGHT/MAPFILE_HEIGHT) inTexture:mapTexture];
	for (y=0; y < MAPCHIP_Y_MAX; y++) {
		for (x=0; x < MAPCHIP_X_MAX; x++) {
			@autoreleasepool {
				SKSpriteNode *mapchipBase = [SKSpriteNode spriteNodeWithTexture:mapchipTextureBase];
				mapchipBase.position = CGPointMake(x*MAPCHIP_WIDTH, y*MAPCHIP_HEIGHT);
				[_world addChild:mapchipBase];
				
				int mapchipType = s_map[MAPCHIP_Y_MAX-y-1][x];
				if (mapchipType > 0) {
					CGFloat mapchipX = (mapchipType % MAPFILE_X_MAX) * MAPCHIP_WIDTH;
					CGFloat mapchipY = (mapchipType / MAPFILE_X_MAX) * MAPCHIP_HEIGHT;
					SKTexture *mapchipTexture = [SKTexture textureWithRect:CGRectMake(mapchipX/MAPFILE_WIDTH, (MAPFILE_HEIGHT-MAPCHIP_HEIGHT-mapchipY)/MAPFILE_HEIGHT, MAPCHIP_WIDTH/MAPFILE_WIDTH, MAPCHIP_HEIGHT/MAPFILE_HEIGHT) inTexture:mapTexture];
					SKSpriteNode *mapchip = [SKSpriteNode spriteNodeWithTexture:mapchipTexture];
					mapchip.position = CGPointMake(x*MAPCHIP_WIDTH, y*MAPCHIP_HEIGHT);
					[_world addChild:mapchip];
				}
			}
		}
	}
	
	SKTexture *charTexture = [SKTexture textureWithImageNamed:@"pipo-charachip001.png"];
	SKTexture *charTextureBase = [SKTexture textureWithRect:CGRectMake(0.0/CHARFILE_WIDTH, (CHARFILE_HEIGHT-CHARCHIP_HEIGHT-0.0)/CHARFILE_HEIGHT, CHARCHIP_WIDTH/CHARFILE_WIDTH, CHARCHIP_HEIGHT/CHARFILE_HEIGHT) inTexture:charTexture];
	SKSpriteNode *charSprite = [SKSpriteNode spriteNodeWithTexture:charTextureBase];
	[self addChild:charSprite];
	SKTexture *charAnim1 = [SKTexture textureWithRect:CGRectMake(0*CHARCHIP_WIDTH/CHARFILE_WIDTH, (CHARFILE_HEIGHT-CHARCHIP_HEIGHT-0.0)/CHARFILE_HEIGHT, CHARCHIP_WIDTH/CHARFILE_WIDTH, CHARCHIP_HEIGHT/CHARFILE_HEIGHT) inTexture:charTexture];
	SKTexture *charAnim2 = [SKTexture textureWithRect:CGRectMake(1*CHARCHIP_WIDTH/CHARFILE_WIDTH, (CHARFILE_HEIGHT-CHARCHIP_HEIGHT-0.0)/CHARFILE_HEIGHT, CHARCHIP_WIDTH/CHARFILE_WIDTH, CHARCHIP_HEIGHT/CHARFILE_HEIGHT) inTexture:charTexture];
	SKTexture *charAnim3 = [SKTexture textureWithRect:CGRectMake(2*CHARCHIP_WIDTH/CHARFILE_WIDTH, (CHARFILE_HEIGHT-CHARCHIP_HEIGHT-0.0)/CHARFILE_HEIGHT, CHARCHIP_WIDTH/CHARFILE_WIDTH, CHARCHIP_HEIGHT/CHARFILE_HEIGHT) inTexture:charTexture];
	SKTexture *charAnim4 = [SKTexture textureWithRect:CGRectMake(1*CHARCHIP_WIDTH/CHARFILE_WIDTH, (CHARFILE_HEIGHT-CHARCHIP_HEIGHT-0.0)/CHARFILE_HEIGHT, CHARCHIP_WIDTH/CHARFILE_WIDTH, CHARCHIP_HEIGHT/CHARFILE_HEIGHT) inTexture:charTexture];
	SKAction *charAction = [SKAction animateWithTextures:@[charAnim1, charAnim2, charAnim3, charAnim4] timePerFrame:0.2];
	[charSprite runAction:[SKAction repeatActionForever:charAction]];
}

- (void) didSimulatePhysics
{
	[self centerOnNode:[self childNodeWithName:@"//camera"]];
}

- (void) centerOnNode:(SKNode *)node
{
	CGPoint cameraPositionInScene = [node.scene convertPoint:node.position fromNode:node.parent];
	node.parent.position = CGPointMake(node.parent.position.x - cameraPositionInScene.x, node.parent.position.y - cameraPositionInScene.y);
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
	UITouch *touch = [touches anyObject];
	CGPoint location = [touch locationInNode:_world];
	CGFloat distance = sqrtf((_camera.position.x - location.x)*(_camera.position.x - location.x)+(_camera.position.y - location.y)*(_camera.position.y - location.y));
	SKAction *cameraAction = [SKAction moveTo:location duration:distance/100.0];
	[_camera runAction:cameraAction withKey:@"move"];
}
```

実行結果はこのようになります。

![spritekit_25_02.png](https://qiita-image-store.s3.amazonaws.com/0/30731/fc9b1640-c51d-43be-6ac7-76d128a9a10a.png "spritekit_25_02.png")

今回はここまで。