Sprite Kit教程:初学者
作者:Ray Wenderlich
原文出处:点击打开链接
http://www.raywenderlich.com/42699/spritekit-tutorial-for-beginners

转自破船之家,原文:Sprite Kit Tutorial for Beginners





- #import "MyScene.h"
- // 1
- @interface MyScene ()
- @property (nonatomic) SKSpriteNode * player;
- @end
- @implementation MyScene
- -(id)initWithSize:(CGSize)size {
- if (self = [super initWithSize:size]) {
- // 2
- NSLog(@"Size: %@", NSStringFromCGSize(size));
- // 3
- self.backgroundColor = [SKColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
- // 4
- self.player = [SKSpriteNode spriteNodeWithImageNamed:@"player"];
- self.player.position = CGPointMake(100, 100);
- [self addChild:self.player];
- }
- return self;
- }
- @end

- SpriteKitSimpleGame[3139:907] Size: {320, 568}
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- // Configure the view.
- SKView * skView = (SKView *)self.view;
- skView.showsFPS = YES;
- skView.showsNodeCount = YES;
- // Create and configure the scene.
- SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];
- scene.scaleMode = SKSceneScaleModeAspectFill;
- // Present the scene.
- [skView presentScene:scene];
- }
- - (void)viewWillLayoutSubviews
- {
- [super viewWillLayoutSubviews];
- // Configure the view.
- SKView * skView = (SKView *)self.view;
- if (!skView.scene) {
- skView.showsFPS = YES;
- skView.showsNodeCount = YES;
- // Create and configure the scene.
- SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];
- scene.scaleMode = SKSceneScaleModeAspectFill;
- // Present the scene.
- [skView presentScene:scene];
- }
- }

- self.player.position = CGPointMake(self.player.size.width/2, self.frame.size.height/2);
- - (void)addMonster {
- // Create sprite
- SKSpriteNode * monster = [SKSpriteNode spriteNodeWithImageNamed:@"monster"];
- // Determine where to spawn the monster along the Y axis
- int minY = monster.size.height / 2;
- int maxY = self.frame.size.height - monster.size.height / 2;
- int rangeY = maxY - minY;
- int actualY = (arc4random() % rangeY) + minY;
- // Create the monster slightly off-screen along the right edge,
- // and along a random position along the Y axis as calculated above
- monster.position = CGPointMake(self.frame.size.width + monster.size.width/2, actualY);
- [self addChild:monster];
- // Determine speed of the monster
- int minDuration = 2.0;
- int maxDuration = 4.0;
- int rangeDuration = maxDuration - minDuration;
- int actualDuration = (arc4random() % rangeDuration) + minDuration;
- // Create the actions
- SKAction * actionMove = [SKAction moveTo:CGPointMake(-monster.size.width/2, actualY) duration:actualDuration];
- SKAction * actionMoveDone = [SKAction removeFromParent];
- [monster runAction:[SKAction sequence:@[actionMove, actionMoveDone]]];
- }
- @property (nonatomic) NSTimeInterval lastSpawnTimeInterval;
- @property (nonatomic) NSTimeInterval lastUpdateTimeInterval;
- - (void)updateWithTimeSinceLastUpdate:(CFTimeInterval)timeSinceLast {
- self.lastSpawnTimeInterval += timeSinceLast;
- if (self.lastSpawnTimeInterval > 1) {
- self.lastSpawnTimeInterval = 0;
- [self addMonster];
- }
- }
- - (void)update:(NSTimeInterval)currentTime {
- // Handle time delta.
- // If we drop below 60fps, we still want everything to move the same distance.
- CFTimeInterval timeSinceLast = currentTime - self.lastUpdateTimeInterval;
- self.lastUpdateTimeInterval = currentTime;
- if (timeSinceLast > 1) { // more than a second since last update
- timeSinceLast = 1.0 / 60.0;
- self.lastUpdateTimeInterval = currentTime;
- }
- [self updateWithTimeSinceLastUpdate:timeSinceLast];
- }


