Cómo Hacer Un Juego Como Fruit Ninja Con Box2D y Cocos2D-Parte 1

Esta es una publicación de Allen Tan, miembro del equipo de Tutoriales de iOS, desarrollador de iOS y cofundador de White Widget. También lo puedes encontrar en Google+ y Twitter.

En este tutorial, aprenderás a hacer un juego de corte de sprites para iPhone similar a Fruit Ninja de Halfbrick Studios utilizando las poderosas bibliotecas Cocos2D y Box2D junto con algunas herramientas prefabricadas.

En la mayoría de los juegos de corte, cuando se dibuja una línea de corte a través de un sprite, el juego normalmente convierte la imagen del sprite en dos imágenes de sprite prediseñadas con el corte siempre en la mitad, independientemente de dónde se corte realmente.

Pero este tutorial demostrará una técnica aún más fresca. Nuestras frutas podrán cortarse varias veces y se dividirán dinámicamente en función de las líneas de corte exactas.

Como se puede imaginar, esta es una técnica avanzada, por lo que este tutorial es para desarrolladores avanzados de Cocos2D y Box2D. Si es nuevo en Cocos2D o Box2D, primero debe revisar (como mínimo) los tutoriales introducción a Cocos2D e introducción a Box2D antes de continuar con este tutorial.

Esta serie de tutoriales se divide en tres partes:

  • En esta primera parte de la serie, sentarás las bases para el juego y aprenderás a crear polígonos texturizados.
  • La segunda parte le mostrará cómo dividir & estos polígonos texturizados.
  • La tercera parte te mostrará cómo convertir esto en un juego completo añadiendo jugabilidad y efectos.

Me gustaría dar un agradecimiento especial a Rick Smorawski por sentar las bases para el proyecto en el que se basa este tutorial. Fue responsable de portar esta demo de corte basada en flash a Cocos2D, y también de portar CCBlade y PRKit a Cocos2D 2.0.

Sigue leyendo para ver el video de lo que harás y para comenzar a aprender algunas nuevas técnicas geniales.

Demo del juego

Aquí hay un video de demostración que te muestra lo que harás en esta serie de tutoriales:

Como mencioné, verás que el efecto de corte de fruta es realmente dinámico. La fruta se corta dinámicamente en función de dónde se corta, y dado que puede cortar objetos varias veces, ¡realmente puede cortar las cosas!

Puedes ver que también implementarás un efecto de rastro de rebanado fresco, algunos sistemas de partículas, lógica de juego y sonidos para darle vida a las cosas.

Hay mucho que cubrir, ¡así que comencemos!

Primeros pasos: Configuración del proyecto

Vas a usar Cocos2D 2.X en este proyecto, así que adelante y descárguelo si aún no lo tiene. Tenga en cuenta que es libre de usar Cocos2D 1.X en lugar de 2.X. Con 1.X, puede omitir las partes sobre la conversión de PRKit y CCBlade a Cocos2D 2.X, pero asegúrese de prestar atención a los otros pequeños cambios que haga en esas clases.

Después de la descarga, haga doble clic en el tar para desarchivarlo y, a continuación, instale las plantillas con los siguientes comandos en el Terminal:

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

Inicie Xcode y cree un nuevo proyecto con iOS \ cocos2d v2.x \ cocos2d iOS con plantilla Box2d y llámelo CutCutCut.

Su nuevo proyecto debería verse algo como esto:

 Inicio del proyecto

Lo primero es lo primero: debe limpiar un poco la plantilla para llegar a un buen punto de partida.

Abrir HelloWorldLayer.h y elimine la siguiente línea:

CCTexture2D *spriteTexture_;// weak ref

Cambiar a HelloWorldLayer.mm y realice los siguientes cambios

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

En este punto, ha eliminado todas las referencias a PhysicsSprite de HelloWorldLayer,pero no elimine los archivos del proyecto todavía. Más adelante, deberá copiar un método que PhysicsSprite.mm contiene en otro lugar, así que déjalo por ahora.

Pulse Comando + R para compilar y ejecutar su proyecto, y debería ver una pantalla en blanco con un borde verde alrededor:

Borrón y cuenta nueva

El código de plantilla restante ha configurado el dibujo de depuración de Box2D, que dibuja bordes alrededor de los cuerpos de Box2D en la pantalla. ¿Ves las finas líneas verdes dibujadas alrededor de la pantalla? Esos son los muros generados por el método initPhysics predeterminado que viene con la plantilla.

