Hoe maak je een spel als Fruit Ninja met Box2D en Cocos2D – deel 1

Dit is een bericht van iOS Tutorial teamlid Allen Tan, een iOS ontwikkelaar en medeoprichter Bij White Widget. Je kunt hem ook vinden op Google+ en Twitter.

in deze tutorial leer je hoe je een sprite cutting game maakt voor de iPhone vergelijkbaar met Fruit Ninja door Halfbrick Studios met behulp van de krachtige Cocos2D en Box2D bibliotheken samen met enkele vooraf gemaakte tools.

in de meeste slicing spellen, Wanneer je een snijlijn door een sprite trekt, converteert het spel meestal de sprite afbeelding in twee vooraf getekende sprite afbeeldingen met de slice altijd in het midden, ongeacht waar je eigenlijk snijdt.

maar deze handleiding zal een nog koelere techniek demonstreren. Onze vruchten kunnen meerdere malen worden gesneden, en ze zullen dynamisch worden verdeeld op basis van de exacte snijlijnen!

zoals u zich kunt voorstellen, is dit een geavanceerde techniek, dus deze tutorial is voor geavanceerde Cocos2d en Box2D ontwikkelaars. Als je nieuw bent in Cocos2D of Box2D, moet je (op zijn minst) eerst de intro naar Cocos2D en intro naar Box2D tutorials doorlopen voordat je verder gaat met deze tutorial.

deze tutorial serie bestaat uit drie delen:

  • In dit eerste deel van de serie leg je de basis voor het spel en leer je hoe je getextureerde polygonen maakt.
  • het tweede deel laat u zien hoe u & splitst deze getextureerde polygonen.
  • het derde deel laat je zien hoe je dit in een compleet spel kunt veranderen door gameplay en effecten toe te voegen.

Ik wil in het bijzonder Rick Smorawski bedanken voor het leggen van de basis voor het project waarop deze handleiding is gebaseerd. Hij was verantwoordelijk voor het overzetten van deze flash-gebaseerde slicing demo naar Cocos2D, en ook voor het overzetten van CCBlade en PRKit naar Cocos2D 2.0.

Lees verder om de video te bekijken van wat je gaat maken en om aan de slag te gaan met het leren van enkele coole nieuwe technieken!

Speldemo

hier is een demovideo die u laat zien wat u in deze tutorial serie gaat maken:

zoals ik al zei, Zult u zien dat het fruitsnijeffect echt dynamisch is. Het fruit wordt dynamisch gesneden op basis van waar je snijdt, en omdat je objecten meerdere keren kunt snijden, kun je echt dingen hakken!

u kunt zien dat u ook een cool slicing trail-effect zult implementeren, sommige particle-systemen, gameplay-logica en geluiden om dingen op te fleuren.

er is veel te bespreken – dus laten we beginnen!

aan de slag: projectinstellingen

u gaat Cocos2D 2 gebruiken.X in dit project, dus ga je gang en download het als je het nog niet hebt. Merk op dat u vrij bent om Cocos2D 1 te gebruiken.X in plaats van 2.X. Met 1.X, kunt u de delen over het omzetten van PRKit en CCBlade naar Cocos2D 2 overslaan.X, maar zorg ervoor dat u aandacht besteedt aan de andere kleine wijzigingen die u aanbrengt in die klassen.

na het downloaden dubbelklikt u op de tar om het te verwijderen en installeert u de sjablonen met de volgende commando ‘ s in de Terminal:

cd ~/Downloads/cocos2d-iphone-2.0-beta./install-templates.sh -f -u

Start Xcode op en maak een nieuw project aan met de iOS \ cocos2d v2.x \ cocos2d iOS met Box2d sjabloon en noem het CutCutCut.

uw nieuwe project ziet er ongeveer zo uit:

Project Start

eerste dingen eerst-U moet het sjabloon een beetje opschonen om tot een goed beginpunt te komen.

Open HelloWorldLayer.h en verwijder de volgende regel:

CCTexture2D *spriteTexture_;// weak ref

schakelen naar HelloWorldLayer.mm en maak de volgende wijzigingen

// 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;

op dit punt heb je alle verwijzingen naar PhysicsSprite verwijderd uit HelloWorldLayer, maar verwijder de bestanden nog niet helemaal uit het project. Later, je nodig hebt om een methode te kopiëren die PhysicsSprite.mm bevat ergens anders, dus laat het maar even zitten.

