青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

兔子的技術博客

兔子

   :: 首頁 :: 聯系 :: 聚合  :: 管理
  202 Posts :: 0 Stories :: 43 Comments :: 0 Trackbacks

留言簿(10)

最新評論

閱讀排行榜

評論排行榜

免責申明(必讀!):本博客提供的所有教程的翻譯原稿均來自于互聯網,僅供學習交流之用,切勿進行商業傳播。同時,轉載時不要移除本申明。如產生任何糾紛,均與本博客所有人、發表該翻譯稿之人無任何關系。謝謝合作!

原文鏈接地址:http://www.raywenderlich.com/3997/introduction-to-augmented-reality-on-the-iphone

教程截圖:

Create a simple augmented reality game where you can blast some aliens!

Create a simple augmented reality game where you can blast some aliens!

  在這篇教程中,你將學習到如何為你的iphone和ipod touch制作一個簡單的增強現實游戲。

  在這個游戲中,你將使用到攝像頭,陀螺儀和cocos2d框架。聽起來很振奮人心吧?

  在寫作這篇教程的時候,探索上面提到的一些技術的過程真的是非常有趣。這里有一些數學和轉換,不過不要擔心---沒有什么事情是很難的!

  學習這篇教程的時候,你需要一個iPhone4,因為這個教程使用陀螺儀來移動游戲世界視圖。

  你也需要一些基本的cocos2d方面的知識,當然要安裝好cocos2d。如果你對于cocos2d完全陌生的話,你可以先看看本博客上的其它cocos2d教程

  你準備好爆頭一些虛擬外星人了嗎?跟我來吧!

 

Getting Started

  打開Xcode,然后從File菜單中選擇New\New Project。然后選擇 iOS\cocos2d\cocos2d template,接著點擊Next。把工程命名為ARSpaceShips,并點擊Next,同時選擇一個文件夾位置來保存本項目,最后點Create。

  我們將重用Space Shooter游戲的一些資源文件,所以,先下載它們并解壓縮。

  下載完后,把Fonts,Sounds和Spritesheet文件夾拖到Resources分組下面。同時確保 Copy items into destination group’s folder被復選中,并且ARSpaceships target也要被選中。然后點擊Finish。這時,你的工程看起來應該如下圖所示:

  我們將在后面使用到這些資源。

玩一玩攝像頭!

  如果你現在運行項目,那簡單太無聊了,就是一個黑屏的HelloWorld,這玩意兒誰沒看過!讓我們往里面添加一些非常好玩的內容吧。選擇AppDelegate.h,然后在interface里面添加一個UIView成員變量。

UIView *overlay;

  現在,打開AppDelegate.m文件,找到EAGLView *glView所在的代碼行,把像素格式改成kEAGLColorFormatRGBA8。改完后如下圖所示:

EAGLView *glView = [EAGLView viewWithFrame:[window bounds]
pixelFormat:kEAGLColorFormatRGBA8 depthFormat:
0];

  如果你不改變像素格式的話,那么攝像頭里拍攝出來的圖像就顯示不出來。因為我們現在正在做一個增強現實的游戲,所以必須這樣做!

  在 [window addSubview: viewController.view];下面,我們添加了以下代碼:


// set the background color of the view
[CCDirector sharedDirector].openGLView.backgroundColor = [UIColor clearColor];
[CCDirector sharedDirector].openGLView.opaque
= NO;

// set value for glClearColor
glClearColor(0.0, 0.0, 0.0, 0.0);

// prepare the overlay view and add it to the window
overlay = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
overlay.opaque
= NO;
overlay.backgroundColor
=[UIColor clearColor];
[window addSubview:overlay];

  這里,我們把openGLView的背景顏色清除了,把視圖設置為透明的,同時指定了glClearColor,最后,我們創建并添加了一個新的視圖,叫做overlay。這個視圖后面用來顯示camera里的內容。

  接下來,在你剛剛添加的代碼后面增加以下代碼行:

#define CAMERA_TRANSFORM 1.24299

UIImagePickerController
*uip;

@try {
uip
= [[[UIImagePickerController alloc] init] autorelease];
uip.sourceType
= UIImagePickerControllerSourceTypeCamera;
uip.showsCameraControls
= NO;
uip.toolbarHidden
= YES;
uip.navigationBarHidden
= YES;
uip.wantsFullScreenLayout
= YES;
uip.cameraViewTransform
= CGAffineTransformScale(uip.cameraViewTransform,
CAMERA_TRANSFORM, CAMERA_TRANSFORM);
}
@catch (NSException * e) {
[uip release];
uip
= nil;
}
@finally {
if(uip) {
[overlay addSubview:[uip view]];
[overlay release];
}
}