Eche un vistazo al código de plantilla restante para asegurarse de comprender lo que está pasando hasta ahora: inicializa un mundo Box2D, configura el suelo (bordes verdes), configura el dibujo de depuración, etc. Este es un buen punto de partida «casi en blanco» con Box2D que podemos aprovechar a partir de aquí.

Kit de recursos

A continuación, descargue los recursos para este proyecto y descomprima el archivo.

No agregue todo al proyecto todavía; algunos de los archivos son en realidad opcionales. Sin embargo, mantenga la carpeta a mano: a medida que avanza por el tutorial, de vez en cuando le pediré que agregue algunos de estos archivos al proyecto.

Esto es lo que encontrarás dentro:

  • Una imagen de fondo y un montón de arte de frutas hechas por Vicki, y otras imágenes diversas en la carpeta de Imágenes
  • La mezcla de sonido de fondo hecha con gomix.en la carpeta Sonidos
  • Efectos de sonido realizados con bfxr o descargados de freesound en la carpeta Sonidos
  • Todos los sistemas de partículas creados con Particle Designer en la carpeta Partículas
  • Un archivo PLIST generado por PhysicsEditor que contiene información de vértices para las Fruits & Clases Bomba en la carpeta Misc
  • Fruits & Clases Bomba en la carpeta Clases
  • Las versiones de PRKit y CCBlade que usará en el tutorial en la carpeta Clases
  • Una lista de atribución para los recursos que están bajo la Licencia de atribución en el Misc carpeta

Dibujar polígonos texturizados con PRKit

Nuestro objetivo es cortar sprites en varias piezas. Un CCSprite típico contiene una textura y un cuadro delimitador sin importar la forma de la imagen. Esto no es adecuado para nuestro juego, ya que conocer las formas reales dentro de las imágenes es un paso crucial para crear sprites que se pueden cortar, rebanar y dividir.

Necesita crear Polígonos Texturizados, que:

  • Crear una correspondencia entre un polígono / forma y una imagen (Mapeo de texturas)
  • Mostrar solo las partes de la imagen que están dentro de los límites del polígono (Relleno de texturas)

Ni Cocos2D ni Box2D vienen con una clase incorporada que maneja las características personalizadas que desea, y normalmente, esto requeriría algo de triangulación junto con código de dibujo OpenGL personalizado.

Suena difícil, ¿verdad?

Afortunadamente, todos los complicados cálculos y dibujo código necesario para lograr este ya han sido escritos por la buena gente de la Clarividencia de Investigación. Crearon una adición a la biblioteca Cocos2D llamada PRKit, que maneja el Mapeo de texturas y el Relleno.

Para comenzar a usar Polígonos texturizados, descargue PRKit, extráigalo y arrastre la carpeta PRKit a su proyecto. Asegúrese de que la opción» Copiar elementos en la carpeta del grupo de destino «esté marcada y que la opción» Crear grupos para las carpetas añadidas » esté seleccionada.

Tenga en cuenta que PRKit se mantiene mediante investigación precognitiva, por lo que puede actualizarse a tiempo. Para evitar confusiones, nuestro kit de recursos también contiene la versión exacta de PRKit que utilicé para hacer este tutorial.

Su proyecto ahora debería incluir estos archivos:

PRKit Yey!

Compilar y ejecutar, y encontrará algunos errores:

PRKit Necesita ser convertido

Los errores aparecen porque PRKit fue creado para Cocos2D 1.X, que usa OpenGL ES 1.1, mientras que usted usa Cocos2D 2.X, que utiliza OpenGL ES 2.0, y hay diferencias significativas entre los dos.

Para arreglar esto, abra PRFilledPolygon.m y hacer estos cambios:

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

Repasemos estos cambios poco a poco.

Primero, en Cocos2D cada CCNode tiene un programa de sombreado OpenGL ES 2.0 adjunto. Para dibujar el polígono Prfilled, debe demandar al sombreador «Posición/Textura» incorporado, que asigna en el método init.

