Calendario de Linkvent, Día 3: MVC con Cocos2D

El 3 de diciembre de 2010, en Cocos2D Linkvent Calendario, por Steffen Itterheim by Steffen Itterheim

La relación de hoy es sobre el regulador de la Visión modelo (MVC) el modelo de diseño y como ponerlo en práctica en Cocos2D. Bartek Wilczyński de Polonia ha escrito un seminario de dos partes sobre como poner en práctica este modelo de diseño, y explica por qué esto es una opción de diseño buena:

Como poner en práctica el modelo MVC en el juego Cocos2D – la Parte 1
Como poner en práctica el modelo MVC en el juego Cocos2D – la Parte 2

Mientras yo leía que, recordé que Jeremy Flores había creado un depósito github con su realización de un modelo MVC en Cocos2D. Él dobló su proyecto Cocos2D-MNC, como en el regulador del Nodo modelo. El código es publicado según la licencia de MIT. The code is published under the MIT license.

El modelo MVC es algo similar a un sistema de componente de objeto animoso que describí aquí. Para ambos sistemas, la idea general no es subclasificar CCSprite y poner su lógica animosa en allí. CCSprite ya es una clase de representación visual completa para su jugador, enemigo, y que no. Pero en algunos casos, usted necesita más de un elfo, o una combinación de efectos de partícula y un elfo. Una vez que usted se pone allí, es mucho mejor tener un CCNode que contiene (agregando) todos los elementos visuales de su objeto animoso, manejando toda la lógica animosa de aquel objeto y actualizando los elementos visuales. El CCNode se hace el regulador, controlando las visiones. Como las visiones (elfos, efectos, dibujos de GL, etc.) movimiento en pantalla, el nodo de regulador vota los nodos visuales para la información estatal y dirige el código lógico animoso, que por su parte puede actualizar las visiones. CCSprite already is a complete visual representation class for your player, enemy, and what not. But in some cases, you need more than one sprite, or a combination of a sprite and particle effects. Once you get there, it’s much better to have a CCNode containing (aggregating) all the visual elements of your game object, while handling all the game logic of that object and updating the visual elements. The CCNode becomes the controller, controlling the views. As the views (sprites, effects, GL drawings, etc.) move on screen, the controller node polls the visual nodes for state information and runs the game logic code, which in turn may update the views.

En términos muy simples, esto es mi enfoque pragmático del modelo MVC que también trabaja completamente bien. Es definitivamente ya un salto grande adelante comparado con subclasificar extensivamente la clase CCSprite. Si usted nota que hace esto mucho, usted debería hacerse un favor y leer en el modelo de diseño de MVC. If you notice that you’re doing that a lot, you should do yourself a favor and read up on the MVC design pattern.

Añada su relación al Cocos2D Linkvent Calendario

¿Tiene usted algo para compartir con la comunidad Cocos2D? No he recibido bastantes sumisiones para llenar todos los días hasta Xmas, aunque yo realmente tenga bastantes relaciones para fijar el que cada día, prefiero fijar una relación a su sitio web o entrada de bitácora.

Cocos2D Xcode Proyecto en Github

El 4 de noviembre de 2010, en cocos2d, instrumentos, Xcode, por Steffen Itterheim by Steffen Itterheim

Mi Cocos2D Xcode proyecto está ahora en Github. La fuente abierta, libre, correctamente MIT Autorizado, incluye el rootViewController y apoya Cocos2D v0.99.5 rc0.

También sigo trabajando (con) una versión enormemente realzada del proyecto de Xcode. Esto integra la cera (Lua) y un Sistema de Componente de Objeto Animoso que llamé “gocos”. También viene con clases de conveniencia mucho más útiles. Also comes with a lot more useful convenience classes.

Pero la idea grande realmente es cargar (o relación dentro de github, si puedo entender si y como esto trabaja) todos los proyectos dependientes en un depósito, de modo que usted pueda descargar todo inmediatamente y esto trabaja de la caja. Actualmente hay 3 proyectos referidos por el cocos2d-proyecto: el gocos (van a llamarlo una biblioteca de conveniencia y código de gameplay para Cocos2D), la cera (apoyo de Lua) y obviamente cocos2d-I-Phone. Entonces todo esto es necesario va a ser atado en un fardo en un paquete grande, qué vacíos toda la incompatibilidad de versión publica. gocos (let’s call it a library of convenience and gameplay code for Cocos2D), wax (Lua support) and obviously cocos2d-iphone. So everything that’s needed is going to be bundled in one big package, which voids all of the version incompatibility issues.