[window bringSubviewToFront:viewController.view];

  首先,我們了一個常量來縮放攝像頭。攝像頭的比率是4:3,而iphone屏幕的比例是3:4,所以,我們需要縮放一下攝像頭,使之與屏幕匹配。

  其次,我們創建了一個UIImagePickerController,設置了它的一些屬性,具體效果就是沒有控件并且縮放了的攝像頭。然后,我們把它添加到了overlay視圖中。

  最后,我們需要把 viewController.view顯示到前面來(因為它包含了cocos2d的顯示內容)。這樣子攝像頭拍攝的內容也就會顯示到前臺來了。

  現在,運行一下應用程序。現在,你將看到攝像頭里面捕捉的畫面是你的Hello World的背景了。

Shake, Rattle, and Roll…Well at Least Yaw!

  因為我們現在的程序已經可以把現實捕捉并顯示出來了,接下來,我們將集中精力來解決本教程中比較難的部分。

  首先,我們需要把CoreMotion framework添加到項目中去。點擊project文件,然后選擇ARSpaceships target,再選擇Build Phases標簽頁,展開 Link Binary With Libraries.。

  點擊上圖中的+號,選擇 CoreMotion.framework,然后點擊Add按鈕。現在,我們就可以在項目中使用陀螺儀啦。

  打開HelloWorldLayer.h,然后導入一些頭文件:

#include <CoreMotion/CoreMotion.h>
#import <CoreFoundation/CoreFoundation.h>

  然后在interface里面添加一些成員變量:

CMMotionManager *motionManager;
CCLabelTTF
*yawLabel;
CCLabelTTF
*posIn360Label;

  同時添加屬性聲明語句:

@property (nonatomic, retain) CMMotionManager *motionManager;

  現在,重點要來了!打開HelloWorldLayer.m文件,在if ((self=[super init]))語句內部,刪除原來的“Hello World”標簽語句,同時添加下面的代碼來設置一些新的標簽.

// add and position the labels
yawLabel = [CCLabelTTF labelWithString:@"Yaw: " fontName:@"Marker Felt" fontSize:12];
posIn360Label
= [CCLabelTTF labelWithString:@"360Pos: " fontName:@"Marker Felt" fontSize:12];
yawLabel.position
= ccp(50, 240);
posIn360Label.position
= ccp(50, 300);
[self addChild: yawLabel];
[self addChild:posIn360Label];

  目前為止,并沒有什么特別的。只是添加了一些標簽,指明了字體和一些文字。標簽的位置都是在屏幕的左邊。

  接下來,你需要設置motion manager,它會啟動陀螺儀。

self.motionManager = [[[CMMotionManager alloc] init] autorelease];
motionManager.deviceMotionUpdateInterval
= 1.0/60.0;
if (motionManager.isDeviceMotionAvailable) {
[motionManager startDeviceMotionUpdates];
}

[self scheduleUpdate];

  這里,我們分配并初始化了 motion manager對象。同時,我們還設置了更新間隔為每秒60次。如果設置支持陀螺儀的話,那么就啟動更新。最后,我們觸發一個update定時器。

  不要忘了在.m文件中添加synthesize語句,如下所示:

@synthesize motionManager;

  因為我們觸發了update定時器,所以我們需要添加一個update方法。同時,在init方法的下面增加下面一個方法:

-(void)update:(ccTime)delta {
CMDeviceMotion
*currentDeviceMotion = motionManager.deviceMotion;
CMAttitude
*currentAttitude = currentDeviceMotion.attitude;

// 1: Convert the radians yaw value to degrees then round up/down
float yaw = roundf((float)(CC_RADIANS_TO_DEGREES(currentAttitude.yaw)));

// 2: Convert the degrees value to float and use Math function to round the value
[yawLabel setString:[NSString stringWithFormat:@"Yaw: %.0f", yaw]];

// 3: Convert the yaw value to a value in the range of 0 to 360
int positionIn360 = yaw;
if (positionIn360 < 0) {
positionIn360
= 360 + positionIn360;
}

[posIn360Label setString:[NSString stringWithFormat:
@"360Pos: %d", positionIn360]];

}

  現在,你可以運行應用程序了。你將會看到Yaw和positionIn360的對應標簽值在改變。