A continuación, debe configurar las coordenadas de textura correctas para cada punto del polígono. Para ello, debe realizar dos cambios en el método calculateTextureCoordinates:Escala

  • : Dado que esta clase hace sus propios cálculos en las coordenadas de su textura, no maneja automáticamente la pantalla retina. Para arreglar esto, simplemente multiplica la textura.pixelsWide con CC_CONTENT_SCALE_FACTOR: un valor multiplicador conveniente proporcionado por Cocos2D para convertir valores entre equivalentes regulares y retina.
  • Voltear Y: Por alguna razón, PRFIlledPolygon dibuja texturas al revés, por lo que simplemente voltea el valor y aquí.

Por último, el código de dibujo se actualiza a OpenGL ES 2.0, de manera similar a cómo CCSprite cambió el dibujo de Cocos2D 1.X a Cocos2D 2.X:

  • Comience llamando a CC_NODE_DRAW_SETUP () para preparar el nodo para dibujar.
  • Las llamadas a glDisableClientState () y glEnableClientState () son obsoletas y se descartan.
  • Los comandos glVertexPointer() y glTexCoordPointer() son reemplazados por glVertexAttribPointer(), que ahora acepta la Posición de Vértice o la Coordenada de textura como su primera opción.
  • La configuración de glTexEnvf (), que era responsable de repetir el sprite en caso de que el polígono fuera más grande que la textura, se reemplaza por llamadas a glTexParameteri ().

Si estás confundido por algo de esto, es posible que quieras ver nuestro OpenGL ES 2.0 para iPhone y Cocos2D 2 personalizado.Tutoriales de X Shaders para obtener más información de fondo. Pero no necesita preocuparse demasiado, porque en este punto todo lo que estamos haciendo es portar la clase para que funcione en Cocos2D 2.X:]

Compilar y ejecutar, ¡y todos los errores de PRKit deberían desaparecer!

Es hora de poner PRKit en acción. Subclasificarás la clase PRFilledPolygon de PRKit para crear una clase base PolygamSprite que dibujará nuestras frutas.

El polígono se basa en PRFilledPolygon adjuntando un cuerpo Box2D al sprite, y también contendrá otras variables y métodos personalizados para los frutos en la implementación de nuestro juego.

Vamos a ello. Pulse Comando + N y cree un nuevo archivo con iOS \ cocos2d v2.plantilla de clase x\CCNode. Conviértelo en una subclase de PRFilledPolygon y nómbralo Polígono-Prito.m.

Cambie a PoligonSprite.h y realice los siguientes cambios:

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

El código anterior declara las variables base y los métodos que necesita para crear un polígono. Estos son:

  • cuerpo: Este es el cuerpo de Box2D que está unido a nuestro sprite. Es necesario para la simulación física.
  • original: Los sprites completos y cortados utilizarán la misma clase de polígono, como tal, diferenciando entre los dos será importante. Si esto es SÍ, significa que es el objeto sin cortar u original que creó, de lo contrario, es solo una pieza del todo.
  • centroide: El centro del polígono dentro de la imagen no siempre será el mismo que el centro de la imagen, por lo que es útil almacenar este valor.
  • propiedades: Expone todas las variables usando propiedades para que otras clases puedan acceder a ellas libremente.
  • init/ spriteWith*: Nuestros métodos de inicio principales siguen la misma convención de nomenclatura que Cocos2D.
  • otros métodos: Estos son métodos que crean & que tratan con el cuerpo de Box2D adjunto y sus propiedades.
  • PTM_RATIO: Relación Píxeles / Metros. Box2D necesita este valor de conversión porque se ocupa de metros en lugar de píxeles.

Cambie rápidamente a PoligonSprite.m y cambiarle el nombre PolygonSprite.mm Todas las clases que mezclan código Objective-C (Cocos2D) y C++ (Box2D) deben tener una extensión «.mm» para notificar al compilador la sintaxis mixta.

A continuación, realice los siguientes cambios en 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;}

Al igual que Cocos2D, todos los métodos spriteWith * son solo contrapartes de autorelease de los métodos initWith*, mientras que initWithWorld todavía no tiene uso real para esta clase, pero en su lugar será utilizado por las subclases de PolygamSprite más tarde.

La mayor parte de los cambios se pueden encontrar en los métodos initWithFile e initWithTexture. Para obtener el flujo de las cosas, la creación de una fruta se llamará en esta secuencia:

Secuencia de Inicio

  • initWithWorld: Está destinado a subclases de polígonos, por lo que no hace nada, excepto devolver nil, y tratar con él más tarde.
  • initWithFile: Esto agrega la textura de nuestro archivo y pasa todo a initWithTexture.
  • initWithTexture: Nuestra inicialización principal. PRFilledPolygon necesita una textura y todos los vértices del polígono que rellena. Dado que el paso anterior ya manejaba la parte de textura, este paso maneja los vértices recolectándolos del cuerpo Box2D del sprite. Después de pasarlas a PRFilledPolygon, procede a inicializar las variables que ha declarado previamente.
  • initWithPoints: Todo lo que esto hace está contenido dentro de PRKit y lo bueno es que ya no necesitas tocar PRKit ahora que has actualizado su código.

Todavía dentro PolygonSprite.mm, agregue los siguientes 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);}

En el código anterior, primero sobrecarga el método setPosition de CCNode para que cuando actualice la posición del sprite, también se actualice la posición del cuerpo de Box2D asociado.

A continuación, crea un método conveniente para crear y definir un cuerpo de Box2D. Para crear un cuerpo, debe definir una definición de cuerpo, un objeto de cuerpo, una forma y una definición de accesorio. No se están asignando valores duros reales aquí todavía, ya que este método será utilizado por subclases de polígono más adelante.

Lo único que hay que tener en cuenta es la categoryBits y maskBits. Estos dos se utilizan para filtrar colisiones entre objetos de modo que si un bit de categoría de un objeto coincide con un bit de máscara de otro objeto y viceversa, habrá una colisión entre esos dos objetos. Se establece primero en 0 porque no desea que se produzcan colisiones cuando los objetos se inicialicen por primera vez.

Por último, define dos métodos que simplemente reemplazan los bloques de categorías y los bloques de máscaras para que pueda activar y desactivar las colisiones de nuestros polígonos.

Hay una cosa más a la que añadir 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_;}

¿Recuerdas cuando mencioné que necesitabas algo de PhysicsSprite? Bueno, esto es todo. Todo lo que hace esto es asegurarse de que nuestra forma Box2D y nuestro sprite estén en la misma posición cuando se mueven. Está preparado para nosotros por Cocos2D y eso lo hace aún más impresionante.

Después de copiar el código anterior, ahora puede eliminar ambos PhysicsSprite.h y PhysicsSprite.mm del proyecto ya que ha eliminado por completo su utilidad.

Compilar y ejecutar, y todo debería estar bien. Has terminado con PolygamSprite por ahora.

Planificar nuestras frutas

Antes de crear clases para nuestras frutas, debe tener claras las reglas que deben seguir las imágenes y sus formas. Dado que asignará nuestras texturas a polígonos Box2D individuales, también debe cumplir con las limitaciones de polígonos de Box2D. Necesitas tener dos cosas en mente:

  • Los polígonos deben ser convexos, lo que significa que ningún ángulo interior es mayor que 180.
  • Los polígonos no deben exceder de 8 vértices.

Puede evitar esta limitación si permite que cada cuerpo contenga varias formas. Box2D puede manejar formas cóncavas si utiliza un método de triangulación y crea formas cóncavas a partir de varios triángulos, pero esto está más allá del alcance del tutorial.

Para mantener las cosas simples, en este tutorial tendrá una regla de forma de 1 Cuerpo a 1.

Nota: PhysicsEditor, la herramienta que veremos más adelante en este tutorial, en realidad contiene código para triangular automáticamente polígonos que dibujas en un conjunto de formas convexas. Sin embargo, como dije, estamos tratando de mantener las cosas simples aquí, así que nos aseguraremos de dibujar nuestras formas convexas para que solo tengamos una forma por cuerpo.

Eche un vistazo a estas dos frutas:

Cóncavo vs Convexo

Usar el Plátano no es una buena idea porque es naturalmente cóncavo. La Sandía, por otro lado, es muy buena porque se puede definir un polígono convexo que se asemeja mucho a su forma.

Si tuviera que definir formas de polígono que sigan las reglas de Box2D para las dos frutas, más o menos terminaría con estas:

 Contorno de forma Box2D

El polígono de Sandía se ajusta perfectamente a la imagen, mientras que el polígono de Plátano tiene un gran espacio vacío donde la imagen se curva hacia adentro. Box2D tratará ese espacio como parte de nuestro objeto, y podría hacer que el Plátano se sienta antinatural cuando choca con otros objetos o cuando se corta.

Esto no significa que no pueda usar el Plátano, sino que simplemente no se recomienda usar el Plátano. De hecho, el juego que crearás en este tutorial usará este mismo Plátano.

