1. 如何優化cocos2d程序的內存使用和程序大小
避免一個接一個地載入PNG和JPG紋理(他們之間至少等待一幀)
cocos2d裡面紋理載入分為兩個階段:1.從圖片文件中創建一個UIImage對象。2.以這個創建好的UIImage對象來創建
CCTexture2D對象。這意味著,當一個紋理被載入的時候,在短時候內,它會消耗兩倍於它本身內存佔用的內存大小。(譯註:為什麼只是短時間內呢?
因為autoRelease pool和引用計數的關系,臨時創建的UIImage對象會被回收。)
當你在一個方法體內,接二連三地載入4個紋理的時候,這個內存問題會變得更加糟糕。因為在這個方法還沒結束之前,每一個紋理都會消耗兩倍於它本身的內存。
我不是很確定,現在的cocos2d是否仍然如此。或者這種情況是否只適用於手工引用計數管理,或許ARC不會如此呢?我習慣於按順序載入紋理,但是在加
載下一個紋理之前要等待一幀。這將會使得任何紋理載入的消耗對內存的壓力降低。因為等待一幀,引用計數會把臨時的UIImage對象釋放掉,減少內存壓
力。此外,在後續的文章中,如果你想在背景線程中按序載入紋理的話,也可以採用這種方法。
不要使用JPG圖片!
cocos2d-iphone使用JPG紋理的時候有一個問題。因為JPG紋理在載入的時候,會實時地轉化為PNG格式的紋理。這意味著cocos2d-iphone載入紋理是非常慢的(這里有演示),而且JPG紋理將消耗三倍於本身內存佔用大小的內存。
一個2048*2048大小的紋理會消耗16M的內存。當你載入它的時候,在短時間內,它將消耗32MB內存。現在,如果這個圖片是JPG格式,你會看到
這個數字會達到48MB,因為額外的UIImage對象的創建。雖然,最終內存都會降到16M,但是,那一個時刻的內存飆高,足以讓os殺死你的游戲進
程,造成crash,影響用戶體驗。
JPG不論在載入速度和內存消耗方面都很差。所以,千萬不要使用JPG!
忽視文件圖片大小
這種情況,我見到很多。它乍聽起來可能覺得有點荒誕,但事實如此,因為它需要關於文件格式的知識,而這些知識並不是每一個程序員都了解的。我經常聽到的論斷就是「嘿!我的程序不可能有內存警告,我所有的圖片資源加起來還不到30MB!」。
怎麼說呢,因為圖片文件大小和紋理內存佔用是兩碼事。假設他們是帳篷。圖片文件就相當於帳篷被裝在行李箱。但是,如果你想要使用帳篷的話,它必須被撐起來,被「膨脹」。
圖片文件和紋理的關系與此類似。圖片文件大多是壓縮過的,它們被使用的話必須先解壓縮,然後才能會GPU所處理,變成我們熟知的紋理。一個
2048*2048的png圖片,採用32位顏色深度編碼,那麼它在磁碟上佔用空間只有2MB。但是,如果變成紋理,它將消耗16MB的內存!
當然,減少紋理佔用內存大小是有辦法滴。
使用16-bit紋理
最快速地減少紋理內存佔用的辦法就是把它們作為16位顏色深度的紋理來載入。cocos2d默認的紋理像素格式是32位顏色深度。如果把顏色深度減半,那麼內存消耗也就可以減少一半。並且這還會帶來渲染效率的提升,大約提高10%。
你可以使用CCTexture2D對象的類方法setDefaultAlphaPixelFormat來更改默認的紋理像素格式,代碼如下:
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGB5A1];
[[CCTextureCache sharedTextureCache] addImage:@"ui.png"];
這里有個問題:首先,紋理像素格式的改變會影響後面載入的所有紋理。因此,如果你想後面載入紋理使用不同的像素格式的話,必須再調用此方法,並且重新設置一遍像素格式。
其次,如果你的CCTexture2D設置的像素格式與圖片本身的像素格式不匹配的話,就會導致顯示嚴重失真。比如顏色不對,或者透明度不對等等。
有哪些比較有用的紋理像素格式呢?
generate 32-bit textures: kCCTexture2DPixelFormat_RGBA8888 (default)
generate 16-bit textures: kCCTexture2DPixelFormat_RGBA4444
generate 16-bit textures: kCCTexture2DPixelFormat_RGB5A1
generate 16-bit textures: kCCTexture2DPixelFormat_RGB565 (no alpha)
RGBA8888是默認的格式。對於16位的紋理來說,使用RGB565可以獲得最佳顏色質量,因為16位全部用來顯示顏色:總共有65536總顏色值。
但是,這里有個缺點,除非圖片是矩形的,並且沒有透明像素。所以RBG565格式比較適合背景圖片和一些矩形的用戶控制項。
RBG5A1格式使用一位顏色來表示alpha通道,因此圖片可以擁有透明區域。只是,1位似乎有點不夠用,它只能表示32768種可用顏色值。而且圖片
要麼只能全部是透明像素,或者全部是不透明的像素。因為一位的alpha通道的緣故,所以沒有中間值。但是你可以使用fade
in/out動作來改變紋理的opacity屬性。
如果你的圖片包含有半透明的區域,那麼RBGA4444格式很有用。它允許每一個像素值有127個alpha值,因此透明效率與RGBA8888格式的紋理差別不是很大。但是,由於顏色總量減少至4096,所以,RBGA4444是16點陣圖片格式裡面顏色質量最差的。
現在,你可以得到16位紋理的不足之處了:它由於顏色總量的減少,有一些圖片顯示起來可能會失真,而且可能會產生「梯度」。
使16位紋理看起來更棒
幸運的是,我們有TexturePacker.(後面簡稱TP)
TP有一個特性叫做「抖動」,它可以使得原本由於顏色數量減少而產生的失真問題得到改善。(TP裡面有很多抖動演算法,關於這些演算法,讀者可以參考我翻譯的另一篇文章)。
特別是在擁有Retina顯示的像素密度下,你幾乎看不出16位與32位的紋理之間的顯示差別。當然,前提是你需要採用「抖動」演算法。
cocos2d默認的顏色深度將會把所有的紋理都渲染到16位的color
framebuffer裡面,然後再顯示到你的設備屏幕上面。既然這樣,我們為什麼不把所有的紋理的格式都弄成16位呢,32位又有什麼用呢?反正它本來
就會渲染到16位的framebuffer上去的。這個問題有點太底層了,我不想深挖下去,而且我也不適合解釋這個問題。(譯者:哈哈,知之為知之,不知
為不知)
使用NPOT紋理
NOPT是「non power of two」的縮寫,譯作「不是2的冪」。NPOT stands for 「non power of
two」. 在cocos2d1.x的時候,你必須在ccConfig.h文件中開啟對NPOT的支持,但是,cocos2d
2.x就不需要了,它默認是支持NPOT的。所有3代(iphone 3GS)以後的ios設置都支持cocos2d 2.x(因為它們支持OpenGL
ES2.0),所以也都能支持NPOT紋理。
如果紋理圖集(texture
atlas)使用NPOT的紋理,它將有一個具大的優勢:它允許TP更好地壓縮紋理。因此,我們會更少地浪費紋理圖集的空白區域。而且,這樣的紋理在載入
的時候,會少使用1%到49%左右的內存。而且你可以使用TP強制生成NPOT的紋理。(你只需要勾選「allow free size」即可)
為什麼要關心NPOT呢?因為蘋果的OpenGL驅動有一個bug,導致如果使用POT的紋理,則會產生額外33%的內存消耗。
默認使用PVR格式的紋理
TP讓你可以創建PVR格式的紋理。除了PVR紋理支持NPOT外,它們不僅可以不是2的冪,而且還可以不是方形的。
PVR是最靈活的紋理文件格式。除了支持標準的未壓縮的RGB圖片格式外,支持有損壓縮的pvrtc格式。另外,未壓縮的pvr格式的紋理的內存消耗非常
地低。不像png圖片那樣要消耗2倍於本身內存佔用大小的內存,pvr格式只需要消耗紋理本身內存大小再加上一點點處理該圖片格式的內存大小。
pvr格式的一個缺點就是,你不能在Mac上面打開查看。但是,如果你安裝了TP的話,就可以使用TP自帶的pvr圖片瀏覽器來瀏覽pvr格式的圖片了。(強烈建議大家購買TP,支持TP,不要再盜版了)
使用PVR格式的文件幾乎沒有缺點。此外,它還可以極大地提高載入速度,後面我會解釋到。
使用pvr.ccz文件格式
在三種可選用的pvr文件格式中,優先選擇pvr.ccz格式。它是專門為cocos2d和TP設計的。在TP裡面,這是它生成的最小的pvr文件。而且pvr.ccz格式比其它任何文件格式的載入速度都要快。
當在cocos2d裡面使用pvr格式的紋理時,只使用pvr.ccz格式,不要使用其它格式!因為它載入速度超快,而且載入的時候使用更少的內存!
當視覺察覺不出來的時候,可以考慮使用PVRTC壓縮
PVR紋理支持PVRTC紋理壓縮格式。它主要是採用的有損壓縮。如果拿PVRTC圖片與JPG圖片作對比的話,它只有JPG圖片中等質量,但是,最大的好處是可以不用在內存裡面解壓縮紋理。
這里把32位的png圖片(左邊)與最佳質量的PVRTC4(4位)圖片(點擊圖片查看完整的大小)作對比:
注意,在一些高對比度的地方,明顯有一些瑕疵。有顏色梯度的地方看起來還好一點。
PVRTC肯定不是大部分游戲想要採用的紋理格式。但是,它們對於粒子效果來說,非常適用。因為那些小的粒子在不停地移動、旋轉、縮放,所以你很難看出一些視覺瑕疵。
PVRTC壓縮圖片格式
TP提供的PVR格式不僅有上面兩種,還包括TC2和TC4這兩種沒有alpha通道的格式。
這里的alpha和16位紋理的alpha是一樣的。沒有alpha通道意味著圖片裡面沒有透明像素,但是,更多的顏色位會用來表示顏色,那麼顏色質量看起來也會更好一些。
有時候,PVRTC圖片格式指的是使用4位或者2位顏色值 ,但是,並不完全是那樣。PVRTC圖片格式可以編碼更多的顏色值。
預先載入所有的紋理
就像標題所說,盡你所能,一定要預先載入所有的紋理。如果你的所有的紋理加起來不超過80MB內存消耗的話(指的是擁有Retina顯示的設備,非Retina的減半考慮),你可以在第一個loading場景的時候就全部載入進來。
這樣做最大的好處在於,你的游戲體驗會表現得非常平滑,而且你不需要再擔心資源的載入和卸載問題了。
這樣也使得你可以讓每一個紋理都使用合適的紋理像素格式,而且可以更方便地找出其它與紋理無關的內存問題。因為如果與紋理有關,那麼在第一次載入所有的紋
理的時候,這個問題就會暴露出來的。如果所有的紋理都載入完畢,這時候再出現內存問題,那麼肯定就與紋理無關了,而是其它的問題了。
如果你知道問題與紋理無關的話,那麼你查找剩下的內存問題將會變得更加簡單。而且你避免了前面說的這種情況:當2048*2048的紋理載入的時候,它本
來只需要消耗16MB內存,但是短時間會沖到32MB內存。後面會提出一種方法來解決「間歇性內存飆高」(「譯者發明滴」)的方法。(譯者:希望下次開發
者的對話中「間歇性內存飆高」的說法會出現,呵呵)
按照紋理size從大到小的順序載入紋理
由於載入紋理時額外的內存消耗問題,所以,採用按紋理size從大到小的方式來載入紋理是一個最佳實踐。
假設,你有一個占內存16MB的紋理和四個佔用內存4MB的紋理。如果你首先載入4MB的紋理,這個程序將會使用16MB的內存,而當它載入第四張紋理的
時候,短時間內會飆到20MB。這時,你要載入16MB的那個紋理了,內存會馬上飆到48MB(4*4 + 16*2),然後再降到32MB(4*4 +
16)。
但是,反過來,你先載入16MB的紋理,然後短時候內飆到32MB。然後又降到16MB。這時候,你再依次載入剩下的4個4MB的,這時,最多會彪到(4*3 + 4*2 + 16=36)MB。
在這兩種情況下,內存的峰值使用相差12MB,要知道,可能就是這12MB會斷送你的游戲進程的小命哦!
避免在收到內存警告消息的時候清除緩存
我有時候看到了一種奇怪的「自己開槍打自己的腳」的行為:紋理已經全部在Loading場景裡面載入完畢了,這時候,內存警告發生了,然後cocos2d就會把沒有使用的紋理從緩存中釋放掉。
聽起來不錯,沒有使用到的紋理都被釋放掉了,但是!。。。
你剛剛把所有的紋理都載入進來,還沒有進入任何一個場景中(此時所有的紋理都被當作「unused」),但是馬上被全部從texture
cache中移除出去。可是,你又需要在其它場景中使用它們。怎麼辦?你需要接著判斷,如果有紋理沒有載入,就繼續載入。但是,一載入,由於「間歇性內存
飆高」,又馬上收到了內存警告,再釋放,再判斷,再載入。。。。
我的天,這是一個死循環啊!這也能解釋為什麼有些童鞋,在loading場景完了之後進入下一個場景 的時候很卡的原因了。
現在,當我收到內存警告的時候,我的做法是----什麼也不做。內存警告仍然在發生,但是,它只是在程序剛開始載入的時候。我知道這是為什麼,因為「間歇
性內存飆高」嘛,所以,我不去管它。(但是,如果是游戲過程中再收到內存警告,你就要注意了,因為這時候可能你有內存泄漏了!!!)
我有時候會想辦法改善一下,通過移除掉一些不使用的紋理和一些只有在很特殊的場景才會使用的圖片(比如settings界面,玩家是不經常訪問的)。然
後,不管什麼時候,當我需要某張圖片的時候,我會首先檢查一下該sprite
frame是否在cache中,如果沒有就載入。你會在後面看到具體的做法。
理解在什麼時候、在哪裡去清除緩存
不要隨機清除緩存,也可以心想著釋放一些內存而去移除沒有使用的紋理。那不是好的代碼設計。有時候,它甚至會增加載入次數,並多次引發「間歇內存飆高」。分析你的程序的內存使用,看看內存裡面到底有什麼,以及什麼應該被清除,然後只清除該清除的。
你可以使用mpCachedTextureInfo方法來觀察哪些紋理被緩存了:
[[CCTextureCache sharedTextureCache] mpCachedTextureInfo];
2. 求cocos2d-x大神,這個ccBlendFunc怎麼用
因為這個函數不是用來去黑底的,而是用來正片疊底的。
想要有效果就必須在HelloWorld.png下面再加一張不是黑色的背景圖。
比如這樣:
CCSprite*bg=CCSprite::create("bg.png");//白色或其他顏色的背景,黑色的會沒效果
bg->setPosition(ccp(240,160));
this->addChild(bg,0);
CCSprite*p=CCSprite::create("HelloWorld.png");
p->setPosition(ccp(240,160));
this->addChild(p,1);
ccBlendFunccb={GL_ONE,GL_ZERO};
p->setBlendFunc(cb);
3. 開發iphone的游戲時,怎麼把游戲背景設置自己想要的圖片求代碼參考
lz用什麼引擎的?cocos2d?如果是的話就是載入一幅與游戲區域等大小的圖片即可 。
那更簡單了,別用導航欄,同時隱藏狀態欄,弄一個imageView弄的和游戲場景一樣大,載入一個圖片放到最底層就好了
回復 zhuxurong123:這個就要用到touchesmoved(好像叫這個,你看看api)。通過這個方法的參數可以獲得手指在屏幕上的位置,每次手指移動都會調用這個方法。在這個方法里記錄下每次手指的位置然後對你想要移動的uiview或其子類創建一個移動動畫(在動畫開始前記得停止本view的所有動畫,否則移動路徑就亂了),這樣做可以做出view跟隨手指移動的效果,或者更簡單一點,通過手指位置坐標點直接設置view坐標,也可以達到view隨手指移動的效果
#pragma mark - Finger Move View
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSArray *pointArray = [touches allObjects];
UITouch *touch = [pointArray objectAtIndex:0];
CGPoint pointInView = [touch locationInView:self.view];
self.curView.center = pointInView;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSArray *pointArray = [touches allObjects];
UITouch *touch = [pointArray objectAtIndex:0];
CGPoint pointInView = [touch locationInView:self.view];
self.curView.center = pointInView;
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIView *newView = [[UIView alloc] initWithFrame:CGRectMake(0.f, 0.f, 60.f, 60.f)];
newView.backgroundColor = [UIColor orangeColor];
self.curView = newView;
[self.view addSubview:newView];
newView = nil;
}
4. 如何使用cocos2d製作一個太空射擊游戲
在這個教程裡面,你將會學習到如何開發一個太空射擊游戲!
你可以使用加速計(重力感應)來控制飛船的移動,並且可以點擊屏幕來發射激光武器。
如果你對於如何製作基於cocos2d-x3.0的游戲完全陌生的話,這個教程可以幫助你!你將會學習到,如何從頭至尾構建一個完整的游戲,不需要任何的經驗!
假如你對cocos2d-x3.0編程完全陌生的話,那麼你可能需要先學習一下相關的教程了。
這個教程對於中級開發者來說也非常好,因為它覆蓋了一些比較高級的主題,比如視差滾動(parallax scrolling),預分配Node,加速計移動以及粒子系統的使用。
話不多說,直入主題!
添加相關資源文件
為了做這樣一個手機游戲,你將需要一些跟太空主題相關的圖片資源和聲音資源。
你可以直接下載我老婆製作的太空游戲資源。
因此,請直接下載吧,並且把它解壓到你的項目的Resources目錄下面去。
如果你很好奇,你可以隨便看看你剛剛向工程裡面添加進去了一些什麼東西。下面是完整的內容列表:
Backgrounds: 一些背景圖片,你等下會使用它們來製作一個滾動背景。裡麵包含星系,太陽,和空間異常(它移動速度比較慢),還有一組空間塵埃圖片(它們會出現在背景前面,而且會移動地稍微快一點)
Fonts: 使用 Glyph Designer製作的點陣圖字體,我們將使用這些字體來在游戲中顯示文字。
Particles: 使用 Particle Designer製作的一些特殊的粒子效果。 在這里,我們用來創建星星飛動的效果。
Sounds: 一些與太空相關的背景音樂和音效。使用 Garage Band 和 cxfr製作的。
Spritesheets: 一張格式為pvr.ccz的大圖片,裡麵包含了游戲中將要用到的許多小圖片,比如隕石,太空船等。這個文件使用 Texture Packer製作的---如果你想使用pvr.ccz文件格式的話,你可能就需要使用這個工具。當然pvr.ccz格式的優點就是文件小,載入速度快。
如果你還沒安裝上面任何一款工具的話,也不用擔心!對於這個教程來說,你完全不需要他們,你可以使用我已經製作好的這些資源就夠了。以後,如果有條件,你可以再去試試上面提到的工具。
你可能會奇怪,為什麼要把所有的這些圖片都弄成這樣一張大圖呢?因為,首先,它可以幫助節省內存,同時還可以提高性能。
接下來,讓我們開始coding吧!:)
添加一個太空船
首先,讓我們在屏幕上添加一艘太空船吧!
讓我們試試,看是否工作!打開HelloWorld.h,在HelloWorld類開頭加入下面代碼(在已有public:行的上面)
SpriteBatchNode *_batchNode;
Sprite *_ship;
上面的代碼創建了兩個私有實例變數 – 一個是SpriteBatchNode,一個是太空飛船精靈。
現在切換到HelloWorldScene.cpp,在init()方法里,刪除從注釋「2. add a menu item」到方法最後的所有代碼,加入下面代碼:
_batchNode = SpriteBatchNode::create("Sprites.pvr.ccz"); // 1
this->addChild(_batchNode); // 2
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("Sprites.plist"); // 3
_ship = Sprite::createWithSpriteFrameName("SpaceFlier_sm_1.png"); // 4
auto winSize = Director::getInstance()->getWinSize(); // 5
_ship->setPosition(Point(winSize.width *0.1, winSize.height *0.5)); // 6
_batchNode->addChild(_ship,1); // 7
注意這些代碼與你過去使用的Objective-C版的cocos2d 非常類似。API是有很多相同的地方的,僅僅是有一些與C++的語法不同。
編譯運行,你應該可以看到你的船出現在屏幕上
增加視差滾動
接下來,我們會加入宇宙背景,使它以視差滾動這種很酷的方式來滾動。
首先,我們不得不在所有的類名前面加上cocos2d::這個名字空間,這太煩人了!所以在HelloWorld.h類聲明前加入下面行:
USING_NS_CC;
接著在HelloWorld的private部分加入一些新的變數(注意我們不再需要加cocos2d前綴):
ParallaxNodeExtras *_backgroundNode;
Sprite *_spacest1;
Sprite *_spacest2;
Sprite *_planetsunrise;
Sprite *_galaxy;
Sprite *_spacialanomaly;
Sprite *_spacialanomaly2;
然後,在HelloWorldScene.cpp的init方法中,return語句前加入下面代碼:
// 1) Create the ParallaxNodeExtras
_backgroundNode = ParallaxNodeExtras::node();
this->addChild(_backgroundNode,-1);
// 2) Create the sprites we'll add to the ParallaxNodeExtras
_spacest1 = Sprite::create("bg_front_spacest.png");
_spacest2 = Sprite::create("bg_front_spacest.png");
_planetsunrise = Sprite::create("bg_planetsunrise.png");
_galaxy = Sprite::create("bg_galaxy.png");
_spacialanomaly = Sprite::create("bg_spacialanomaly.png");
_spacialanomaly2 = Sprite::create("bg_spacialanomaly2.png");
// 3) Determine relative movement speeds for space st and background
Point stSpeed = Point(0.1, 0.1);
Point bgSpeed = Point(0.05, 0.05);
// 4) Add children to ParallaxNodeExtras
_backgroundNode->addChild(_spacest1,0,stSpeed,Point(0, winSize.height / 2));
_backgroundNode->addChild(_spacest2,0,stSpeed,Point(_spacest1->getContentSize().width, winSize.height / 2));
_backgroundNode->addChild(_galaxy, -1, bgSpeed,Point(0, winSize.height *0.7));
_backgroundNode->addChild(_planetsunrise, -1, bgSpeed,Point(600, winSize.height * 0));
_backgroundNode->addChild(_spacialanomaly, -1, bgSpeed,Point(900, winSize.height *0.3));
_backgroundNode->addChild(_spacialanomaly2, -1, bgSpeed,Point(1500, winSize.height *0.9));
編譯運行,你應該可以看到一個宇宙場景的啟動
而,這還不是很有趣,因為還沒有任何東西在動!
為了移動太空塵埃和相關背景層,你只需要移動一樣東西就可以了,ParallaxNodeExtras。對於移動parallax node的每一個y值,灰塵就會移動0.1y值,同時背景會移動0.05y值。
為了移動parallax節點,你只需要飛一幀更新一下它的位置就可以了。打開HelloWorldLayer.m文件,加入下列的代碼:(添加位置注意看注釋)
this->scheleUpdate();
void HelloWorld::update(float dt)
{
Point backgroundScrollVel = Point(-1000, 0);
_backgroundNode->setPosition(_backgroundNode->getPosition()+backgroundScrollVel*dt);
}
編譯並運行工程,你會看到,使用parallax來做視差滾動效果真是太簡潔了!
5. cocos2djs 怎樣創建imageview
本節我們會通過一個實例介紹紋理對象創建Sprite對象使用,這個實例如圖5-2所示,其中地面上的草是放在背景(如下圖所示)中的,場景中的兩棵樹是從後圖所示的「樹」紋理圖片中截取出來的,圖5-5所示是樹的紋理坐標,注意它的坐標原點在左上角。
創建Sprite對象實例
場景背景圖片
「樹」紋理圖片
「樹」紋理圖片
下面我們看看app.js 中HelloWorldLayer中初始化代碼如下:
var HelloWorldLayer = cc.Layer.extend({
ctor:function () {
this._super();
var size = cc.director.getWinSize();
var bg = new cc.Sprite(res.background_png); ①
bg.x = size.width/2;
bg.y = size.height/2;
this.addChild(bg);
var tree1 = new cc.Sprite(res.tree_png,cc.rect(604, 38, 302, 295)); ②
tree1.x = 200;
tree1.y = 230;
this.addChild(tree1);
var texture = cc.textureCache.addImage(res.tree_png); ③
var tree2 = new cc.Sprite(texture, cc.rect(73, 72,182,270)); ④
tree2.x = 500;
tree2.y = 200;
this.addChild(tree2);
}
});
在上面代碼第①行通過圖片創建精靈,變數res.background_png是圖片的完整路徑,它是在resource.js文件中定義的,它代表的圖片是background.png,background.png圖片如圖5-3所示。第②行代碼是通過tree1.png圖片(res.tree_png變數保存的內容)和矩形裁剪區域創建精靈,矩形裁剪區域為(604, 38, 302, 295),如圖所示。
rect類可以創建矩形裁剪區,rect構造函數如下:
rect (x, y, width, height)
其中x,y是UI坐標,坐標原點在左上角,width是裁剪矩形的寬度,height是裁剪矩形的高度。
第③行代碼把tree1.png圖片添加到紋理緩存中,第④行代碼是通過指定紋理和裁剪的矩形區域來創建精靈。
資料由:成都點點通軟體開發公司提供!
6. 談談對quick-cocos2d-x和cocos2d-x lua的區別理解
下面簡單舉個例子吧,還是顯示經典的HelloWorldScene中那張背景圖片,如果我們在quick中使用原生lua的寫法,就和使用C++寫一樣
function MainScene:ctor()
self.size = CCDirector:sharedDirector():getWinSize()
local sp = CCSprite:create("HelloWorld.png")
sp:setPosition(ccp(self.size.width/2, self.size.height/2))
self:addChild(sp)
end
需要這樣些語句才能完成,不過用quick提供的API,那麼就簡單太多了,真的感動的要哭
function MainScene:ctor()
local sp = display.newSprite("HelloWorld.png", display.cx, display.cy)
self:addChild(sp)
end
就這些,是不是太方便,對於坐標的提供大大簡化了需求,32個贊!
下面說一說對於quick的學習方法吧,我覺得C++那一套編寫游戲的方法你掌握的話,對於lua開發游戲難度到並不是太大,畢竟相應的函數方法都是有的,困難之處在於怎麼使用lua的方式寫出來,比如一個觸摸響應事件,如果用quick提供的方式寫出來,這就需要好好看看API了,當然quick提供的在線API還不是很完整,有些地方還是不太詳細的,所以看sample是另一個途徑了,quick裡面提供了大量的sample,這對於我們來說比任何資源都重要。一旦把這些基礎的用法掌握了,可以看看那個CoinFlip這個完整的游戲示例,我覺得這樣一來差不多自己就能用quick開發游戲了。
7. cocos2d載入程序時的那個背景圖片如何添加,那個背景圖片在給定的plist文件里
cocos2d載入程序時的那個文件是一個命名為Default.png的圖片,你可以命名一個同名圖片去覆蓋它。
通常游戲的開始畫面可能不僅僅是一張圖片,載入了。
我不記得是cocos2d哪個版本了,在AppDelegate文件里有一個removeStartupFlicker方法,裡面注釋著以下內容
- (void) removeStartupFlicker
{
//
// THIS CODE REMOVES THE STARTUP FLICKER
//
// Uncomment the following code if you Application only supports landscape mode
//
#if GAME_AUTOROTATION ==
//CC_ENABLE_DEFAULT_GL_STATES();
//CCDirector *director = [CCDirector sharedDirector];
//CGSize size = [director winSize];
//CCSprite *sprite = [CCSprite spriteWithFile:@"Default.png"];
//sprite.position = ccp(size.width/2, size.height/2);
//sprite.rotation = -90;
//[sprite visit];
//[[director openGLView] swapBuffers];
//CC_ENABLE_DEFAULT_GL_STATES();
#endif // GAME_AUTOROTATION ==
}
把CCSprite *sprite = [CCSprite spriteWithFile:@"Default.png"];
在這里你可以取你plist里的那個圖片路徑來顯示它
當然,通常的做法是自己創建一個初始畫面的類,不去顯示Default.png,自己在類裡面做這個初始畫面,是淡入淡出也好,甚至播動畫也好,都可以自己把控。要記得把初始場景設為它。
8. 如何使用cocos2d
cocos2d是一個非常強大的開源庫,它可以為你開發iphone上面的游戲節省大量的時間。目前支持精靈(sprite)、動畫、物理引擎、聲音引擎以及許許多多非常酷的圖像效果等等。
我也是剛開始學習cocos2d,目前已經有許多非常好的教程來教你如何使用cocos2d了。但是,那些都不是我想要的。我真正想要的是一個非常簡單,但是可以跑起來的游戲。這個游戲包括怎麼使用動畫、碰撞檢測和播放聲音,這就夠了,並不需要使用太多高級的特性。最終,我自己做了一個這樣的游戲,因此,基於我的一些經驗寫了這篇教程,希望會對初學者有所幫助。
這篇教程將會從頭至尾、一步一步地教你如何使用cocos2d來製作一個簡單的iphone游戲。你可以按照教程一步步來,或者乾脆直接跳到文章的最後,下載樣常式序。沒錯!游戲裡面有忍者。
下載並安裝cocos2d
你可以從下面的鏈接來下載cocos2d的最新版本(以前是google,現在採用git了) the Cocos2D Google Code page.
在你下載完代碼以後,你可能想安裝非常有用的項目模板。打開終端窗口,然後cd到你的cocos2d解壓縮目錄下面,輸入./install_template.sh
請注意,你可以傳遞一些參數給這個安裝腳本,比如你把xcode安裝在了一個非標準的目錄下面。(或者你有多個版本的sdk安裝在你的機器上面)
Hello, Cocos2D!
讓我們從最簡單的HelloWorld項目開始吧!啟動xcode,點file->new project,然後選擇cocos2dApplicationtemplate來創建一個新的cocos2d項目並把它命名為「Cocos2dSimpleGame」
繼續,點編譯並運行這個工程模板,如何一切都ok的話,那麼你會看到下面的內容:
cocos2d是按照「場景」(scene)的概念組織的,對一個游戲來說,就好像某個關卡或者屏幕之類的。比如,你可能需要一個場景來為你的游戲建立初使化菜單界面,另外一個場景當作玩游戲的主要界面,還有一個游戲結束的時候的界面。在一個場景裡面,你可以有許多「層」(layer)(這個和photoshop有點類似)。每一個層又可以包含一些結點,比如精靈、標簽、菜單等。而且一個結點也可以包含其它的結點。(比如,一個精靈可以包含一個子精靈)
如果你看一下樣例工程,你會看到只有一個場景HelloWorldScene--我們接下來將會在這個場景裡面實現我們的游戲邏輯。繼續打開它,你會在init方法裡面看到,它把一個帶有「HelloWorld」字樣的標簽加到了當前場景中。我們將把這些代碼去掉,並且放一個精靈在上面。
增加一個精靈
在我們增加一個精靈之前,我們需要一些圖片。你可以自己去創建一些,或者使用我可愛的妻子為這個項目所創建的圖片: a Player image, a Projectile image, and a Target image.
一旦你獲得了這些圖片,你就可以把它們用滑鼠拖到xcode的resource文件夾中去,並且保證「 Copy items into destination group』s folder (if needed)」勾上了。現在,我們擁有自己的圖片了,我們先得計算一下,應該把player放在哪裡。請注意,cocos2d坐標系的原點在屏幕的左下角,即(0,0)位置在左下角,這與一般的窗口坐標系統在左上角有所區別。x方嚮往右是正,y方嚮往上是正。由於項目是landscape(橫版)模式,這就意味著右上角的坐標是(480,320)。
還有需要注意的是,當我們設置一個對象的位置的時候,這個位置是相對於所加精靈的中心點來加的。因此,如果我們想讓我們的player精靈與屏幕的左邊界水平對齊,並且垂直居中的話。
那麼對於x軸:我們需要設置為[player sprite's width]/2。y坐標設置為[window height]/2。
下面有一張圖,可以更加清楚一些:
好,讓他開始射擊吧!打開Class文件夾並點擊HelloWorldScene.m,然後把init方法用下面的代碼替換掉:
復制代碼
-(id) init
{
if( (self=[super init] )) {
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *player = [CCSp www.hbbz08.com rite spriteWithFile:@"Player.png"
rect:CGRectMake(0, 0, 27, 40)];
player.position = ccp(player.contentSize.width/2, winSize.height/2);
[self addChild:player];
}
return self;
}
復制代碼
編譯並運行,你的精靈這時候應該出現在正確的位置上了。但是,這個前景默認是黑的。對於這張忍者圖片來說,白色的背景可能看起來更好一些。在cocos2d裡面,有一種非常簡單的方式來改變層的背景顏色,那就是使用CCColoredLayer類。好,跟我來吧!點擊HelloWorldScene.h,然後把HelloWorld介面聲明改成下面這樣:
@interface HelloWorld : CCColorLayer
然後點擊HelloWorldScene.m文件,在init方法裡面做一些小小的修改,以便使我們能把層的背景顏色改成白的:
9. cocos2d怎麼使用texture素材
我使用張圖片給我歷圖片添加邊框種帶波紋效邊框四邊形張圖片透明部遮罩效部白色區域則歷圖片顯示區域
實現效我使用OpenGL混合模式
看《何使用CCRenderTexture態創建紋理》篇教程我討論OpenGL混合模式我提非便線工具用見化調節混合模式效
完我想要效我需要採取面策略:
我首先渲染mask精靈src color(mask精靈)設置GL_ONE並且destination
color(空buffer)設置GL_ZERO所效簡單mask圖片顯示
接我渲染歷圖片精靈src
color(歷)設置GL_DST_ALPHA意思看看mask圖片前alpha值少0(完全透明)顯示mask1(完全透明)顯示歷圖片(譯者註:家明白參考鏈接)dst
color(the mask)設計GL_ZERO前渲染mask消失
酷吧能覺我需要先mask精靈渲染再渲染歷精靈並且指定兩精靈blendFunc行實際行通
面所提混合算精靈面些精靈渲染候問題---比背景圖片面精靈作假設面做完1步驟imgae
buffer面存唯張圖片mask(假設確啦要切換歷圖片)
我需要種式建立干凈黑板執行12步製作遮罩紋理幸運用RenderTexture非便
Masking
and CCRenderTexture]
RenderTexture類讓屏幕外buffer面渲染
用起非便主要原---使用給游戲截屏高效緩存用戶渲染內容運行態創建sprite
sheet或者像本教程製作mask sprite
使用RenderTexture需要採取4步:
創建RenderTexture類像素單位指定想要繪制紋理寬度高度
調用RenderTexturebegin初始化渲染操作
調用OpenGL函數繪制實際內容--些OpenGL調用終都繪制屏幕外影響游戲現渲染圖像
調用RenderTextureend結束繪制操作旦完RenderTexturesprite屬性用Sprite用
要覺第3步奇怪---使用Cocos2d90%情況需要手直接調用OpenGL函數想渲染節點直接調用某節點visitsprite->visit函數自發射些OpenGL函數指針給圖形硬體顯示
點需要注意坐標問題(00)點渲染紋理左角位置所使用RenderTexture候定要坐標設置
能聽些煩程序員喜歡看代碼讓我始coding吧
給精靈添加遮罩: 終實現
打HelloWorldScene.minit面添加面注意靜態文件聲明需要注意:
//a static method
Sprite* HelloWorld::maskedSpriteWithSprite(Sprite* textureSprite, Sprite* maskSprite)
{
// 1
RenderTexture * rt = RenderTexture::create( maskSprite->getContentSize().width,
maskSprite->getContentSize().height );
// 2
maskSprite->setPosition(maskSprite->getContentSize().width/2,
maskSprite->getContentSize().height/2);
textureSprite->setPosition(textureSprite->getContentSize().width/2,
textureSprite->getContentSize().height/2);
// 3
maskSprite->setBlendFunc( BlendFunc{GL_ONE, GL_ZERO} );
textureSprite->setBlendFunc( BlendFunc{GL_DST_ALPHA, GL_ZERO} );
// 4
rt->begin();
maskSprite->visit();
textureSprite->visit();
rt->end();
// 5
Sprite *retval = Sprite::createWithTexture(rt->getSprite()->getTexture());
retval->setFlippedY(true);
return retval;
}
讓我步步解面操作:
使用mask精靈創建CCRenderTexture
重新設置mask精靈texture精靈位置使左角(00)
按照我前討論設置每精靈blendFunc
調用CCRenderTexturebegin始渲染操作依渲染masktexture精靈調用end
基於CCRenderTexturesprite屬性texture創建新精靈同翻轉y紋理創建倒
接我使用面函數製作遮罩效:
//cal->setPosition(visibleSize.width/2, visibleSize.height/2);
Sprite * mask = Sprite::create("CalendarMask.png");
Sprite * maskedCal = maskedSpriteWithSprite(cal, mask);
maskedCal->setPosition(visibleSize.width/2, visibleSize.height/2);
//pRet->addChild(cal);
pRet->addChild(maskedCal);
編譯並運行