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

聚星亭

吾笨笨且懶散兮 急須改之而奮進(jìn)
posts - 74, comments - 166, trackbacks - 0, articles - 0
  C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
轉(zhuǎn)載聲明         本文轉(zhuǎn)載于 冥冥之中 的163博客,地址: http://blog.163.com/fengyi1103@126/blog/static/138356274201081741324532/
         感謝 毛叔 網(wǎng)友 翻譯。

        在這篇教程里,我們會(huì)講解如何使用cocos2d和Tiled Map Editor創(chuàng)建一個(gè)基于tiled map的游戲.作為例子,我們會(huì)制作一個(gè)小游戲.游戲的主要內(nèi)容是一個(gè)忍者在沙漠里尋找可口的西瓜吃.
        這篇教程主要學(xué)習(xí)的內(nèi)容有:
  1. 如何創(chuàng)建Tiled Map。
  2. 如何將地圖載入到游戲內(nèi)。
  3. 如何讓地圖跟隨玩家滾動(dòng);如何使用對(duì)象層。
  4. 如何在地圖里創(chuàng)建可碰撞(不可穿越)區(qū)域。
  5. 如何使用tile屬性。
  6. 如何使用可碰撞物體和動(dòng)態(tài)修改地圖。
  7. 如何確定你的主角沒(méi)有產(chǎn)生穿越
        如果你是個(gè)iphone開(kāi)發(fā)新手,作為基礎(chǔ)知識(shí)的準(zhǔn)備,我建議你先閱讀一下How To Make A Simple iPhone Game with Cocos2D Tutorial Series.

創(chuàng)建游戲骨架
       下面我們要?jiǎng)?chuàng)建游戲骨架.并且準(zhǔn)備好需要的資源文件,打開(kāi)XCode,File\New Project,選擇cocos2d Application創(chuàng)建一個(gè)新工程。
       接下來(lái),下載這個(gè)zip文件,這里面包含了游戲需要的資源:

  • 主角精靈
  • 一些游戲音效(使用cxfr工具制作)
  • 游戲背景音(使用Garage Band制作,詳細(xì)信息)
  • 用于構(gòu)造tiled map的元件
  • 一些特殊的元件,后面會(huì)詳細(xì)解釋

       將下載到的資源解包拖入xcode的resources組,記得選中”Copy items into destination group’s folder(if needed)”。
       這樣,一切準(zhǔn)備就緒.

創(chuàng)建游戲地圖
        Cocos2d支持使用開(kāi)源軟件Tiled Map Editor(貌似被偉大的墻擋住了,天朝的用戶(hù)可以直接訪(fǎng)問(wèn)它在sourceforge的項(xiàng)目主頁(yè),杯具!)創(chuàng)建的TMX格式地圖.如果你訪(fǎng)問(wèn)上面的鏈接,你會(huì)發(fā)現(xiàn)有兩個(gè)版本可用.
一個(gè)使用Qt應(yīng)用程序框架編寫(xiě),另一個(gè)使用Java編寫(xiě).這是因?yàn)樽畛鮐iled Map Editor使用Java編寫(xiě),后來(lái)移植到Qt框架上.使用哪個(gè)版本都可以.在這篇教程里,我們以使用Qt版本的為例,因?yàn)樗鼘⒆鳛榻窈蟮拈_(kāi)發(fā)主線(xiàn).
有些人喜歡使用java版本,是因?yàn)檫€有些老版本上的功能尚未移植到Qt框架上.

         運(yùn)行Tiled Map Editor,新建一個(gè)地圖.填寫(xiě)如下對(duì)話(huà)框:

        

        在orientation選項(xiàng)內(nèi),可以選擇Orthogonal(平面直角)或Isometric(45度視角,傳說(shuō)中的2.5D),這里選擇Orthogonal.
        接下來(lái)需要設(shè)置地圖大小.這里的數(shù)值是指有多少格tiled元件,并不是像素.選擇50×50即可.
        最后,確定tile元件的大小.根據(jù)美工提供的元件大小設(shè)置.這個(gè)教成立,我們使用32×32的大小. 接下來(lái),將tile元件添加到地圖內(nèi)繪制地圖.在Map菜單許做呢New Tileset,填寫(xiě)下面的對(duì)話(huà)框:
       
       點(diǎn)擊Browser從電腦里找到tmw_desert_spacing.png文件(下載的資源包內(nèi))
       保持長(zhǎng)寬數(shù)據(jù)為32×32.
       對(duì)于margin和spacing,我沒(méi)有找到文檔說(shuō)明,但是我認(rèn)為它們的意義是:
  • Margin 表示當(dāng)前tiled在開(kāi)始搜索實(shí)際像素時(shí)應(yīng)該忽略多少個(gè)像素 (譯者注:我理解應(yīng)該是兩個(gè)tiled元件之間的間距)
  • Spacing 表示讀取下一個(gè)tiled數(shù)據(jù)后應(yīng)該向前推進(jìn)多少個(gè)像素(譯者注:我理解應(yīng)該是兩個(gè)tiled元件之間的空隙,不過(guò),這好像與Margin重復(fù)了…)
        如果你仔細(xì)觀察tmw_desert_spacing.png,你會(huì)發(fā)現(xiàn)每個(gè)tiled元件之間都有1像素的黑邊.這樣的圖片需要將margin和spacing設(shè)置為1
        

         點(diǎn)擊OK,tiled元件將被顯示在Tilesets窗口內(nèi).現(xiàn)在你可以開(kāi)始繪制地圖了.點(diǎn)擊工具條上的Stamp(印章)圖標(biāo),選擇一個(gè)tiled元件,在地圖內(nèi)需要的位置點(diǎn)擊放置地圖元件.
         

          按上面的方法繪制一張地圖. 至少在地圖上繪制幾個(gè)建筑,因?yàn)楹竺嫖覀円玫剿鼈?
         

          一些快速技巧最好記住:
  • 你可以一次添加多個(gè)tiled元件到地圖里.(畫(huà)一個(gè)方塊選中多個(gè)tiled元件).
  • 可以使用油漆筒按鈕填充地圖背景.
  • 可以在view菜單里放大縮小地圖.
           畫(huà)好地圖后,雙擊Layers窗口里的層(一般是取名為L(zhǎng)ayer1),改名為Background.在File菜單內(nèi)選擇Save,將地圖保存到xcode項(xiàng)目?jī)?nèi),取名tiledmap.tmx

           將Tiled Map添加到Cocos2d Scene中,將剛才創(chuàng)建的tmx文件拖入項(xiàng)目resources內(nèi).打開(kāi)HelloWorldLayer.h文件,添加一些代碼:

#import "cocos2d.h"

// HelloWorld Layer
@interface HelloWorld : CCLayer
{
    CCTMXTiledMap 
*_tileMap;
    CCTMXLayer 
*_background;

}
@property (nonatomic, retain) CCTMXTiledMap 
*tileMap;
@property (nonatomic, retain) CCTMXLayer 
*background;
// returns a Scene that contains the HelloWorld as the only child
+(id) scene;

@end
            在HelloWorldLayer.m添加代碼:
// Import the interfaces
#import "HelloWorldScene.h"

// HelloWorld implementation
@implementation HelloWorld

// Right after the implementation section
@synthesize tileMap = _tileMap;
@synthesize background 
= _background;

// Replace the init method with the following
-(id) init
{
    
if( (self=[super init] )) {
       
        self.tileMap 
= [CCTMXTiledMap tiledMapWithTMXFile:@"TileMap.tmx"];
        self.background 
= [_tileMap layerNamed:@"Background"];
       
        [self addChild:_tileMap z:
-1];
       
    }
    
return self;
}

+(id) scene
{
    
// 'scene' is an autorelease object.
    CCScene *scene = [CCScene node];
   
    
// 'layer' is an autorelease object.
    HelloWorld *layer = [HelloWorld node];
   
    
// add layer as a child to scene
    [scene addChild: layer];
   
    
// return the scene
    return scene;
}

// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
    self.tileMap 
= nil;
    self.background 
= nil;
    [super dealloc];
}
@end

           這里我們調(diào)用CCTMXTiledMap從map文件創(chuàng)建了一個(gè)地圖.

          關(guān)于CCTMXTiledMap的一些簡(jiǎn)要介紹
  • 它是CCNode的子類(lèi).所以我們可以設(shè)置position, scale等.
  • 這個(gè)node包含著地圖的層,并且包含一些函數(shù)使你可以通過(guò)名字找到它們.
  • 為了提高性能,每一層使用的都是CCSpriteSheet的子 類(lèi). 這也意味著每個(gè)tiled元件在每一層都只有一個(gè)實(shí)例.
           接下來(lái)我們要做的是利用地圖和層的引用把他們添加到HelloWorld層,編譯運(yùn)行代碼,你將能夠看到地圖的左下角.
          

          看起來(lái)不錯(cuò)!不過(guò)作為一個(gè)游戲,我們還需要做三件事:
  1. 一個(gè)游戲主角;
  2. 一個(gè)放置主角的起始點(diǎn);
  3. 移動(dòng)視圖,讓我們的視角一直跟隨主角.
          這些才是開(kāi)發(fā)這個(gè)游戲關(guān)鍵工作,我們一個(gè)個(gè)解決.