那玩意兒究竟如何工作?

  盡管可以跑起來了,但是你可能會問,它究竟是如何工作的呢?讓我們花幾分鐘時間來一步步解釋上面的代碼是如何工作的。

  首先,下載iTunes app store上面的免費程序 Gyrosocope app。安裝并運行它,當你移動iphone的時候,就可以看到每個值究竟是怎么變化的。

  我們關心的值是Yaw。這個值代表往左或往右移動。在Gyroscope程序中,它的單位是度,然而 motion manager獲取的值卻是弧度。這就是為什么我們需要使用內置的函數CC_RADIANS_TO_DEGREES來把弧度轉換成角度的原因啦。

  因此,在第一部分中,我們得到了yaw的弧度值,并且把它轉換成角度,最后賦值給yaw變量。第二部分,我們只是把yaw的值顯示到屏幕上去。如果你運行工程,你會看到yaw值的變化范圍是從0~180,然后又從-180回到0.

  現在看看第三部分,你可能會奇怪positionIn360的值倒底是什么啊?好吧,這里只是一個手段,目的是使得放置飛碟的過程變得容易。

  這里的邏輯其實非常簡單。如果yaw值是正的,那么我們什么也不做。如果是負的,那么就減去360.(加上一個負值和減去一個正值是一樣的)。最后一行代碼只是在屏幕上顯示那個值。

  如果你還沒完全理解,沒關系,運行一下程序,看看具體值是怎么變化的吧。

燈光,攝像機,Action!

  現在,我們為陀螺儀的使用奠定基礎了,讓我們往里面添加一些太空飛船吧!我們將創建一個新的文件。首先,左鍵點ARSpaceships工程文件,然后選擇New File。接著選 iOS\Cocoa Touch\Objective-C class,然后點擊Next。確保NSObject被選中基類,然后點Next。把文件命名為EnemyShip.m,最后點Save。

  把 EnemyShip.h里的內容換成下面的代碼:

#import "cocos2d.h"

@interface EnemyShip : CCSprite {
int yawPosition;
int timeToLive;
}

@property (readwrite)
int yawPosition;
@property (readwrite)
int timeToLive;

@end

  同時修改EnemyShip.m:

#import "EnemyShip.h"


@implementation EnemyShip

@synthesize yawPosition, timeToLive;

-(id)init {
self
= [super init];
if (self){
yawPosition
= 0;
timeToLive
= 0;
}
return self;
}

@end

  現在,回到HelloWorldLayer.h。在頂部導入EnemyShip類的頭文件,如下所示:

#import "EnemyShip.h"

  在interface里面聲明以下成員變量:

NSMutableArray *enemySprites;
int enemyCount;
CCSpriteBatchNode
*batchNode;

  最后,在interface聲明下面,添加enemyCount屬性,同時定義一些方法,具體如下圖所示:

@property (readwrite) int enemyCount;

-(EnemyShip *)addEnemyShip:(int)shipTag;
-(void)checkEnemyShipPosition:(EnemyShip *)enemyShip withYaw:(float)yawPosition;
-(void)updateEnemyShipPosition:(int)positionIn360 withEnemy:(EnemyShip *)enemyShip;
-(void)runStandardPositionCheck:(int)positionIn360 withDiff:(int)difference withEnemy:(EnemyShip *)enemyShip;

  打開 HelloWorldLayer.m文件,同時作以下修改:

// Place after the #import statement
#include <stdlib.h>

// Place after the other @synthesize statement
@synthesize enemyCount;
#define kXPositionMultiplier 15
#define kTimeToLive 100

// Add to the bottom of init
batchNode = [CCSpriteBatchNode batchNodeWithFile:@"Sprites.pvr.ccz"];
[self addChild:batchNode];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:
@"Sprites.plist"];

  這里,我們加載了spritesheet,它的資源文件在一開始的時候,我們就把它拖到項目中來了。

  接下來,我們將添加一個新的方法來創建新的敵人太空飛船。在dealloc方法的上面添加下列方法:

-(EnemyShip *)addEnemyShip:(int)shipTag {

EnemyShip
*enemyShip = [EnemyShip spriteWithSpriteFrameName:@"enemy_spaceship.png"];

// Set position of the space ship randomly
int x = arc4random() % 360;
enemyShip.yawPosition
= x;

// Set the position of the space ship off the screen, but in the center of the y axis
// we will update it in another method
[enemyShip setPosition:ccp(5000, 160)];

// Set time to live on the space ship
enemyShip.timeToLive = kTimeToLive;
enemyShip.visible
= true;

[batchNode addChild:enemyShip z:
3 tag:shipTag];

return enemyShip;
}

  這個方法接收一個整數值作為tag,并且返回一個EnemyShip CCSprite。下面一行代碼,我們從精靈表單中創建一個EnemyShip精靈。接著,我們使用arc4random方法來得到一個0~360的隨機數。最后,我們設置了飛船的位置,并把timeToLive的值設置為100,把飛船添加到batchNode里面,最后返回飛船精靈對象。

  在addEnemyShip下面,我們添加一個checkEnemyShipPosition方法:

-(void)checkEnemyShipPosition:(EnemyShip *)enemyShip withYaw:(float)yawPosition {
// Convert the yaw value to a value in the range of 0 to 360
int positionIn360 = yawPosition;
if (positionIn360 < 0) {
positionIn360
= 360 + positionIn360;
}

BOOL checkAlternateRange
= false;

// Determine the minimum position for enemy ship
int rangeMin = positionIn360 - 23;
if (rangeMin < 0) {
rangeMin
= 360 + rangeMin;
checkAlternateRange
= true;
}

// Determine the maximum position for the enemy ship
int rangeMax = positionIn360 + 23;
if (rangeMax > 360) {
rangeMax
= rangeMax - 360;
checkAlternateRange
= true;
}

if (checkAlternateRange) {
if ((enemyShip.yawPosition < rangeMax || enemyShip.yawPosition > rangeMin ) || (enemyShip.yawPosition > rangeMin || enemyShip.yawPosition < rangeMax)) {
[self updateEnemyShipPosition:positionIn360 withEnemy:enemyShip];
}
}
else {
if (enemyShip.yawPosition > rangeMin && enemyShip.yawPosition < rangeMax) {
[self updateEnemyShipPosition:positionIn360 withEnemy:enemyShip];
}
}
}

  這個方法看起來似乎有點讓人摸不著頭腦,一會最大值,一會兒最小值,一會候選值。不過,不要擔心,其實非常簡單。首先,我們檢查設置的yaw坐標址(positionIn360),然后把此值限制在0~360之間。

  因為,我們有兩端范圍都是0~360,所以需要檢查一下設置的positionIn360具體屬于哪一端。我們使用一個任意數23來代表將在屏幕一半處顯示的度數。

  因為,我們只需要關心變化范圍是0~23和337~360的空間了。因為,另一端的線將會包過來。(這里相像成3維空間的一個圓)

  最后,如果敵人飛船在屏幕46度的范圍之內的話,那么就要更新敵人飛船。checkAlternateRange判斷語句只是用來決定什么時候來更新敵人飛船。

  如果checkAlternateRange為真的話,那么我們就檢查敵船的位置是否落在min和max的范圍之內。

positionIn360 = 20
rangeMin
= 357
rangeMax
= 20
enemyShip.yawPosition
= 359

  因為我們要考慮線段的兩端,我們的min范圍比max范圍要大一些。現在,我們做一個判斷,看敵船的位置是不是大于rangeMin,如果是,則顯示在屏幕上。

  if語句中的else就更加明了了。他檢查敵船的位置是不是大于min且小于max。

  多么復雜的一個update方法啊!我們在checkEnemyShipPosition方法下面添加以下代碼:

-(void)updateEnemyShipPosition:(int)positionIn360 withEnemy:(EnemyShip *)enemyShip {
int difference = 0;
if (positionIn360 < 23) {
// Run 1
if (enemyShip.yawPosition > 337) {
difference
= (360 - enemyShip.yawPosition) + positionIn360;
int xPosition = 240 + (difference * kXPositionMultiplier);
[enemyShip setPosition:ccp(xPosition, enemyShip.position.y)];
}
else {
// Run Standard Position Check
[self runStandardPositionCheck:positionIn360 withDiff:difference withEnemy:enemyShip];
}
}
else if(positionIn360 > 337) {
// Run 2
if (enemyShip.yawPosition < 23) {
difference
= enemyShip.yawPosition + (360 - positionIn360);
int xPosition = 240 - (difference * kXPositionMultiplier);
[enemyShip setPosition:ccp(xPosition, enemyShip.position.y)];
}
else {
// Run Standard Position Check
[self runStandardPositionCheck:positionIn360 withDiff:difference withEnemy:enemyShip];
}
}
else {
// Run Standard Position Check
[self runStandardPositionCheck:positionIn360 withDiff:difference withEnemy:enemyShip];
}
}

  在這個方法中,我們測試,看是否設備的positionIn360是不是在討論的3個范圍內。在第一個測試中,我們檢測positionIn360是不理小于23,如果是,我們就看看是不是有一些敵船在線的另一端(大于337)。

  第二部分測試,看是否positionIn360大于337.如果是的話,就再檢測它是否小于23.

  第二部分測試,看敵船是否在23和337之間。如果是,則調用runStandardPositionCheck方法。這個方法的定義如下所示:

-(void)runStandardPositionCheck:(int)positionIn360 withDiff:(int)difference withEnemy:(EnemyShip *)enemyShip {
if (enemyShip.yawPosition > positionIn360) {
difference
= enemyShip.yawPosition - positionIn360;
int xPosition = 240 - (difference * kXPositionMultiplier);
[enemyShip setPosition:ccp(xPosition, enemyShip.position.y)];
}
else {
difference
= positionIn360 - enemyShip.yawPosition;
int xPosition = 240 + (difference * kXPositionMultiplier);
[enemyShip setPosition:ccp(xPosition, enemyShip.position.y)];
}
}

  在這個方法中,我們檢查看是否enemyShip是否在設備的positionIn360的左邊還是右邊。當enemyShip的位置小于positionIn360時,它將出現在屏幕的左邊。當enemyShip的位置大于positionIn360,那么它將出現在屏幕的右邊。

  現在,你會說,請等一下!你忘了描述這些變量的作用了!好吧,接下來就解釋一下。

  如果敵船的yaw坐標值在屏幕的范圍之內(從 positionIn360 – 23到 positionIn360 + 23),然后,首先我們計算它位于屏幕的哪一邊。如果大于positionIn360,那么就在屏幕的右邊,否則就在屏幕的左邊。

  difference變量的作用是保存設備的positionIn360和敵船的 yaw位置的角度差值。一旦計算出來后,我們就把這個差值乘以一個任意的倍數。這個倍數代表每一度的像素個數。這個里,我們選擇15.

  基于它位于于當前屏幕的位置,我們將把這個計算出來的值增加240或者減去240。

  現在,所有需要的方法已經全部準備就緒啦。

  在init方法的底部,添加下面的代碼,在屏幕中增加5個飛船:

// Loop through 1 - 5 and add space ships
enemySprites = [[NSMutableArray alloc] init];
for(int i = 0; i < 5; ++i) {
EnemyShip
*enemyShip = [self addEnemyShip:i];
[enemySprites addObject:enemyShip];
enemyCount
+= 1;
}

  因為,我們添加了敵船到屏幕中了,我們確保它們的位置被更新。在udpate方法的底部添加下面方法:

// Loop through array of Space Ships and check the position
for (EnemyShip *enemyShip in enemySprites) {
[self checkEnemyShipPosition:enemyShip withYaw:yaw];
}

  在我們忘記之前,在dealloc里面添加清理代碼來清理我們之前創建的enemySpritesArray數組:

[enemySprites release];

  現在,編譯并運行工程吧!當你旋轉設備的時候,你將會看到5個飛船在不同的地方。

免費的激光和爆炸

  目前為止,這個現實增加的游戲完成的差不多了。不過,還有一個很嚴重的問題:這里飛船打中后沒什么感覺。

  很明顯,我們并不想這樣,所以,讓我們添加一些很酷的激光和爆炸效果吧。

  在開始之前,讓我們移除屏幕上的label--他們只是作為調試時用的。因此,找開 HelloWorldLayer.m中關于labels的代碼,并把它們注釋掉。完成之后,編譯并運行,保證沒有錯誤。

  現在,看看有趣的部分---讓我們往游戲中添加一些火力吧!首先,我們將添加一個方法用來判斷玩家的開火區域是否擊中了飛船。在HelloWorldLayer.h文件中,在@end之前聲明下列方法:

- (BOOL) circle:(CGPoint) circlePoint withRadius:(float) radius collisionWithCircle:(CGPoint) circlePointTwo collisionCircleRadius:(float) radiusTwo;

  打開HelloWorldLayer.m,然后在dealloc方法上面實現上述方法:

- (BOOL) circle:(CGPoint) circlePoint withRadius:(float) radius collisionWithCircle:(CGPoint) circlePointTwo collisionCircleRadius:(float) radiusTwo {
float xdif = circlePoint.x - circlePointTwo.x;
float ydif = circlePoint.y - circlePointTwo.y;

float distance = sqrt(xdif*xdif+ydif*ydif);
if(distance <= radius+radiusTwo) return YES;

return NO;
}
  

  這個方法用來檢測是否兩個點的半徑有交集。輸入的參數是敵方飛船位置和屏幕的中心點位置。兩個點的半徑都設置為50.

  首先,我們計算兩個點X和Y值的差。接下來計算兩點的距離。這個在高中就學過的,叫勾股定理。你可以從這里得到更多的信息。

  接下來,我們往屏幕中添加一個區域,用作火力瞄準器。下載這些資源文件,解壓縮,然后把scope.png拖到Resouces文件夾下去。確保“Copy items into destination group’s folder”被復選中,然后點Finish。

  打開HelloWorldLayer.m的init方法,然后在 [self scheduleUpdate]方法之前,添加以下代碼:

// Add the scope crosshairs
CCSprite *scope = [CCSprite spriteWithFile:@"scope.png"];
scope.position
= ccp(240, 160);
[self addChild:scope z:
15];

// Allow touches with the layer
[self registerWithTouchDispatcher];

  如果你現在運行程序,你將看到一個瞄準器出現在屏幕的中間。

  非常好,現在讓我們添加一些爆炸效果,在玩家點擊屏幕的時候就觸發。我們將按照添加scope.png的方法一樣,來添加Explision.plist。先找到之前下載的本項目資源文件。把Explosion.plist拖到資源文件夾中,確保“Copy items into destination group’s folder”被復選上,然后點擊Finish。

  你可能會奇怪這個文件到底是什么?我使用一個很酷的軟件制作的,你可能之前也聽說過了,叫做 Particle Designer,它是由71 Squared的工程師所開發的。我不會在這里講解如何使用此軟件來制作這樣的粒子效果文件,但是,實際上這個過程是非常簡單的。選擇一種粒子效果,然后調節一些參數,最后導出plist文件就可以了。

  現在,在dealloc方法之前,添加下列代碼:

-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint location
= CGPointMake(240,160);

// 1
for (EnemyShip *enemyShip in enemySprites) {
if (enemyShip.timeToLive > 0) {
// Check to see if yaw position is in range
BOOL wasTouched = [self circle:location withRadius:50 collisionWithCircle:enemyShip.position collisionCircleRadius:50];

if (wasTouched) {
enemyShip.timeToLive
= 0;
enemyShip.visible
= false;
enemyCount
-= 1;
}
}
}

// 2
CCParticleSystemQuad *particle = [CCParticleSystemQuad particleWithFile:@"Explosion.plist"];
particle.position
= ccp(240,160);
[self addChild:particle z:
20];
particle.autoRemoveOnFinish
= YES;

// 3
if (enemyCount == 0) {
// Show end game
CGSize winSize = [CCDirector sharedDirector].winSize;
CCLabelBMFont
*label = [CCLabelBMFont labelWithString:@"You win!" fntFile:@"Arial.fnt"];
label.scale
= 2.0;
label.position
= ccp(winSize.width/2, winSize.height/2);
[self addChild:label z:
30];
}
}

  這段代碼的第一部分用來做碰撞檢測,用來測試是否飛船在瞄準器范圍之內。如果其中一個飛船被擊中了,我們就飛船的屬性來隱藏它,同時把enemyCount計數減1.第二部分代碼,往屏幕中心添加了一個爆炸粒子系統。第二部分代碼,也是最后一部分代碼,它用來檢查enemyCount是否為0,如果是的話,就顯示一個label,告知玩家游戲結束了。

  這個游戲如果就這樣的話,有點無聊。所以,讓我們往游戲中添加一些基本的AI吧。其實也很簡單的,就是隨著時間的推移,我們會改變一下飛船的位置。所以,在update方法底部添加下列代碼:

// Loop through array of Space Ships and if the timeToLive is zero
// change the yawPosition of the sprite
for (EnemyShip *enemyShip in enemySprites) {
enemyShip.timeToLive
--;
if (enemyShip.timeToLive == 0) {
int x = arc4random() % 360;
[enemyShip setPosition:ccp(
5000, 160)];
enemyShip.yawPosition
= x;
enemyShip.timeToLive
= kTimeToLive;
}
}

  這段代碼將會遍歷所有的enemySprites,然后更新timeToLive屬性。然后,檢查這個timeToLive屬性是否等于0,如果是的話,那么就給飛船的yawPositon設置一個隨機值,同時重置timeToLive屬性。編譯并運行工程吧,現在你想要打中飛船的話就有一些難度了,開火!

Pump up the Volume!

  游戲如果沒有聲音的話,那就太沒意思了!所以,讓我們添加一些音樂吧!

  在HellowWorldLayer.m文件頂部包含Simple Audio Engine所需的頭文件,具體如下所示:

#import "SimpleAudioEngine.h"

  然后在init方法的最后添加下列代碼,記得添加在 if ((self=[super init]))語句內部:

[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"SpaceGame.caf" loop:YES];
[[SimpleAudioEngine sharedEngine] preloadEffect:
@"explosion_large.caf"];
[[SimpleAudioEngine sharedEngine] preloadEffect:
@"laser_ship.caf"];
  

  這里會加載背景音樂,同時預加載音效。

  現在,找到ccTouchesBegan,然后在這個方法的開頭添加下列代碼:

[[SimpleAudioEngine sharedEngine] playEffect:@"laser_ship.caf"];

  這里會在你點擊屏幕的時候播放一個發射激光的音效。

  還是在ccTouchesBegan方法里面,打開遍歷enemySprites那個循環,然后在 (wasTouched)的if判斷句內添加下列代碼:

[[SimpleAudioEngine sharedEngine] playEffect:@"explosion_large.caf"];

  當飛船被打中的時候,將會播放爆炸的音效!

  編譯并運行代碼,盡情玩吧!

何去何從?

  這里有本教程的完整源代碼

  如果你想學習更多有關制作增強現實的游戲的話,下面有一些比較好的資源:

  我希望你在學習這個教程的時候會得到許多快樂!如果有什么建議或意見,請留言,謝謝!


