Empezando un juego

Consulte acerca de programas, técnicas, algoritmos etc.

Empezando un juego

Notapor kkmrmd » Mié Oct 03, 2007 5:44 pm

Hola, nunca antes había posteado, pero la página si la había visitado. Dicho esto entro en materia.

Después de hacer mis minijuegos de rigor: un pang, un pilla-pilla, un juego de navecillas cutres y algunas cositas de poca importancia, y ya familiarizado con las SDL, almenos lo más básico, quiero hacer algo de más peso.
El problema es que no paso de la etapa de "diseño", me explico: cuando hago los ejemplos o leo los tutoriales siempre se hacen juegos muy limitados, no pensados para ser ampliados, configurados ect. Cuando tengo en mente un juego intento hacer la estructura en módulos, que tipos de datos usaré y tal y cual, intentando que sean lo más genéricos posibles para poderse cambiar o ampliarse con archivos de configuración y no tocando el código. Pero llegados a este punto siempre me acabo desbordando debido a cosas que no están bien, vuelvo a empezar de 0 intentado corregir los errores, pero acabo irremediablemente por una cosa u otra en el mismo sitio.
No sé muy bien cómo explicarlo, mirando los foros y tal normalmente se preguntan cosas concretas y específicas, por resumirlo de una manera: conocéis algún recurso (léase manual, libro, ejemplo comentado, tutorialweb...) que te explique como modular y dividir un programa, y si está enfocado a los videojuegos mejor. Porque vamos, la teoría creo que la tengo asimilada, aislar tipos de datos, crear una interficie para poder comunicarte con ellos y bla bla, pero a la hora de hacer el esqueleto y definir las funciones, sus parámetros para luego poder ser expandidos me acaba saliendo mal. Tengo la impresión de que si pudiera definir bien la estructura, lo que ha de hacer cada función ect luego implementarlo sería bastante fácil.


La verdad es que después de haber intentado hacer algunas cosas sin mucho éxito tengo bastantes dudas, pero me limitaré a poner las que tienen un poco relación con el tema.
Aunque el problema de modular un programa es genérico y no depende mucho del lenguaje de programación tengo algunas dudillas sobre la mejor manera de utilizar C y si es conveniente en depende de que casos utilizarlo. Aunque en los juegos está claro que la OOP ayuda mucho, no me atrevo a meterme con C++, todo y tener un nivel más básico; conozco la STL bastante, definir clases, trabajar con objetos, iteradores y toda la pesca, me siento más cómodo en C y me gusta más. Así que acabo utilizando structs con punteros a funciones para simular objetos con métodos.
Si no lo hago así, qué maneras habría de poder tratar, por ejemplo, todos los disparos iguales, teniendo en cuenta que el movimiento de cada disparo está definido por una función? Y poner un enum que identifique el tipo de disparo para luego en la función mover_disparos() { for(...) swhitch(disparo.tipo) { case...}} no creo que vaya muy ligado con la idea de ser modular y poder definir nuevos disparos de manera fácil.
No queda muy elegante eso de hacer struct con métodos, sobretodo porque los métodos y atributos estáticos no me quedan transparentes (usando macros podría, pero no me acaba de gusta ésta solucion). Y cómo no soy un entendido en OOP (principal razón para no usar C++) no hago cosas raras en tiempo de ejecucción y tal, así que para heréncias me basta y sobra los structs. Pero quizás me vendría mejor usar C++? Me gustaría saber opiniones de alguien que esté un poco más metido en el tema y con experiencia.


Ya que he escrito bastante hago aún dos preguntillas más, en todos los juegos que he visto en el loopgame pueden llamar tanto a métodos del juego, como del menu ect dependiendo de el estado del juego, realmente no hay alguna otra manera de separar realmente menus de antes del juego, la configuración, con el juego propiamente dicho? Y para acabar, viendo códigos también ajenos, veo que usan bastantes variables globales, supongo que para el estado del juego, el screen ect. es normal, pero hasta que punto se puede llegar? Por ejemplo, en un juego de navecitas, sería bueno tener el conjunto de disparos, naves en variables globales? No acaba siendo contraproducente? Para un juego sencillo vale, pero si luego cambias algo afectará bastante.