對(duì)象層和設(shè)置Tiled Map的位置.
        Tiled Map Editor支持兩種層: tile layers(鋪展層,前面我們使用過(guò))和object layers(對(duì)象層).
        Object layers 允許你以一點(diǎn)為中心在地圖上圈定一個(gè)區(qū)域.這個(gè)區(qū)域內(nèi)可以觸發(fā)一些事件.比如:你可以制作一個(gè)區(qū)域來(lái)產(chǎn)生怪物,或者制作一個(gè)區(qū)域進(jìn)去就會(huì)死亡.在我們的例子里,我們制作一個(gè)區(qū)域作為主角的產(chǎn)生點(diǎn).


        打開(kāi)TiledMapEditor,在Layer菜單選擇Add Object Layer.新layer取名objects.注意,在object layer里不會(huì)繪制tiled元件,它會(huì)繪制一些灰色的圓角形狀.你可以展開(kāi)或者移動(dòng)這些形狀.
        我們是想選擇一個(gè)tile元件作為主角的進(jìn)入點(diǎn).所以,在地圖里點(diǎn)擊一個(gè)tiled元件,產(chǎn)生的形狀的大小無(wú)所謂,我們會(huì)使用x,y坐標(biāo)來(lái)指定.
        

        接下來(lái),右鍵選擇剛才添加的灰色形狀,點(diǎn)擊Properties.設(shè)置名字為 “SpawnPoint”

        也許你可以設(shè)置這個(gè)對(duì)象的Type為Cocos2D的類(lèi)名.并且它會(huì)創(chuàng)建一個(gè)對(duì)象(比如CCSprite),但是我沒(méi)有找到源代碼里如何完成這些工作.不管它,我們保留type區(qū)域?yàn)榭?它將創(chuàng)建一個(gè)NSMutableDictionary用來(lái)訪(fǎng)問(wèn)對(duì)象的各種參數(shù),比如x,y坐標(biāo).保存地圖回到xcode.

        修改HelloWorldScene.h
// Inside the HelloWorld class declaration
CCSprite *_player;
 
// After the class declaration
@property (nonatomic, retain) CCSprite *player;

        修改HelloWorldScene.m
// Right after the implementation section
@synthesize player = _player;
 
// In dealloc
self.player = nil;
 
// Inside the init method, after setting self.background
CCTMXObjectGroup *objects = [_tileMap objectGroupNamed:@"Objects"];
NSAssert(objects 
!= nil, @"'Objects' object group not found");
NSMutableDictionary 
*spawnPoint = [objects objectNamed:@"SpawnPoint"];        
NSAssert(spawnPoint 
!= nil, @"SpawnPoint object not found");
int x = [[spawnPoint valueForKey:@"x"] intValue];
int y = [[spawnPoint valueForKey:@"y"] intValue];
 
self.player 
= [CCSprite spriteWithFile:@"Player.png"];
_player.position 
= ccp(x, y);
[self addChild:_player];
 
[self setViewpointCenter:_player.position];

         我們先花一點(diǎn)時(shí)間解釋一下object layer和object groups.
                 首先,      我們通過(guò)CCTMXTiledMap對(duì)象的objectGroupNamed方法取回object layers.這個(gè)方法返回的是一個(gè)CCTMXObjectGroup對(duì)象.
                 接下來(lái),  調(diào)用CCTMXObjectGroup對(duì)象的objectNamed方法得到包含一組重要信息的NSMutableDictionary.包括x,y坐標(biāo),寬度,高度等.
                 在這里,  我們主要需要的是x,y坐標(biāo).我們?nèi)〉米鴺?biāo)并用它們來(lái)設(shè)置主角精靈的位置.
                 最后,      我們要把主角作為視覺(jué)中心來(lái)顯示.現(xiàn)在,添加下面的代碼:
-(void)setViewpointCenter:(CGPoint) position
{
    CGSize winSize 
= [[CCDirector sharedDirector] winSize];
 
    
int x = MAX(position.x, winSize.width / 2);
    
int y = MAX(position.y, winSize.height / 2);
    x 
= MIN(x, (_tileMap.mapSize.width * _tileMap.tileSize.width)
        
- winSize.width / 2);
    y 
= MIN(y, (_tileMap.mapSize.height * _tileMap.tileSize.height)
        
- winSize.height/2);
    CGPoint actualPosition 
= ccp(x, y);
 
    CGPoint centerOfView 
= ccp(winSize.width/2, winSize.height/2);
    CGPoint viewPoint 
= ccpSub(centerOfView, actualPosition);
    self.position 
= viewPoint;
 
}

        同樣做一下簡(jiǎn)要的解釋.想象這個(gè)函數(shù)是把視線(xiàn)設(shè)置到取景中心.我們可以在地圖里設(shè)置任何x,y坐標(biāo),但是有些坐標(biāo)不能正確的處理顯示.比如,我們不能讓顯示區(qū)域超出地圖的邊界.否則就會(huì)出現(xiàn)空白區(qū).下面的圖片更能說(shuō)明這個(gè)問(wèn)題:
        
        屏幕的寬高計(jì)算后,要與顯示區(qū)域的寬高做相應(yīng)的適配.我們需要檢測(cè)屏幕到達(dá)地圖邊緣的情況.
        在cocos2d里本來(lái)有一些操控camera(可以理解為可視取景區(qū))的方法,但是使用它可能搞得更復(fù)雜.還不如靠直接移動(dòng)layer里的元素來(lái)解決更簡(jiǎn)單有效.
        繼續(xù)看下面這張圖:
      

        把整張地圖想象為一個(gè)大的世界,我們的可見(jiàn)區(qū)是其中的一部分.主角實(shí)際的坐標(biāo)并不是世界實(shí)際的中心.但是在我們的視覺(jué)內(nèi),要把主角放在中心點(diǎn),所以,我們只需要根據(jù)主角的坐標(biāo)便宜,調(diào)整世界中心的相對(duì)位置就可以了.
        實(shí)現(xiàn)的方法是把實(shí)際中心與屏幕中心做一個(gè)差值,然后把HelloWorld Layer設(shè)置到相應(yīng)的位置.好,現(xiàn)在編譯運(yùn)行,我們會(huì)看到小忍者出現(xiàn)在屏幕上.
       