Creando la Primera fruta

Es hora de crear la primera fruta: la Sandía (al menos una rebanada de ella).

Pensando en el flujo del proceso de inicialización de nuestro polígono Printe, sabe que initWithTexture espera un cuerpo de Box2D, pero el paso anterior, initWithFile, no proporciona esto.

La razón de esto es que necesita crear y definir el cuerpo individualmente por fruta, por lo que tendrá que ser el primer paso, initWithWorld, que crea el cuerpo y establece otros valores específicos para cada fruta.

Para crear nuestro cuerpo Box2D, primero debe conocer los vértices de la forma de polígono que desea crear. Hay diferentes maneras de hacer esto, pero para este tutorial, utilizará una herramienta ingeniosa llamada PhysicsEditor. Esta herramienta está llena de características, pero solo la usará para guiarnos en la obtención de las coordenadas de los vértices de nuestro polígono.

Si no lo tiene, descargue PhysicsEditor, instálelo y enciéndalo. Obtendrá un proyecto en blanco con 3 paneles / columnas.

Trabajar con PhysicsEditor es bastante sencillo. A la izquierda, pones todas las imágenes con las que quieres trabajar. En el centro, se define visualmente un polígono para la imagen. A la derecha, tiene los parámetros para el cuerpo.

 ¡Editor de física!

Coge sandía.png de la carpeta Imágenes del kit de recursos y arrástrelo al panel izquierdo. Ahora debería ver la Sandía en el panel central.

Aumente la ampliación, que se encuentra en la parte inferior de este panel, a un nivel cómodo, y luego toque el botón Pentágono en la parte superior de este panel para crear una forma de polígono de 3 lados.

Haga clic con el botón derecho en el polígono y elija «Agregar vértice» hasta que tenga 5-8 vértices en total. Mueva los vértices alrededor de los bordes de la Sandía, mientras se asegura de dos cosas:

  • El Polígono que está creando es Convexo.
  • Todos los píxeles de la Sandía están dentro del polígono.

Nota: Otro atajo para dibujar las formas es usar la herramienta varita mágica del editor físico. Simplemente establezca la tolerancia alta (5-8) para que termine con aproximadamente 5-8 puntos, y ajuste los puntos a partir de ahí.

Agregue todos los demás frutos y la imagen de bomba de la carpeta Imágenes del kit de recursos y haga lo mismo por ellos.

Debe definir formas para las siguientes imágenes:

  • banana.png
  • bomba.png
  • uvas.png
  • piña.png
  • fresa.png
  • sandía.png

Cuando haya terminado, en la esquina superior derecha, cambie el valor de Exportador a » Box2D generic (PLIST)», y debería terminar con algo como esto:

¡Defina Formas Fácilmente con PhysicsEditor!

Pulse «Publicar» o «Publicar Como» para exportar el archivo PLIST que contiene la información del vértice. Guarde el archivo como frutas.plist.

Por ejemplo, los frutos.plist que utilizó para este tutorial está dentro de la carpeta Misc del kit de recursos.

Solo desea ver la información contenida en el archivo PLIST, por lo que no agregue este archivo a su proyecto, sino que simplemente abra fruits.plist usando Xcode para ver su contenido de una manera organizada.

Haga clic en el icono de triángulo junto a «cuerpos» para expandir esta sección y verá la lista de imágenes para las que definió formas. Necesitas profundizar hasta el nivel más profundo para obtener los vértices de los polígonos de la sandía de esta manera:

El editor físico PLIST

Expanda sandía/accesorios / Elemento 0 / polígonos y ahora debería ver otro elemento 0 de Tipo Array bajo polígonos. Esta última matriz es tu forma. Si ha definido correctamente una forma convexa con 8 vértices o menos, solo debería ver una matriz bajo polígonos.

Si ve más de uno, i.e Array de elemento 0, Array de elemento 1, etc., entonces significa que el editor físico hizo una forma compleja porque se definieron demasiados vértices o se formó un polígono cóncavo. Si esto sucede, vuelve al editor físico y arregla tu forma.

A continuación, expanda el elemento 0 del tipo Array para ver la lista final de elementos. Estos son sus vértices, y el valor que ve en el lado derecho con este formato { número, número } son sus coordenadas x & y para cada vértice.

Ahora que tiene los valores exactos para los vértices de su polígono, puede continuar creando la clase Sandía.

