Sådan laver du et spil som Fruit Ninja med Boks2d og Cocos2D – Del 1
dette er et indlæg af iOS Tutorial-teammedlem Allen Tan, en iOS-udvikler og medstifter hos hvid kontrol. Du kan også finde ham på Google+ og kvidre.
i denne tutorial lærer du, hvordan du laver et sprite-skærespil til iPhone, der ligner Fruit Ninja by Halfbrick Studios ved hjælp af de kraftfulde Cocos2D-og Boks2d-biblioteker sammen med nogle foruddefinerede værktøjer.
i de fleste skærespil, når du tegner en snitlinie gennem en sprite, konverterer spillet typisk sprite-billedet til to forudtegnede sprite-billeder med skiven altid nede i midten, uanset hvor du faktisk skærer.
men denne tutorial vil demonstrere en endnu køligere teknik. Vores frugter vil kunne skæres flere gange, og de vil blive opdelt dynamisk baseret på de nøjagtige snitlinjer!
som du måske forestiller dig, er dette en avanceret teknik, så denne tutorial er til avancerede Cocos2D-og Boks2d-udviklere. Hvis du er ny til Cocos2D eller Boks2d, skal du først gennemgå (i det mindste) introen til Cocos2D og intro til Boks2d-tutorials, før du fortsætter med denne tutorial.
denne tutorial serie er opdelt i tre dele:
- i denne første del af serien vil du lægge grundlaget for spillet og lære at oprette teksturerede polygoner.
- den anden del viser dig, hvordan du skærer & opdele disse strukturerede polygoner.
- den tredje del viser dig, hvordan du gør dette til et komplet spil ved at tilføje gameplay og effekter.
Jeg vil gerne takke Rick Smoravski for at lægge grundlaget for projektet, som denne tutorial er baseret på. Han var ansvarlig for portering af denne flash-baserede skivedemo til Cocos2D og også for portering af CCBlade og PRKit til Cocos2D 2.0.
fortsæt med at læse for at tjekke videoen af, hvad du vil lave, og for at komme i gang med at lære nogle seje nye teknikker!
Game Demo
her er en demo video, der viser dig, hvad du vil lave i denne tutorial serie:
som jeg nævnte, vil du se, at frugtskæringseffekten er virkelig dynamisk. Frugten skæres dynamisk baseret på hvor du skiver, og da du kan skære objekter flere gange, kan du virkelig hugge ting op!
du kan se, at du også vil gennemføre en cool udskæring trail effekt, nogle partikel systemer, gameplay logik, og lyde til at krydre tingene op.
der er meget at dække – så lad os komme i gang!
Kom godt i gang: Projektopsætning
du skal bruge Cocos2D 2.I dette projekt, så gå videre og hente det, hvis du ikke har det allerede. Bemærk, at du er fri til at bruge Cocos2D 1.I stedet for 2.S. Med 1.Du kan springe dele om konvertering af PRKit og CCBlade til Cocos2D 2 over.Vær opmærksom på de andre små ændringer, du foretager i disse klasser.
dobbeltklik på tjære for at fjerne arkiveringen, og installer derefter skabelonerne med følgende kommandoer i terminalen:
cd ~/Downloads/cocos2d-iphone-2.0-beta./install-templates.sh -f -u
Opret et nyt projekt med iOS \ cocos2d v2.cocos2d iOS med boks 2D skabelon og navngiv det CutCutCut.
dit nye projekt skal se sådan ud:
første ting først – du skal rydde op i skabelonen lidt for at komme til et godt udgangspunkt.
Åben Hellorldlayer.h og fjern følgende linje:
CCTexture2D *spriteTexture_;// weak ref
Skift til HelloWorldLayer.mm og foretag følgende ændringer
// 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;
på dette tidspunkt har du fjernet alle henvisninger til Fysikprite fra Hellorldlayer, men fjern ikke filerne fra projektet endnu. Senere skal du kopiere en metode, der PhysicsSprite.mm indeholder et andet sted, så lad det sætte for nu.
Hit Command + R for at kompilere og køre dit projekt, og du skal se en tom skærm med en grøn kant omkring den:
den resterende skabelonkode har oprettet Boks2d debug-tegning, der trækker grænser rundt om Boks2d-organerne på skærmen. Se de tynde grønne linjer trukket rundt på skærmen? Det er væggene genereret af standard initphysics-metoden, der fulgte med skabelonen.
se på den resterende skabelonkode for at sikre dig, at du forstår, hvad der foregår indtil videre – den initialiserer en Boks2d-verden, opretter jorden (grønne grænser), opretter debug-tegning osv. Dette er et ret godt “næsten tomt” udgangspunkt med Boks2d, vi kan bygge videre på herfra.
Resource Kit
næste Hent ressourcerne til dette projekt og Pak filen ud.
tilføj ikke alt i projektet endnu; nogle af filerne er faktisk valgfri. Hold mappen handy selv-som du går gennem tutorial, fra tid til anden vil jeg bede dig om at tilføje nogle af disse filer i projektet.
her er hvad du finder indeni:
- et baggrundsbillede og en flok frugtkunst lavet af Vicki og andre diverse billeder i mappen Billeder
- baggrundslydblandingen lavet ved hjælp af gomiks.det i mappen lyde
- lydeffekter lavet ved hjælp af freesound i mappen lyde
- alle partikelsystemer oprettet med Partikeldesigner i mappen partikler
- en PLIST-fil genereret af PhysicsEditor indeholdende toppunktinformation for frugterne & Bomb-klasser i mappen Misc
- frugter & Bomb-klasser i mappen klasser
- versionerne af prkit og Ccblade, du vil bruge i vejledningen i klassemappen
- en tilskrivningsliste for ressourcer, der er under tilskrivningslicensen i Misc folder
tegning teksturerede polygoner med PRKit
vores mål er at skære sprites i flere stykker. En typisk CCSprite indeholder en tekstur og en afgrænsningsboks, uanset hvilken form billedet er. Dette er ikke egnet til vores spil, da kendskab til de faktiske former i billederne er et afgørende skridt til at skabe sprites, der kan skæres, skiver og opdeles.
du skal oprette teksturerede polygoner, som:
- Opret en korrespondance mellem en polygon / form og et billede (Teksturkortlægning)
- Vis kun de dele af billedet, der er inden for polygonens grænser (Teksturfyldning)
hverken Cocos2D eller Boks2d leveres med en indbygget klasse, der håndterer de brugerdefinerede funktioner, du ønsker, og normalt, dette ville tage en vis triangulering kombineret med brugerdefineret OpenGL-tegningskode.
lyder hårdt rigtigt?
heldigvis er alle de komplicerede beregninger og tegnekoder, der er nødvendige for at opnå dette, allerede skrevet af de gode folk på Precognitive Research. De skabte en tilføjelse til Cocos2D-biblioteket ved navn PRKit, som håndterer Teksturkortlægning og påfyldning.
for at komme i gang med teksturerede polygoner skal du hente PRKit, udpakke det og trække prkit-mappen ind i dit projekt. Sørg for, at” kopier elementer til destinationsgruppens mappe “er markeret, og” Opret grupper for eventuelle tilføjede mapper ” er valgt.
Bemærk, at PRKit vedligeholdes af Prækognitiv forskning, så det kan blive opdateret i tide. For at undgå forvirring indeholder vores ressourcesæt også den nøjagtige version af prkit, jeg brugte til at lave denne tutorial.
dit projekt skal nu indeholde disse filer:
kompilere og køre, og du vil støde på et par fejl:
fejlene dukker op, fordi PRKit blev lavet til Cocos2D 1.OpenGL ES 1.1, mens du bruger Cocos2D 2.OpenGL ES 2.0, og der er betydelige forskelle mellem de to.
for at løse dette skal du åbne PRFilledPolygon.m og foretage disse ændringer:
// 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);}
lad os gennemgå disse ændringer lidt efter lidt.
først i Cocos2D har hver CCNode et OpenGL ES 2.0 shader-program knyttet til det. At tegne PRFilledPolygon, skal du sagsøge den indbyggede “Position/tekstur” shader, som du tildeler i init-metoden.
Dernæst skal du oprette de korrekte teksturkoordinater for hvert punkt i polygonen. For at gøre dette skal du foretage to ændringer calculateteksturecoordinates-metoden:
- skala: da denne klasse foretager sine egne beregninger på koordinaterne for dens struktur, håndterer den ikke automatisk retina-skærmen. For at løse dette multiplicerer du bare tekstur.CC_CONTENT_SCALE_FACTOR – en praktisk multiplikatorværdi leveret af Cocos2D til konvertering af værdier mellem almindelige og retina-ækvivalenter.
- Flip Y: af en eller anden grund tegner PRFIlledPolygon teksturer på hovedet, så du bare vender y-værdien her.
sidst opdateres tegningskoden til OpenGL ES 2.0, på samme måde som hvordan CCSprite tegning ændret fra Cocos2D 1.Til Cocos2D 2.K:
- Start med at ringe til CC_NODE_TRÆK_SETUP () for at forberede noden til tegning.
- opkald til glDisableClientState() og glEnableClientState() er forældede og kasseres.
- kommandoerne glverpointer() og glverpointer() erstattes begge af glverpointer(), som nu accepterer Toppunktposition eller Teksturkoordinat som sin første mulighed.
- opsætningen af glteksenvf(), som var ansvarlig for at gentage spriten, hvis polygonen var større end tekstur, erstattes af opkald til glteksparameteri().
hvis du er forvirret af noget af dette, kan du tjekke vores OpenGL ES 2.0 til iPhone og Custom Cocos2D 2.Shaders tutorials for mere baggrundsinformation. Men du behøver ikke bekymre dig om det for meget, for på dette tidspunkt er alt, hvad vi laver, at overføre klassen til at arbejde i Cocos2D 2.
kompilere og køre, og alle prkit fejl bør forsvinde!
det er tid til at sætte PRKit i aktion. Du vil underklassere Prkits Prfiledpolygon-klasse for at lave en base PolygonSprite-klasse, der vil tegne vores frugter.
PolygonSprite bygger på PRFilledPolygon ved at vedhæfte en Boks2d-krop til sprite, og den vil også indeholde andre brugerdefinerede variabler og metoder til frugterne i vores spilimplementering.
lad os komme til det. Hit Command + N og oprette en ny fil med iOS \ cocos2d v2.CCNode klasse skabelon. Gør det til en underklasse af PRFilledPolygon og navngiv det PolygonSprite.m.
Skift til PolygonSprite.h og foretage følgende ændringer:
// 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;
ovenstående kode erklærer de grundlæggende variabler og metoder, du har brug for for at oprette en Polygonskrite. Disse er:
- krop: Dette er Boksen2d krop, der er knyttet til vores sprite. Det er nødvendigt for fysik simulering.
- original: komplette og skiver sprites vil bruge den samme PolygonSprite klasse, som sådan vil det være vigtigt at skelne mellem de to. Hvis dette er ja, betyder det, at det er det uklippede eller originale objekt, du oprettede, ellers er det bare et stykke af helheden.
- centroid: Midten af polygonen i billedet vil ikke altid være det samme som midten af billedet, så det er nyttigt at gemme denne værdi.
- egenskaber: Udsæt alle variabler ved hjælp af egenskaber, så andre klasser kan få adgang til dem frit.
- init/spritmed*: vores vigtigste init-metoder følger den samme navngivningskonvention som Cocos2D.
- andre metoder: disse er metoder, der skaber & beskæftiger sig med den vedhæftede Boks2d-krop og dets egenskaber.
- PTM_RATIO: forholdet mellem billedpunkter og meter. Boks2d har brug for denne konverteringsværdi, fordi den beskæftiger sig med målere i stedet for billedpunkter.
skift hurtigt til PolygonSprite.m og omdøb det PolygonSprite.mm. alle klasser, der blander Objective – C (Cocos2D) og C++ (Boks2d) kode, skal have en “.mm” udvidelse for at underrette kompilatoren om den blandede syntaks.
foretag derefter følgende ændringer til 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;}
i lighed med Cocos2D er alle spritmed* – metoder bare autorelease-modstykker til initmed* – metoderne, mens initmedverden endnu ikke har nogen egentlig brug for denne klasse, men i stedet vil den blive brugt af PolygonSprite ‘ s underklasser senere.
hovedparten af ændringerne kan findes i init med fil og init med teksturmetoder. For at få strømmen af ting, vil skabelsen af en frugt blive kaldt i denne rækkefølge:
- dette er beregnet til underklasser af Polygonskrite, så du ikke gør andet end at vende tilbage nul og håndtere det senere.
- initmedfil: dette tilføjer tekstur fra vores fil og overfører alt til initmedtekstur.
- initmedtekstur: vores vigtigste initialisering. PRFilledPolygon har brug for en tekstur og alle hjørner af polygonen, den fylder. Da det forrige trin allerede håndterede teksturdelen, håndterer dette trin hjørnerne ved at samle dem fra sprites Boks2d-krop. Efter at have passeret dem til PRFilledPolygon, fortsætter den med at initialisere de variabler, du tidligere har erklæret.
- initmedpoints: alt dette gør er indeholdt i PRKit, og det gode er, at du ikke rigtig behøver at røre ved PRKit længere, nu hvor du har opdateret sin kode.
stadig inde PolygonSprite.mm, tilføj følgende metoder:
-(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);}
i ovenstående kode overbelaster du først setPosition-metoden for CCNode, så når du opdaterer sprites position, opdateres den tilknyttede boks 2D-krops position også.
du laver derefter en bekvemmelighedsmetode til oprettelse og definition af en Boks2d-krop. For at oprette en krop skal du definere en kropsdefinition, et kropsobjekt, en form og en armaturdefinition. Ingen reelle hårde værdier tildeles her endnu, da denne metode vil blive brugt af underklasser af PolygonSprite senere.
den eneste ting at bemærke er kategorienbits og maskBits. Disse to bruges til filtrering af kollisioner mellem objekter, således at hvis en kategoribit af et objekt matcher en maskebit af et andet objekt og omvendt, vil der være en kollision mellem disse to objekter. Du indstiller disse til 0 først, fordi du ikke vil have nogen kollisioner, der sker, når objekterne først initialiseres.
endelig definerer du to metoder, der blot erstatter kategorienbits og maskBits, så du kan aktivere og deaktivere kollisionerne af vores PolygonSprites.
der er endnu en ting at tilføje til 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_;}
Husk, da jeg nævnte, at du havde brug for noget fra Fysikprite? Så er det nu. Alt dette gør er at sikre, at vores Boks2d form og vores sprite er i samme position, når du flytter. Det er forberedt til os af Cocos2D, og det gør det endnu mere fantastisk.
efter kopiering af ovenstående kode kan du nu slette begge Fysikerprite.h og PhysicsSprite.mm fra projektet, da du helt har elimineret deres anvendelighed.
kompilere og køre, og alt skal være fint. Du er færdig med PolygonSprite for nu.
planlægning af vores frugter
før du opretter klasser for vores frugter, skal du være klar over de regler, som billederne og deres former skal følge. Da du vil kortlægge vores teksturer til enkeltboks2d polygoner, skal du også overholde Boks2ds polygonbegrænsninger. Du skal huske to ting:
- polygoner skal være konvekse, hvilket betyder, at ingen indvendig vinkel er større end 180.
- polygoner må ikke overstige 8 hjørner.
du kan faktisk omgå denne begrænsning, hvis du tillader, at hver krop indeholder flere former. Boks2d kan håndtere konkave former, hvis du bruger en trianguleringsmetode og laver de konkave former ud af flere trekanter, men dette er uden for tutorial.
for at holde tingene enkle, i denne tutorial vil du have en 1 krop er til 1 form regel.
Bemærk: PhysicsEditor, det værktøj, vi vil dække senere i denne tutorial, indeholder faktisk kode til automatisk at triangulere polygoner, du tegner i et sæt konvekse former. Men som jeg sagde, forsøger vi at holde tingene enkle her, så sørg for at tegne vores former konvekse, så vi kun har en form pr.
Tag et kig på disse to frugter:
brug af bananen er ikke en god ide, fordi den er naturligt konkav. Vandmelonen er derimod meget god, fordi du kan definere en konveks polygon, der ligner dens form.
hvis du skulle definere polygonformer, der følger Boks2ds regler for de to frugter, ville du mere eller mindre ende med disse:
Vandmelonpolygonen passer perfekt til billedet, mens Bananpolygonen har et stort tomt rum, hvor billedet kurver indad. Boks 2D vil behandle det rum som en del af vores objekt, og det kan få bananen til at føle sig unaturlig, når den kolliderer med andre genstande, eller når den bliver skåret.
dette betyder ikke, at du ikke kan bruge bananen, men snarere at det bare ikke anbefales at bruge bananen. Faktisk vil det spil, du opretter i denne tutorial, bruge den samme banan.
oprettelse af den første frugt
det er tid til at skabe den første frugt: vandmelonen (i det mindste et stykke af det).
når du tænker tilbage på strømmen af vores Polygonskrites initialiseringsproces, ved du, at init medtekstur forventer en Boks2d-krop, men trinnet før, init medfil, giver ikke dette.
årsagen til dette er, at du skal skabe og definere kroppen individuelt pr.frugt, så det bliver nødt til at være det allerførste skridt, init med verden, der skaber kroppen og sætter andre værdier, der er specifikke for hver frugt.
for at oprette vores Boks2d-krop skal du først kende hjørnerne af den polygonform, du vil oprette. Der er forskellige måder at gøre dette på, men til denne tutorial bruger du et smukt værktøj kaldet PhysicsEditor. Dette værktøj er fyldt med funktioner, men du vil kun bruge det til at guide os i at få koordinaterne for hjørnerne af vores polygon.
hvis du ikke har det, hente PhysicsEditor, installere det, og fyre det op. Du får et tomt projekt med 3 paneler/kolonner.
arbejde med Fysikredaktør er ret ligetil. Til venstre lægger du alle de billeder, du vil arbejde med. I midten definerer du visuelt en polygon til dit billede. Til højre har du parametrene for kroppen.
Grab vandmelon.png fra mappen Billeder i ressourcesættet og træk det til venstre panel. Du skal nu se vandmelonen på midtpanelet.
Forøg forstørrelsen, der findes i bunden af dette panel, til et behageligt niveau, og tryk derefter på Femkantknappen på den øverste del af dette panel for at oprette en 3-sidet polygonform.
Højreklik på polygonen og vælg “Tilføj toppunkt”, indtil du har 5-8 hjørner i alt. Flyt hjørnerne rundt om vandmelonens kanter, mens du sørger for to ting:
- den Polygon, du opretter, er konveks.
- alle vandmelonens billedpunkter er inde i polygonen.
bemærk: en anden genvej til at tegne figurerne er at bruge Physicseditors tryllestavværktøj. Bare indstil tolerancen høj (5-8), så du ender med omkring 5-8 point, og juster punkterne derfra.
Tilføj alle de andre frugter og bombebilledet fra mappen Billeder i ressourcesættet og gør det samme for dem.
du skal definere figurer for følgende billeder:
- banan.png
- bombe.png
- druer.png
- ananas.png
- jordbær.PNG
- vandmelon.png
når du er færdig, i øverste højre hjørne, skal du ændre værdien af eksportør til “Boks2d generisk (PLIST)”, og du skal ende med noget som dette:
tryk på “Udgiv” eller “Udgiv som” for at eksportere PLIST-filen, der indeholder toppunktets oplysninger. Gem filen som frugter.plist.
som et eksempel, frugterne.plist, du brugte til denne tutorial, er inde i Misc-mappen i ressourcesættet.
du vil kun se på oplysningerne i plist-filen, så tilføj ikke denne fil til dit projekt, men snarere bare åbne frugter.plist ved hjælp af kode for at se dens indhold på en organiseret måde.
Klik på trekantsikonet ved siden af “organer” for at udvide dette afsnit, og du vil se listen over billeder, som du definerede figurer til. Du skal bore ned til det dybeste niveau for at få vandmelonens polygonhjørner som sådan:
Udvid vandmelon/inventar/vare 0/polygoner, og du skal nu se et andet emne 0 af type Array under polygoner. Dette sidste array er din form. Hvis du korrekt havde defineret en konveks form med 8 eller mindre hjørner, skal du kun se et array under polygoner.
hvis du ser mere end en, jeg.e vare 0 Array, vare 1 Array, etc, så betyder det PhysicsEditor lavede en kompleks form, fordi du enten definerede for mange hjørner, eller du dannede en konkav polygon. Hvis dette sker, skal du gå tilbage til Fysikredaktør og rette din form.
udvid derefter elementet 0 af type Array for at se den endelige liste over elementer. Dette er dine hjørner, og den værdi, du ser i højre side med dette format { nummer, nummer } er dine & Y koordinater for hvert toppunkt.
nu hvor du har de nøjagtige værdier for din polygons hjørner, kan du fortsætte med at oprette Vandmelonklassen.
Opret en ny fil med iOS\cocos2d v2.CCNode klasse skabelon. Gør det til en underklasse af Polygonskrite og navngiv det Vandmelon. Åben Vandmelon.h og foretage følgende ændringer:
// Add to top of file#import "PolygonSprite.h"
Skift til vandmelon.m, Omdøb det til Watermelon.mm, og tilføj følgende init-metode:
// 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;}
i ovenstående kode definerer du først, hvor mange hjørner der er, som i dette tilfælde er 7. Dernæst opretter du en række hjørner, der indeholder alle de koordinater, du lige har set i PLISTEN. Du bruger disse oplysninger til at oprette en krop ved hjælp af den bekvemmelighedsmetode, du definerede i PolygonSprite.
du lægger en lille friktion, så figurerne ikke glider uendeligt, og du lægger også en lille restitution, så figurer ikke stopper, når de hopper mod hinanden.
Sidst opretter du objektet ved at kalde superklassen’ initialisering og passere i navnet på billedfilen, Boksen2d krop, og angiv at dette er en original frugt.
du har brug for vandmelonbillederne fra ressourcesættet, så nu ville det være et godt tidspunkt at bare tilføje alle de grafiske ressourcer, du har brug for til resten af selvstudiet.
Højreklik på ressourcer i dit Projektnavigatorpanel og vælg “Tilføj filer til CutCutCut”. Føj mappen Billeder fra ressourcesættet til projektet. Sørg for, at” kopier elementer til destinationsgruppens mappe “er markeret, og” Opret grupper for eventuelle tilføjede mapper ” er valgt.
Følg de samme trin for at skabe banan, druer, ananas, jordbær og bombe.
du tacklede kun, hvordan du opretter den første frugt trin for trin, da det dybest set er en skylning & gentagelsesproces for hver frugt. Ressourcesættet indeholder færdige frugt-og bombeklasser i mappen klasser, som du kan se på, hvis du stadig har brug for vejledning, eller du kan tilføje dem alle til dit projekt, hvis du vil springe dette trin over.
kompilere og køre, og sørg for alt er fint.
tilføjelse af en frugt til scenen
indtil videre er der ikke sket noget på skærmen endnu, og du klør naturligvis for at se frugterne af din arbejdskraft – ordspil beregnet! :]
Skift til Hellorldlayer.h og foretage følgende ændringer:
// Add to top of file#import "PolygonSprite.h"// Add inside the @interfaceCCArray *_cache;// Add after the @interface@property(nonatomic,retain)CCArray *cache;
Skift tilbage til HelloWorldLayer.mm og foretage disse ændringer:
// 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]; ; ; ;}
du erklærer en cache array, som vil holde alle de frugter og bomber, du opretter i fremtiden. Derefter opretter du 1 vandmelon og tilføjer den til scenen. Du kalder aktivkollisioner, så vandmelonen ikke passerer gennem væggene.
kompilere og køre, og du bør se en vandmelon falder fra midten område af skærmen, og lander i bunden som vist nedenfor.
du bemærker måske, at vandmelonen ikke er nøjagtigt i centrum. Årsagen til dette er, at du placerede objektet baseret på dets Boks2d-krop, og vores Boks2d-krops oprindelse er i nederste venstre hjørne af objektet. Den tynde kontur omkring vandmelonen er synlig, fordi debug-tegningstilstand stadig er tændt.
Hvor Skal Vi Hen Herfra?
her er et eksempelprojekt med al koden fra ovenstående tutorial.
det er det for del 1 af serien. Indtil videre har du en vandmelon tekstureret Polygon, der bare falder til bunden af skærmen.
men i stedet for at tegne en rektangulær sprite med gennemsigtigt rum, som du normalt ser i Boks2d-tutorials, bruger dette PRKit til kun at tegne de dele af tekstur, der svarer til boks2d-kroppens hjørner. Dette kommer snart til nytte!
nu er du klar til Del 2 af selvstudiet, hvor du tilføjer muligheden for at skære frugterne!
i mellemtiden, hvis du har spørgsmål eller kommentarer til denne del, kan du deltage i forumdiskussionen nedenfor!
dette er et indlæg af iOS Tutorial-teammedlem Allen Tan, en iOS-udvikler og medstifter hos hvid kontrol. Du kan også finde ham på Google+ og kvidre.
raywenderlich.com ugentlig
den raywenderlich.com nyhedsbrev er den nemmeste måde at holde dig opdateret om alt hvad du behøver at vide som mobiludvikler.
få en ugentlig fordøjelse af vores tutorials og kurser, og modtag et gratis dybtgående e-mail-kursus som en bonus!