Como Fazer Um Jogo Como Fruit Ninja Com Box2D e Cocos2D – Parte 1
Este é um post com o iOS Tutorial Membro da Equipe de Allen Tan, um desenvolvedor de aplicativos para iOS e co-fundador em Branco Widget. Você também pode encontrá-lo no Google+ e Twitter.Neste tutorial, você aprenderá como fazer um jogo de corte de sprite para o iPhone semelhante ao Fruit Ninja by Halfbrick Studios usando as poderosas bibliotecas Cocos2D e Box2D, juntamente com algumas ferramentas pré-fabricadas.
na maioria dos jogos de corte, quando você desenha uma linha de corte através de um sprite, o jogo normalmente converte a imagem do sprite em duas imagens de sprite pré-desenhadas com a fatia sempre no meio, independentemente de onde você realmente corta.
mas este tutorial irá demonstrar uma técnica ainda mais legal. Nossos frutos poderão ser cortados várias vezes e serão divididos dinamicamente com base nas linhas de corte exatas!
como você pode imaginar, esta é uma técnica avançada, então este tutorial é para desenvolvedores Cocos2D e Box2D avançados. Se você é novo no Cocos2D ou Box2D, deve passar (pelo menos) pela introdução ao Cocos2D e pela introdução aos tutoriais Box2D antes de prosseguir com este tutorial.
Esta série tutorial é dividida em três partes:
- nesta primeira parte da série, você lançará as bases para o jogo e aprenderá a criar polígonos texturizados.
- a segunda parte mostrará como cortar & dividir esses polígonos texturizados.
- a terceira parte mostrará como transformar isso em um jogo completo adicionando jogabilidade e efeitos.
gostaria de agradecer especialmente a Rick Smorawski por lançar as bases para o projeto em que este tutorial se baseia. Ele foi responsável por portar esta demonstração de corte baseada em flash em Cocos2D, e também por portar CCBlade e PRKit para Cocos2D 2.0.
Continue lendo para conferir o vídeo do que você vai fazer e começar a aprender algumas novas técnicas legais!
demonstração do jogo
aqui está um vídeo de demonstração mostrando o que você fará nesta série de tutoriais:
como mencionei, você verá que o efeito de corte de frutas é realmente dinâmico. A fruta é cortada dinamicamente com base em onde você corta e, como você pode cortar objetos várias vezes, você pode realmente cortar as coisas!
você pode ver que também implementará um efeito de trilha de corte Legal, Alguns sistemas de partículas, lógica de jogo e sons para apimentar as coisas.
há muito a cobrir-então vamos começar!
introdução: configuração do projeto
você vai usar Cocos2D 2.X neste projeto, então vá em frente e faça o download se você ainda não o tiver. Observe que você está livre para usar Cocos2D 1.X em vez de 2.X. Com 1.X, você pode pular as partes sobre a conversão de PRKit e CCBlade para Cocos2D 2.X, mas não se esqueça de prestar atenção às outras pequenas mudanças que você faz para essas classes.
após o download, clique duas vezes no tar para desarquivá – lo e instale os modelos com os seguintes comandos no Terminal:
cd ~/Downloads/cocos2d-iphone-2.0-beta./install-templates.sh -f -u
Inicie o Xcode e crie um novo projeto com o iOS \ cocos2d v2.x \ cocos2d iOS com modelo Box2d e nomeá-lo CutCutCut.
seu novo projeto deve se parecer com isso:
primeiras coisas primeiro – você deve limpar um pouco o modelo para chegar a um bom ponto de partida.
Abra HelloWorldLayer.h e remova a seguinte linha:
CCTexture2D *spriteTexture_;// weak ref
Mudar para HelloWorldLayer.mm e faça as seguintes alterações
// 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;
neste ponto, você já removeu todas as referências ao PhysicsSprite de HelloWorldLayer, mas não remove os arquivos do projeto e muito mais. Mais tarde, você precisará copiar um método que PhysicsSprite.mm contém em outro lugar, então deixe-o por enquanto.
pressione Command+R para compilar e executar seu projeto, e você verá uma tela em branco com uma borda verde ao redor:
o código de modelo restante configurou o desenho de depuração Box2D, que desenha bordas ao redor dos corpos Box2D na tela. Veja as finas linhas verdes desenhadas ao redor da tela? Essas são as paredes geradas pelo método initphysics padrão que veio com o modelo.
dê uma olhada no código do modelo restante para ter certeza de que você entende o que está acontecendo até agora – ele inicializa um mundo Box2D, configura o terreno (bordas verdes), configura o desenho de depuração, etc. Este é um bom ponto de partida” quase em branco ” com Box2D que podemos construir a partir daqui.
Resource Kit
próximo baixe os recursos para este projeto e descompacte o arquivo.
não adicione tudo ao projeto ainda; alguns dos arquivos são realmente opcionais. Mantenha a pasta à mão embora-como você passar pelo tutorial, de vez em quando eu vou pedir-lhe para adicionar alguns desses arquivos para o projeto.
aqui está o que você encontrará dentro:
- uma imagem de fundo e um monte de arte de frutas feitas por Vicki, e outras imagens diversas na pasta de imagens
- a mistura de som de fundo feita usando gomix.ele na pasta Sons
- efeitos de Som feita usando bfxr ou baixado a partir de freesound na pasta Sons
- Todos os sistemas de partículas criado com Partículas de Designer em Partículas pasta
- UM arquivo PLIST gerado pelo PhysicsEditor que contém o vértice de informações para os Frutos & Bomba de classes na pasta Misc
- Frutas & Bomba de classes na pasta Classes
- As versões de PRKit e CCBlade você vai usar no tutorial na pasta Classes
- Uma atribuição lista de recursos que estão sob a Licença de Atribuição em Diversos pasta
desenhando polígonos texturizados com PRKit
nosso objetivo é cortar sprites em vários pedaços. Um CCSprite típico contém uma textura e uma caixa delimitadora, independentemente da forma da imagem. Isso não é adequado para o nosso jogo, pois conhecer as formas reais dentro das imagens é um passo crucial para criar sprites que podem ser cortados, cortados e divididos.
você precisa criar polígonos texturizados, que:
- Criar uma correspondência entre um polígono e forma e uma imagem (Mapeamento de Textura)
- Mostrar apenas as partes da imagem que estão dentro dos limites do polígono (Textura de Enchimento)
Nem Cocos2D nem Box2D vem com um built-in de classe que lida com os recursos personalizados que você deseja, e normalmente, isso levaria alguns triangulação juntamente com OpenGL código de desenho.
parece difícil, certo? Felizmente, todos os cálculos complicados e código de desenho necessários para conseguir isso já foram escritos pelas pessoas boas da Precognitive Research. Eles criaram uma adição à biblioteca Cocos2D chamada PRKit, que lida com mapeamento e preenchimento de textura.
para começar a usar polígonos texturizados, baixe o PRKit, extraia-o e arraste a pasta PRKit para o seu projeto. Certifique-se de que “Copiar itens para a pasta do grupo de destino” está marcada e “criar grupos para quaisquer pastas adicionadas” está selecionado.
observe que o PRKit é mantido por pesquisas pré-cognitivas, portanto, pode ser atualizado a tempo. Para evitar confusão, nosso kit de recursos também contém a versão exata do PRKit que usei para fazer este tutorial.
seu projeto agora deve incluir esses arquivos:
Compilar e executar, e você irá encontrar alguns erros:
Os erros pop-up porque PRKit foi feito para Cocos2D 1.X, que usa OpenGL ES 1.1, enquanto você está usando Cocos2D 2.X, que usa OpenGL ES 2.0, e existem diferenças significativas entre os dois.
para corrigir isso, abra PRFilledPolygon.m e faça essas mudanças:
// 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);}
vamos rever essas mudanças pouco a pouco.
primeiro, em Cocos2D cada CCNode tem um programa OpenGL ES 2.0 shader anexado a ele. Para desenhar o prfilledpolygon, você precisa processar o shader embutido “posição/textura”, que você atribui no método init.
em seguida, você precisa configurar as coordenadas de textura corretas para cada ponto no polígono. Para fazer isso, você deve fazer duas alterações no método calculateTextureCoordinates:
- escala: como essa classe faz seus próprios cálculos nas coordenadas de sua textura, ela não lida automaticamente com a tela retina. Para corrigir isso, basta multiplicar a textura.pixelsWide com CC_CONTENT_SCALE_FACTOR-um valor multiplicador conveniente fornecido pelo Cocos2D para converter valores entre equivalentes regulares e retina.
- Flip Y: por algum motivo, PRFIlledPolygon desenha texturas de cabeça para baixo, então você simplesmente vira o valor y aqui.
por último, o código de desenho é atualizado para OpenGL ES 2.0, de maneira semelhante a como o desenho CCSprite mudou de Cocos2D 1.X para Cocos2D 2.X:
- comece chamando CC_NODE_DRAW_SETUP () para preparar o nó para o desenho.
- as chamadas para glDisableClientState () e glEnableClientState () estão obsoletas e são descartadas.
- os comandos glVertexPointer() e glTexCoordPointer() são substituídos por glVertexAttribPointer(), que agora aceita a posição do vértice ou a coordenada de textura como sua primeira opção.
- a configuração de glTexEnvf (), que foi responsável por repetir o sprite caso o polígono fosse maior que a textura, é substituída por chamadas para glTexParameteri ().
se você está confuso com qualquer um destes, você pode querer verificar o nosso OpenGL ES 2.0 para iPhone e personalizado Cocos2D 2.X Shaders tutoriais para mais informações de fundo. Mas você não precisa se preocupar muito com isso, porque neste momento tudo o que estamos fazendo é portar a classe para trabalhar no Cocos2D 2.X :]
Compile e execute, e todos os erros do PRKit devem desaparecer!
é hora de colocar o PRKit em ação. Você estará subclassificando a classe PRFilledPolygon do PRKit para criar uma classe base PolygonSprite que atrairá nossos frutos.
o PolygonSprite se baseia em PRFilledPolygon anexando um corpo Box2D ao sprite, e também conterá outras variáveis e métodos personalizados para os frutos em nossa implementação do jogo.
vamos lá. Pressione Command + N e crie um novo arquivo com o iOS \ cocos2d v2.modelo de classe X \ CCNode. Torne – o uma subclasse de PRFilledPolygon e nomeie-o PolygonSprite.M.
mude para PolygonSprite.h e faça as seguintes alterações:
// 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;
o código acima declara as variáveis e métodos básicos que você precisa para criar um polígono. Estes são:
- corpo: este é o corpo Box2D que está ligado ao nosso sprite. É necessário para simulação de física.
- original: sprites completos e fatiados usarão a mesma classe PolygonSprite, como tal, diferenciar entre os dois será importante. Se isso for SIM, significa que é o objeto sem cortes ou original que você criou, caso contrário, é apenas um pedaço do todo.
- centroide: O centro do polígono dentro da imagem nem sempre será o mesmo que o centro da imagem, por isso é útil armazenar esse valor.Propriedades: exponha todas as variáveis usando propriedades para que outras classes possam acessá-las livremente.
- init/spriteWith*: nossos principais métodos init seguindo a mesma convenção de nomenclatura que Cocos2D.
- outros métodos: Estes são métodos que criam & lidando com o corpo Box2D anexado e suas propriedades.
- PTM_RATIO: Pixels para Metros relação. Box2D precisa desse valor de conversão porque lida com medidores em vez de Pixels.
mude rapidamente para PolygonSprite.m e renomeá – lo PolygonSprite.mm. todas as classes que misturam o código Objective-C (Cocos2D) e C++ (Box2D) precisam ter uma extensão “.mm” para notificar o compilador da sintaxe mista.
em seguida, faça as seguintes alterações 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;}
Semelhante a Cocos2D, todos os spriteWith* métodos são apenas autorelease homólogos do initWith* métodos, enquanto initWithWorld não tem uso real para esta classe, mas, em vez disso, ele será usado por PolygonSprite do subclasses mais tarde.
a maior parte das alterações pode ser encontrada nos métodos initWithFile e initWithTexture. Para obter o fluxo das coisas, a criação de uma fruta será chamada nesta sequência:
- initWithWorld: destina-se a subclasses de polígonos para que você não faça nada, exceto return nil, e lide com isso mais tarde.
- initWithFile: isso adiciona a textura do nosso arquivo e passa tudo para initWithTexture.
- initWithTexture: nossa inicialização principal. PRFilledPolygon precisa de uma textura e todos os vértices do polígono que preenche. Como a etapa anterior já lidava com a parte da textura, esta etapa lida com os vértices coletando-os do corpo Box2D do sprite. Depois de passá-los para PRFilledPolygon, ele começa a inicializar as variáveis que você declarou anteriormente.
- initWithPoints: tudo o que isso faz está contido no PRKit e o bom é que você realmente não precisa mais tocar no PRKit agora que atualizou seu código.
ainda dentro PolygonSprite.mm, adicione os seguintes métodos:
-(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);}
no código acima, você primeiro sobrecarrega o método setPosition do CCNode para que, ao atualizar a posição do sprite, a posição do corpo Box2D associado também seja atualizada.
você então faz um método de conveniência para criar e definir um corpo Box2D. Para criar um corpo, você precisa definir uma definição de corpo, um objeto de corpo, uma forma e uma definição de fixação. Nenhum valor real difícil está sendo atribuído aqui ainda, uma vez que este método será usado por subclasses de PolygonSprite mais tarde.
a única coisa a notar são os categoryBits e maskBits. Esses dois são usados para filtrar colisões entre objetos de forma que, se um bit de categoria de um objeto corresponder a um bit de máscara de outro objeto e vice-versa, haverá uma colisão entre esses dois objetos. Você os define como 0 primeiro porque não deseja que nenhuma colisão aconteça quando os objetos forem inicializados pela primeira vez.
por último, você define dois métodos que simplesmente substituem os categoryBits e maskBits para que você possa ativar e desativar as colisões de nossos polígonos.
há mais uma coisa a acrescentar 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_;}
lembre-se quando eu mencionei que você precisava de algo de Physicsprite? Bem, é isso. Tudo isso é para garantir que nossa forma Box2D e nosso sprite estejam na mesma posição ao se mover. Está preparado para nós pelo Cocos2D e isso torna tudo ainda mais incrível.
depois de copiar o código acima, Agora você pode excluir ambos Physicsprite.h E PhysicsSprite.mm do projeto como você eliminou completamente a sua utilidade.
Compile e execute, e tudo deve estar bem. Você acabou com o PolygonSprite por enquanto.
planejando nossos frutos
Antes de criar aulas para nossos frutos, você precisa ter clareza sobre as regras que as imagens e suas formas devem seguir. Como você mapeará nossas texturas para polígonos Box2D únicos, Você também deve seguir as limitações do polígono Box2D. Você precisa manter duas coisas em mente:
- os polígonos devem ser convexos, o que significa que nenhum ângulo interno é maior que 180.
- os polígonos não devem exceder 8 vértices.
você pode realmente contornar essa limitação se permitir que cada corpo contenha várias formas. Box2D pode lidar com formas côncavas se você usar um método de triangulação e fazer as formas côncavas de vários triângulos, mas isso está além do escopo do tutorial.
para manter as coisas simples, neste tutorial você terá um corpo 1 é para 1 regra de forma.
Nota: PhysicsEditor, a ferramenta que estaremos cobrindo mais tarde neste tutorial, na verdade contém código para triangular automaticamente polígonos que você desenha em um conjunto de formas convexas. No entanto, como eu disse, Estamos tentando manter as coisas simples aqui, então certifique-se de desenhar nossas formas convexas para que tenhamos apenas uma forma por corpo.
dê uma olhada nessas duas frutas:
usar a Banana não é uma boa ideia porque é naturalmente côncavo. A melancia, por outro lado, é muito boa porque você pode definir um polígono convexo que se assemelha muito à sua forma.
se você definisse formas de polígono que seguem as regras do Box2D para as duas frutas, você acabaria mais ou menos com estas:
o polígono da melancia se encaixa perfeitamente na imagem, enquanto o polígono da Banana tem um grande espaço vazio onde a imagem se curva para dentro. O Box2D tratará esse espaço como parte de nosso objeto, e isso pode fazer com que a Banana não pareça natural quando colide com outros objetos ou quando é cortada. Isso não significa que você não pode usar a Banana, mas sim que não é recomendado usar a Banana. Na verdade, o jogo que você criará neste tutorial usará essa mesma Banana.
criando a primeira fruta
é hora de criar a primeira fruta: a melancia (pelo menos uma fatia dela).
pensando no fluxo do processo de inicialização do nosso PolygonSprite, você sabe que initWithTexture espera um corpo Box2D, mas a etapa anterior, initWithFile, não fornece isso.
a razão para isso é que você precisa criar e definir o corpo individualmente por fruta, por isso terá que ser o primeiro passo, emitwithworld, que cria o corpo e define quaisquer outros valores específicos para cada fruta.
para criar nosso corpo Box2D, você deve primeiro conhecer os vértices da forma do polígono que deseja criar. Existem diferentes maneiras de fazer isso, mas para este tutorial, você estará usando uma ferramenta bacana chamada PhysicsEditor. Esta ferramenta é preenchida com recursos, mas você só a usará para nos guiar na obtenção das coordenadas dos vértices do nosso polígono.
se você não tiver, baixe PhysicsEditor, instale-o e dispare-o. Você receberá um projeto em branco com 3 painéis / colunas.
trabalhar com PhysicsEditor é bastante simples. À esquerda, você coloca todas as imagens com as quais deseja trabalhar. No meio, você define visualmente um polígono para sua imagem. À direita, você tem os parâmetros para o corpo.
pegue melancia.png da pasta Imagens do kit de recursos e arraste-o para o painel esquerdo. Agora você deve ver a melancia no painel central.
aumente a ampliação, encontrada na parte inferior deste painel, para um nível confortável e, em seguida, toque no botão Pentágono na parte superior deste painel para criar uma forma de polígono de 3 lados.
clique com o botão direito do mouse no polígono e escolha “Adicionar vértice” até ter 5-8 vértices ao todo. Mova os vértices ao redor das bordas da melancia, certificando-se de duas coisas:
- o polígono que você está criando é convexo.
- todos os pixels da melancia estão dentro do polígono.
Nota: outro atalho para desenhar as formas é usar a ferramenta Varinha Mágica do PhysicsEditor. Basta definir a tolerância alta (5-8) para que você acabe com cerca de 5-8 pontos e ajustar os pontos a partir daí.
adicione todas as outras frutas e a imagem da bomba da pasta Imagens do kit de recursos e faça a mesma coisa por elas.
você deve definir formas para as seguintes imagens:
- banana.png
- bomba.png
- uvas.png
- abacaxi.png
- morango.png
- melancia.png
Quando você terminar, no canto superior direito, altere o valor do Exportador “Box2D genérico (PLIST)”, e você deve acabar com algo como isto:
clique em “Publicar”, ou “Publicar como”, para exportar o arquivo PLIST contendo as informações do vértice. Salve o arquivo como frutas.plist.
como exemplo, os frutos.plist que você usou para este tutorial está dentro da pasta Misc do resource kit.
você só quer olhar para as informações contidas no arquivo PLIST, então não adicione este arquivo ao seu projeto, mas sim, basta abrir frutas.plist usando o Xcode para visualizar seu conteúdo de maneira organizada.
clique no ícone do triângulo ao lado de “corpos” para expandir esta seção e você verá a lista de imagens para as quais definiu formas. Você precisa detalhar o nível mais profundo para obter os vértices do polígono da melancia assim:
expandir melancia/luminárias/Item 0/polígonos e agora você deve ver outro Item 0 do tipo Array sob polígonos. Esta última matriz é a sua forma. Se você definiu corretamente uma forma convexa com 8 ou menos vértices, você deve ver apenas uma matriz sob polígonos.
se você vir mais de um, eu.e item 0 Array, item 1 Array, etc, então significa PhysicsEditor fez uma forma complexa porque você definiu muitos vértices ou formou um polígono côncavo. Se isso acontecer, volte ao Físicoditor e corrija sua forma.
em seguida, expanda o Item 0 do tipo Array para ver a lista final de itens. Estes são seus vértices, e o valor que você vê no lado direito com este formato { Número, Número } são suas coordenadas x & y para cada vértice.
agora que você tem os valores exatos para os vértices do seu polígono, você pode prosseguir com a criação da classe melancia.
no Xcode, crie um novo arquivo com o iOS \ cocos2d v2.modelo de classe X \ CCNode. Faça uma subclasse de Polígonosprite e nomeie-a melancia. Melancia Aberta.h e faça as seguintes alterações:
// Add to top of file#import "PolygonSprite.h"
mude para Melancia.m, renomeie-o para a Melancia.mm, e adicione o seguinte método 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;}
No código acima, primeiro você define quantos vértices existem, que neste caso é 7. Em seguida, você cria uma matriz de vértices contendo todas as coordenadas que acabou de ver no PLIST. Você usa essas informações para criar um corpo usando o método de conveniência que você definiu no PolygonSprite. Você coloca um pouco de atrito para que as formas não deslizem sem parar, e você também coloca uma pequena restituição para que as formas não parem quando saltam umas contra as outras.
por último, você cria o objeto chamando a inicialização da superclasse e passa o nome do arquivo de imagem, o corpo Box2D e afirma que esta é uma fruta original.
você precisa das imagens de melancia do kit de recursos, então agora seria um bom momento para apenas adicionar todos os recursos gráficos que você precisa para o resto do tutorial.
no painel do navegador do projeto, clique com o botão direito do mouse em Recursos e selecione “Adicionar arquivos ao CutCutCut”. Adicione a pasta Imagens do kit de recursos ao projeto. Certifique-se de que “Copiar itens para a pasta do grupo de destino” está marcada e “criar grupos para quaisquer pastas adicionadas” está selecionado.
siga os mesmos passos para criar Banana, uvas, abacaxi, morango e bomba.
você só abordou como criar a primeira fruta passo a passo, pois é basicamente um processo de repetição de enxágüe & para cada fruta. O kit de recursos contém classes de frutas e bombas prontas na pasta Classes para você observar caso ainda precise de orientação, ou você pode adicioná-las todas ao seu projeto se quiser pular esta etapa.
Compile e execute e verifique se está tudo bem.
adicionando uma fruta à cena
até agora, nada tem acontecido na tela ainda, e você está obviamente ansioso para ver os frutos do seu trocadilho de trabalho pretendido! :]
mudar para HelloWorldLayer.h e faça as seguintes alterações:
// Add to top of file#import "PolygonSprite.h"// Add inside the @interfaceCCArray *_cache;// Add after the @interface@property(nonatomic,retain)CCArray *cache;
voltar para HelloWorldLayer.mm e faça essas mudanças:
// 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]; ; ; ;}
você declara uma matriz de cache, que irá conter todas as frutas e bombas que você criar no futuro. Em seguida, você cria 1 melancia e a adiciona à cena. Você chama ativocolisões para que a melancia não passe pelas paredes.
Compile e execute, e você deve ver uma melancia caindo da área central da tela e pousar na parte inferior, conforme mostrado abaixo.
você pode notar que a melancia não está exatamente no centro. A razão para isso é que você posicionou o objeto com base em seu corpo Box2D, e a origem do nosso corpo Box2D está no canto inferior esquerdo do objeto. O contorno fino ao redor da melancia é visível porque o modo de desenho de depuração ainda está ativado.
Para Onde Ir Daqui?
aqui está um projeto de amostra com todo o código do tutorial acima.
é isso para a parte 1 da série. Até agora, você tem um polígono texturizado de melancia que simplesmente cai na parte inferior da tela.
Mas, em vez de desenhar um retângulo sprite com espaço transparente como você costuma ver em Box2D tutoriais, este usa PRKit para desenhar apenas as partes da textura que correspondem aos vértices do Box2D corpo. Isso será útil em breve!
Agora você está pronto para a parte 2 do tutorial, onde você adiciona a capacidade de cortar as frutas!
enquanto isso, se você tiver alguma dúvida ou comentário sobre esta parte, participe da discussão do fórum abaixo!
este é um post do membro da equipe do iOS Tutorial Allen Tan, um desenvolvedor e co-fundador do iOS no White Widget. Você também pode encontrá-lo no Google+ e Twitter.
raywenderlich.com Semanal
O raywenderlich.com newsletter é a maneira mais fácil de ficar atualizado sobre tudo o que você precisa saber como um desenvolvedor móvel.
obtenha um resumo semanal de nossos tutoriais e cursos e receba um curso de E-mail detalhado gratuito como bônus!