Usted todavía puede experimentar con versiones diferentes de estas bibliotecas pero en este caso creo que usted sabe lo que usted hace y esto resulta deben ser esperados. Pero siendo un depósito github, usted puede reproducir por supuesto y destinar cambios.

Aperitivo

Aquí está lo que he hecho con Lua. Lo uso actualmente sólo como un mejor reemplazo plist para ajustes. Es mejor que plist porque usted puede comentar sobre cada artículo, usted puede clasificarlos fácilmente, usted puede dirigir funciones y algoritmos para generar valores o cargar datos adicionales, y en general es mucho más fácil trabajar con que el redactor plist. Aquí está config.lua reducido que es cargado en el tiempo de ejecución en una jerarquía de objetos de NSDictionary: It’s better than plist because you can comment on each item, you can sort them easily, you can run functions and algorithms to generate values or load additional data, and in general it’s a lot easier to work with than the plist editor. Here’s a reduced config.lua that is loaded at runtime into a hierarchy of NSDictionary objects:

config local =
{
  AccelerometerControls =
  {
    UpdatesPerSecond = 60, - 60 Hz -- 60 Hz
    Sensibilidad = 0.997,
    SensitivityX =-2,,
    SensitivityY = 2,
    MaxVelocity = 100,
  },
}

devuelva config

Y esta línea del código carga estos valores y los adjudica a las propiedades proporcionalmente llamadas de la clase objetivo:

[Config loadPropertiesFromKeyPath:@ "AccelerometerControls" target:self];"AccelerometerControls" target:self];

Esto es todo que usted tiene que hacer para transferir los valores de config.lua en un caso de clase. ¡Timesaver enorme! El único inconveniente consiste en que esto actualmente no puede distinguir entre flotador, intervalo y bool (debido a NSNumber), entonces esto actualmente sólo apoya propiedades de flotador. The only drawback is that it currently can’t differentiate between float, int and bool (due to NSNumber), so it currently only supports float properties.

Libro de cocos2d, el Capítulo 6: Spritesheets & Zwoptex

El 30 de julio de 2010, en Anuncios, libro, cocos2d, por Steffen Itterheim by Steffen Itterheim

El capítulo 6 – Spritesheets y Zwoptex

En este capítulo el foco estará en Spritesheets (Atlas de Textura), lo que ellos son y cuando, donde y por qué usarlos. Por supuesto un capítulo sobre Spritesheets no sería completo sin introducir el instrumento de Zwoptex. La gráfica añadida en este capítulo será usada entonces para el juego creado en el capítulo siguiente. The graphics added in this chapter will then be used for the game created in the following chapter.

El capítulo será presentado el viernes, 6 de agosto.

¿Algo sobre Spritesheets usted siempre quería saber?

Sólo avíseme. Investigaré que tipo de gente de cuestiones era y tiene en cuanto a Spritesheets. Quiero asegurarme que ellos son todos cubiertos en el libro. I want to make sure that they are all covered in the book.

Por favor deje un comentario o escríbame un correo electrónico.

Resumen de trabajo en el Capítulo 5 – Componentes básicos Animosos

Finalmente encontré un mejor título para el capítulo. Una parte grande es sobre el funcionamiento con Escenas y Capas. Una clase de LoadingScene es puesta en práctica para evitar el traslapo de memoria cuando transitioning entre dos escenas. Las capas son usadas para modificar los objetos animosos seperately de UI estático. Explico como usar a tratantes de toque apuntados para manejar la entrada de toque para cada capa individual, toques que tragan o no. A LoadingScene class is implemented to avoid the memory overlap when transitioning between two scenes. Layers are used to modify the game objects seperately from the static UI. I explain how to use targeted touch handlers to handle touch input for each individual layer, either swallowing touches or not.