轉自:http://www.cnblogs.com/andyque/archive/2011/07/03/2096510.html
posted on 2011-07-04 11:57 會飛的兔子 閱讀(2186) 評論(0)  編輯 收藏 引用 所屬分類: 蘋果相關
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美一区观看| 亚洲国产毛片完整版| 久久精品国产免费| 久久蜜臀精品av| 久久久一二三| 乱人伦精品视频在线观看| 欧美在线免费看| 美女网站久久| 欧美日韩一视频区二区| 国产乱子伦一区二区三区国色天香 | 国产精品豆花视频| 国产精品亚洲片夜色在线| 国产综合久久久久久鬼色| 在线观看一区二区精品视频| 亚洲精品男同| 欧美一级理论片| 欧美二区不卡| 亚洲图片欧美一区| 久久只精品国产| 欧美视频一区在线观看| 国产日韩综合| 亚洲视频一区二区在线观看 | 国产精品久久久久三级| 伊人久久综合97精品| 在线亚洲激情| 欧美国产日韩一二三区| 亚洲一区二区精品视频| 久久久久久久精| 国产精品一二| 日韩亚洲在线| 麻豆精品传媒视频| 亚洲婷婷在线| 欧美日韩国产页| 久久成人av少妇免费| av不卡在线看| 亚洲欧美国产精品桃花| 欧美一区二区三区免费视| 亚洲一级黄色| 欧美电影免费观看高清完整版| 亚洲美女网站| 国产专区一区| 国产精品亚洲一区二区三区在线| 亚洲一区二区三区精品视频| 久久久久国产一区二区三区四区 | 国产一区99| 亚洲一区免费网站| 91久久在线观看| 欧美一区二区三区在线看| 欧美日韩专区| 99视频精品在线| 欧美黄色片免费观看| 久久精品一区二区三区不卡| 国产精品自在线| 欧美亚洲一区三区| 亚洲深夜福利网站| 国产精品福利在线| 亚洲一区欧美二区| 亚洲小视频在线| 国产精品久久久一本精品| 亚洲天堂av图片| 一区二区三区国产| 国产精品视频一区二区高潮| 午夜精品久久久久久久久| 99精品国产99久久久久久福利| 欧美日韩国语| 亚洲欧美国产毛片在线| 国产精品99久久久久久人| 国产精品乱人伦一区二区| 亚洲欧美日韩综合一区| 亚洲小说欧美另类婷婷| 国产一区二区三区久久久| 两个人的视频www国产精品| 久久婷婷国产综合国色天香| 亚洲高清一区二区三区| 亚洲国产美女精品久久久久∴| 欧美精品手机在线| 亚洲欧美日本伦理| 久久aⅴ国产欧美74aaa| 91久久在线| 一区二区日韩免费看| 国产三级欧美三级日产三级99| 久久综合色综合88| 欧美精品一区二区三区久久久竹菊 | 亚洲欧洲av一区二区| 国产美女精品人人做人人爽| 久久久久青草大香线综合精品| 久久久久久亚洲精品中文字幕 | 在线观看国产精品网站| 亚洲电影免费观看高清完整版在线| 久久午夜羞羞影院免费观看| 久久偷看各类wc女厕嘘嘘偷窃| 亚洲激情一区二区三区| 妖精视频成人观看www| 国产婷婷色一区二区三区在线 | 99视频日韩| 国产在线视频不卡二| 亚洲黄色免费电影| 国产精品色在线| 欧美激情国产高清| 国产精品丝袜白浆摸在线| 免费在线观看精品| 国产精品入口日韩视频大尺度| 久久夜色精品一区| 欧美性猛交xxxx乱大交蜜桃 | 亚洲国产日韩一区| 国产视频不卡| 一本色道久久综合精品竹菊 | 欧美v国产在线一区二区三区| 亚洲女爱视频在线| 欧美jjzz| 六月婷婷久久| 国产美女精品视频免费观看| 亚洲欧洲另类| 亚洲国产另类久久久精品极度| 亚洲欧美在线看| 亚洲婷婷综合久久一本伊一区| 老司机67194精品线观看| 欧美在线播放一区| 国产精品成人一区二区网站软件| 亚洲福利视频网| 极品中文字幕一区| 欧美在线视频免费观看| 欧美影院久久久| 国产精品一区二区久久国产| 99视频一区二区三区| 亚洲精品综合精品自拍| 免费欧美日韩| 亚洲动漫精品| 亚洲精品亚洲人成人网| 噜噜噜久久亚洲精品国产品小说| 久久免费黄色| 在线观看不卡| 老司机成人网| 91久久精品视频| 99xxxx成人网| 欧美日韩在线一区| 一道本一区二区| 久久精品国产久精国产爱| 亚洲欧洲一区二区在线播放| 久久久九九九九| 另类尿喷潮videofree| 狠狠v欧美v日韩v亚洲ⅴ| 久久成年人视频| 国产视频精品免费播放| 久久av资源网站| 美女黄网久久| 亚洲美女中文字幕| 欧美性片在线观看| 亚洲一区高清| 久久亚洲国产成人| 亚洲激情影视| 国产精品h在线观看| 亚洲女优在线| 免费成人黄色av| 99riav久久精品riav| 国产精品看片你懂得| 欧美一区二区三区在线免费观看 | 亚洲激情一区二区三区| 欧美激情导航| 亚洲香蕉网站| 欧美电影打屁股sp| 中日韩男男gay无套| 国产精品免费区二区三区观看| 欧美一级二级三级蜜桃| 欧美77777| 亚洲一区二区不卡免费| 国产日韩欧美在线视频观看| 久久视频这里只有精品| 亚洲精品三级| 久久久久99精品国产片| 亚洲激情网站| 国产精品一区视频| 欧美va亚洲va香蕉在线| 亚洲一区二区三区欧美| 欧美成人精品一区| 亚洲欧美日本日韩| 在线视频国产日韩| 欧美日韩色一区| 久久久久一区| 亚洲一区二区三区乱码aⅴ蜜桃女| 久久久综合精品| 亚洲午夜在线观看| 亚洲丁香婷深爱综合| 国产精品美女久久久免费| 久久人91精品久久久久久不卡| 一本色道久久综合狠狠躁的推荐| 久久综合狠狠| 欧美制服丝袜| 亚洲一区免费看| 亚洲另类自拍| 黄色成人免费网站| 国产精品永久免费观看| 欧美日韩亚洲综合| 欧美大片一区| 蜜臀av在线播放一区二区三区| 欧美一级久久久| 亚洲男人的天堂在线观看| 亚洲毛片播放| 亚洲免费不卡| 亚洲精品一区二区三区四区高清 |