Cómo implementar mvc en cocos2d
Cocos2d tiene algunas clases internas, como CCSprite, CCLayer y CCScene. Básicamente, cuando desarrolles un juego usando cocos2d, seguirás los siguientes pasos para implementar la lógica del juego:
Inicializa el primer CCScene (es decir, el primer CCScene en AppDelegate) a través de la clase de proxy de la aplicación, / p>
En CCScene, cree una instancia de una o más CCLayers en CCScene y agréguelas como subclases.
CCLayer crea una instancia de uno o más CCSprites en CCScene y los agrega como nodos secundarios llamando a addChild.
CCScene maneja la entrada del usuario (como eventos táctiles y cambios de acelerómetro) y actualiza las propiedades. de CCLayer y CCSpirte, como cambiar la posición de CCSprite, dejar que el sprite ejecute una o más acciones, etc.
CCScene ejecuta un bucle de juego (normalmente actualizaciones 1/60) y luego CCLayer y CCSprite realizan algunas actualizaciones y lógica de juego dentro de ese bucle de juego.
El proceso parece muy sencillo y te permite crear un juego muy rápidamente. Por eso cocos2d es tan popular, es tan simple. Sin embargo, a medida que la lógica del juego se vuelve más compleja, el mantenimiento del código se vuelve cada vez más difícil. El problema más destacado aquí es que la clase CCScene es responsable de demasiadas cosas: no solo maneja la interacción del usuario, sino también es responsable de la lógica del juego (capa lógica) y la visualización de la pantalla (capa de presentación). (Nota del traductor Según los principios de SoC, esto obviamente no es razonable. Deberíamos separar las responsabilidades para que el código sea más fácil de mantener. Al mismo tiempo, SRP (principio de responsabilidad única) también requiere que una clase solo sea responsable de una cosa).
Modelo
MVC divide un sistema en los siguientes componentes:
Modelo, que es responsable del procesamiento lógico del código relacionado con el dominio. que es la capa lógica o capa de dominio.
Ver, solo es responsable de la visualización de la interfaz.
Controlador, responsable de gestionar la interacción del usuario.
Comencemos con un modelo que representa la lógica del juego. Dado que estoy trabajando en un juego de plataformas en este momento, parte de lo que voy a hablar está relacionado con las plataformas. El modelo de mi juego contiene las siguientes clases (por supuesto, solo una parte de ellas):
Jugador
contiene algunas propiedades como: posición del jugador, velocidad actual (velocidad del eje X , velocidad del eje Y), etc.
Contiene la posición del jugador, velocidad actual (velocidad del eje X, velocidad del eje Y), etc.
Contiene lógica de juego.
Contiene alguna lógica de procesamiento relacionada con el jugador, como: correr, caminar, jmup, etc.
Contiene un método de actualización, que se llama cada vez que se actualiza el bucle principal. Este método es responsable de actualizar el modelo del reproductor.
Plataforma,
Contiene propiedades como: posición de la plataforma, ancho, alto, etc.
Contiene alguna lógica de procesamiento relacionada con la plataforma, como plegado, etc.
Contiene un método de actualización, que se llama cada vez que se actualiza el bucle principal del juego y es el principal responsable de actualizar el modelo de plataforma.
GameModel,
Contiene algunas propiedades del mundo del juego, como la gravedad.
Contiene algunos métodos para ejecutar la lógica del juego.
Contiene un método de actualización que el bucle del juego llama en cada actualización de cuadro, que luego actualiza su estado y activa otros objetos en el mundo del juego para actualizar su estado en consecuencia.
Quizás te preguntes: Algunas propiedades no necesitan ser redefinidas, puedes obtenerlas directamente desde CCSprite, como posición, ancho, alto, etc. Lo que intento decir es que hay una manera correcta y una incorrecta de hacer esto, una manera correcta y una incorrecta de hacerlo. Yo diría: hay bien y hay mal. Sí porque son realmente similares y puedes usarlos directamente. La razón del error es que es posible que el mod esté usando algunas unidades de medida diferentes, como metros, en lugar de píxeles. (Por ejemplo, box2d no utiliza píxeles como unidades). En mi modelo estoy usando metros, pero por supuesto puedes usar pies u otras unidades. El motor de renderizado es transparente para el MOD y el MOD no necesita preocuparse en absoluto.
Vista
Según el principio MVC, la vista solo debe ser responsable de la visualización de la interfaz. En realidad, esta es una de las cosas más simples que puede hacer al implementar mvc en cocos2d. Si tiene un mod, puede usar CCLayer y agregar algunas clases CCSprite u otras clases de coocs2d para manejar la visualización. La ventaja de separar el mod de la vista es que no es necesario asignar las propiedades del mod directamente a las propiedades de la vista. Por ejemplo, tu reproductor se mueve en la dirección del eje x, pero quieres que siempre esté 10 píxeles a la izquierda de la pantalla. En este punto, puedes mover CCLayer sin mover realmente el objeto. Tienes que pensar en unidades al mostrar objetos MOD externamente, si usas metros como unidad de medida, debes convertirlos a píxeles al renderizar. (Puedes definir un PTM_RATIO en box2d) Entonces, ¿cómo maneja tu MOD las vistas? Puedes obtener la vista desde el interior del controlador o hacer que el modelo del juego sea un singleton y usar métodos estáticos para manejarlo.
Controladores
Los controladores son responsables de conectar las vistas a los modelos. Su principal responsabilidad es manejar la entrada del usuario. Dado que necesitamos crear instancias tanto del modelo como de la vista, creo que la creación de instancias en el controlador es una buena opción. Heredé la clase de controlador de la clase CCScene y luego necesitamos crear una clase de controlador inicial de la que appDelegate crea una instancia. Sin embargo, hay un problema aquí: CCLayer maneja el evento táctil y la función de CCLayer en mi diseño es la vista. No quiero que la vista maneje la entrada del usuario, por lo que necesito pasar la referencia de la vista. al controlador (no pasarlo directamente a través del delegado) y luego ejecutar el código de manejo de eventos táctiles del controlador a través de appDelegate. Bien, ahora mi clase de controlador puede manejar eventos de usuario en la vista. Luego puede operar el modelo basándose en la entrada del usuario, ya sea modificando las propiedades del modelo o llamando a los métodos del modelo. Después de actualizar el modelo nuevamente, nuestras vistas también deben ser notificadas y actualizadas. Todo esto se hace dentro del bucle del juego, que en realidad es un controlador cuyo trabajo es llamar al método de actualización de la vista y luego dejar que la vista haga el resto.