Dan la cuestión de si a la subclase CCSprite o no es hablado y un ejemplo como crear objetos animosos usando la composición y sin subclasificar de CCNode y como esto cambia la entrada de toque y la programación.

Al final dan las clases CCNode especializadas restantes, como CCProgressTimer, CCParallaxNode y la clase CCRibbon con CCMotionStreak un tratamiento.

Como usted puede ver de los cuadros, también hago el progreso bueno en hacerme un grande artista de pixel. Sólo tengo un camino looooooong delante de mí todavía. Pero confieso, poco sé sobre el arte y cuánto menos lo he practicado, soy bastante contento con los resultados y divirtiéndome con él. El aspecto chulo de ello es que esto debería ser el arte instructivo. No tiene que estar bien. Entonces sólo sigo adelante y lo hago y tiendo a ser positivamente sorprendido por los resultados. Tocaré probablemente este sujeto en el siguiente capítulo sobre Spritesheets: hacer su propio arte. No es mejor que nada, es el trabajo todavía creativo aun si puede ser feo a otros, y es mucho más satisfacción para hacer todo usted mismo, aun si esto toma un poco más largo y no mira como bueno. Al menos es todo el suyo, usted se divierte, y aprende algo a lo largo del camino. Y usted siempre puede encontrar a un artista algún día más tarde que dibujará sólo sobre sus imágenes existentes o quién sustituye sus efectos sonoros de pedo por algo más apropiado. But I admit, the little I know about art and how much less I’ve practiced it, I’m pretty happy about the results and having fun with it. The cool aspect of it is that this should be instructive art. It doesn’t have to be good. So I just go ahead and do it and tend to be positively surprised by the results. I’ll probably touch this subject in the next chapter about Spritesheets: doing your own art. It’s better than nothing, it’s still creative work even if it may be ugly to others, and it’s a lot more satisfying to do everything yourself, even if it takes a bit longer and doesn’t look as good. At least it’s all yours, you’re having fun, and learn something along the way. And you can always find an artist sometime later who will just draw over your existing images or who replaces your fart sound effects with something more appropriate.

Btw, si usted busca un programa de edición de imágenes decente y libre para Mac, he estado usando la Costa del mar durante aproximadamente un año ahora y soy bastante contento con ello.

Levantamiento de conciencia: uso de memoria & agujeros

El 25 de julio de 2010, en cocos2d, Programación, que Habla De Experiencia, por Steffen Itterheim by Steffen Itterheim

Ayudando a otros a solucionar sus cuestiones de proyecto de cocos2d durante el año pasado se hizo obvio que muchos proyectos tienen al menos un problema principal en una de estas áreas:

  • dirección de memoria
  • administración de recursos
  • estructura de código

Ejemplos

Las cuestiones de dirección de memoria normalmente se extienden de asignar demasiada memoria, cargando demasiadas texturas frente que sólo van a ser necesarios más tarde, o por agujeros de memoria, como escenas que no desasignan cambiando escenas. Los problemas de administración de recursos se extienden de no añadir los recursos correctos al objetivo correcto, a menudo causando la talla de App aumentada porque los recursos son añadidos al bulto, pero nunca usados por App. Esto también podría significar cargar archivos de recurso idénticos salvo que ellos tienen nombres del archivo diferentes (¿copias?), consumiendo memoria adicional. O no elfos que hacen las maletas fuertemente en Atlas de Textura pero en cambio utilización de un Atlas de Textura por objeto animoso – mientras esto es comprensible desde un punto de vista de seperation lógico realmente gasta oportunidades de la optimización. It could also mean loading identical resource files except that they have different filenames (copies?), using up additional memory. Or not tightly packing sprites into Texture Atlases but instead using one Texture Atlas per game object – while this is understandable from a standpoint of logical seperation it does waste opportunities for optimization.