druk op Command + R om uw project te compileren en uit te voeren, en u ziet een leeg scherm met een groene rand eromheen:

Clean Slate

de resterende template code heeft Box2D debug-tekening ingesteld, die randen tekent rond de Box2D-lichamen op het scherm. Zie je de dunne groene lijnen rond het scherm? Dat zijn de muren gegenereerd door de standaard initphysics methode die bij de template werd geleverd.

kijk naar de resterende template code om er zeker van te zijn dat u begrijpt wat er tot nu toe gaande is – het initialiseert een Box2D wereld, stelt de grond (groene randen), stelt debug tekening, enz. Dit is een vrij goed “bijna leeg” startpunt met Box2D waar we vanaf hier op kunnen voortbouwen.

Resource Kit

download vervolgens de resources voor dit project en pak het bestand uit.

voeg nog niet alles toe aan het project; sommige bestanden zijn eigenlijk optioneel. Houd de map wel bij de hand – als je door de tutorial gaat, zal ik je van tijd tot tijd vragen om een aantal van deze bestanden toe te voegen aan het project.

hier is wat u binnen vindt:

  • een achtergrondafbeelding en een bos fruitkunst gemaakt door Vicki, en andere diverse afbeeldingen in de map Afbeeldingen
  • de achtergrondgeluidsmix gemaakt met behulp van gomix.in de map Geluiden
  • geluidseffecten gemaakt met behulp van bfxr of gedownload van freesound in de map Geluiden
  • Alle systemen zijn gemaakt met een Deeltjesgrootte van de Ontwerper in de Deeltjes map
  • EEN PLIST-bestand gegenereerd door PhysicsEditor met vertex informatie voor de Vruchten & Bom klassen in de Misc-map
  • Fruit & Bom-lessen in de Klassen map
  • De versies van PRKit en CCBlade je zal gebruiken in de tutorial in de Klassen map
  • Een attribuut lijst voor de middelen die in het kader van de Toekenning van Licentie in de Diversen map

gestructureerde polygonen tekenen met PRKit

ons doel is om sprites in meerdere stukken te snijden. Een typische CCSprite bevat een textuur, en een bounding box maakt niet uit welke vorm de afbeelding is. Dit is niet geschikt voor ons spel, omdat het kennen van de werkelijke vormen in de beelden is een cruciale stap om sprites die kunnen worden gesneden, gesneden, en splitsen.

u moet getextureerde polygonen maken, die:

  • Maak een overeenkomst aan tussen een veelhoek / vorm en een afbeelding (Texture Mapping)
  • Toon alleen de delen van de afbeelding die binnen de grenzen van de veelhoek liggen (Texture vulling)

noch Cocos2D noch Box2D wordt geleverd met een ingebouwde klasse die de aangepaste functies die u wilt behandelt, en normaal gesproken, zou dit enige triangulatie in combinatie met aangepaste OpenGL tekencode.

klinkt moeilijk, toch?

gelukkig zijn alle ingewikkelde berekeningen en tekencode die nodig zijn om dit te bereiken al geschreven door de goede mensen bij Precognitief onderzoek. Ze creëerden een toevoeging aan de Cocos2D bibliotheek genaamd PRKit, die textuur Mapping en vulling behandelt.

om te beginnen met gestructureerde polygonen, download PRKit, pak het uit en sleep de prkit-map naar uw project. Zorg ervoor dat “items kopiëren naar de map van de doelgroep” is aangevinkt en “groepen maken voor toegevoegde mappen” is geselecteerd.

merk op dat PRKit wordt onderhouden door Precognitief onderzoek, dus het kan op tijd worden bijgewerkt. Om verwarring te voorkomen, onze resource kit bevat ook de exacte versie van PRKit die ik gebruikte bij het maken van deze tutorial.

uw project zou nu deze bestanden moeten bevatten:

PRKit Yey!

compileren en uitvoeren, en u zult een paar fouten tegenkomen:

PRKit moet geconverteerd worden

de fouten verschijnen omdat PRKit gemaakt is voor Cocos2D 1.X, die OpenGL ES 1.1 gebruikt, terwijl u Cocos2D 2 gebruikt.X, die gebruik maakt van OpenGL ES 2.0, en er zijn aanzienlijke verschillen tussen de twee.

open PRFilledPolygon om dit op te lossen.m en maak deze veranderingen:

