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 ...
随机推荐
- View的getLeft, getRight, getTop, getBottom
View的getLeft, getRight, getTop, getBottom方法得到的分别是相对于其父组件原点坐标不同方向的距离 网上找了张图说明: 其中right和left的计算方法如下: r ...
- Oracle RAC的五大优势及其劣势
Oracle RAC的五大优势及其劣势 不同的集群产品都有自己的特点,RAC的特点包括如下几点: 双机并行.RAC是一种并行模式,并不是传统的主备模式.也就是说,RAC集群的所有成员都可以同时接收客户 ...
- Web Services的相关名词解释:WSDL与SOAP
在对Web Services进行性能测试时,接触到最多的两个名词就是WSDL和SOAP.利用LoadRunner对Web Services进行调用的时候,也存在两种常用方法,即基于WSDL的[Add ...
- Linux学习笔记25——命名管道(FIFO)
1 命名管道(FIFO) 管道应用的一个重大缺陷就是没有名字,因此只能用于亲缘进程之间的通信.后来从管道为基础提出命名管道(named pipe,FIFO)的概念,该限制得到了克服.FIFO不同于管道 ...
- Learn Objectvie-C on the Mac 2nd Edition 笔记
Chapter 1Apple’s Cocoa (for OS X) 和 Cocoa Touch (for iOS) toolkits 都是用 Objective-C写的. Chapter 2 (1) ...
- UValive 5713 Qin Shi Huang's National Road System
Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/3 ...
- MVC项目初次发布到IIS可能会遇到的问题
MVC4 + .NET Framework 4.5 +Windows Server 2008+ IIS7.5 + 4.0集成模式池 ,初次发布后可能会遇到404.0 或者403.14错误,加入以下代码 ...
- lightoj 1037 状态压缩
题目链接:http://lightoj.com/volume_showproblem.php?problem=1037 #include<cstdio> #include<cstri ...
- Installing scikit-learn
Installing scikit-learn http://scikit-learn.org/stable/install.html Installing scikit-learn There ar ...
- IOS学习之路十五(UIView 添加背景图片以及加边框)
怎样给UIview添加背景图片呢很简单,就是先给view添加一个subview,然后设为背景图片: 效果图如下: 很简单直接上代码: //设置内容 self.myTopView.backgroundC ...