Finalmente, cifre la estructura o carezca de eso con regularidad lleva “a todo en una clase” diseño de código que es el más probable un proceso evolutivo, más bien que intencional. Es bastante común ver clases con miles de líneas del código, que a veces hasta va 10 000 líneas pasadas del código en una clase. Otras cosas usan demasiados CCLayers sin ellos añadiendo una ventaja clara, por ejemplo sólo para agrupar todos los nodos en un pedido de z específico juntos o agruparlos por la funcionalidad, eg una capa para enemigos, un para jugadores, un para el fondo, un para UI, un para el resultado, un para efectos de partícula, etcétera – sin cualquiera de estas capas usadas para en qué ellos están realmente bien: modificación de nodos múltiples inmediatamente, como movimiento, escalamiento, giro o z-nuevo-pedido ellos. Y por supuesto hay el infierno de pasta & copia, los bloques grandes del código reproducido en varios sitios sólo para modificar algunos parámetros en vez de crear un método que toma los parámetros modificables como argumentos. Incluso los profesionales trabajé con el conseguido tan acostumbrado para hacer que se hizo difícil sólo vencer la resistencia de piso de alquiler van de viejos hábitos. Pero ellos aprendieron. Other things are using too many CCLayers without them adding a clear benefit, for example just to group all nodes at a specific z order together or to group them by functionality, eg one layer for enemies, one for players, one for background, one for UI, one for score, one for particle effects, and so on – without any of these layers being used for what they’re really good at: modifying multiple nodes at once, like moving, scaling, rotating or z-reordering them. And of course there’s the copy & paste hell, large blocks of code reproduced in various places only to modify some parameters instead of creating a method which takes the modifiable parameters as arguments. Even professionals I worked with got so used to doing that it became hard just to overcome the resistance of letting go of old habits. But they learned.

Resumen

Nada de este diseño de código y estructuración me golpea como raro o sorprendente. He escrito el código como esto yo mismo. ¿También creo si está bastante bien y trabajos, entonces por qué diablos no? Es un asunto de experiencia y sólo es con la experiencia que usted claramente ve como mejorar cosas. Esto se reduce a la curva de aprendizaje regular donde sólo la formación y enseñar y sólo simplemente la fabricación de errores y el aprendizaje de ellos ayudan en la carrera larga. Esto es como aprendemos cosas. I also believe if it’s good enough and works, then why the hell not? It’s a matter of experience and it’s only with experience that you clearly see how to improve things. This boils down to the regular learning curve where only training and tutoring and just simply making mistakes and learning from them helps in the long run. That’s how we learn things.

Por otra parte, las cosas como Memoria y Administración de recursos también pueden ser aprendidas pero ellos tienen una naturaleza diferente. Ellos pueden ser según las estadísticas tasados, ellos podrían ser calculados y verificados automáticamente. ¿Esto me hace preguntarme si no hay los una especie de instrumentos de información y automatización que ayudarían a reveladores a conseguir mejores resultados en términos de uso de memoria y administración de recursos? Mientras tanto es todo sobre el levantamiento de la conciencia … This makes me wonder if there isn’t some kind of automation and information tools that would help developers achieve better results in terms of memory usage and resource management? In the meantime it’s all about raising awareness …

Levantamiento de Conciencia de Memoria

El más importantemente creo que tenemos que levantar más conciencia a estas cuestiones a reveladores cocos2d. Un paso hacia esto sería para cocos2d para mostrar un “contador de memoria disponible” junto al contador de FPS. Yo solía remendar CCDirector para mostrar simplemente la memoria en vez de FPS ya que siempre era más importante para mí. El revelador cocos2d del mismo tipo Joseph me envió su versión para mostrar a ambos – simplemente no pensé en el obvio. Tan si le gustara ver FPS y memoria disponible el uno al lado del otro creo que usted puede manejar los cambios en CCDirector perfilado aquí: I used to patch CCDirector to simply display memory instead of FPS since that was always more important to me. Fellow cocos2d developer Joseph sent me his version to display both – I simply didn’t think of the obvious. So if you’d like to see FPS and available memory next to each other I think you can handle the changes to CCDirector outlined here:


//CCDirector.h, añaden debajo de @interface:
+ (doble) getAvailableBytes;
+ (doble) getAvailableKiloBytes;
+ (doble) getAvailableMegaBytes;

//CCDirector.m, añaden como apropiado:
#include <sys/sysctl.h>  
#import <mach/mach.h>
#import <mach/mach_host.h>