// 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);}

laten we deze veranderingen beetje bij beetje doornemen.

eerst heeft elke CCNode in Cocos2D een OpenGL ES 2.0 shader programma eraan gekoppeld. Om de PRFilledPolygon te tekenen, moet je de ingebouwde “Position/Texture” shader aanklagen, die je toewijst in de init methode.

vervolgens moet u de juiste textuurcoördinaten instellen voor elk punt in de veelhoek. Om dit te doen, moet je twee wijzigingen maken de calculatetexturecoördinates methode:

  • schaal: aangezien deze klasse haar eigen berekeningen uitvoert op de coördinaten van haar textuur, verwerkt zij niet automatisch het Retina-display. Om dit op te lossen, vermenigvuldig je gewoon textuur.pixelsWide met CC_CONTENT_SCALE_FACTOR – een handige vermenigvuldigingswaarde van Cocos2D voor het converteren van waarden tussen reguliere en retina equivalenten.
  • Flip Y: om de een of andere reden tekent PRFIlledPolygon texturen ondersteboven, dus u kunt de y-waarde hier gewoon omdraaien.

Laatst is de tekencode bijgewerkt naar OpenGL ES 2.0, op dezelfde manier als Hoe Ccsprite tekening veranderde van Cocos2D 1.X naar Cocos2D 2.X:

  • begin met cc_node_draw_setup() aan te roepen om het knooppunt voor te bereiden op tekenen.
  • aanroepen naar glDisableClientState () en glEnableClientState() zijn verouderd en worden weggegooid.
  • de commando ‘ s glVertexPointer() en glTexCoordPointer() worden beide vervangen door glVertexAttribPointer(), die nu als eerste optie Vertexpositie of Textuurcoördinaat accepteert.
  • de instelling van glTexEnvf (), die verantwoordelijk was voor het herhalen van de sprite in het geval de veelhoek groter was dan de texture, wordt vervangen door aanroepen naar glTexParameteri ().

als u in de war bent door een van deze, wilt u misschien onze OpenGL ES 2.0 Voor iPhone en aangepaste Cocos2D 2 bekijken.X Shaders tutorials voor meer achtergrondinformatie. Maar je hoeft je er niet al te veel zorgen over te maken, want op dit moment is alles wat we doen het porten van de klas om te werken in Cocos2D 2.X:]

compileren en uitvoeren, en alle PRKit fouten moeten verdwijnen!

het is tijd om PRKit in actie te brengen. U zult sub-classing prkit ‘ s prfilledpolygon klasse om een basis PolygonSprite klasse die onze vruchten zal trekken te maken.

de PolygonSprite bouwt voort op PRFilledPolygon door een Box2D body aan de sprite te koppelen, en het zal ook andere aangepaste variabelen en methoden bevatten voor de fruits in onze spelimplementatie.

laten we ter zake komen. Druk op Command + N en maak een nieuw bestand aan met de iOS \ cocos2d v2.X \ Ccnode Class sjabloon. Maak er een subklasse van PRFilledPolygon van en noem het PolygonSprite.m.

schakel over op PolygonSprite.h en maak de volgende wijzigingen:

// 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;

de bovenstaande code declareert de basisvariabelen en methoden die je nodig hebt om een PolygonSprite aan te maken. Deze zijn:

  • body: Dit is de Box2D body die aan onze sprite is bevestigd. Het is nodig voor fysica simulatie.
  • origineel: Complete en gesneden sprites zullen dezelfde PolygonSprite Klasse gebruiken, als zodanig, onderscheid maken tussen de twee zal belangrijk zijn. Als dit ja is, betekent dit dat het het ongesneden of originele object is dat je hebt gemaakt, anders is het gewoon een stuk van het geheel.
  • centroid: Het midden van de veelhoek in de afbeelding zal niet altijd hetzelfde zijn als het midden van de afbeelding, dus het is handig om deze waarde op te slaan.
  • eigenschappen: Toon alle variabelen met eigenschappen zodat andere klassen ze vrij kunnen benaderen.
  • init / spriteWith*: onze belangrijkste init-methoden volgen dezelfde naamgevingsconventie als Cocos2D.
  • andere methoden: dit zijn methoden die & creëren en omgaan met de bijgevoegde Box2D-body en zijn eigenschappen.
  • PTM_RATIO: Verhouding Pixels / Meters. Box2D heeft deze conversiewaarde nodig omdat het gaat om Meters in plaats van Pixels.