使主角移動(dòng)
        前面進(jìn)行的都不錯(cuò),但是到目前為止,我們的小忍者還不會(huì)動(dòng).
        接下來(lái),我們讓小忍者根據(jù)用戶(hù)在屏幕上點(diǎn)擊的位置方向來(lái)移動(dòng)(點(diǎn)擊屏幕上半部分向上移,依此類(lèi)推),修改HelloWorldScene.m的代碼:
// Inside init method
self.isTouchEnabled = YES;
 
-(void) registerWithTouchDispatcher
{
    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self
            priority:
0 swallowsTouches:YES];
}
 
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
    
return YES;
}
 
-(void)setPlayerPosition:(CGPoint)position {
    _player.position 
= position;
}
 
-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
 
    CGPoint touchLocation 
= [touch locationInView: [touch view]];      
    touchLocation 
= [[CCDirector sharedDirector] convertToGL: touchLocation];
    touchLocation 
= [self convertToNodeSpace:touchLocation];
 
    CGPoint playerPos 
= _player.position;
    CGPoint diff 
= ccpSub(touchLocation, playerPos);
    
if (abs(diff.x) > abs(diff.y)) {
        
if (diff.x > 0) {
            playerPos.x 
+= _tileMap.tileSize.width;
        } 
else {
            playerPos.x 
-= _tileMap.tileSize.width;
        }    
    } 
else {
        
if (diff.y > 0) {
            playerPos.y 
+= _tileMap.tileSize.height;
        } 
else {
            playerPos.y 
-= _tileMap.tileSize.height;
        }
    }
 
    
if (playerPos.x <= (_tileMap.mapSize.width * _tileMap.tileSize.width) &&
        playerPos.y 
<= (_tileMap.mapSize.height * _tileMap.tileSize.height) &&
        playerPos.y 
>= 0 &&
        playerPos.x 
>= 0 )
    {
            [self setPlayerPosition:playerPos];
    }
 
    [self setViewpointCenter:_player.position];
 
}

         首先,我們?cè)趇nit方法里設(shè)置屏幕接受觸摸事件.接下來(lái),覆蓋registerWithTouchDispatcher方法來(lái)注冊(cè)我們自己的觸摸 事件句柄.
這樣,ccTouchBegan/ccTouchEnded方法會(huì)在觸摸發(fā)生時(shí)回調(diào)(單點(diǎn)觸摸),并且屏蔽掉ccTouchesBegan /ccTouchesEnded方法的回調(diào)(多點(diǎn)觸摸)

         你可能奇怪,為什么不能使用ccTouchesBegan/ccTouchesEnded方法呢?是的,我們的確可以使用,但是不建議這么做,有兩點(diǎn)原因:
  • 你不需要再處理NSSets,事件分發(fā)器會(huì)幫你處理它們,你會(huì)在每次觸摸得到獨(dú)立的回調(diào).
  • 你可以在ccTouchBegan事件返回YES來(lái)告知delegate這事你想要的事件,這樣你可以在move/ended/cancelled等后續(xù)的事件里方便的處理.這比起使用多點(diǎn)觸摸要省去很多的工作.
          通常,我們會(huì)將觸摸的位置轉(zhuǎn)換為view坐標(biāo)系,然后再轉(zhuǎn)換為GL坐標(biāo)系.這個(gè)例子里的小變化,只是調(diào)用了一下 [self convertToNodeSpace:touchLocation].

          這是因?yàn)橛|摸點(diǎn)給我們的是顯示區(qū)的坐標(biāo),而我們其實(shí)已經(jīng)移動(dòng)過(guò)地圖的位置.所以,調(diào)用這個(gè)方法來(lái)得到便宜后的坐標(biāo).

          接下來(lái),我們要搞清楚觸摸點(diǎn)與主角位置的相對(duì)關(guān)系.然后根據(jù)向量的正負(fù)關(guān)系,決定主角的移動(dòng)方向.我們相應(yīng)的調(diào)節(jié)主角的位置,然后設(shè)置屏幕中心到主角上. 

          注意: 我們需要做一個(gè)安全檢查,不要讓我們的主角移出了地圖. 
         
          好了,現(xiàn)在可以編譯運(yùn)行了,嘗試觸摸屏幕來(lái)移動(dòng)一下小忍者吧.
         

        這里是根據(jù)這篇教程完成的代碼:猛擊這里下載

        接下來(lái),我們將學(xué)習(xí)如何在地圖里創(chuàng)建可碰撞(不可穿越)區(qū)域,如何使用tile屬性,如何使用可碰撞物體和動(dòng)態(tài)修改地圖,如何確定你的主角沒(méi)有產(chǎn)生穿越。