Bueno, no molesto más, si alguien me lee ya le estaré agradecido, y si responde aún más.
kkmrmd
 
Mensajes: 1
Registrado: Mié Oct 03, 2007 4:24 pm

Notapor Juan Carlos » Mié Oct 03, 2007 11:28 pm

Puff, mucho texto.

En fin, con respecto a la programacion estructurada, la idea es dado un problema dificil de resolver (un juego), dividir el problema en varios problemas mas faciles de resolver (crear un enemigo, mover al enemigo, crear un disparo, etc). Estos problemas se pueden dividir a su vez en problemas mas chicos, una y otra vez, creando asi funciones especificas.
Lo util de este metodo es que puedes armarte pequeños programas e ir probando esta funciones. Te suguiero que antes de juntar todas las funciones y armar el juego, pruebes por separado cada funcion.

Con respecto a la POO, te sugiero que uses C++ ya que tiene una sintaxis practicamente igual a la de C.

En el tema de variables globales, solo usalas si son usadas por el 99.99% de tus funciones. La superficie principal (screen) de SDL suele ser el unico caso en que es valido usar una variable global. Para otros casos usa variables locales.

Saludos
Juan Carlos
 
Mensajes: 97
Registrado: Sab Jul 07, 2007 1:05 pm

Notapor julen26 » Jue Oct 04, 2007 9:26 am

Bueno, me e leido todo, y tardado algo en hacerlo jej.

Seré breve, yo a este mundo llegue despues de estar un tiempo metido en el GameMaker, con el cual e logrado tener experiencia en la creacion de juegos, en general.

Y por eso me gustaría recomendarte un articulo que escribió el creador de este programa, y en realidad a sido útil para todo tipo de programadores de un juego, no importa el mètodo, lenguaje o demas.

Se llama "Que es un buen juego" y comenta los aspectos de un juego, comparandolos con otros. Te ayudará y es interesante. Te lo e subido aquí, esta traducido:

http://www.savefile.com/files/1099481

Ademas de esto también me gustaria que entraras en http://www.gamedev.net/reference/ y miraras todos los articulos que hay, muchos estan en diferentes idiomas y son muy úiles, sino habrá que darle uso al ingles.

Si vas mirando por el final veras uno que es el desarrollo de juegos en general! navega un poco.

saludos
Avatar de Usuario
julen26
 
Mensajes: 10
Registrado: Dom May 13, 2007 3:04 pm

respondienote

Notapor josepil » Dom Oct 07, 2007 9:16 pm

bueno pues yo tengo poca experiencia en esto pero mira lo que tu quieres hacer se realiza facilmente en c++ y no importa se no estas familiarizado puesto que la mayoria de los compiladores soportan a c y solo tendrias que usar muy pocas cosas de c++ por ejemplo sobrecarga funciones virtuales y yap con eso se termina todo el problema con eso tu programa queda como una plastilina averigua un poco sobre esto y ya esta sino prueba con las listas y aunqeu no son tan variables te pueden servir para tu objetivo espero te haya ayudado en algo
josepil
 
Mensajes: 4
Registrado: Lun Sep 24, 2007 2:25 am

Empezando un juego

Notapor carleto » Dom Oct 07, 2007 10:36 pm

Hola

Yo también soy novato en esto de los juegos, y como tú, siempre ha sido C mi lenguaje preferido. Pero me parece que C++ es muy adecuado para hacer juegos, así que también me he puesto manos a la obra a aprender C++.

Ahora mismo tengo casi terminado un pequeño juego (de marcianitos) y lo estoy haciendo en C++, vale que me está costando bastante esfuerzo pero creo que al final merecerá la pena aprender C++.