schakel snel over naar PolygonSprite.m en hernoem het PolygonSprite.mm. alle klassen die Objective-C (Cocos2D) en C++ (Box2D) code combineren moeten een “.mm” extensie hebben om de compiler op de hoogte te stellen van de gemengde syntaxis.

volgende, breng de volgende wijzigingen aan in 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;}

net als bij Cocos2D zijn alle spriteWith* methoden gewoon autorelease tegenhangers van de initwith* methoden, terwijl initWithWorld nog geen gebruik heeft voor deze klasse, maar in plaats daarvan zal het later worden gebruikt door PolygonSprite ‘ s subklassen.

het grootste deel van de veranderingen kan worden gevonden in de initwithfile en initWithTexture methoden. Om de stroom van dingen te krijgen, zal het creëren van een vrucht in deze volgorde worden genoemd:

init-reeks

  • initWithWorld: dit is bedoeld voor subklassen van PolygonSprite dus je doet niets anders dan nul terug te geven, en er later mee om te gaan.
  • initWithFile: dit voegt de textuur van ons bestand toe en geeft alles door aan initWithTexture.
  • initWithTexture: onze belangrijkste initialisatie. PRFilledPolygon heeft een textuur nodig en alle hoekpunten van de veelhoek die het vult. Aangezien de vorige stap al het textuurgedeelte behandelde, behandelt deze stap de hoekpunten door ze te verzamelen uit de Box2D body van de sprite. Nadat ze aan PRFilledPolygon zijn doorgegeven, gaat het verder met het initialiseren van de variabelen die je eerder hebt gedeclareerd.
  • initWithPoints: alles wat dit doet zit in PRKit en het goede is dat je PRKit niet meer hoeft aan te raken nu je de code hebt bijgewerkt.

nog binnen PolygonSprite.mm, voeg de volgende methoden toe:

-(void)setPosition:(CGPoint)position{ ; _body->SetTransform(b2Vec2(position.x/PTM_RATIO,position.y/PTM_RATIO), _body->GetAngle());}-(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{ b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; bodyDef.position = position; bodyDef.angle = rotation; b2Body *body = world->CreateBody(&bodyDef); b2FixtureDef fixtureDef; fixtureDef.density = density; fixtureDef.friction = friction; fixtureDef.restitution = restitution; fixtureDef.filter.categoryBits = 0; fixtureDef.filter.maskBits = 0; b2PolygonShape shape; shape.Set(vertices, count); fixtureDef.shape = &shape; body->CreateFixture(&fixtureDef); return body;}-(void)activateCollisions{ b2Fixture *fixture = _body->GetFixtureList(); b2Filter filter = fixture->GetFilterData(); filter.categoryBits = 0x0001; filter.maskBits = 0x0001; fixture->SetFilterData(filter);}-(void)deactivateCollisions{ b2Fixture *fixture = _body->GetFixtureList(); b2Filter filter = fixture->GetFilterData(); filter.categoryBits = 0; filter.maskBits = 0; fixture->SetFilterData(filter);}

in de bovenstaande code overbelast u eerst de setPosition methode van CCNode, zodat wanneer u de positie van de sprite bijwerkt, de bijbehorende Box2D body positie ook wordt bijgewerkt.

u maakt dan een eenvoudige methode voor het maken en definiëren van een Box2D-body. Om een lichaam te maken, moet je een lichaamsdefinitie, een lichaamsobject, een vorm en een armatuurdefinitie definiëren. Er worden hier nog geen echte harde waarden toegekend aangezien deze methode later zal worden gebruikt door subklassen van PolygonSprite.

alleen de categoryBits en maskBits vallen op. Deze twee worden gebruikt voor het filteren van botsingen tussen objecten, zodat als een categorie bit van een object overeenkomt met een masker bit van een ander object en vice versa, er een botsing zal zijn tussen die twee objecten. Je stelt deze eerst in op 0 omdat je niet wilt dat er botsingen plaatsvinden wanneer de objecten voor het eerst worden geïnitialiseerd.

tenslotte definieert u twee methoden die simpelweg de categoryBits en maskBits vervangen, zodat u de botsingen van onze PolygonSprites kunt activeren en deactiveren.

er is nog één ding toe te voegen 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_;}