[...]

+ (doble) getAvailableBytes
{
  vm_statistics_data_t vmStats;
  mach_msg_type_number_t infoCount = HOST_VM_INFO_COUNT;
  kern_return_t kernReturn = host_statistics (mach_host_self (), HOST_VM_INFO, (host_info_t)&vmStats, &infoCount);

  si (¡kernReturn! = KERN_SUCCESS)
  {
    devuelva NSNotFound;
  }

  vuelva (vm_page_size * vmStats.free_count);
}

+ (doble) getAvailableKiloBytes
{
  vuelva [CCDirector getAvailableBytes] / 1024.0;
}

+ (doble) getAvailableMegaBytes
{
  vuelva [CCDirector getAvailableKiloBytes] / 1024.0;
}

[...]

- (vacío) showFPS
{
  marcos ++;
  accumDt + = dt;

  si (accumDt> CC_DIRECTOR_FPS_INTERVAL)  {
    frameRate = frames/accumDt;
    marcos = 0;
    accumDt = 0;

    //el único cambio de showFPS es esta línea:
    NSString *str = [[NSString alloc] initWithFormat:@" %.1f  %.1f", frameRate, [CCDirector getAvailableMegaBytes]];

    [FPSLabel setString:str];
    [liberación de str];
  }
}

El levantamiento de conciencia a escape de Escenas

Además muy, fuertemente y con el refuerzo sumo (sin sacar un arma) recomiendo a reveladores cocos2d por comprobar con frecuencia los métodos dealloc de su escena. Preferentemente añada un límite de facturación allí, o por lo menos añada la línea de registro: CCLOG (”dealloc: %”, mí). Si usted quiere un método más visible pero menos intruso usted podría hacer algo como centelleo de la pantalla o juego de un sonido siempre que la última escena sea desasignada, de modo que usted se haga tan acostumbrado para ello que cuando usted no lo ve u oye más esto inmediatamente levanta su atención. CCLOG(@”dealloc: %@”, self). If you want a more visible but less intrusive method you could do something like flashing the screen or playing a sound whenever the last scene is deallocated, so that you get so used to it that when you’re not seeing or hearing it anymore it immediately raises your attention.

Si en cualquier momento durante el desarrollo de su proyecto el método dealloc de una escena no es llamado cuando usted cambia escenas, usted divulga la memoria. El escape de la escena entera es un agujero de memoria de la clase peor. Usted quiere agarrar esto temprano mientras usted todavía puede volver sobre sus pasos que podrían haber causado el problema. Una vez que usted se pone a la utilización de cientos de activos y miles de líneas del código y luego realiza que la escena no es desasignada, usted estará en para un paseo divertido que trata de entender donde esto viene de. En este caso, quitar nodos no comentándolos hasta que usted pueda acercarse en el culpable es probablemente la mejor estrategia, al lado de la utilización de Instrumentos (que no he encontrado demasiado provechoso en aquellos casos). You want to catch that early while you can still retrace your steps that might have caused the problem. Once you get to using hundreds of assets and thousands of lines of code and then realize the scene isn’t deallocated, you’ll be in for a fun ride trying to figure out where that’s coming from. In that case, removing nodes by uncommenting them until you can close in on the culprit is probably the best strategy, next to using Instruments (which I haven’t found too helpful in those cases).

Me topé con tal problema una vez porque yo pasaba el objeto de CCScene a subclases de modo que ellos tengan el acceso a los métodos de la escena. La subclase retuvo la escena y fue sacada de CCNode y añadió al CCScene como el niño. El problema con esto: durante la limpieza de la escena esto correctamente quitó todos los nodos de niño pero algunos nodos de niño todavía retenían la escena. A causa de aquel su método dealloc nunca fue llamado, y por su parte la escena nunca fue desasignada. The problem with that: during cleanup of the scene it correctly removed all child nodes but some of the child nodes still retained the scene. Because of that their dealloc method was never called, and in turn the scene was never deallocated.

Prefiera Composición sobre Herencia

El 11 de junio de 2010, en Programación, que Habla De Experiencia, por Steffen Itterheim by Steffen Itterheim