En Xcode, cree un nuevo archivo con iOS\cocos2d v2.plantilla de clase x\CCNode. Conviértelo en una subclase de Polígono y llámelo Sandía. Abre la Sandía.h y realice los siguientes cambios:

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

Cambia a Sandía.m, cámbiale el nombre a Watermelon.mm y agregue el siguiente 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;}

En el código anterior, primero define cuántos vértices hay, que en este caso es 7. A continuación, crea una matriz de vértices que contiene todas las coordenadas que acaba de ver en el PLIST. Utilice esta información para crear un cuerpo utilizando el método de conveniencia que definió en PolygamSprite.

Pones un poco de fricción para que las formas no se deslicen sin fin, y también pones un poco de restitución para que las formas no se detengan cuando reboten entre sí.

Por último, crea el objeto llamando a la inicialización de la superclase y pasa el nombre del archivo de imagen, el cuerpo de Box2D, y declara que se trata de una fruta original.

Necesita las imágenes de sandía del kit de recursos, por lo que ahora sería un buen momento para agregar todos los recursos gráficos que necesita para el resto del tutorial.

En el panel Navegador de proyectos, haga clic con el botón derecho en Recursos y seleccione «Agregar archivos a CutCutCut». Agregue la carpeta Imágenes del kit de recursos al proyecto. Asegúrese de que la opción» Copiar elementos en la carpeta del grupo de destino «esté marcada y que la opción» Crear grupos para las carpetas añadidas » esté seleccionada.

Siga los mismos pasos para crear Banana, Uvas, Piña, Fresa y Bomba.

Solo abordaste cómo crear la primera fruta paso a paso, ya que básicamente es un proceso de enjuague & repetir para cada fruta. El kit de recursos contiene clases de frutas y bombas listas para usar en la carpeta de clases para que las vea en caso de que aún necesite orientación, o puede agregarlas todas a su proyecto si desea omitir este paso.

Compilar y ejecutar, y asegurarse de que todo está bien.

Agregar una Fruta a la Escena

Hasta ahora, no ha pasado nada en la pantalla todavía, y obviamente tienes ganas de ver los frutos de tu trabajo – ¡juego de palabras intencionado! :]

Cambiar a HelloWorldLayer.h y realice los siguientes cambios:

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

Cambiar de nuevo a HelloWorldLayer.mm y hacer estos cambios:

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

Declaras una matriz de caché, que guardará todas las frutas y bombas que crees en el futuro. A continuación, crea 1 sandía y añádela a la escena. Se llama colisiones activas para que la sandía no pase a través de las paredes.

Compile y ejecute, y debería ver una Sandía cayendo desde el área central de la pantalla, y aterrizar en la parte inferior como se muestra a continuación.

 El fruto de su trabajo

Puede notar que la sandía no está exactamente en el centro. La razón de esto es que posicionó el objeto en función de su cuerpo Box2D, y el origen de nuestro cuerpo Box2D está en la esquina inferior izquierda del objeto. El contorno delgado alrededor de la Sandía es visible porque el modo de dibujo de depuración todavía está activado.

¿A Dónde Ir Desde Aquí?

Aquí hay un proyecto de ejemplo con todo el código del tutorial anterior.

Eso es todo para la parte 1 de la serie. Hasta ahora, tienes un Polígono con textura de Sandía que cae al fondo de la pantalla.

Pero en lugar de dibujar un sprite rectangular con espacio transparente como se suele ver en los tutoriales de Box2D, utiliza PRKit para dibujar solo las partes de la textura que corresponden a los vértices del cuerpo de Box2D. ¡Esto será útil pronto!

Ahora está listo para la Parte 2 del tutorial, donde agrega la capacidad de cortar las frutas.

Mientras tanto, si tiene alguna pregunta o comentario sobre esta parte, ¡únase a la discusión del foro a continuación!


Esta es una publicación de Allen Tan, miembro del equipo de Tutoriales de iOS, desarrollador de iOS y cofundador de White Widget. También lo puedes encontrar en Google+ y Twitter.

raywenderlich.com Semanalmente

raywenderlich.com el boletín de noticias es la forma más fácil de mantenerse al día sobre todo lo que necesita saber como desarrollador móvil.

Obtenga un resumen semanal de nuestros tutoriales y cursos, y reciba un curso gratuito en profundidad por correo electrónico como bono!

Leave a Reply

Tu dirección de correo electrónico no será publicada.