Weet je nog toen ik zei dat je iets nodig had van PhysicsSprite? Dit is het dan. Het enige wat dit doet is ervoor zorgen dat onze Box2D vorm en onze sprite in dezelfde positie zijn wanneer ze bewegen. Het is voor ons voorbereid door Cocos2D en dat maakt het des te meer geweldig.

na het kopiëren van de bovenstaande code, kunt u nu beide PhysicsSprite verwijderen.h en PhysicsSprite.mm van het project als je volledig geëlimineerd hun nut.

compileren en uitvoeren, en alles zou in orde moeten zijn. Je bent klaar met PolygonSprite voor nu.

onze vruchten plannen

voordat u klassen voor onze vruchten maakt, moet u duidelijk zijn over de regels die de afbeeldingen en hun vormen moeten volgen. Aangezien u onze texturen wilt toewijzen aan enkele Box2D-polygonen, moet u zich ook houden aan de polygoonbeperkingen van Box2D. Je moet twee dingen in gedachten houden:

  • veelhoeken moeten convex zijn, wat betekent dat geen binnenlandse hoek groter is dan 180.
  • polygonen mogen niet groter zijn dan 8 hoekpunten.

u kunt deze beperking omzeilen als u toestaat dat elk lichaam meerdere vormen bevat. Box2D kan concave vormen aan als u een triangulatiemethode gebruikt en de concave vormen uit verschillende driehoeken maakt, maar dit valt buiten het bereik van de tutorial.

om het simpel te houden, heb je in deze tutorial een 1 Body is to 1 Shape regel.

opmerking: Fysicseditor, het gereedschap dat we later in deze tutorial zullen behandelen, bevat eigenlijk code om automatisch polygonen te trianguleren die u tekent in een verzameling convexe vormen. Maar, zoals ik al zei, We proberen het hier simpel te houden, zodat we er zeker van zijn dat we onze vormen convex tekenen, zodat we maar één vorm per lichaam hebben.

kijk eens naar deze twee vruchten:

concaaf vs Convex

het gebruik van de banaan is geen goed idee omdat hij van nature concaaf is. De watermeloen aan de andere kant is erg goed omdat je een convexe veelhoek kunt definiëren die sterk lijkt op zijn vorm.

als u polygoonvormen zou definiëren die de regels van Box2D voor de twee vruchten volgen, zou u min of meer deze vormen krijgen:

Kader2d Vormomtrek

de watermeloen-veelhoek past perfect bij de afbeelding, terwijl de banaan-veelhoek een grote lege ruimte heeft waar de afbeelding naar binnen kromt. Box2D zal die ruimte behandelen als onderdeel van ons object, en het kan de banaan onnatuurlijk laten voelen wanneer het botst met andere objecten, of wanneer het wordt gesneden.

dit betekent niet dat u de banaan niet kunt gebruiken, maar eerder dat het gewoon niet wordt aanbevolen om de banaan te gebruiken. In feite, het spel dat u zal maken in deze tutorial zal deze dezelfde banaan te gebruiken.

de eerste vrucht aanmaken

het is tijd om de eerste vrucht te maken: de watermeloen (minstens een plakje).

als je terugdenkt aan de stroom van ons polygonsprite ‘ s initialisatie proces, Weet je dat initWithTexture een Box2D body verwacht, maar de stap daarvoor, initWithFile, biedt dit niet.

de reden hiervoor is dat je het lichaam per vrucht afzonderlijk moet creëren en definiëren, dus het zal de allereerste stap moeten zijn, initWithWorld, die het lichaam creëert en elke andere specifieke waarde voor elke vrucht bepaalt.

om onze Box2D body te maken, moet u eerst de hoekpunten kennen van de polygoonvorm die u wilt maken. Er zijn verschillende manieren om dit te doen, maar voor deze tutorial, zul je een handige tool genaamd PhysicsEditor gebruiken. Deze tool is gevuld met functies, maar u zult het alleen gebruiken om ons te begeleiden bij het verkrijgen van de coördinaten van de hoekpunten van onze veelhoek.

als je het niet hebt, download dan PhysicsEditor, installeer het en start het op. U krijgt een leeg project met 3 panelen/kolommen.

werken met PhysicsEditor is vrij eenvoudig. Aan de linkerkant zet je alle afbeeldingen waar je mee wilt werken. In het midden definieert u visueel een veelhoek voor uw afbeelding. Rechts heb je de parameters voor het lichaam.