- static inline CGPoint rwAdd(CGPoint a, CGPoint b) {
- return CGPointMake(a.x + b.x, a.y + b.y);
- }
- static inline CGPoint rwSub(CGPoint a, CGPoint b) {
- return CGPointMake(a.x - b.x, a.y - b.y);
- }
- static inline CGPoint rwMult(CGPoint a, float b) {
- return CGPointMake(a.x * b, a.y * b);
- }
- static inline float rwLength(CGPoint a) {
- return sqrtf(a.x * a.x + a.y * a.y);
- }
- // Makes a vector have a length of 1
- static inline CGPoint rwNormalize(CGPoint a) {
- float length = rwLength(a);
- return CGPointMake(a.x / length, a.y / length);
- }
- -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
- // 1 - Choose one of the touches to work with
- UITouch * touch = [touches anyObject];
- CGPoint location = [touch locationInNode:self];
- // 2 - Set up initial location of projectile
- SKSpriteNode * projectile = [SKSpriteNode spriteNodeWithImageNamed:@"projectile"];
- projectile.position = self.player.position;
- // 3- Determine offset of location to projectile
- CGPoint offset = rwSub(location, projectile.position);
- // 4 - Bail out if you are shooting down or backwards
- if (offset.x <= 0) return;
- // 5 - OK to add now - we've double checked position
- [self addChild:projectile];
- // 6 - Get the direction of where to shoot
- CGPoint direction = rwNormalize(offset);
- // 7 - Make it shoot far enough to be guaranteed off screen
- CGPoint shootAmount = rwMult(direction, 1000);
- // 8 - Add the shoot amount to the current position
- CGPoint realDest = rwAdd(shootAmount, projectile.position);
- // 9 - Create the actions
- float velocity = 480.0/1.0;
- float realMoveDuration = self.size.width / velocity;
- SKAction * actionMove = [SKAction moveTo:realDest duration:realMoveDuration];
- SKAction * actionMoveDone = [SKAction removeFromParent];
- [projectile runAction:[SKAction sequence:@[actionMove, actionMoveDone]]];
- }

