Box2DとCocos2DでFruit Ninjaのようなゲームを作る方法–パート1
これは、Ios開発者であり、White Widgetの共同創設者であるiOSチュートリアルチームメンバーのAllen Tanによる投稿です。 また、Google+やTwitterで彼を見つけることができます。
このチュートリアルでは、強力なCocos2DおよびBox2Dライブラリといくつかの既製のツールを使用して、Halfbrick StudiosのFruit Ninjaに似たiPhone用のスプライト切断ゲームを作
ほとんどのスライシングゲームでは、スプライトを介してカットラインを描画すると、ゲームは通常、実際にカットした場所に関係なく、スプライトイ
しかし、このチュートリアルではさらにクールなテクニックを紹介します。 私たちの果物は、複数回切断することができるようになります、と彼らは正確なカットラインに基づいて動的に分割されます!
ご想像のとおり、これは高度なテクニックなので、このチュートリアルは高度なCocos2DとBox2D開発者のためのものです。 Cocos2DまたはBox2Dを初めて使用する場合は、このチュートリアルに進む前に、(少なくとも)Cocos2DのintroとBox2Dのintroチュートリアルを最初に通過する必要が
このチュートリアルシリーズは三つの部分に分割されています:
- シリーズのこの最初の部分では、ゲームの基礎を築き、テクスチャポリゴンを作成する方法を学びます。
- 第二部は、これらのテクスチャポリゴンをスライスする方法を紹介します&これらのテクスチャポリゴンを分割します。
- 第三部では、ゲームプレイと効果を追加することによって、これを完全なゲームに変える方法を紹介します。
このチュートリアルが基づいているプロジェクトの基礎を築いてくれたRick Smorawskiに特別な感謝をしたいと思います。 彼はこのフラッシュベースのスライスデモをCocos2Dに移植し、CCBladeとPRKitをCocos2D2.0に移植する責任がありました。
あなたが作るもののビデオをチェックアウトし、いくつかのクールな新しいテクニックを学び始めるために読んでください!
ゲームデモ
ここでは、このチュートリアルシリーズで作るものを示すデモビデオです:
私が述べたように、あなたは果物の切断効果が本当に動的であるこ 果物はスライスする場所に基づいて動的にカットされ、オブジェクトを複数回スライスすることができるので、本当に物事を切り刻むことがで
クールなスライシングトレイルエフェクト、パーティクルシステム、ゲームプレイロジック、サウンドを実装して、物事を盛り上げることもできます。
カバーすることがたくさんあります–それでは始めましょう!
はじめに:プロジェクト設定
Cocos2D2を使用します。Xこのプロジェクトでは、まだ持っていない場合は、先に進んでダウンロードしてください。 Cocos2D1は自由に使用できます。2の代わりにX。X.と1.X、PRKitとCCBladeをCocos2D2に変換することについての部分をスキップすることができます。しかし、それらのクラスに加えた他の小さな変更に注意を払うようにしてください。
ダウンロード後、tarをダブルクリックしてアーカイブを解除し、ターミナルに次のコマンドを使用してテンプレートをインストールします:
cd ~/Downloads/cocos2d-iphone-2.0-beta./install-templates.sh -f -u
Xcodeを起動し、iOS\cocos2d v2で新しいプロジェクトを作成します。X\cocos2d IosとBox2Dテンプレートを使用して、CutCutCutという名前を付けます。
新しいプロジェクトは次のようになります:
まず最初に–良い出発点に到達するためにテンプレートを少しクリーンアップする必要があります。
HelloWorldLayerを開きます。hと次の行を削除します:
CCTexture2D *spriteTexture_;// weak ref
に切り替えるHelloWorldLayer.mm そして、次の変更を行います
// Remove this line from the top#import "PhysicsSprite.h"// Replace the init method with this-(id) init{ if( (self=)) { // enable events self.isTouchEnabled = YES; self.isAccelerometerEnabled = YES; CGSize s = .winSize; // init physics ; ; } return self;}// Remove these two methods-(void) createMenu { //all content}-(void) addNewSpriteAtPosition:(CGPoint)p methods { //all content}// Remove this line from ccTouchesEnded;
この時点で、HelloworldlayerからPhysicsSpriteへのすべての参照を削除しましたが、プロジェクトからファイルをまだ削除しないでくださ 後で、次のようなメソッドをコピーする必要がありますPhysicsSprite.mm どこか別の場所に含まれているので、今のところ入れておきます。
Command+Rを押してプロジェクトをコンパイルして実行すると、空白の画面が表示され、周囲に緑色の境界線が表示されます:
残りのテンプレートコードは、画面上のBox2Dボディの周りに境界線を描画するBox2Dデバッグ描画を設定しています。 画面の周りに描かれた細い緑色の線を参照してください? これらは、テンプレートに付属のデフォルトのinitPhysicsメソッドによって生成された壁です。
残りのテンプレートコードを見て、これまでに何が起こっているのかを理解していることを確認してください–Box2Dワールドを初期化し、地面(緑の境界線) これは、ここから構築できるBox2Dのかなり良い「ほぼ空白」の出発点です。
リソースキット
次に、このプロジェクトのリソースをダウンロードし、ファイルを解凍します。
まだプロジェクトにすべてを追加しないでください。 しかし、便利なフォルダを維持–あなたはチュートリアルを通過するように、随時、私はプロジェクトにこれらのファイルのいくつかを追加するように
ここにあなたが中に見つけるものがあります:
- 画像フォルダ
- gomixを使用して作られた背景サウンドミックスの背景画像とvickiによって作られたフルーツアートの束、およびその他の雑多な画像。Soundsフォルダ
- bfxrを使用して作成された効果音またはsoundsフォルダ内のfreesoundからダウンロードされた効果音
- Particlesフォルダ内のParticle Designerで作成されたすべてのパーティクルシステム
- Physicseditorによって生成されたplistファイルには、Miscフォルダ内のFruits&Bombクラスの頂点情報が含まれています
- Fruits&Classesフォルダ内のBombクラス
- Fruits&Bombクラスの頂点情報が含まれています。9445>
- classesフォルダ
- miscのアトリビューションライセンスの下にあるリソースのアトリビューションリストのチュートリアルで使用するprkitとCcbladeのバージョン フォルダ
PRKitでテクスチャポリゴンを描画
私たちの目標は、スプライトを複数の部分にカットすることです。 一般的なCCSpriteには、画像の形状に関係なく、テクスチャと境界ボックスが含まれています。 画像内の実際の形状を知ることは、カット、スライス、および分割できるスプライトを作成するための重要なステップであるため、これはゲームには適し
テクスチャポリゴンを作成する必要があります。:
- ポリゴン/シェイプと画像の対応を作成する(テクスチャマッピング)
- ポリゴンの境界内にある画像の部分のみを表示する(テクスチャ塗りつぶし))
Cocos2DもBox2Dには、必要なカスタム機能を処理する組み込みクラスが付属していませんが、通常、これはカスタムOpenGL描画コードと結合された三角測量
難しいでしょうか?
幸いなことに、これを達成するために必要なすべての複雑な計算と描画コードは、予知研究の善良な人々によってすでに書かれています。 彼らは、テクスチャマッピングと塗りつぶしを処理するPrkitという名前のCocos2Dライブラリに追加を作成しました。
テクスチャポリゴンを開始するには、PRKitをダウンロードして抽出し、PRKitフォルダをプロジェクトにドラッグします。 “コピー先グループのフォルダに項目をコピーする”がチェックされ、”追加されたフォルダのグループを作成する”が選択されていることを確認します。
PRKitは予知研究によって維持されているため、時間内に更新される可能性があることに注意してください。 混乱を避けるために、私たちのリソースキットには、このチュートリアルの作成に使用したPRKitの正確なバージョンも含まれています。
プロジェクトに次のファイルが含まれるようになりました:
コンパイルして実行すると、いくつかのエラーが発生します:
PRKitはCocos2D1用に作られたため、エラーがポップアップ表示されます。XはOpenGL ES1.1を使用しますが、Cocos2D2を使用しています。Xは、OpenGL ES2を使用しています。0であり、両者の間には大きな違いがあります。
これを修正するには、PRFilledPolygonを開きます。mとこれらの変更を行います:
// Add inside the initWithPoints: andTexture: usingTriangulator: methodself.shaderProgram = programForKey:kCCShader_PositionTexture];// Replace the calculateTextureCoordinates method with this-(void) calculateTextureCoordinates { for (int j = 0; j < areaTrianglePointCount; j++) { textureCoordinates = ccpMult(areaTrianglePoints,1.0f/texture.pixelsWide*CC_CONTENT_SCALE_FACTOR()); textureCoordinates.y = 1 - textureCoordinates.y; }}// Replace the draw method with this-(void) draw{ CC_NODE_DRAW_SETUP(); ccGLBindTexture2D( self.texture.name ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); ccGLBlendFunc( blendFunc.src, blendFunc.dst); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords ); glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, areaTrianglePoints); glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates); glDrawArrays(GL_TRIANGLES, 0, areaTrianglePointCount);}
これらの変更を少しずつ見てみましょう。
まず、Cocos2Dでは、すべてのCCNodeにOpenGL ES2.0シェーダープログラムが添付されています。 PRFilledPolygonを描画するには、initメソッドで割り当てる組み込みの”Position/Texture”シェーダを使用する必要があります。
次に、ポリゴン内の各ポイントに正しいテクスチャ座標を設定する必要があります。 これを行うには、calculateTextureCoordinatesメソッドに2つの変更を加える必要があります:
- スケール:このクラスはテクスチャの座標に対して独自の計算を行うため、retinaディスプレイを自動的に処理しません。 これを修正するには、テクスチャを乗算するだけです。pixelsWide with CC_CONTENT_SCALE_FACTOR-通常と網膜同等の間で値を変換するためのCocos2Dによって提供される便利な乗数値。
- Flip Y:何らかの理由で、PRFIlledPolygonはテクスチャを逆さまに描画するので、ここでy値を反転するだけです。
最後に、描画コードがOpenGL ES2に更新されます。0、CCSprite描画がCocos2D1からどのように変更されたかと同様の方法で。XをCocos2D2に変換する。X:
- まず、CC_NODE_DRAW_SETUP()を呼び出して、描画用のノードを準備します。
- glDisableClientState()およびglEnableClientState()への呼び出しは廃止され、破棄されます。
- glVertexPointer()とglTexCoordPointer()コマンドはどちらもglVertexAttribPointer()に置き換えられ、頂点位置またはテクスチャ座標を最初のオプションとして受け入れるようになりました。
- ポリゴンがテクスチャよりも大きかった場合にスプライトを繰り返すglTexEnvf()の設定は、glTexParameteri()の呼び出しに置き換えられます。
このいずれかに混乱している場合は、OpenGL ES2.0for iPhoneとカスタムCocos2D2をチェックしてみてください。より多くの背景情報のためのXシェーダのチュートリアル。 しかし、この時点ではCocos2D2で動作するようにクラスを移植するだけなので、あまり心配する必要はありません。X:]
コンパイルして実行すると、すべてのPRKitエラーが消えるはずです!
PRKitを実行する時が来ました。 PrkitのPRFilledPolygonクラスをサブクラス化して、果物を描画するベースのPolygonSpriteクラスを作成します。
PolygonSpriteは、スプライトにBox2DボディをアタッチすることによってPRFilledPolygon上に構築され、ゲーム実装ではfruitsの他のカスタム変数とメソッドも含まれます。
それを取得してみましょう。 Command+Nを押して、iOS\cocos2d v2で新しいファイルを作成します。x\CCNodeクラステンプレート。 それをPRFilledPolygonのサブクラスにし、PolygonSpriteという名前を付けます。m。
ポリゴンプライトに切り替えます。hを実行し、次の変更を行います:
// Add to top of file#import "Box2D.h"#import "PRFilledPolygon.h"#define PTM_RATIO 32// Add inside @interfaceb2Body *_body;BOOL _original;b2Vec2 _centroid;// Add after the @interface@property(nonatomic,assign)b2Body *body;@property(nonatomic,readwrite)BOOL original;@property(nonatomic,readwrite)b2Vec2 centroid;// Add before the @end-(id)initWithTexture:(CCTexture2D*)texture body:(b2Body*)body original:(BOOL)original;-(id)initWithFile:(NSString*)filename body:(b2Body*)body original:(BOOL)original;+(id)spriteWithFile:(NSString*)filename body:(b2Body*)body original:(BOOL)original;+(id)spriteWithTexture:(CCTexture2D*)texture body:(b2Body*)body original:(BOOL)original;-(id)initWithWorld:(b2World*)world;+(id)spriteWithWorld:(b2World*)world;-(b2Body*)createBodyForWorld:(b2World*)world position:(b2Vec2)position rotation:(float)rotation vertices:(b2Vec2*)vertices vertexCount:(int32)count density:(float)density friction:(float)friction restitution:(float)restitution;-(void)activateCollisions;-(void)deactivateCollisions;
上記のコードは、PolygonSpriteを作成するために必要な基本変数とメソッドを宣言しています。 これらは:
- body:これはスプライトにアタッチされているBox2Dボディです。 これは、物理シミュレーションのために必要とされています。
- original:Completeスプライトとslicedスプライトは同じPolygonSpriteクラスを使用するため、両者を区別することが重要になります。 これがYESの場合、それはあなたが作成したノーカット、または元のオブジェクトであることを意味します。
- セントロイド: 画像内のポリゴンの中心が画像の中心と常に同じであるとは限らないため、この値を格納すると便利です。
- プロパティ:他のクラスが自由にアクセスできるように、プロパティを使用してすべての変数を公開します。
- init/spriteWith*:Cocos2Dと同じ命名規則に従った主なinitメソッド。
- その他のメソッド:これらは、添付されたBox2D本体とそのプロパティを扱う&を作成するメソッ
- PTM_RATIO:ピクセルとメートルの比率。 Box2dはピクセルではなくメートルを扱うため、この変換値が必要です。
すぐにPolygonSpriteに切り替えます。mと名前を変更しますPolygonSprite.mm Objective-C(Cocos2D)とC++(Box2D)コードを混在させるすべてのクラスには、混合構文をコンパイラに通知するための「.mm」拡張子が必要です。
次に、以下の変更を行いますPolygonSprite.mm:
// Add inside the @implementation@synthesize body = _body;@synthesize original = _original;@synthesize centroid = _centroid;+(id)spriteWithFile:(NSString *)filename body:(b2Body *)body original:(BOOL)original{ return initWithFile:filename body:body original:original] autorelease];}+(id)spriteWithTexture:(CCTexture2D *)texture body:(b2Body *)body original:(BOOL)original{ return initWithTexture:texture body:body original:original] autorelease];}+(id)spriteWithWorld:(b2World *)world{ return initWithWorld:world] autorelease];}-(id)initWithFile:(NSString*)filename body:(b2Body*)body original:(BOOL)original{ NSAssert(filename != nil, @"Invalid filename for sprite"); CCTexture2D *texture = addImage: filename]; return ;}-(id)initWithTexture:(CCTexture2D*)texture body:(b2Body*)body original:(BOOL)original{ // gather all the vertices from our Box2D shape b2Fixture *originalFixture = body->GetFixtureList(); b2PolygonShape *shape = (b2PolygonShape*)originalFixture->GetShape(); int vertexCount = shape->GetVertexCount(); NSMutableArray *points = ; for(int i = 0; i < vertexCount; i++) { CGPoint p = ccp(shape->GetVertex(i).x * PTM_RATIO, shape->GetVertex(i).y * PTM_RATIO); ]; } if ((self = )) { _body = body; _body->SetUserData(self); _original = original; // gets the center of the polygon _centroid = self.body->GetLocalCenter(); // assign an anchor point based on the center self.anchorPoint = ccp(_centroid.x * PTM_RATIO / texture.contentSize.width, _centroid.y * PTM_RATIO / texture.contentSize.height); // more init stuff here later when you expand PolygonSprite } return self;}-(id)initWithWorld:(b2World *)world{ //nothing to do here return nil;}
Cocos2Dと同様に、すべてのspriteWith*メソッドはinitWith*メソッドのautorelease対応していますが、initWithWorldはまだこのクラスの実際の使用はありませんが、後でPolygonSpriteのサブクラスで使用され
変更の大部分はinitWithFileメソッドとinitWithTextureメソッドで見つけることができます。 物事の流れを得るために、果物を作成することはこの順序で呼び出されます:
- initWithWorld:これはPolygonSpriteのサブクラスを対象としているため、return nil以外は何もせず、後で処理します。
- initWithFile:これにより、ファイルからテクスチャが追加され、すべてがinitWithTextureに渡されます。
- initWithTexture:メインの初期化です。 PRFilledPolygonには、テクスチャとそれが塗りつぶすポリゴンのすべての頂点が必要です。 前のステップでは既にテクスチャパーツを処理していたため、このステップではスプライトのBox2Dボディから頂点を収集して処理します。 それらをPRFilledPolygonに渡した後、以前に宣言した変数を初期化します。
- initWithPoints:これが行うことはすべてPRKitに含まれており、コードを更新したので、PRKitに触れる必要はもうないということが良いことです。
まだ中PolygonSprite.mm、次のメソッドを追加します:上記のコードでは、最初にCCNodeのsetPositionメソッドをオーバーロードして、スプライトの位置を更新すると、関連するBox2Dボディの位置も更新されるようにします。
その後、Box2Dボディを作成および定義するための便利なメソッドを作成します。 ボディを作成するには、ボディ定義、ボディオブジェクト、シェイプ、およびフィクスチャ定義を定義する必要があります。 このメソッドは後でPolygonSpriteのサブクラスで使用されるため、実際のハード値はまだここに割り当てられていません。
注意すべき唯一のことは、categoryBitsとmaskBitsです。 これらの2つは、オブジェクトのカテゴリビットが別のオブジェクトのマスクビットと一致し、その逆の場合に、これら2つのオブジェクト間の衝突が発生するように、オブジェクト間の衝突をフィルタリングするために使用されます。 オブジェクトが最初に初期化されたときに衝突が発生しないようにするため、これらを最初に0に設定します。
最後に、categoryBitsとmaskBitsを置き換えるだけの二つのメソッドを定義して、PolygonSpritesの衝突を有効または無効にすることができます。
に追加するもう一つのことがありますPolygonSprite.mm:
-(CGAffineTransform) nodeToParentTransform{ b2Vec2 pos = _body->GetPosition(); float x = pos.x * PTM_RATIO; float y = pos.y * PTM_RATIO; if ( !isRelativeAnchorPoint_ ) { x += anchorPointInPoints_.x; y += anchorPointInPoints_.y; } // Make matrix float radians = _body->GetAngle(); float c = cosf(radians); float s = sinf(radians); if( ! CGPointEqualToPoint(anchorPointInPoints_, CGPointZero) ){ x += c*-anchorPointInPoints_.x+ -s*-anchorPointInPoints_.y; y += s*-anchorPointInPoints_.x+ c*-anchorPointInPoints_.y; } // Rot, Translate Matrix transform_ = CGAffineTransformMake( c, s, -s,c, x,y ); return transform_;}
私はあなたがPhysicsSpriteから何かを必要としていることを言及したときに覚えていますか? まあ、これはそれです。 これは、移動時にBox2D shapeとspriteが同じ位置にあることを確認することだけです。 それはCocos2Dによって私たちのために準備されており、それはそれをもっと素晴らしいものにします。
上記のコードをコピーした後、両方のPhysicsSpriteを削除できるようになりました。hとPhysicsSprite.mm あなたは完全にその有用性を排除しているように、プロジェクトから。
コンパイルして実行すると、すべてが正常になります。 あなたは今のところPolygonSpriteで終わっています。
私たちの果物を計画
私たちの果物のためのクラスを作成する前に、画像とその形状が従わなければならないルールを明確にする必要があります。 テクスチャを単一のBox2Dポリゴンにマッピングするため、Box2Dのポリゴンの制限にも従わなければなりません。 あなたは心の中で二つのことを維持する必要があります:
- ポリゴンは凸でなければならず、内角が180より大きくないことを意味します。
- ポリゴンは8つの頂点を超えてはなりません。
各ボディに複数の図形を含めることを許可すると、実際にこの制限を回避できます。 三角形分割法を使用し、いくつかの三角形から凹面形状を作成する場合、box2dは凹面形状を処理できますが、これはチュートリアルの範囲外です。
物事を簡単に保つために、このチュートリアルでは、1Body is to1Shapeルールがあります。
注:このチュートリアルの後半で説明するツールであるPhysicsEditorには、凸形状のセットに描画するポリゴンを自動的に三角測量するコードが含まれています。 しかし、私が言ったように、私たちはここで物事をシンプルにしようとしているので、私たちは体ごとに一つの形しか持っていないので、私たちの形を凸
この二つの果物を見てみましょう:
バナナを使うのは、自然に凹面なので良い考えではありません。 一方、スイカは、その形状によく似た凸多角形を定義できるため、非常に優れています。
2つの果物についてBox2Dの規則に従う多角形を定義すると、多かれ少なかれ次のようになります:
スイカのポリゴンは画像に完全にフィットしますが、バナナポリゴンは画像が内側にカーブする大きな空のスペースを持っています。 Box2dはその空間をオブジェクトの一部として扱い、他のオブジェクトと衝突したときや切断されたときにバナナが不自然に感じる可能性があり
これは、バナナを使えないという意味ではなく、バナナを使うことは推奨されないということです。 実際には、このチュートリアルで作成されるゲームは、この同じバナナを使用します。
最初の果物を作成する
最初の果物を作成する時が来ました:スイカ(少なくともそのスライス)。PolygonSpriteの初期化プロセスの流れに戻って考えると、initWithTextureはBox2D本体を期待していますが、前のステップinitWithFileはこれを提供していません。
この理由は、fruitごとにbodyを個別に作成および定義する必要があるため、bodyを作成し、各fruitに固有の他の値を設定する最初のステップ、initWithWorldでなければな
Box2Dボディを作成するには、まず作成するポリゴンシェイプの頂点を知っている必要があります。 これを行うにはさまざまな方法がありますが、このチュートリアルでは、PhysicsEditorと呼ばれる気の利いたツールを使用します。 このツールは機能で満たされていますが、ポリゴンの頂点の座標を取得するためにのみ使用します。
お持ちでない場合は、PhysicsEditorをダウンロードしてインストールし、起動してください。 あなたは3つのパネル/列を持つ空白のプロジェクトを取得します。
PhysicsEditorの操作は非常に簡単です。 左側には、作業したいすべての画像を配置します。 中央では、画像のポリゴンを視覚的に定義します。 右側には、身体のパラメータがあります。
スイカをつかむ。resource kitのImagesフォルダからpngを左パネルにドラッグします。 これで、中央のパネルにスイカが表示されます。
このパネルの下部にある倍率を快適なレベルに上げ、このパネルの上部にある五角形ボタンをタップして3面の多角形を作成します。
多角形を右クリックし、すべてに5-8個の頂点があるまで”頂点を追加”を選択します。 二つのことを確認しながら、スイカのエッジの周りに頂点を移動します:
- 作成しているポリゴンは凸です。
- スイカのすべてのピクセルはポリゴンの内側にあります。
注:図形を描画するための別のショートカットは、PhysicsEditorの魔法の杖ツールを使用することです。 ちょうどあなたが約5-8ポイントで終わるように許容値を高く(5-8)設定し、そこからポイントを微調整します。
リソースキットのImagesフォルダから他のすべての果物と爆弾の画像を追加し、それらのために同じことを行います。
次の画像の形状を定義する必要があります:
- バナナpng
- 爆弾。
- png
- png
終了したら、右上隅でExporterの値を「Box2D generic(PLIST)」に変更すると、次のようになります:
頂点情報を含むPLISTファイルをエクスポートするには、”Publish”または”Publish As”を押します。 ファイルをfruitsとして保存します。プリスト
一例として、果物。このチュートリアルで使用したplistは、resource kitのMiscフォルダ内にあります。
PLISTファイルに含まれている情報だけを見たいので、このファイルをプロジェクトに追加するのではなく、fruitsを開くだけです。Xcodeを使用してplistその内容を組織的に表示します。
このセクションを展開するには、”ボディ”の横にある三角形のアイコンをクリックすると、図形を定義した画像のリストが表示されます。 スイカの多角形の頂点を次のように取得するには、最も深いレベルまでドリルダウンする必要があります:
スイカ/fixtures/Item0/polygonsを展開すると、polygonsの下に配列型の別のアイテム0が表示されるはずです。 この最後の配列はあなたの形です。 頂点が8個以下の凸形状を適切に定義した場合、ポリゴンの下には1つの配列しか表示されません。
複数見たら、俺。eアイテム0配列、アイテム1配列など、それはあなたがあまりにも多くの頂点を定義したか、凹面多角形を形成したため、PhysicsEditorが複雑な形状を作ったことを この問題が発生した場合は、PhysicsEditorに戻り、シェイプを修正します。
次に、Array型の項目0を展開して、項目の最後のリストを表示します。 これらは頂点であり、この形式{number、number}の右側に表示される値は、各頂点のx&y座標です。
ポリゴンの頂点の正確な値が得られたので、スイカクラスの作成に進むことができます。Xcodeで、iOS\cocos2d v2で新しいファイルを作成します。x\CCNodeクラステンプレート。 それをPolygonSpriteのサブクラスにして、それにスイカという名前を付けます。 スイカを開く。hを実行し、次の変更を行います:
// Add to top of file#import "PolygonSprite.h"
スイカに切り替えます。m、に名前を変更しますWatermelon.mm、次のinitメソッドを追加します:
// Add inside the @implementation-(id)initWithWorld:(b2World *)world{ int32 count = 7; NSString *file = @"watermelon.png"; b2Vec2 vertices = { b2Vec2(5.0/PTM_RATIO,15.0/PTM_RATIO), b2Vec2(18.0/PTM_RATIO,7.0/PTM_RATIO), b2Vec2(32.0/PTM_RATIO,5.0/PTM_RATIO), b2Vec2(48.0/PTM_RATIO,7.0/PTM_RATIO), b2Vec2(60.0/PTM_RATIO,14.0/PTM_RATIO), b2Vec2(34.0/PTM_RATIO,59.0/PTM_RATIO), b2Vec2(28.0/PTM_RATIO,59.0/PTM_RATIO) }; CGSize screen = winSize]; b2Body *body = ; if ((self = )) { // We will initialize more values for the fruit here later } return self;}
上記のコードでは、最初に頂点がいくつあるかを定義します(この場合は7です)。 次に、PLISTで見たすべての座標を含む頂点の配列を作成します。 この情報を使用して、PolygonSpriteで定義した便利なメソッドを使用してbodyを作成します。
あなたは、図形が延々と滑らないように少し摩擦を入れ、また、図形が互いに跳ね返ったときに停止しないように少し反発を入れました。
最後に、スーパークラスの初期化を呼び出してオブジェクトを作成し、画像ファイルの名前、Box2D本体を渡し、これが元の果実であることを示します。
リソースキットからスイカの画像が必要なので、チュートリアルの残りの部分に必要なすべてのグラフィックリソースを追加するのに適しています。
プロジェクトナビゲータパネルで、リソースを右クリックし、”CutCutCutにファイルを追加”を選択します。 リソースキットからプロジェクトにImagesフォルダーを追加します。 “コピー先グループのフォルダに項目をコピーする”がチェックされ、”追加されたフォルダのグループを作成する”が選択されていることを確認します。
バナナ、ブドウ、パイナップル、イチゴ、爆弾を作成するには、同じ手順に従ってください。
最初の果物を段階的に作成する方法に取り組んだのは、基本的には各果物のリンス&繰り返しプロセスであるためです。 リソースキットには、まだガイダンスが必要な場合に備えて見るためのClassesフォルダに既製のfruitクラスとbombクラスが含まれています。
コンパイルして実行し、すべてが正常であることを確認してください。
シーンに果物を追加する
これまでのところ、まだ画面上で何も起こっていない、とあなたは明らかにあなたの労働しゃれが意図したの果物を見てかゆみ :]
HelloWorldLayerに切り替えます。hを実行し、次の変更を行います:
// Add to top of file#import "PolygonSprite.h"// Add inside the @interfaceCCArray *_cache;// Add after the @interface@property(nonatomic,retain)CCArray *cache;
に戻るHelloWorldLayer.mm これらの変更を行います:
// Add to top of file#import "Watermelon.h"// Add inside the @implementation@synthesize cache = _cache;// Add inside the init method, below ;// Add inside the dealloc method, before calling ;_cache = nil;// Add anywhere inside the @implementation and before the @end-(void)initSprites{ _cache = initWithCapacity:53]; // Just create one sprite for now. This whole method will be replaced later. PolygonSprite *sprite = initWithWorld:world]; ; ; ;}
あなたは、将来的に作成したすべての果物や爆弾を保持するキャッシュ配列を宣言します。 次に、1つのスイカを作成し、それをシーンに追加します。 あなたはactivateCollisionsを呼び出して、スイカが壁を通過しないようにします。
コンパイルして実行すると、画面の中央部からスイカが落ちて、下に示すように下に着陸するはずです。
あなたはスイカが正確に中央にないことに気づくかもしれません。 この理由は、オブジェクトをそのBox2Dボディに基づいて配置し、Box2Dボディの原点がオブジェクトの左下隅にあるためです。 デバッグ描画モードがオンのままであるため、スイカの周りの薄い輪郭が表示されます。
ここからどこへ行く?
ここでは、上記のチュートリアルのすべてのコードを含むサンプルプロジェクトです。
それはシリーズのパート1のためのそれです。 これまでのところ、あなただけの画面の下部に落ちるスイカテクスチャ多角形を持っています。
しかし、Box2Dチュートリアルで通常見られるような透明なスペースを持つ長方形のスプライトを描画する代わりに、Prkitを使用してBox2Dボディの頂点に対応するテクスチャの部分のみを描画します。 これはすぐに便利になります!
今、あなたは果物をスライスする機能を追加するチュートリアルのパート2の準備が整いました!
それまでの間、この部分について質問やコメントがある場合は、以下のフォーラムの議論に参加してください!
これは、Iosの開発者であり、White Widgetの共同創設者であるiOS Tutorial TeamのメンバーであるAllen Tanによる投稿です。 また、Google+やTwitterで彼を見つけることができます。
raywenderlich.com 週刊
raywenderlich.com ニュースレターは、あなたがモバイル開発者として知っておく必要があるすべてのものに最新の滞在する最も簡単な方法です。
私たちのチュートリアルやコースの毎週のダイジェストを取得し、ボーナスとして無料の詳細な電子メールコースを受け取ります!