Tiled Maps和碰撞

        你可能注意到了,上一篇里完成的游戲,小忍者可以穿過(guò)各種障礙。它是忍者,不是上帝!所以,我們要想辦法讓地圖里的障礙物產(chǎn)生碰撞(不可穿越)。
有很多辦法可以解決這個(gè)問(wèn)題(包括使用對(duì)象層objects layers),但是我準(zhǔn)備告訴你種新技術(shù),我認(rèn)為這種技術(shù)更有效,同時(shí)也是作為學(xué)習(xí)課程的好素材。使用meta layer和層屬性。廢話(huà)少說(shuō),我們開(kāi)始吧。

        用Tiled Map Editor打開(kāi)之前創(chuàng)建的地圖,點(diǎn)擊Layer菜單的Add Tile Layer取名Meta。我們會(huì)在這一層上放置一些假的Tile指示特殊的tile元件。點(diǎn)擊Map菜單的New Tileset,選擇meta_tile.png圖片。將Margin和Spacing設(shè)置為1。
你會(huì)在Tilesets窗口看到meta_tiles的標(biāo)簽。
       

        這些tiles元件其實(shí)沒(méi)什么特別的,只是帶有透明特性的紅色和綠色方塊。我們擬定紅色表示“可碰撞”的(綠色的后面會(huì)用到)。選中Meta層,選擇印章(stamp)工具,選擇紅色tile元件。把它繪制到忍者不能穿越的地方。繪制好之后,看起來(lái)應(yīng)該是這樣的:
       

       接下來(lái),我們要給這些Tile元件設(shè)置一些標(biāo)記屬性,這樣在代碼里我們可以確定哪些tile元件是不可穿越的。在Tilesets窗口里右鍵點(diǎn)擊紅色tile元件。添加一個(gè)新的屬性Collidable”,設(shè)置值為true。
     
      保存地圖,回到xcode。修改HelloWorldScene.h文件。
// Inside the HelloWorld class declaration
CCTMXLayer *_meta;
 
// After the class declaration
@property (nonatomic, retain) CCTMXLayer *meta;
[\cc]
修改HelloWorldScene.m文件
[cc lang
="objc"]
// Right after the implementation section
@synthesize meta = _meta;
 
// In dealloc
self.meta = nil;
 
// In init, right after loading background
self.meta = [_tileMap layerNamed:@"Meta"];
_meta.visible 
= NO;
 
// Add new method
- (CGPoint)tileCoordForPosition:(CGPoint)position {
    
int x = position.x / _tileMap.tileSize.width;
    
int y = ((_tileMap.mapSize.height * _tileMap.tileSize.height) - position.y) / _tileMap.tileSize.height;
    
return ccp(x, y);
}

        簡(jiǎn)單的對(duì)上面的代碼做一些解釋。我們定義了一個(gè)CCTMXLayer對(duì)象meta作為類(lèi)成員。注意,我們將這個(gè)層設(shè)置為不可見(jiàn),因?yàn)樗皇怯脕?lái)處理碰撞的。
        接下來(lái)我們編寫(xiě)了一個(gè)tileCoordForPosition方法,用來(lái)將x,y坐標(biāo)轉(zhuǎn)換為地圖網(wǎng)格坐標(biāo)。地圖左上角為(0,0)右下角為(49,49)。

        上面帶有坐標(biāo)顯示的截圖來(lái)自java版本的編輯器。順便說(shuō)一聲,我覺(jué)得在Qt版本里這個(gè)功能可能不再會(huì)被移植了。
        不管怎么樣,用地圖網(wǎng)格坐標(biāo)要比用x,y坐標(biāo)方便。得到x坐標(biāo)比較方便,但是y坐標(biāo)有點(diǎn)麻煩,因?yàn)樵赾ocos2d里,是以左下作為原點(diǎn)的。也就是說(shuō),y坐標(biāo)的向量與地圖網(wǎng)格坐標(biāo)是相反的。
        接下來(lái),我們要修改一下setPlayerPosition方法。
