#import <Foundation/Foundation.h>
@interface BFViewController : UIViewController
@end
#import "BFViewController.h"
@import SpriteKit;
@implementation BFViewController
- (void)loadView {
SKView *skView = [[SKView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.view = skView;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
SKView *skView = (SKView *)self.view;
skView.showsDrawCount = YES;
skView.showsNodeCount = YES;
skView.showsFPS = YES;
SKScene *scene = [SKScene sceneWithSize:self.view.bounds.size];
[skView presentScene:scene];
}
- (BOOL)prefersStatusBarHidden {
return YES;
}
@end
#import <UIKit/UIKit.h>
#import "BFViewController.h" // ViewControllerクラスをインポート
@interface BFAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong,nonatomic) BFViewController *viewController; // viewControllerのインスタンスを保持するためのプロパティ追加
@end
#import "BFAppDelegate.h"
#import "BFViewController.h" // ViewControllerクラスをインポート
@implementation BFAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[BFViewController alloc] init];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {}
- (void)applicationDidEnterBackground:(UIApplication *)application {}
- (void)applicationWillEnterForeground:(UIApplication *)application {}
- (void)applicationDidBecomeActive:(UIApplication *)application {}
- (void)applicationWillTerminate:(UIApplication *)application {}
@end
#import <Foundation/Foundation.h>
@import SpriteKit;
@interface BFTitleScene : SKScene
@end
#import "BFTitleScene.h"
@implementation BFTitleScene
- (id)initWithSize:(CGSize)size {
self = [super initWithSize:size];
if (self) {
SKLabelNode *titleLabel = [SKLabelNode labelNodeWithFontNamed:@"HelveticaNeue"];
titleLabel.text = @"BREAKOUT!";
titleLabel.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
titleLabel.fontSize = 50.0f;
[self addChild:titleLabel];
}
return self;
}
@end
#import "BFViewController.h"
#import "BFTitleScene.h"
@import SpriteKit;
@implementation BFViewController
- (void)loadView {
SKView *skView = [[SKView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.view = skView;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
SKView *skView = (SKView *)self.view;
skView.showsDrawCount = YES;
skView.showsNodeCount = YES;
skView.showsFPS = YES;
// SKScene *scene = [SKScene sceneWithSize:self.view.bounds.size];
SKScene *scene = [BFTitleScene sceneWithSize:self.view.bounds.size];
[skView presentScene:scene];
}
- (BOOL)prefersStatusBarHidden {
return YES;
}
@end
{
"block" : {
"margin" : 16.0,
"width" : 34.0,
"height" : 16.0,
"rows" : 5,
"max_life" : 5
}
}
#import <Foundation/Foundation.h>
@import SpriteKit;
@interface BFPlayScene : SKScene
@end
#import "BFPlayScene.h"
@implementation BFPlayScene
- (id)initWithSize:(CGSize)size {
self = [super initWithSize:size];
if (self) {
[self addBlocks];
}
return self;
}
static NSDictionary *config = nil;
+ (void)initialize {
NSString *path = [[NSBundle mainBundle] pathForResource:@"config" ofType:@"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
if (!config) {
config = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
}
}
# pragma mark - Block
- (void)addBlocks {
int rows = [config[@"block"][@"rows"] intValue];
CGFloat margin = [config[@"block"][@"margin"] floatValue];
CGFloat width = [config[@"block"][@"width"] floatValue];
CGFloat height = [config[@"block"][@"height"] floatValue];
int cols = floor(CGRectGetWidth(self.frame) - margin) / (width + margin);
CGFloat y = CGRectGetHeight(self.frame) - margin - height / 2;
for (int i = 0; i < rows; i++) {
CGFloat x = margin + width / 2;
for (int j = 0; j < cols; j++) {
SKNode *block = [self newBlock];
block.position = CGPointMake(x, y);
x += width + margin;
}
y -= height + margin;
}
}
- (SKNode *)newBlock {
CGFloat width = [config[@"block"][@"width"] floatValue];
CGFloat height = [config[@"block"][@"height"] floatValue];
int maxLife = [config[@"block"][@"max_life"] floatValue];
SKSpriteNode *block = [SKSpriteNode spriteNodeWithColor:[SKColor cyanColor] size:CGSizeMake(width, height)];
block.name = @"block";
int life = (arc4random() % maxLife) + 1;
block.userData = @{ @"life" : @(life) }.mutableCopy;
[self updateBlockAlpha:block];
[self addChild:block];
return block;
}
- (void)updateBlockAlpha:(SKNode *)block {
int life = [block.userData[@"life"] intValue];
block.alpha = life * 0.2f;
}
@end
#import "BFTitleScene.h"
#import "BFPlayScene.h"
@implementation BFTitleScene
- (id)initWithSize:(CGSize)size {
self = [super initWithSize:size];
if (self) {
SKLabelNode *titleLabel = [SKLabelNode labelNodeWithFontNamed:@"HelveticaNeue"];
titleLabel.text = @"BREAKOUT!";
titleLabel.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
titleLabel.fontSize = 50.0f;
[self addChild:titleLabel];
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
SKScene *scene = [BFPlayScene sceneWithSize:self.size];
SKTransition *transition = [SKTransition pushWithDirection:SKTransitionDirectionUp duration:1.0f];
[self.view presentScene:scene transition:transition];
}
@end
"paddle" : {
"width" : 70.0,
"height" : 14.0,
"y" : 40.0,
},
"ball" : {
"radius" : 6.0,
},
[self addPaddle];
# pragma mark - Paddle
- (void)addPaddle {
CGFloat width = [config[@"paddle"][@"width"] floatValue];
CGFloat height = [config[@"paddle"][@"height"] floatValue];
CGFloat y = [config[@"paddle"][@"y"] floatValue];
SKSpriteNode *paddle = [SKSpriteNode spriteNodeWithColor:[SKColor brownColor] size:CGSizeMake(width, height)];
paddle.name = @"paddle";
paddle.position = CGPointMake(CGRectGetMidX(self.frame), y);
[self addChild:paddle];
}
- (SKNode *)paddleNode {
return [self childNodeWithName:@"paddle"];
}
# pragma mark - Ball
- (void)addBall {
CGFloat radius = [config[@"ball"][@"radius"] floatValue];
SKShapeNode *ball = [SKShapeNode node];
ball.name = @"ball";
ball.position = CGPointMake(CGRectGetMidX([self paddleNode].frame), CGRectGetMaxY([self paddleNode].frame) + radius);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddArc(path, NULL, 0, 0, radius, 0, M_PI * 2, YES);
ball.path = path;
ball.fillColor = [SKColor yellowColor];
ball.strokeColor = [SKColor clearColor];
CGPathRelease(path);
[self addChild:ball];
}
- (SKNode *)ballNode {
return [self childNodeWithName:@"ball"];
}
# pragma mark - Touch
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (![self ballNode]) {
[self addBall];
return;
}
UITouch *touch = [touches anyObject];
CGPoint locaiton = [touch locationInNode:self];
CGFloat speed = [config[@"paddle"][@"speed"] floatValue];
CGFloat x = locaiton.x;
CGFloat diff = abs(x - [self paddleNode].position.x);
CGFloat duration = speed * diff;
SKAction *move = [SKAction moveToX:x duration:duration];
[[self paddleNode] runAction:move];
}
$ sudo gem update --system
$ xcode-select --install
$ sudo gem install cocoapods
$ pod setup
$ pod --version
0.29.0
pod 'AFNetworking', '~> 1.0'
$ pod install
pod 'PhysicsDebugger', git: 'https://github.com/ymc-thzi/PhysicsDebugger.git'
#import "YMCPhysicsDebugger.h"
@implementation BFYourScene
- (id)initWithSize:(CGSize)size {
self = [super initWithSize:size];
if (self) {
[YMCPhysicsDebugger init];
/* Create scene contens */
[self drawPhysicsBodies];
}
return self;
}
@end
"paddle" : {
"width" : 70.0,
"height" : 14.0,
"y" : 40.0,
"speed" : 0.005
},
"ball" : {
"radius" : 6.0,
"velocity" : {
"x" : 50.0,
"y" : 120.0
}
},
@interface BFPlayScene () <SKPhysicsContactDelegate>
self.physicsWorld.contactDelegate = self;
#import "BFPlayScene.h"
static const uint32_t blockCategory = 0x1 << 0;
static const uint32_t ballCategory = 0x1 << 1;
@interface BFPlayScene () <SKPhysicsContactDelegate>
@end
@implementation BFPlayScene
- (id)initWithSize:(CGSize)size {
self = [super initWithSize:size];
if (self) {
[self addBlocks];
[self addPaddle];
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
self.physicsWorld.contactDelegate = self;
}
return self;
}
static NSDictionary *config = nil;
+ (void)initialize {
NSString *path = [[NSBundle mainBundle] pathForResource:@"config" ofType:@"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
if (!config) {
config = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
}
}
# pragma mark - Block
- (void)addBlocks {
int rows = [config[@"block"][@"rows"] intValue];
CGFloat margin = [config[@"block"][@"margin"] floatValue];
CGFloat width = [config[@"block"][@"width"] floatValue];
CGFloat height = [config[@"block"][@"height"] floatValue];
int cols = floor(CGRectGetWidth(self.frame) - margin) / (width + margin);
CGFloat y = CGRectGetHeight(self.frame) - margin - height / 2;
for (int i = 0; i < rows; i++) {
CGFloat x = margin + width / 2;
for (int j = 0; j < cols; j++) {
SKNode *block = [self newBlock];
block.position = CGPointMake(x, y);
x += width + margin;
}
y -= height + margin;
}
}
# pragma mark - Paddle
- (void)addPaddle {
CGFloat width = [config[@"paddle"][@"width"] floatValue];
CGFloat height = [config[@"paddle"][@"height"] floatValue];
CGFloat y = [config[@"paddle"][@"y"] floatValue];
SKSpriteNode *paddle = [SKSpriteNode spriteNodeWithColor:[SKColor brownColor] size:CGSizeMake(width, height)];
paddle.name = @"paddle";
paddle.position = CGPointMake(CGRectGetMidX(self.frame), y);
paddle.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:paddle.size];
paddle.physicsBody.dynamic = NO;
[self addChild:paddle];
}
- (SKNode *)paddleNode {
return [self childNodeWithName:@"paddle"];
}
# pragma mark - Ball
- (void)addBall {
CGFloat radius = [config[@"ball"][@"radius"] floatValue];
CGFloat velocityX = [config[@"ball"][@"velocity"][@"x"] floatValue];
CGFloat velocityY = [config[@"ball"][@"velocity"][@"y"] floatValue];
SKShapeNode *ball = [SKShapeNode node];
ball.name = @"ball";
ball.position = CGPointMake(CGRectGetMidX([self paddleNode].frame), CGRectGetMaxY([self paddleNode].frame) + radius);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddArc(path, NULL, 0, 0, radius, 0, M_PI * 2, YES);
ball.path = path;
ball.fillColor = [SKColor yellowColor];
ball.strokeColor = [SKColor clearColor];
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:radius];
ball.physicsBody.affectedByGravity = NO;
ball.physicsBody.velocity = CGVectorMake(velocityX, velocityY);
ball.physicsBody.restitution = 1.0f;
ball.physicsBody.linearDamping = 0;
ball.physicsBody.friction = 0;
ball.physicsBody.usesPreciseCollisionDetection = YES;
ball.physicsBody.categoryBitMask = ballCategory;
ball.physicsBody.contactTestBitMask = blockCategory;
CGPathRelease(path);
[self addChild:ball];
}
- (SKNode *)ballNode {
return [self childNodeWithName:@"ball"];
}
# pragma mark - Touch
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (![self ballNode]) {
[self addBall];
return;
}
UITouch *touch = [touches anyObject];
CGPoint locaiton = [touch locationInNode:self];
CGFloat speed = [config[@"paddle"][@"speed"] floatValue];
CGFloat x = locaiton.x;
CGFloat diff = abs(x - [self paddleNode].position.x);
CGFloat duration = speed * diff;
SKAction *move = [SKAction moveToX:x duration:duration];
[[self paddleNode] runAction:move];
}
- (SKNode *)newBlock {
CGFloat width = [config[@"block"][@"width"] floatValue];
CGFloat height = [config[@"block"][@"height"] floatValue];
int maxLife = [config[@"block"][@"max_life"] floatValue];
SKSpriteNode *block = [SKSpriteNode spriteNodeWithColor:[SKColor cyanColor] size:CGSizeMake(width, height)];
block.name = @"block";
int life = (arc4random() % maxLife) + 1;
block.userData = @{ @"life" : @(life) }.mutableCopy;
block.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:block.size];
block.physicsBody.dynamic = NO;
block.physicsBody.categoryBitMask = blockCategory;
[self updateBlockAlpha:block];
[self addChild:block];
return block;
}
- (void)decreaseBlockLife:(SKNode *)block {
int life = [block.userData[@"life"] intValue] - 1;
block.userData[@"life"] = @(life);
[self updateBlockAlpha:block];
}
- (void)updateBlockAlpha:(SKNode *)block {
int life = [block.userData[@"life"] intValue];
block.alpha = life * 0.2f;
}
# pragma mark - SKPhysicsContactDelegate
- (void)didBeginContact:(SKPhysicsContact *)contact {
SKPhysicsBody *firstBody, *secondBody;
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) {
firstBody = contact.bodyA;
secondBody = contact.bodyB;
} else {
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if (firstBody.categoryBitMask & blockCategory) {
if (secondBody.categoryBitMask & ballCategory) {
[self decreaseBlockLife:firstBody.node];
}
}
}
@end
static const uint32_t blockCategory = 0x1 << 0;
static const uint32_t ballCategory = 0x1 << 1;
- (void)decreaseBlockLife:(SKNode *)block {
int life = [block.userData[@"life"] intValue] - 1;
block.userData[@"life"] = @(life);
[self updateBlockAlpha:block];
if (life < 1) {
[self removeNodeWithSpark:block];
}
}
# pragma mark - Utilities
- (void)removeNodeWithSpark:(SKNode *)node {
NSString *sparkPath = [[NSBundle mainBundle] pathForResource:@"spark" ofType:@"sks"];
SKEmitterNode *spark = [NSKeyedUnarchiver unarchiveObjectWithFile:sparkPath];
spark.position = node.position;
spark.xScale = spark.yScale = 0.3f;
[self addChild:spark];
SKAction *fadeOut = [SKAction fadeOutWithDuration:0.3f];
SKAction *remove = [SKAction removeFromParent];
SKAction *sequence = [SKAction sequence:@[fadeOut, remove]];
[spark runAction:sequence];
[node removeFromParent];
}
"label" : {
"margin" : 5.0,
"font_size" : 14.0,
},
"max_life" : 5
#import <Foundation/Foundation.h>
@import SpriteKit;
@interface BFPlayScene : SKScene;
@property (nonatomic) int life;
@property (nonatomic) int stage;
- (id)initWithSize:(CGSize)size life:(int)life stage:(int)stage;
@end
#import "BFPlayScene.h"
#import "BFGameOverScene.h"
static const uint32_t blockCategory = 0x1 << 0;
static const uint32_t ballCategory = 0x1 << 1;
@interface BFPlayScene () <SKPhysicsContactDelegate>
@end
@implementation BFPlayScene
- (id)initWithSize:(CGSize)size life:(int)life stage:(int)stage {
self = [super initWithSize:size];
if (self) {
self.life = life;
self.stage = stage;
[self addBlocks];
[self addPaddle];
[self addStageLabel];
[self addLifeLabel];
[self updateLifeLabel];
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
self.physicsWorld.contactDelegate = self;
}
return self;
}
- (id)initWithSize:(CGSize)size {
return [self initWithSize:size life:[config[@"max_life"] intValue] stage:1];
}
static NSDictionary *config = nil;
+ (void)initialize {
NSString *path = [[NSBundle mainBundle] pathForResource:@"config" ofType:@"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
if (!config) {
config = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
}
}
# pragma mark - Block
- (void)addBlocks {
int rows = [config[@"block"][@"rows"] intValue];
CGFloat margin = [config[@"block"][@"margin"] floatValue];
CGFloat width = [config[@"block"][@"width"] floatValue];
CGFloat height = [config[@"block"][@"height"] floatValue];
int cols = floor(CGRectGetWidth(self.frame) - margin) / (width + margin);
CGFloat y = CGRectGetHeight(self.frame) - margin - height / 2;
for (int i = 0; i < rows; i++) {
CGFloat x = margin + width / 2;
for (int j = 0; j < cols; j++) {
SKNode *block = [self newBlock];
block.position = CGPointMake(x, y);
x += width + margin;
}
y -= height + margin;
}
}
# pragma mark - Paddle
- (void)addPaddle {
CGFloat width = [config[@"paddle"][@"width"] floatValue];
CGFloat height = [config[@"paddle"][@"height"] floatValue];
CGFloat y = [config[@"paddle"][@"y"] floatValue];
SKSpriteNode *paddle = [SKSpriteNode spriteNodeWithColor:[SKColor brownColor] size:CGSizeMake(width, height)];
paddle.name = @"paddle";
paddle.position = CGPointMake(CGRectGetMidX(self.frame), y);
paddle.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:paddle.size];
paddle.physicsBody.dynamic = NO;
[self addChild:paddle];
}
- (SKNode *)paddleNode {
return [self childNodeWithName:@"paddle"];
}
# pragma mark - Ball
- (void)addBall {
CGFloat radius = [config[@"ball"][@"radius"] floatValue];
CGFloat velocityX = [config[@"ball"][@"velocity"][@"x"] floatValue];
CGFloat velocityY = [config[@"ball"][@"velocity"][@"y"] floatValue];
SKShapeNode *ball = [SKShapeNode node];
ball.name = @"ball";
ball.position = CGPointMake(CGRectGetMidX([self paddleNode].frame), CGRectGetMaxY([self paddleNode].frame) + radius);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddArc(path, NULL, 0, 0, radius, 0, M_PI * 2, YES);
ball.path = path;
ball.fillColor = [SKColor yellowColor];
ball.strokeColor = [SKColor clearColor];
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:radius];
ball.physicsBody.affectedByGravity = NO;
ball.physicsBody.velocity = CGVectorMake(velocityX + self.stage, velocityY + self.stage);
ball.physicsBody.restitution = 1.0f;
ball.physicsBody.linearDamping = 0;
ball.physicsBody.friction = 0;
ball.physicsBody.usesPreciseCollisionDetection = YES;
ball.physicsBody.categoryBitMask = ballCategory;
ball.physicsBody.contactTestBitMask = blockCategory;
CGPathRelease(path);
[self addChild:ball];
}
- (SKNode *)ballNode {
return [self childNodeWithName:@"ball"];
}
# pragma mark - Touch
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (![self ballNode]) {
[self addBall];
return;
}
UITouch *touch = [touches anyObject];
CGPoint locaiton = [touch locationInNode:self];
CGFloat speed = [config[@"paddle"][@"speed"] floatValue];
CGFloat x = locaiton.x;
CGFloat diff = abs(x - [self paddleNode].position.x);
CGFloat duration = speed * diff;
SKAction *move = [SKAction moveToX:x duration:duration];
[[self paddleNode] runAction:move];
}
- (SKNode *)newBlock {
CGFloat width = [config[@"block"][@"width"] floatValue];
CGFloat height = [config[@"block"][@"height"] floatValue];
int maxLife = [config[@"block"][@"max_life"] floatValue];
SKSpriteNode *block = [SKSpriteNode spriteNodeWithColor:[SKColor cyanColor] size:CGSizeMake(width, height)];
block.name = @"block";
int life = (arc4random() % maxLife) + 1;
block.userData = @{ @"life" : @(life) }.mutableCopy;
block.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:block.size];
block.physicsBody.dynamic = NO;
block.physicsBody.categoryBitMask = blockCategory;
[self updateBlockAlpha:block];
[self addChild:block];
return block;
}
- (void)decreaseBlockLife:(SKNode *)block {
int life = [block.userData[@"life"] intValue] - 1;
block.userData[@"life"] = @(life);
[self updateBlockAlpha:block];
if (life < 1) {
[self removeNodeWithSpark:block];
}
if ([self blockNodes].count < 1) {
[self nextLevel];
}
}
- (NSArray *)blockNodes {
NSMutableArray *nodes = @[].mutableCopy;
[self enumerateChildNodesWithName:@"block" usingBlock:^(SKNode *node, BOOL *stop) {
[nodes addObject:node];
}];
return nodes;
}
# pragma mark - Label
- (void)addStageLabel {
CGFloat margin = [config[@"label"][@"margin"] floatValue];
CGFloat fontSize = [config[@"label"][@"font_size"] floatValue];
SKLabelNode *label = [SKLabelNode labelNodeWithFontNamed:@"HelveticaNeue-Bold"];
label.text = [NSString stringWithFormat:@"STAGE %d", _stage];
label.verticalAlignmentMode = SKLabelVerticalAlignmentModeTop;
label.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeRight;
label.position = CGPointMake(CGRectGetMaxX(self.frame) - margin, CGRectGetMaxY(self.frame) - margin);
label.fontSize = fontSize;
label.zPosition = 1.0f;
[self addChild:label];
}
- (void)addLifeLabel {
CGFloat margin = [config[@"label"][@"margin"] floatValue];
CGFloat fontSize = [config[@"label"][@"font_size"] floatValue];
SKLabelNode *label = [SKLabelNode labelNodeWithFontNamed:@"HiraKakuProN-W3"];
label.verticalAlignmentMode = SKLabelVerticalAlignmentModeTop;
label.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft;
label.position = CGPointMake(margin, CGRectGetMaxY(self.frame) - margin);
label.fontSize = fontSize;
label.zPosition = 1.0f;
label.color = [SKColor magentaColor];
label.colorBlendFactor = 1.0f;
label.name = @"lifeLabel";
[self addChild:label];
}
- (void)updateLifeLabel {
NSMutableString *s = @"".mutableCopy;
for (int i = 0; i < _life; i++) {
[s appendString:@"◆"];
}
[self lifeLabel].text = s;
}
- (SKLabelNode *)lifeLabel {
return (SKLabelNode *)[self childNodeWithName:@"lifeLabel"];
}
# pragma mark - Callbacks
- (void)update:(NSTimeInterval)currentTime {
if((int)currentTime % 5 == 0) {
CGVector velocity = [self ballNode].physicsBody.velocity;
velocity.dx *= 1.001f;
velocity.dy *= 1.001f;
[self ballNode].physicsBody.velocity = velocity;
}
}
- (void)didEvaluateActions {
CGFloat width = [config[@"paddle"][@"width"] floatValue];
CGPoint paddlePosition = [self paddleNode].position;
if (paddlePosition.x < width / 2) {
paddlePosition.x = width / 2;
} else if (paddlePosition.x > CGRectGetWidth(self.frame) - width / 2) {
paddlePosition.x = CGRectGetWidth(self.frame) - width / 2;
}
[self paddleNode].position = paddlePosition;
}
- (void)didSimulatePhysics {
if ([self ballNode] && [self ballNode].position.y < [config[@"ball"][@"radius"] floatValue] * 2) {
[self removeNodeWithSpark:[self ballNode]];
_life--;
[self updateLifeLabel];
if (_life < 1) {
[self gameOver];
}
}
}
# pragma mark - Utilities
- (void)removeNodeWithSpark:(SKNode *)node {
NSString *sparkPath = [[NSBundle mainBundle] pathForResource:@"spark" ofType:@"sks"];
SKEmitterNode *spark = [NSKeyedUnarchiver unarchiveObjectWithFile:sparkPath];
spark.position = node.position;
spark.xScale = spark.yScale = 0.3f;
[self addChild:spark];
SKAction *fadeOut = [SKAction fadeOutWithDuration:5.0f];
SKAction *remove = [SKAction removeFromParent];
SKAction *sequence = [SKAction sequence:@[fadeOut, remove]];
[spark runAction:sequence];
[node removeFromParent];
}
- (void)updateBlockAlpha:(SKNode *)block {
int life = [block.userData[@"life"] intValue];
block.alpha = life * 0.2f;
}
# pragma mark - SKPhysicsContactDelegate
- (void)didBeginContact:(SKPhysicsContact *)contact {
SKPhysicsBody *firstBody, *secondBody;
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) {
firstBody = contact.bodyA;
secondBody = contact.bodyB;
} else {
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if (firstBody.categoryBitMask & blockCategory) {
if (secondBody.categoryBitMask & ballCategory) {
[self decreaseBlockLife:firstBody.node];
}
}
}
- (void)gameOver {
SKScene *scene = [BFGameOverScene sceneWithSize:self.size];
SKTransition *transition = [SKTransition pushWithDirection:SKTransitionDirectionDown duration:1.0f];
[self.view presentScene:scene transition:transition];
}
- (void)nextLevel {
BFPlayScene *scene = [[BFPlayScene alloc] initWithSize:self.size life:self.life stage:self.stage + 1];
SKTransition *transition = [SKTransition doorwayWithDuration:1.0f];
[self.view presentScene:scene transition:transition];
}
@end
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
#import <SpriteKit/SpriteKit.h>
@interface BFGameOverScene : SKScene
@end
#import "BFGameOverScene.h"
#import "BFPlayScene.h"
@implementation BFGameOverScene
- (id)initWithSize:(CGSize)size {
self = [super initWithSize:size];
if (self) {
SKLabelNode *titleLabel = [SKLabelNode labelNodeWithFontNamed:@"HelveticaNeue"];
titleLabel.text = @"GAVE OVER...";
titleLabel.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
titleLabel.fontSize = 40.0f;
[self addChild:titleLabel];
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
SKScene *scene = [BFPlayScene sceneWithSize:self.size];
SKTransition *transition = [SKTransition pushWithDirection:SKTransitionDirectionUp duration:1.0f];
[self.view presentScene:scene transition:transition];
}
@end
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint locaiton = [touch locationInNode:self];
CGFloat speed = [config[@"paddle"][@"speed"] floatValue];
CGFloat x = locaiton.x;
CGFloat diff = abs(x - [self paddleNode].position.x);
CGFloat duration = speed * diff;
SKAction *move = [SKAction moveToX:x duration:duration];
[[self paddleNode] runAction:move];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (![self ballNode]) {
[self addBall];
return;
}
}
$ afconvert -f caff -d ima4 pi.wav -o pi.caf
$ afplay pi.caf
[self runAction:[SKAction playSoundFileNamed:@"pi.caf" waitForCompletion:NO]];
*** Terminating app due to uncaught exception 'Failed to Load Resource', reason: 'Resource pi.caf can not be loaded'
@property (nonatomic, strong) SKAction *projectileSoundEffectAction;
self.projectileSoundEffectAction = [SKAction playSoundFileNamed:@"pew-pew-lei.caf" waitForCompletion:NO];
SKAction *moveAction = [SKAction moveTo:realDest duration:realMoveDuration];
SKAction *projectileCastAction = [SKAction group:@[moveAction,self.projectileSoundEffectAction]];
[projectile runAction:projectileCastAction completion:^{
[projectile removeFromParent];
[self.projectiles removeObject:projectile];
}];
[self runAction:self.projectileSoundEffectAction];
#import <AVFoundation/AVFoundation.h>
@property (nonatomic, strong) AVAudioPlayer *bgmPlayer;
NSString *bgmPath = [[NSBundle mainBundle] pathForResource:@"background-music-aac" ofType:@"caf"];
self.bgmPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:bgmPath] error:NULL];
self.bgmPlayer.numberOfLoops = -1;
[self.bgmPlayer play];
[self.bgmPlayer stop];
self.bgmPlayer = nil;
BitMask | default | description |
---|---|---|
categoryBitMask | 0xFFFFFFFF | そのノードがどのカテゴリか示す(デフォルトでは全てのカテゴリに含まれる) |
contactTestBitMask | 0x00000000 | どのカテゴリのノードと衝突した場合に、デリゲートメソッドを呼び出すか示すフラグ |
collisionBitMask | 0xFFFFFFFF | どのカテゴリのノードと衝突した場合に、反射運動させるかを示すフラグ |
*** Terminating app due to uncaught exception 'Missing Resource', reason: 'Resource pi.caf cannont be found in the main bundle'
*** Terminating app due to uncaught exception 'Failed to Load Resource', reason: 'Resource pi.caf can not be loaded'
***.xcodeproj The file “Pods.xcconfig” couldn’t be opened because there is no such file. (***.xcconfig)
The file “Pods.xcconfig” couldn’t be opened because there is no such file. (***.xcconfig)
・