Cuando la pregunta subió si a la subclase CCSprite o usan alguna clase modela para construir su jerarquía de entidad animosa en el foro cocos2d, subrayé que habría que tratar de no usar la herencia y guardar la jerarquía de herencia a como pocos niveles como sea posible. He trabajado con codebases con cientos de miles de líneas del código, y cientos de tipos diferentes de actores en el mundo. Aún la jerarquía de herencia era 2 clases (paternales) súper para casi todos los objetos, sólo muy pocos objetos animosos tenían 3 o 4 clases súper. ¿Cómo puede usted hacer juegos complejos este camino? Yet the inheritance hierarchy was 2 super (parent) classes for almost all objects, only very few game objects had 3 or 4 super classes. How can you make complex games this way?

La respuesta está en la composición, a menudo referida Componentes como Animosos por motores como TorqueX y el Motor de PushButton (un motor de juego de Destello de los reveladores de Torsión originales). Este vídeo de PushButton conduce el revelador Ben Garney lo explica muy bien y también ilustra el problema con el uso excesivo de herencia en motores animosos. Algo del cual la mayor parte de reveladores nuevos a la programación orientada al objeto y/o animosa realmente tienden de hecho a abusar – culpo esto de libros mal escritos y otras fuentes OOP introductorias que enfatizan la herencia sin hablar de sus desventajas. Something that most developers new to object-oriented and/or game programming do in fact tend to over-use – i blame that on poorly written books and other introductory OOP sources which emphasize inheritance without discussing its disadvantages.

Usted puede leer más sobre el sistema de Componentes de PushButton en su documentación. Como ellos pusieron en práctica Componentes en TorqueX y lo que las diferencias son a Componentes Animosos XNA adelante realza el entendimiento del concepto.

Ya que la lectura adicional y los argumentos leen el artículo Wikipedia sobre la ingeniería de software basada componente. ¡De hecho, la lengua Objetiva-C fue inventada para ser capaz de crear componentes de software reutilizables!

La conversación de 2002 GDC de Scott Bilas sobre Un Sistema de Objeto Animoso conducido por los Datos (PDF) como usado por el Sitio de Calabozo contiene más agujas en por qué la herencia falla para reveladores animosos y lo que las ventajas (sino también algunas advertencias) son con motores animosos basados en el componente. La conversación puede ser vieja pero todavía es tan válido hoy como esto estuvo de vuelta entonces. De hecho, en 2002 comencé a trabajar en SpellForce que ya hizo incorporar un sistema componente en su corazón, llamado Aspectos, Capacidades y Ortografía. Esto permitió que nosotros entráramos en todos los datos animosos en la base de datos y los programadores sólo tenían que escribir el código genérico que trató con los datos, así como poner ciertos límites y verificaciones de validez (eg. usted no podía usar una ortografía perjudicial en usted, pero si usted quisiera a usted podría apuntar a enemigos con su curar la ortografía, o tener edificios de brote de arqueros … errm). In fact, in 2002 i started working on SpellForce which already had a component system built into its core, called Aspects, Abilities and Spells. It allowed us to enter all the game data in the database and programmers only needed to write the generic code that dealt with the data, as well as setting certain limits and validity checks (eg. you couldn’t use a damaging spell on yourself but if you wanted to you could target enemies with your heal spell, or have archers shoot buildings … errm).

Durante 2009 GDC una presentación similar fue sostenida por Marcin Chady del Entretenimiento Radical. La conversación fue llamada Teoría y Práctica de la Arquitectura de Componente de Objeto Animosa (PPT).

Mick West escribió un artículo Refactoring Game Entities with Components que describe los desafíos y ventajas de cambiar a Tony Hawk codebase de un modelo de herencia a un sistema componente animoso.

Algo más avanzado leído en el uso componente es un papel de colaboración llamado el Sistema de Componente de Objeto Animoso Dinámico para Caracteres de Comportamiento Mudables que habla de componentes en el contexto de máquinas estatales finitas y comportamientos NPC con un sistema de activación basado en la regla.

El blog de Arquitecto Animoso lo llama una Anatomía de Desesperación y resume muy bien lo que las estafas del diseño de clase basado en la herencia es y como la composición los soluciona.