- static const uint32_t projectileCategory = 0x1 << 0;
- static const uint32_t monsterCategory = 0x1 << 1;
- self.physicsWorld.gravity = CGVectorMake(0,0);
- self.physicsWorld.contactDelegate = self;
- monster.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:monster.size]; // 1
- monster.physicsBody.dynamic = YES; // 2
- monster.physicsBody.categoryBitMask = monsterCategory; // 3
- monster.physicsBody.contactTestBitMask = projectileCategory; // 4
- monster.physicsBody.collisionBitMask = 0; // 5
- projectile.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:projectile.size.width/2];
- projectile.physicsBody.dynamic = YES;
- projectile.physicsBody.categoryBitMask = projectileCategory;
- projectile.physicsBody.contactTestBitMask = monsterCategory;
- projectile.physicsBody.collisionBitMask = 0;
- projectile.physicsBody.usesPreciseCollisionDetection = YES;
- - (void)projectile:(SKSpriteNode *)projectile didCollideWithMonster:(SKSpriteNode *)monster {
- NSLog(@"Hit");
- [projectile removeFromParent];
- [monster removeFromParent];
- }
- - (void)didBeginContact:(SKPhysicsContact *)contact
- {
- // 1
- SKPhysicsBody *firstBody, *secondBody;
- if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
- {
- firstBody = contact.bodyA;
- secondBody = contact.bodyB;
- }
- else
- {
- firstBody = contact.bodyB;
- secondBody = contact.bodyA;
- }
- // 2
- if ((firstBody.categoryBitMask & projectileCategory) != 0 &&
- (secondBody.categoryBitMask & monsterCategory) != 0)
- {
- [self projectile:(SKSpriteNode *) firstBody.node didCollideWithMonster:(SKSpriteNode *) secondBody.node];
- }
- }
- @interface MyScene () <SKPhysicsContactDelegate>
- @import AVFoundation;
- @interface ViewController ()
- @property (nonatomic) AVAudioPlayer * backgroundMusicPlayer;
- @end
- NSError *error;
- NSURL * backgroundMusicURL = [[NSBundle mainBundle] URLForResource:@"background-music-aac" withExtension:@"caf"];
- self.backgroundMusicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:backgroundMusicURL error:&error];
- self.backgroundMusicPlayer.numberOfLoops = -1;
- [self.backgroundMusicPlayer prepareToPlay];
- [self.backgroundMusicPlayer play];
- [self runAction:[SKAction playSoundFileNamed:@"pew-pew-lei.caf" waitForCompletion:NO]];
- #import <SpriteKit/SpriteKit.h>
- @interface GameOverScene : SKScene
- -(id)initWithSize:(CGSize)size won:(BOOL)won;
- @end
- #import "GameOverScene.h"
- #import "MyScene.h"
- @implementation GameOverScene
- -(id)initWithSize:(CGSize)size won:(BOOL)won {
- if (self = [super initWithSize:size]) {
- // 1
- self.backgroundColor = [SKColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
- // 2
- NSString * message;
- if (won) {
- message = @"You Won!";
- } else {
- message = @"You Lose :[";
- }
- // 3
- SKLabelNode *label = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
- label.text = message;
- label.fontSize = 40;
- label.fontColor = [SKColor blackColor];
- label.position = CGPointMake(self.size.width/2, self.size.height/2);
- [self addChild:label];
- // 4
- [self runAction:
- [SKAction sequence:@[
- [SKAction waitForDuration:3.0],
- [SKAction runBlock:^{
- // 5
- SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];
- SKScene * myScene = [[MyScene alloc] initWithSize:self.size];
- [self.view presentScene:myScene transition: reveal];
- }]
- ]]
- ];
- }
- return self;
- }
- @end
- #import "GameOverScene.h"
- SKAction * loseAction = [SKAction runBlock:^{
- SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];
- SKScene * gameOverScene = [[GameOverScene alloc] initWithSize:self.size won:NO];
- [self.view presentScene:gameOverScene transition: reveal];
- }];
- [monster runAction:[SKAction sequence:@[actionMove, loseAction, actionMoveDone]]];
- @property (nonatomic) int monstersDestroyed;
- self.monstersDestroyed++;
- if (self.monstersDestroyed > 30) {
- SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];
- SKScene * gameOverScene = [[GameOverScene alloc] initWithSize:self.size won:YES];
- [self.view presentScene:gameOverScene transition: reveal];
- }
Sprite Kit教程:初学者的更多相关文章
- ios游戏开发 Sprite Kit教程:初学者 1
注:本文译自Sprite Kit Tutorial for Beginners 目录 Sprite Kit的优点和缺点 Sprite Kit vs Cocos2D-iPhone vs Cocos2D- ...
- iOS Sprite Kit教程之滚动场景
iOS Sprite Kit教程之滚动场景 滚动场景 在很多的游戏中,场景都不是静止的,而是滚动的,如在植物大战僵尸的游戏中,它的场景如图2.26所示. 图2.26 植物大战僵尸 在图2.26中,用 ...
- iOS Sprite Kit教程之场景的切换
iOS Sprite Kit教程之场景的切换 Sprite Kit中切换场景 每一个场景都不是单独存在的.玩家可以从一个场景中切换到另外一个场景中.本小节,我们来讲解场景切换.在每一个游戏中都会使用到 ...
- iOS Sprite Kit教程之场景的设置
iOS Sprite Kit教程之场景的设置 Sprite Kit中设置场景 在图2.8所示的效果中,可以看到新增的场景是没有任何内容的,本节将讲解对场景的三个设置,即颜色的设置.显示模式的设置以及测 ...
- iOS Sprite Kit教程之真机测试以及场景的添加与展示
iOS Sprite Kit教程之真机测试以及场景的添加与展示 IOS实现真机测试 在进行真机测试之前,首先需要确保设备已经连在了Mac(或者Mac虚拟机)上,在第1.9.1小节开始,设备就一直连接在 ...
- iOS Sprite Kit教程之申请和下载证书
iOS Sprite Kit教程之申请和下载证书 模拟器虽然可以实现真机上的一些功能,但是它是有局限的.例如,在模拟器上没有重力感应.相机机等.如果想要进行此方面的游戏的开发,进行程序测试时,模拟器显 ...
- iOS Sprite Kit教程之使用帮助文档以及调试程序
iOS Sprite Kit教程之使用帮助文档以及调试程序 IOS中使用帮助文档 在编写代码的时候,可能会遇到很多的方法.如果开发者对这些方法的功能,以及参数不是很了解,就可以使用帮助文档.那么帮助文 ...
- iOS Sprite Kit教程之编写程序以及Xcode的介绍
iOS Sprite Kit教程之编写程序以及Xcode的介绍 Xcode界面介绍 一个Xcode项目由很多的文件组成,例如代码文件.资源文件等.Xcode会帮助开发者对这些文件进行管理.所以,Xco ...
- iOS Sprite Kit教程之编敲代码以及Xcode的介绍
iOS Sprite Kit教程之编敲代码以及Xcode的介绍 Xcode界面介绍 一个Xcode项目由非常多的文件组成,比如代码文件.资源文件等.Xcode会帮助开发人员对这些文件进行管理.所以,X ...
随机推荐
- AlarmManager.setRepeating将不再准确
背景: 当我们想让Android应用程序定时为做一件工作时,我们往往会在一个BroadcastReceiver中使用AlarmManager.setRepeating()方法来实现.在API 19(即 ...
- 【HDOJ】2780 Su-Su-Sudoku
模拟+DFS. /* 2780 */ #include <cstdio> #include <cstring> #include <cstdlib> ][]; ][ ...
- 【转】单独编译android framework模块出现的问题
原文网址:http://blog.csdn.net/leonan/article/details/8629561 全编andorid后,单独修改编译一个framwork模块,make snod会有如下 ...
- JPA入门例子(采用JPA的hibernate实现版本) 转
JPA入门例子(采用JPA的hibernate实现版本) jpahibernate数据库jdbcjava框架(1).JPA介绍: JPA全称为Java Persistence API ,Java持久化 ...
- 配置Myeclipse中的项目部署到服务器,报the selected server is enabled, but is not configured properly.
the selected server is enabled, but is not configured properly. deployment to it will not be permitt ...
- HDU-2509 Be the Winner
http://acm.hdu.edu.cn/showproblem.php?pid=2509 Be the Winner Time Limit: 2000/1000 MS (Java/Others) ...
- Jdk5.0新特性
增强for循环:foreach语句,foreach简化了迭代器. 格式:// 增强for循环括号里写两个参数,第一个是声明一个变量,第二个就是需要迭代的容器 for( 元素类型 变量名 : Colle ...
- 将cocos的app直接在我的设备上测试运行
首先,你要有一个写好了的,准备在真机上测试的cocos程序. 1.设置ARC,设置的过程在另外一篇博文上有写. 2.在Target的Build Setting里面 找到Valid Archs 删除里面 ...
- Google辅助类软件
本博文的主要内容有 .Google辅助类软件的介绍 .重点首推! Google软件精选管理器 1.Google辅助类软件的介绍 1. Google软件精选管理器的下载和安装使用 2. Googl ...
- ng-select ng-options ng-repeat的用法与区别
最近在用angularJS里的ng-select,ng-options,ng-repeat,发现有两点不太方便: 1.当数据复杂时,循环起来比较麻烦 2.首选项如果不设置,就会为空 整理一下它们的用法 ...