CGPoint tileCoord = [self tileCoordForPosition:position];
int tileGid = [_meta tileGIDAt:tileCoord];
if (tileGid) {
    NSDictionary 
*properties = [_tileMap propertiesForGID:tileGid];
    
if (properties) {
        NSString 
*collision = [properties valueForKey:@"Collidable"];
        
if (collision && [collision compare:@"True"== NSOrderedSame) {
            
return;
        }
    }
}
_player.position 
= position;

        這里,我們將主角的坐標(biāo)系從x,y坐標(biāo)(左下原點(diǎn))系轉(zhuǎn)換為tile坐標(biāo)系(左上原點(diǎn))。接下來(lái),我們使用meta layer里的tileGIDAt函數(shù)獲取tile坐標(biāo)系里的GID。噢?什么是GID? GID應(yīng)該是“全局唯一標(biāo)識(shí)”(我認(rèn)為).但是在這個(gè)例子里,把它作為tile層的id更貼切。

        我們使用GID來(lái)查找tile層的屬性,返回值是一個(gè)包含屬性列表的dictionary。我們檢查“Collidable”屬性是否設(shè)置為ture。如果是,則說(shuō)明不可以穿越。很好,編譯運(yùn)行工程,你再也不能走入你在tile里設(shè)置為紅色的區(qū)域了。
        

動(dòng)態(tài)改變Tiled Maps

        現(xiàn)在,你的小忍者可以在地圖上漫游了,不過(guò),整個(gè)游戲還是略顯沉悶。
        假設(shè)我們的小忍者非常餓,那么我們?cè)O(shè)置一些食物,讓小忍者可以找到并吃掉它們。

        為了實(shí)現(xiàn)這個(gè)想法,我們要?jiǎng)?chuàng)建一個(gè)前端層,承載所有用于觸碰(吃掉)的物體。這樣,我們可以在忍者吃掉它們的同時(shí),方便的從層上刪除它。并且背景層不受任何影響。

       打開(kāi)Tiled Map Editor,Layer菜單的Add Tile Layer。命名新層為Foreground。選中這個(gè)層,添加一些可觸碰的物件。我比較喜歡用西瓜。
      

      接下來(lái),要讓西瓜變?yōu)榭捎|碰的。這次我們用綠色方塊來(lái)標(biāo)記。記得要在meta_tiles里做這件事。
      

      同樣的,給綠色方塊添加屬性“Collectable”設(shè)置值為 “True”.
      保存地圖,回到xcode。修改代碼:
//in HelloWorldScene.h:
// Inside the HelloWorld class declaration
CCTMXLayer *_foreground;
 
// After the class declaration
@property (nonatomic, retain) CCTMXLayer *foreground;

//in HelloWorldScene.m
// Right after the implementation section
@synthesize foreground = _foreground;
 
// In dealloc
self.foreground = nil;
 
// In init, right after loading background
self.foreground = [_tileMap layerNamed:@"Foreground"];
 
// Add to setPlayerPosition, right after the if clause with the return in it
NSString *collectable = [properties valueForKey:@"Collectable"];
if (collectable && [collectable compare:@"True"== NSOrderedSame) {
    [_meta removeTileAt:tileCoord];
    [_foreground removeTileAt:tileCoord];
}

        這里有個(gè)基本的原則,要同時(shí)刪除meta layer 和the foreground layer的匹配對(duì)象。編譯運(yùn)行,小忍者可以吃到美味的甜西瓜了。
       

創(chuàng)建分?jǐn)?shù)計(jì)數(shù)器
        小忍者現(xiàn)有吃有喝很開(kāi)心,但是,我們想知道到底他吃了多少個(gè)西瓜。
        通常,我們?cè)趌ayer上看著順眼的地方加個(gè)label來(lái)顯示數(shù)量。但是,我們一直在移動(dòng)層,這樣會(huì)給我們帶來(lái)很多的困擾。
        這是一個(gè)演示在一個(gè)場(chǎng)景里使用多個(gè)層的好例子。我們保留HelloWorld層來(lái)進(jìn)行游戲,同時(shí),增加一個(gè)HelloWorldHud層用來(lái)顯示label(Hub = heads up display)。
        當(dāng)然,這兩個(gè)層需要一些方法來(lái)互相通訊。Hub層需要知道小忍者吃到了西瓜。有很多很多方法實(shí)現(xiàn)兩個(gè)層之間的通信,但是我們使用盡量簡(jiǎn)單的方法來(lái)實(shí)現(xiàn)。我 們會(huì)讓HelloWorld層管理一個(gè)HelloworldHub層的引用,在忍者遲到西瓜的時(shí)候,可以調(diào)用一個(gè)方法來(lái)通知Hub層。修改代碼:
// HelloWorldScene.h
// Before HelloWorld class declaration
@interface HelloWorldHud : CCLayer
{  
    CCLabel 
*label;
}
 
- (void)numCollectedChanged:(int)numCollected;
@end
 
// Inside HelloWorld class declaration
int _numCollected;
HelloWorldHud 
*_hud;
 
// After the class declaration
@property (nonatomic, assign) int numCollected;
@property (nonatomic, retain) HelloWorldHud 
*hud;

// HelloWorldScene.m
// At top of file
@implementation HelloWorldHud
 
-(id) init
{
    
if ((self = [super init])) {
        CGSize winSize 
= [[CCDirector sharedDirector] winSize];
        label 
= [CCLabel labelWithString:@"0" dimensions:CGSizeMake(5020)
            alignment:UITextAlignmentRight fontName:
@"Verdana-Bold"
            fontSize:
18.0];
        label.color 
= ccc3(0,0,0);
        
int margin = 10;
        label.position 
= ccp(winSize.width - (label.contentSize.width/2)
            
- margin, label.contentSize.height/2 + margin);
        [self addChild:label];
    }
    
return self;
}
 