Fysica-Editor!

pak watermeloen.png uit de map Afbeeldingen van de resource kit en sleep het naar het linkerpaneel. Je ziet nu de watermeloen op het middenpaneel.

verhoog de vergroting onderaan dit paneel tot een comfortabel niveau en tik vervolgens op de Vijfhoekknop in het bovenste deel van dit paneel om een 3-zijdige polygoonvorm te maken.

Klik met de rechtermuisknop op de veelhoek en kies “Add Vertex” totdat je 5-8 hoekpunten hebt. Verplaats de hoekpunten rond de randen van de watermeloen, terwijl je zorgt voor twee dingen:

  • de veelhoek die u maakt is Convex.
  • alle pixels van de watermeloen bevinden zich in de veelhoek.

Opmerking: Een andere sneltoets om de vormen te tekenen is om het toverstokje van PhysicsEditor te gebruiken. Stel gewoon de tolerantie hoog (5-8), zodat je eindigt met ongeveer 5-8 punten, en tweak de punten vanaf daar.

voeg alle andere vruchten en de bomafbeelding toe uit de map Images van de resource kit en doe hetzelfde voor hen.

u moet vormen definiëren voor de volgende afbeeldingen:

  • banaan.PNG
  • bom.PNG
  • druiven.PNG
  • ananas.PNG
  • aardbei.PNG
  • watermeloen.png

als u klaar bent, wijzig dan rechtsboven de waarde van Exporter naar ” Box2D generic (PLIST)”, en u moet eindigen met iets als dit:

definieer vormen gemakkelijk met PhysicsEditor!

druk op ” publiceren “of” publiceren als ” Om het PLIST-bestand met de vertex-informatie te exporteren. Sla het bestand op als vruchten.plist.

als voorbeeld, de vruchten.plist die u gebruikt voor deze tutorial bevindt zich in de map Misc van de resource kit.

u wilt alleen kijken naar de informatie in het PLIST-bestand, dus voeg dit bestand niet toe aan uw project, maar open gewoon fruit.plist met behulp van Xcode om de inhoud ervan te bekijken op een georganiseerde manier.

klik op het driehoekspictogram naast “lichamen” om deze sectie uit te vouwen en u zult de lijst met afbeeldingen zien waarvoor u vormen hebt gedefinieerd. Je moet naar het diepste niveau boren om de hoekpunten van de watermeloen te krijgen.:

 de PhysicsEditor PLIST

vouw watermeloen/armaturen/Item 0/polygonen uit en u ziet nu een ander Item 0 van type Array onder polygonen. Deze laatste array is jouw vorm. Als je een convexe vorm met 8 of minder hoekpunten goed had gedefinieerd, zou je slechts één array onder polygonen moeten zien.

als u meer dan één ziet, i.E Item 0 Array, Item 1 Array, etc, dan betekent het dat PhysicsEditor een complexe vorm heeft gemaakt omdat je ofwel te veel hoekpunten hebt gedefinieerd, ofwel een holle veelhoek hebt gevormd. Als dit gebeurt, ga dan terug naar Fysicseditor en repareer je vorm.

vouw vervolgens Item 0 van type Array uit om de definitieve lijst van items te zien. Dit zijn uw hoekpunten, en de waarde die u ziet aan de rechterkant met dit formaat { nummer, nummer } zijn uw x & y-Coördinaten voor elk hoekpunt.

Nu u de exacte waarden voor de hoekpunten van uw veelhoek hebt, kunt u doorgaan met het maken van de Watermeloenklasse.

maak in Xcode een nieuw bestand aan met de iOS\cocos2d v2.X \ Ccnode Class sjabloon. Maak er een onderklasse van PolygonSprite van en noem het watermeloen. Open Watermeloen.h en maak de volgende wijzigingen:

// Add to top of file#import "PolygonSprite.h"

schakel over op watermeloen.m, hernoem het naar Watermelon.mm, en voeg de volgende init methode:

// 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;}

in de bovenstaande code definieer je eerst hoeveel hoekpunten er zijn, wat in dit geval 7 is. Vervolgens Maak je een array van hoekpunten met alle coördinaten die je net zag in de PLIST. U gebruikt deze informatie om een body te maken met behulp van de convenience-methode die u hebt gedefinieerd in PolygonSprite.