Yo te animaría a que le eches un vistazo a C++.

En cuanto a lo de las variables globales, supongo que cada uno tiene sus costumbres, a mi no me gustan mucho y es muy raro que las use, en el juego que estoy haciendo no tengo ninguna variable global.

Saludos
Avatar de Usuario
carleto
 
Mensajes: 42
Registrado: Mar Ago 21, 2007 9:38 pm
Ubicación: Almería, España

Notapor hugoruscitti » Lun Oct 08, 2007 2:32 pm

Hola, buen día. Tu mensaje me parece muy interesante, y está superbien
que sea amplio. No soy un experto en estos asuntos de diseño, pero creo que
puedo ayudar en algunas cosas.

kkmrmd escribió:...
conocéis algún recurso (léase manual,
libro, ejemplo comentado, tutorialweb...) que te explique como modular y
dividir un programa, y si está enfocado a los videojuegos mejor. Porque vamos,
la teoría creo que la tengo asimilada, aislar tipos de datos, crear una
interficie para poder comunicarte con ellos y bla bla, pero a la hora de hacer
el esqueleto y definir las funciones, sus parámetros para luego poder ser
expandidos me acaba saliendo mal. Tengo la impresión de que si pudiera definir
bien la estructura, lo que ha de hacer cada función ect luego implementarlo
sería bastante fácil.


Sí, existe documentación donde se analizan muchas buenas soluciones de diseño
en la construcción de software. A grandes rasgos, en el diseño de programas
existen soluciones que han tenido mucho éxito y que resuelven requisitos que
se repiten constantemente. Esto a motivado a diversos analistas y
programadores a construir soluciones a estos problemas, y mejorarlas de modo
tal que se puedan utilizar una y otra vez en otros programas.

Este concepto es muy útil, y recibe el nombre de "patrones de diseño":

http://es.wikipedia.org/wiki/Patr%C3%B3n_de_dise%C3%B1o

Seguramente muchas de las cosas que te detienen en el desarrollo se pueden resolver
estudiando alguno de estos patrones. En la práctica, conociendo algo de patrones de
diseño te encuentras ante un problema y dices "ah, aquí puedo usar el patrón de
nombre X"... así, por lo menos tienes alguna estrategia para empezar... es algo.

Observando tu mensaje completo creo que puedo dar un ejemplo de patrón de diseño
mas adelante...

En lo personal, creo muchas veces la dificultad que los desarrolladores no
está en construir el programa sino en querer hacerlo lo 'mas' extensible y
configurable que se pueda. No creo que sea un buena idea, es interesante, pero
no conduce a muy buenos resultados:

http://www.javahispano.org/contenidos/e ... _patrones/

Hay una idea muy interesante en el desarrollo de programas y recive el nombre
KISS (Keep It Short and Simple - aunque tiene otras traducciones...). La idea
es mantener tu desarrollo tan simple como sea posible, después de todo: tu
juego debería hacer lo que quieres, no el doble.

kkmrmd escribió:Así que acabo utilizando structs con
punteros a funciones para simular objetos con métodos. Si no lo hago así, qué
maneras habría de poder tratar, por ejemplo, todos los disparos iguales,
teniendo en cuenta que el movimiento de cada disparo está definido por una
función? Y poner un enum que identifique el tipo de disparo para luego en la
función mover_disparos() { for(...) swhitch(disparo.tipo) { case...}} no creo
que vaya muy ligado con la idea de ser modular y poder definir nuevos disparos
de manera fácil.


Es interesante, muchos aprendimos a utilizar C antes que C++, y en algún momento
nos sentimos mas cómodos con C. El punto es que si utilizas punteros a funciones
estas mucho mas familiarizado con C, y eso te de más confianza para elegirlo en
lugar de C++. Creo que ayudaría mucho a simplificar tu programa utilizar
directamente C++.