- (void)numCollectedChanged:(int)numCollected {
    [label setString:[NSString stringWithFormat:
@"%d", numCollected]];
}
 
@end
 
// Right after the HelloWorld implementation section
@synthesize numCollected = _numCollected;
@synthesize hud 
= _hud;
 
// In dealloc
self.hud = nil;
 
// Add to the +(id) scene method, right before the return
HelloWorldHud *hud = [HelloWorldHud node];    
[scene addChild: hud];
 
layer.hud 
= hud;
 
// Add inside setPlayerPosition, in the case where a tile is collectable
self.numCollected++;
[_hud numCollectedChanged:_numCollected];

        沒(méi)什么稀奇的,第二個(gè)層繼承CCLayer,并且在右下角添加了一個(gè)label。我們將第二個(gè)層添加到場(chǎng)景(Scene)里并且把hub層的引用傳遞給HelloWorld層。然后修改HelloWorld層調(diào)用通知計(jì)數(shù)改變的方法。
編譯運(yùn)行,應(yīng)該可以在右下角看到吃瓜計(jì)數(shù)器了。

音效和音樂(lè)
        眾所周知,沒(méi)有音效和音樂(lè)的游戲,稱(chēng)不上是個(gè)完整的游戲。接下來(lái),我們做一些簡(jiǎn)單的修改,讓我們的游戲帶有音效和背景音。

// HelloWorldScene.m
// At top of file
#import "SimpleAudioEngine.h"
 
// At top of init for HelloWorld layer
[[SimpleAudioEngine sharedEngine] preloadEffect:@"pickup.caf"];
[[SimpleAudioEngine sharedEngine] preloadEffect:
@"hit.caf"];
[[SimpleAudioEngine sharedEngine] preloadEffect:
@"move.caf"];
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:
@"TileMap.caf"];
 
// In case for collidable tile
[[SimpleAudioEngine sharedEngine] playEffect:@"hit.caf"];
 
// In case of collectable tile
[[SimpleAudioEngine sharedEngine] playEffect:@"pickup.caf"];
 
// Right before setting player position
[[SimpleAudioEngine sharedEngine] playEffect:@"move.caf"];

接下來(lái)做點(diǎn)什么呢?
        通過(guò)這篇教程,你應(yīng)該對(duì)coco2d有了一些基本的了解。
        這里是按照整篇教程完成的工程文件,猛擊這里下載
        如果你感興趣,我的好朋友Geek和Dad編寫(xiě)了一篇后續(xù)教程:Enemies and Combat: How To Make a Tile-Based Game with Cocos2D Part 3! 。這篇教程將告訴你,如何在游戲里添加敵人,武器,勝負(fù)場(chǎng)景等。



Feedback

# HPy4Si , [url=http://oshykvrddhqi.com/]oshykvrddhqi[/url], [link=http://uqxsjxdqwiaw.com/]uqxsjxdqwiaw[/link], http://kbyunqckswea.com/  回復(fù)  更多評(píng)論   