je zet een beetje wrijving in zodat de vormen niet eindeloos glijden, en je zet ook een beetje restitutie in zodat vormen niet stoppen wanneer ze tegen elkaar stuiteren.

als laatste maakt u het object aan door de initialisatie van de superklasse aan te roepen en de naam van het afbeeldingsbestand, de Box2D-body, door te geven en te verklaren dat dit een originele vrucht is.

u hebt de watermeloenafbeeldingen van de resource kit nodig, dus nu is het een goed moment om alle grafische bronnen toe te voegen die u nodig hebt voor de rest van de tutorial.

in uw project Navigator paneel, klik met de rechtermuisknop op Resources en selecteer”Add Files to CutCutCut” (Bestanden toevoegen aan CutCutCut). Voeg de map Afbeeldingen van de bronkit toe aan het project. Zorg ervoor dat “items kopiëren naar de map van de doelgroep” is aangevinkt en “groepen maken voor toegevoegde mappen” is geselecteerd.

volg dezelfde stappen om banaan, druiven, ananas, aardbei en bom te maken.

u hebt alleen stap voor stap onderzocht hoe u de eerste vrucht kunt maken, aangezien het in principe een spoelproces & is dat voor elke vrucht wordt herhaald. De resource kit bevat kant-en-klare fruit en bom klassen in de map klassen voor u om naar te kijken in het geval u nog steeds begeleiding nodig hebt, of u kunt ze allemaal toevoegen aan uw project als u deze stap wilt overslaan.

compileren en uitvoeren, en zorg ervoor dat alles in orde is.

het toevoegen van een vrucht aan de scène

tot nu toe is er nog niets gebeurd op het scherm, en u staat duidelijk te popelen om de vruchten van uw arbeid te zien – woordspeling bedoeld! :]

schakel over naar HelloWorldLayer.h en maak de volgende wijzigingen:

// Add to top of file#import "PolygonSprite.h"// Add inside the @interfaceCCArray *_cache;// Add after the @interface@property(nonatomic,retain)CCArray *cache;

terugschakelen naar HelloWorldLayer.mm en deze veranderingen:

// 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]; ; ; ;}

je declareert een cache array, die alle vruchten en bommen die je maakt in de toekomst zal bevatten. Vervolgens Maak je 1 watermeloen en voeg je deze toe aan de scène. Je roept activateCollisions zodat de watermeloen niet door de muren.

compileer en voer uit, en je zou een watermeloen uit het midden van het scherm moeten zien vallen, en land aan de onderkant zoals hieronder getoond.

de vrucht van uw arbeid

het is mogelijk dat u merkt dat de watermeloen niet precies in het midden staat. De reden hiervoor is dat je het object hebt gepositioneerd op basis van zijn Box2D lichaam, en de oorsprong van ons Box2D lichaam is in de linkerbenedenhoek van het object. De dunne omtrek rond de watermeloen is zichtbaar omdat de debug-tekenmodus nog steeds is ingeschakeld.

Waar Moet Ik Nu Naartoe?

hier is een voorbeeld project met alle code uit de bovenstaande tutorial.

dat is het voor deel 1 van de serie. Tot nu toe heb je een watermeloen getextureerde veelhoek die gewoon naar de onderkant van het scherm valt.

maar in plaats van een rechthoekige sprite met transparante ruimte te tekenen zoals je meestal ziet in Box2D tutorials, gebruikt dit PRKit om alleen de delen van de textuur te tekenen die overeenkomen met de hoekpunten van de Box2D body. Dit komt binnenkort van pas!

nu ben je klaar voor Deel 2 van de tutorial, waar je de mogelijkheid toevoegt om de vruchten te snijden!

in de tussentijd, als je vragen of opmerkingen hebt over dit deel, neem dan deel aan de forumdiscussie hieronder!


Dit is een bericht van iOS Tutorial teamlid Allen Tan, een iOS ontwikkelaar en medeoprichter Bij White Widget. Je kunt hem ook vinden op Google+ en Twitter.

raywenderlich.com wekelijks

de raywenderlich.com nieuwsbrief is de makkelijkste manier om op de hoogte te blijven van alles wat u als mobiele ontwikkelaar moet weten.

ontvang een wekelijks overzicht van onze tutorials en cursussen, en ontvang een gratis uitgebreide e-mail cursus als bonus!

Leave a Reply

Het e-mailadres wordt niet gepubliceerd.