Con respecto al ejemplo de los disparos, en la programación orientada a objetos
existe un concepto llamado "Polimorfismo" que te puede servir; la idea es simple,
consiste en definir una interfaz común entre muchos objetos, de forma que sea fácil
intercambiarlos.

Por ejemplo, en tu juego puedes decir "todos los personajes son objetos, y todos
los personajes tendrán un método llamado 'update'".

Entonces, en el bucle principal del juego no debes preocuparte por que tipo de
objeto es cada cosa, simplemente llamas al método 'update' y te despreocupas por
como debe funcionar internamente. Cada objeto sabe, internamente, cual es su
comportamiento.

Veamos un caso, ¿como funciona el asunto de los disparos?. Bien, tienes que crear
una clase para cada tipo de disparo, te propongo un ejemplo en código fuente
utilizando python, dado que me resulta mas sencillo de escribir...

Código: Seleccionar todo
class Disparo:

    def __init__(self, x, y):
        self.x, self.y = x, y          # define la posicion inicial
        self.image = load_image('disparo.png')

    def update(self):
        print "Soy un disparo y avanzo siempre hacia la derecha"
        self.x += 1


class Misil(Disparo):                  # el misil 'hereda' del disparo

    def __init__(self, x, y, objetivo):
        Disparo.__init__(self, x, y)
        self.objetivo = objetivo

    def update(self):
        print "Soy un misil y busco a mi objetivo"
        angulo = self.obtener_angulo_hacia(self.objetivo)
        self.x += cos(self.angulo) * 5
        self.y += sin(self.angulo) * 5

    def obtener_angulo_hacia(self, objetivo):
        # algún cálculo para saber el ángulo hacia un enemigo
        # ...
        pass


Entonces, tenemos dos tipos de Objetos para un videojuego de disparos: Un
'misil' que busca a su enemigo y un 'disparo' muy simple, que avanza en todo
momento en linea recta.

Luego, puedes crear objetos a partir de cada una de estas clases. Cada objeto
se comportará tal y como hemos definido en los métodos de su clase.

Código: Seleccionar todo
>> a = Disparo(20, 30)
>> a.update()
"Soy un disparo y avanzo siempre hacia la derecha"

>> b = Misil(20, 30, base_enemiga)
>> b.update()
"Soy un misil y busco a mi objetivo"


Es decir, el "Disparo" se comporta diferente al "Misil"; aunque esto no lo
hace mas complicado, desde "afuera" ambos tienen un método "update" y se
pueden tratar de la misma manera:

Código: Seleccionar todo
# creamos los disparos

ataque = [Disparo(40, 40), Misil(30, 40, base_enemigo), Disparo(20, 40)]

while True:
    for a in ataque:             # recorremos la lista actualizando todo
        a.update()

    print "--"


hacemos una lista y colocamos varios 'disparos' y un 'misil', luego podemos
despreocuparnos por que es cada cosa. El anterior programa imprime lo
siguiente en pantalla:

Código: Seleccionar todo
Soy un disparo y avanzo siempre hacia la derecha
Soy un misil y busco a mi objetivo
Soy un disparo y avanzo siempre hacia la derecha
--
Soy un disparo y avanzo siempre hacia la derecha
Soy un misil y busco a mi objetivo
Soy un disparo y avanzo siempre hacia la derecha
--
Soy un disparo y avanzo siempre hacia la derecha
...


Para resumir, si los elementos de tu juego se deben comportar diferente, debes
crear clases distintas para representarlos. Cuando invocas a un método de un
objeto será el lenguaje quien se encarga de 'encontrar' el código a ejecutar;
esto ayuda mucho...

kkmrmd escribió: No queda muy elegante eso de hacer struct con métodos,
sobretodo porque los métodos y atributos estáticos no me quedan transparentes
(usando macros podría, pero no me acaba de gusta ésta solucion)....


Es comprensible que sientas mas "comodidad" utilizando C que C++, le ocurre a
muchos programadores. El punto es que C tiene reglas de funcionamiento mas
simples que C++, quiero decir, tiene menos palabras reservadas y una sintaxis
con menos 'excepciones a la regla'.