2011-05-27 01:38 by kkngqcfgz
HPy4Si , [url=http://oshykvrddhqi.com/]oshykvrddhqi[/url], [link=http://uqxsjxdqwiaw.com/]uqxsjxdqwiaw[/link], http://kbyunqckswea.com/

只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            99视频精品全部免费在线| 欧美在线观看一区二区三区| 久久精品99国产精品| 亚洲作爱视频| 一道本一区二区| 亚洲影音先锋| 久久精品国产清高在天天线 | 亚洲最新在线| 亚洲欧美国产精品va在线观看| 午夜亚洲视频| 久久只精品国产| 亚洲精品一二| 午夜亚洲激情| 欧美二区在线播放| 国产精品欧美激情| 亚洲高清在线视频| 亚洲一卡久久| 麻豆国产精品777777在线| 亚洲精品一线二线三线无人区| 亚洲欧美综合网| 欧美va亚洲va香蕉在线| 国产精品免费区二区三区观看| 国色天香一区二区| 夜夜嗨av一区二区三区中文字幕| 欧美一区二区高清| 亚洲国产婷婷香蕉久久久久久| 欧美激情亚洲激情| 亚洲小视频在线观看| 老牛影视一区二区三区| 国产噜噜噜噜噜久久久久久久久| 亚洲国产精品一区在线观看不卡 | 欧美在线日韩精品| 亚洲高清一二三区| 久久爱www.| 国产精品国产三级国产aⅴ9色| 尤物yw午夜国产精品视频明星| 亚洲视频免费在线观看| 欧美 日韩 国产在线| 亚洲专区欧美专区| 欧美精品在线播放| 亚洲国产成人精品女人久久久| 欧美一区二区三区视频| 一区二区三区欧美成人| 欧美黑人在线观看| 亚洲高清久久网| 久久久综合网站| 午夜亚洲性色视频| 国产精品日韩欧美一区二区三区| 99av国产精品欲麻豆| 欧美顶级艳妇交换群宴| 久久久久久黄| 精品1区2区3区4区| 久久久99爱| 销魂美女一区二区三区视频在线| 亚洲欧洲视频在线| 欧美va亚洲va香蕉在线| 在线观看的日韩av| 久久一区国产| 久久嫩草精品久久久精品| 国产日韩欧美一区二区三区在线观看 | 久久青草久久| 国产一区二区丝袜高跟鞋图片 | 久久成人羞羞网站| 欧美亚洲网站| 黄色成人在线网站| 免费日韩视频| 麻豆国产va免费精品高清在线| 欧美区国产区| 农村妇女精品| 亚洲私人影院在线观看| 国产乱码精品一区二区三区av| 欧美二区不卡| 亚洲大片一区二区三区| 欧美伊久线香蕉线新在线| 亚洲欧美一区二区原创| 欧美天天视频| 在线视频精品一区| 一区二区欧美激情| 欧美大片国产精品| 亚洲国产天堂久久国产91| 91久久精品国产91性色| 老司机亚洲精品| 99re6这里只有精品| 久久国产夜色精品鲁鲁99| 亚洲精品中文字幕在线观看| 亚洲高清不卡在线| 欧美激情综合五月色丁香小说| 一本一本久久a久久精品综合麻豆| 亚洲精选91| 国产精品一区一区| 久久综合伊人77777麻豆| 欧美sm视频| 欧美在线视频a| 欧美福利网址| 午夜精品视频在线观看| 久久久久免费观看| 在线亚洲激情| 久久久久国色av免费观看性色| 亚洲免费电影在线| 午夜精品美女久久久久av福利| 亚洲丶国产丶欧美一区二区三区| 日韩视频一区二区在线观看| 亚洲一区二区精品视频| 一区二区三区在线免费视频| 亚洲国产欧美国产综合一区| 国产精品欧美风情| 亚洲韩国精品一区| 国产一在线精品一区在线观看| 亚洲国产日韩欧美在线图片| 国产日韩欧美高清免费| 亚洲狼人综合| 亚洲福利专区| 欧美一区二区黄| 亚洲一区二区三区高清 | 在线日韩一区二区| 亚洲在线播放电影| 一本久久综合| 免费影视亚洲| 另类春色校园亚洲| 国产精品三级久久久久久电影| 亚洲人成啪啪网站| 亚洲国产成人精品久久| 午夜精品久久久久影视| 午夜久久久久| 国产精品福利在线观看网址| 亚洲国产精品久久久久秋霞影院| 激情久久久久| 久久av一区二区三区| 欧美一二三区在线观看| 国产精品v日韩精品| 日韩视频久久| 国产精品99久久99久久久二8| 免费成年人欧美视频| 玖玖综合伊人| 在线观看日韩av电影| 久久久久久久综合日本| 欧美xx视频| 亚洲国产精品女人久久久| 久久午夜精品一区二区| 男人的天堂成人在线| 亚洲电影在线| 免费人成精品欧美精品| 亚洲高清在线播放| 日韩一区二区高清| 欧美巨乳波霸| 在线视频欧美日韩精品| 亚洲欧美色一区| 国产欧美欧美| 久久久精品国产免大香伊 | 樱花yy私人影院亚洲| 久久免费午夜影院| 亚洲国语精品自产拍在线观看| 99re6这里只有精品视频在线观看| 欧美精品videossex性护士| 亚洲精品一线二线三线无人区| 亚洲新中文字幕| 国产欧美日本一区二区三区| 久久婷婷国产综合国色天香| 亚洲电影免费在线观看| 亚洲小视频在线| 国产亚洲成年网址在线观看| 久久久91精品国产| 亚洲激精日韩激精欧美精品| 亚洲一区图片| 影音先锋日韩资源| 欧美日韩p片| 欧美亚洲视频在线看网址| 99国产精品99久久久久久粉嫩| 欧美精品免费看| 亚洲欧美日韩在线| 欧美高清在线一区二区| 亚洲一二三区精品| 狠狠爱综合网| 欧美日韩免费在线| 久久成人免费电影| 亚洲日韩欧美视频一区| 久久国产精品99精品国产| 亚洲国产精品福利| 国产毛片一区二区| 欧美久久一级| 六月婷婷久久| 香蕉成人啪国产精品视频综合网| 欧美韩日视频| 久久精品视频一| 亚洲午夜影视影院在线观看| 亚洲国产成人在线播放| 国产精品亚洲а∨天堂免在线| 免费看成人av| 久久久久久久久岛国免费| 亚洲私人影院| 亚洲精品一区二区网址| 欧美成人一区在线| 欧美尤物巨大精品爽| 亚洲手机在线| 日韩视频免费在线观看| 在线播放中文字幕一区| 国产欧美视频一区二区| 国产精品theporn| 欧美日韩免费精品| 欧美人与禽性xxxxx杂性|