Por lo tanto si conoces punteros, punteros a funciones y
comprendes como funcionan los tipos de datos. Es probable que puedas resolver
casi todo con C.

Personalmente considero que no existe un lenguaje mejor a otro, en todo caso
debemos observar el tipo de proyecto que tenemos en mente y elegir el
lenguaje que consideramos mas "conveniente".

Si aceptas una recomendación de mi parte, yo elegiría 'python'. Y en raras
ocasiones C++ o C (generalmente si el programa es muy intensivo y requiere
muchas velocidad).

kkmrmd escribió:Ya que he escrito bastante hago aún dos preguntillas más, en todos los juegos
que he visto en el loopgame pueden llamar tanto a métodos del juego, como del
menu ect dependiendo de el estado del juego, realmente no hay alguna otra
manera de separar realmente menus de antes del juego, la configuración, con el
juego propiamente dicho?


Sí, a veces, cuando el juego es algo complejo y se requiere algo de flexibilidad
se puede utilizar el concepto de "Escena":

Cada estado del juego queda representado por un objeto "Escena": el menú, la
pantalla de opciones, el juego. etc.

Siguiendo esta estrategia se deben construir las escenas de modo tal que
puedan se intercambiadas con facilidad. Veamos como se observa desde afuera:

Código: Seleccionar todo
escena = Menu()

while True:
    escena.update()
    escena.draw(screen)
    clock.tick(30)


la primer parte del código genera un objeto "Menu" junto a una referencia.
Unas lineas mas abajo está el bucle de juego, aquí no nos importa como
funciona el objeto apuntado por la variable "escena", solo nos interesa que
tenga los métodos "update" y "draw".

Ahora, si queremos pasar de la escena "menu" a la selección de jugadores
hacemos esto (en cualquier otra parte del programa):

Código: Seleccionar todo
escena = PlayerSelect()


el bucle principal seguirá funcionado sin problemas, aunque se comportará un
poquito diferente. Ya que 'escena.update()' ahora significa otra cosa.

Aquí tienes un dibujo de las clases hecho con el programa
"gaphor":

Imagen


Esta solución se denomina 'patrón estategía', y suelo utilizarla para
controlar los estados de los personajes en un juego y las escenas:

http://www.javahispano.org/contenidos/e ... strategia/

Generalmente existe un objeto encargado de contener el bucle principal del
juego. Es aconsejable que cada escena a su vez conozca a este objeto, así puede
ordenarle cambiar de escenas. Por ejemplo, el 'menú' puede cambiar a la escena
'jugar' y 'jugar' a la escena 'gameover' y 'gameover' a 'menú'. Después de todo
es solo una asignación (o mejor un método)...

Hacer todo esto con C++, en lugar de Python, es un poco mas
complicado: todas las escenas deben heredar de una misma
clase (digamos "escena", abstracta, y con métodos virtuales). Y
el puntero que señala a la escena actual debe ser de tipo "puntero
a escena". Luego, con este puntero puedes señalar a cualquier
objeto que hereda de escena: "Menu", "Opciones" etc.

kkmrmd escribió:Bueno, no molesto más, si alguien me lee ya le estaré agradecido, y si responde aún más.


No es molestia, por favor, he disfrutado mucho leyendo tu mensaje y tratando de
encontrar la manera de explicar mi punto de vista. Aunque no se si lo he
logrado...

Mucha suerte.

PD 1: ¡ Los mensajes extensos son mis favoritos !
PD 2: ¿tienes algunos mini-juegos realizados?, casualmente losersjuegos necesita mas
programillas para la sección 'ejemplos' :)
Avatar de Usuario
hugoruscitti
Site Admin
 
Mensajes: 1242
Registrado: Dom Jul 30, 2006 3:57 am
Ubicación: Buenos Aires, Argentina


Volver a General

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 7 invitados

cron