Ayudaa

Losersjuegos cuenta con una secciones de ejemplos en su web. Utilice esta sección para consultar o proponer ideas acerca de ellos.

Ayudaa

Notapor Jonito11 » Dom May 27, 2012 3:53 am

Buengo gente, soy nuevo en el mundo de los videojuegos y queria comentarles mi situacion. Necesito hacer como TP final para una materia de la universidad un modelo de videojuego el cual pienso reutilizar para otra materia en la cual tengo que presentar un proyecto orientado a objetos. Mi idea es hacer el Battlecity, en su momento lo estuve desarrollando en qbasic pero con el paradigma estructurado. Como soy nuevo en objetos, mucha idea no me hago y queria pedirles si podian darme algun ejemplo. Lo estoy desarrollando en python y ya tengo el codigo de como mover mi tanque, pero no se de que manera definir las clases, como manejarme de esta manera. Desde ya muchas gracias.
Jonito11
 
Mensajes: 14
Registrado: Dom May 27, 2012 3:42 am

Re: Ayudaa

Notapor MrBB4 » Mar May 29, 2012 5:19 pm

Buenas.
Quería avisarte que estoy ecribiendo la respuesta a tu pregunta aunque me tomará algo de tiempo y en este momento no tengo mucho xD Me imagino que estarás usando la librería grafica Pygame. En caso contrario avísame. Posiblemente te tenga la respuesta para esta noche.

Saludos.
Avatar de Usuario
MrBB4
 
Mensajes: 49
Registrado: Mar Dic 14, 2010 11:39 pm
Ubicación: Purto Madryn, Chubut, Argentina.

Re: Ayudaa

Notapor kiketom » Mar May 29, 2012 8:16 pm

Algunas ideas de aquí te pueden servir
http://aventurapygame.blogspot.com.es/?m=1
Avatar de Usuario
kiketom
 
Mensajes: 82
Registrado: Lun Ene 03, 2011 3:01 pm
Ubicación: Valencia, España

Re: Ayudaa

Notapor MrBB4 » Mié May 30, 2012 2:14 am

Buenas.
En general te vas a encontrar con que la mayoria de las clases tienen una función Update(), con la que el objeto observa su "entorno", interactúa con otros objetos y recalcula su posición, imagen, etc; y una función Draw() con la que se dibuja el objeto en pantalla. Con esto, lo unico que el loop principal del juego tendrá que hacer es crear los objetos iniciales y luego simplemente llamarlos uno por uno con la función Update() y luego denuevo, uno por uno con la función Draw().
Algo así:
# -*- coding: utf-8 -*-
import sys
import pygame #Módulo gráfico


def terminate():
pygame.quit() #Cierra el módulo gráfico
sys.exit() #Cierra el intérprete de python

def check_input():
#analiza la input por teclaro del usuario
for event in pygame.event.get():
if event.type == QUIT:
terminate()


class Personaje(object):
"""Clase para los personajes del juego"""

def __init__(self):
#define la superficie, rectangulo y otras variables importante del personaje
pass

def update(self):
#Observa el entorno, interactua con otros personajes y recalcula posición e imagen
pass

def draw(self, ventana):
#Dibuja al personaje sobre la superficie "ventana"
pass


def main():
VENTANA = pygame.display.set_mode((320, 240))

p1 = Personaje()
p2 = Personaje()
p3 = Personaje()

while True:
check_input()

p1.update()
p2.update()
p3.update()

p1.draw(VENTANA)
p2.draw(VENTANA)
p3.draw(VENTANA)

VENTANA.blit()

if __name__ == '__main__':
main()


Las funciones check_input() y terminate() son funciones que yo suelo crear para simplificar todo, no es necesario que tú tambien las hagas. Basicamente check_input() se fija si el usuario quiere salir del programa, en cuyo caso llama a terminate() que se encarga de cerrarlo. Lo Importante en este ejemplo es la función main. Primero prepara el juego, en nuestro caso créa la variable VENTANA y los personajes p1, p2 y p3; y luego pasa al loop principal del juego con la linea while True: (que a mi parecer es la forma más corta y legible de crear un loop infinito) en donde lo único que hace es llamar a todos los personajes con update() y luego con draw(); e imprime los cambios en pantalla con VENTANA.blit(). Bastante simple, no? =)

En caso de que el juego tenga un número exagerado de objetos a actualizar e imprimir, como suele suceder, basta con meter a todos en una lista (o varias por claridad) y luego llamar a la lista con un for in loop y llamar las funciones Update() y Draw()
#...Codigo anterior

def main():
VENTANA = pygame.display.set_mode((320, 240))

p1 = Personaje()
p2 = Personaje()
p3 = Personaje()
p4 = Personaje()
p5 = Personaje()
#... Y así hasta p50
p50 = Personaje()

personajes = [p1, p2, p3, p4, p5, p50] #Solo puse estos seis para que el codigo funcione rirectamente sin modificar

for p in personajes:
p.update()

for p in personajes:
p.draw()

VENTANA.blit()

if __name__ == '__main__':
main()

Te aconsejo de primero actualizar TODOS los objetos antes de imprimir alguno, solo para evitar problemas con que aparescan imagenes que no correspondan, porque aveces el update() de un personajé podría afectar la imagen que corresponda a uno anterior que ya se imprimió. (espero que eso se entienda :mrgreen:)
Tambien sería bueno que definieras algunas funciones, digamos, "estandar" que aparescan en todos los personajes, como puede ser atacar(), defender(), caminar() y cosas por el estilo, ya que esto facilita la comunicación entre personajes. Esto se puede realiza facilmente utilizando la herencia. Lo cual me imagino que ya conoces porque estás estudiando informática. Sino te lo explico, no hay problema.

Obviamente todo lo que te he contado hasta ahora es más que nada para los objetos imprimibles de los juegos, pero la verdad, la mayoria de los objetos en un juego son imprimibles. Y aunque no lo fueran, ponerles una función draw() que no hiciera nada no hace mal a nadie y te simplifica el codigo ya que no tienes que agregar codigo extra en el loop principal, solo para esos pocos objetos no imprimibles.

Y otro detalle. Te recomiendo leer el PEP8 de python que define la manera "correcta" de escribir en python. En realidad no existe una manera correcta pero se marcó como la oficial para mayor legibilidad.

Espero te haya ayudado :)
Un saludo :wink:
Avatar de Usuario
MrBB4
 
Mensajes: 49
Registrado: Mar Dic 14, 2010 11:39 pm
Ubicación: Purto Madryn, Chubut, Argentina.

Re: Ayudaa

Notapor Jonito11 » Dom Jun 03, 2012 11:39 pm

Muchas gracias por la ayuda, lo voy a tener en cuenta. Estuve leyendo el blog de aventuras y segui el ejemplo. El problema que tengo en ese caso es que el movimiento del tanque es cada un tile (por como esta definido en el blog), entoces por cada vez que presiono alguna tecla de movimiento, el tanque se mueve 32px en pantalla lo que hace que sea muy cortado en vez de tener una suavidad moviendolo cada 4px. Si o si el movimiento tiene que ser cada un tile? De ser asi, como le puedo dar suavidad al movimiento para que no sea tan brusco. Mover cada un Tile para mi es mas facil para detectar las colisiones. Voy a probar otras alternativas y voy a tener en cuenta lo que me dijiste MrBB. Gracias
Jonito11
 
Mensajes: 14
Registrado: Dom May 27, 2012 3:42 am

Re: Ayudaa

Notapor Jonito11 » Mar Jun 05, 2012 2:45 am

Pude solucionar lo de las colisiones y el movimiento fluido. Respecto a lo que me dice MrBB4. Recien me inicion en objetos y estuve leyendo algo de conceptos y trato de asimilarlos. Cuando tu me hablas de Herencia, un ejemplo puede ser que tenga una clase Tanque y dentro de ella el tanque manejado por cpu y el otro por el jugador que ambos heredan atributos como posicion, pero que difieren en su imagen de carga y metodos de movimiento? Me conviene separar el juego por estados?
Jonito11
 
Mensajes: 14
Registrado: Dom May 27, 2012 3:42 am

Re: Ayudaa

Notapor MrBB4 » Mar Jun 05, 2012 3:41 am

Hola. Me estoy acostando para dormir en este momento, así que te dejo una respuesta corta.
La herencia se refiere a que las clases heredan las funciones de una (o unas) clase madre. Lo que tu decias sobre las distintas clases teniendo funciones con el mismo nombre pero distinto efecto es lo que se llama Polimorfismo. Te dejo este link con todo lo que tienes que saber sobre Programación Orientada a Objetos (POO, u OOP en ingles), herecia y polimorfismo.

Me conviene separar el juego por estados?

Si con esto te refieres a separar los personjes del juego por estados, pues si, es una buena idea. Yo no lo haría de otro modo, ni sabría de que otro modo hacerlo :mrgreen: Si en cambio te refieres a separar las diversas partes del juego (menú, juego singleplayer, juego multiplayer), pues yo lo hago, pero eso es otro tema. Mejor preocupate antes en lograr hacer un juego simple para empezar a entender por donde va la cosa y luego expande tu conocimiento. Siempre mejor empezar de a poco.

Cualquier duda pregunta :D
Suerte en todo :wink:
Avatar de Usuario
MrBB4
 
Mensajes: 49
Registrado: Mar Dic 14, 2010 11:39 pm
Ubicación: Purto Madryn, Chubut, Argentina.

Re: Ayudaa

Notapor Jonito11 » Mar Jun 05, 2012 4:21 am

Gracias por la Data. Crei haber solucionado lo de las colisiones pero no fue asi. La mejor forma de detectar las colisiones, es que el movimiento del tanque sea cada 32px , largo y ancho del tile. Como dije antes, al dibujar cada 32px el movimiento parece muy brusco y rapido. Hay alguna forma de animar ese movimiento para que no sea bursco al apretar una tecla? O tengo que crear un mapa con tiles mas pequeños para que el movimiento en pixeles del tanque corresponda al ancho o largo del tile?
Jonito11
 
Mensajes: 14
Registrado: Dom May 27, 2012 3:42 am

Re: Ayudaa

Notapor MrBB4 » Mar Jun 05, 2012 5:59 pm

Jonito11 escribió:La mejor forma de detectar las colisiones, es que el movimiento del tanque sea cada 32px , largo y ancho del tile.

Pues en realidad no. Como estás trabajando con un mapa de tile, y por lo tanto con un mapa de cohordenadas (x,y), puedes crear una función que verifique si el personaje puede o no pisar sobre determinado tile. En la sección de ejemplos de LosersJuegos (http://www.losersjuegos.com.ar/referencia/ejemplos) encontraras un ejemplo llamado Mini_RPG creado por Hugo Ruscitti en el cual se puede apreciar dicha función. La encontrarás como puede_pisar_en(), dentro de la clase Escenario(). La pego aquí, pero te recomiendo leer el codigo completo porque te encontrarás con cosas muy interesantes.
class Escenario:
#... codigo
def puede_pisar_en(self, x, y):
"Informa si se puede pisar sobre un bloque del escenario."

fila = (y) / 32
columna = x / 32

try:
celda = int(self.grilla[fila][columna])
except:
# si no puede obtener la celda prohibe pisar ahí
return False

if celda in [0, 1, 2]:
return True

return False

La clase Personaje() se cirve de esta funcion de Escenario() de esta madera:
import pygame
from pygame.locals import K_LEFT, K_RIGHT, K_UP, K_DOWN, QUIT, KEYDOWN

class Personaje:
#... codigo
def update(self):
"Realiza movimientos de la cámara en base a la pulsación de teclas."
teclas_pulsadas = pygame.key.get_pressed()
dx = 0
dy = 0

if teclas_pulsadas[K_UP]:
dy -= 2
elif teclas_pulsadas[K_DOWN]:
dy = 2

if teclas_pulsadas[K_LEFT]:
dx = -2
elif teclas_pulsadas[K_RIGHT]:
dx = 2

if not self.escenario.puede_pisar_en(self.rect.x + dx, self.rect.y):
dx = 0

if not self.escenario.puede_pisar_en(self.rect.x, self.rect.y + dy):
dy = 0

self.rect.move_ip(dx, dy)

Es bastante simple, no creo que haga falta explicar el código. Aunque si tienes alguna duda pregunta tranquilo :wink:
Solo un detalle a tener en mente. En Escenario() veras que aparece self.grilla, esto no es más que el mapa de coordenadas. Cuando leas Mini_RPG lo vas a entender.

Para administrar las coliciones con otros personasjes u objetos del escenario basta con que una ves que hayas llamado a puede_pisar_en() y que hayas movido el personaje con rect.move_ip(), debes verificar que su rect no se encuentre en contacto con el de otro personaje/objeto usando la función rect.colliderect(rect2). En caso de que haya contacto simplemente cancela el move_ip() anterior. Para hacer esto lo mejor es poner a todos los personajes en un lista y se llama a cada elemento de la lista con colliderect(). Así de fácil.

class Personaje:
#... codigo
def update(self, lista):
#... codigo

self.rect.move_ip(dx, dy)
for personaje in lista:
if self.rect.colliderect(personaje):
self.rect.move_ip(-dx, -dy)
break


La tecnica de solo moverse por tiles se utiliza solo en juegos rpg al estilo pokemon, pero como tu juego tiene un tanque sunpongo que no se trata de ese tipo de juegos :mrgreen:

Espero se entienda.
Saludos.
Avatar de Usuario
MrBB4
 
Mensajes: 49
Registrado: Mar Dic 14, 2010 11:39 pm
Ubicación: Purto Madryn, Chubut, Argentina.

Re: Ayudaa

Notapor Jonito11 » Mar Jun 05, 2012 6:48 pm

Gracias por el ejemplo. Es muy similar a la forma en que yo lo estaba haciendo en quickbasic (donde no tuve problema con las colisiones xD. Voy a leerlo tranquilo. Gracias por tu disposicion.


Edit:

Baje el mini rpg, y entendi bastante, lo que no me cierra mucho es lo del personaje, porque inicia con el rect.move_ip(120,70). En mi caso, en vez de iniciar con el rect.move, uso los rect.center para que me lo dibuje centrado en la celda inicial. Lo de la matriz, si o si tiene que ser como el ejemplo del txt? Probe por las dudas, usar la matriz de tiles que es de ((0..19),(0..11)), la capa de paredes. Si esa celda es 0, puede pisar sino no,pero el camino que es de una celda, con esa funcion pasan a ser de dos celdas, por lo tanto choca con paredes aveces, y otras no. No se si tengo que adaptar la funcion, o dejar de usar la matriz de tiles. Hacer un mapa txt, era lo ultimo que buscaba, pero si esa es la mejor solucion, lo hare.
Por ultimo, lei en la documentacion de pygame lo de los rect pero no entiendo muy bien lo de move_ip, podrias darme un ejemplo?
Jonito11
 
Mensajes: 14
Registrado: Dom May 27, 2012 3:42 am

Re: Ayudaa

Notapor Jonito11 » Mié Jun 06, 2012 2:54 am

Hice una segunda prueba, esta vez con el mapa creada a traves de un txt, y lo probe con el codigo de mini RPG. Por lo que vi, los movimientos del personaje, en realidad son los de la camara pero como en mi juego la camara es fija, que debo hacer? sinceramente no entiendo nada.
Jonito11
 
Mensajes: 14
Registrado: Dom May 27, 2012 3:42 am

Re: Ayudaa

Notapor Jonito11 » Mié Jun 06, 2012 11:59 pm

Sigo agregando informacion por las dudas, segui revisando el codigo del mini rpg y al tener un vista pseudo 3d (no se como llamarla), las colisiones disimulan, pero el personaje se llega a poscionarse partes de las celdas en las cual no puede pisar. En mi caso, como el juego se ve desde arriba se nota mas. Lo que hice fue agregarle unos offsets para corregir esos detalles. Quedan algunos pequeños, como que al posicionarse en una celda, pero queda parte del tanque en otra (una pequeña diferencia de 5px) traspasa un poco las paredes. Ejemplo. Mi tanque esta en la (6,11) mira para la (5,11) y colisiona porque hay pared. Me voy moviendo para la (6,10) y sin terminar de colocarme totalmente en el centro de la celda, el valor ya cambia a (6,10). Si quiero doblar a la izquierda, mira a la (5,10), no hay pared entonces va por ahi, pero como parte del sprite del tanque seguia en la celda anterior (6,11), trapasa un poco las paredes. Ese tipo de detalles el profesor no los va a tener en cuenta, mientras el modelo del juego funcione, pero como soy detallista voy a tratar de corregirlo. Cuando tenga un poco mas de tiempo les paso el codigo, ya que estoy comentando desde el celular y no estoy en casa.
Por ultimo, me convendria usar el rect.top y bottom en casos como doblar izquierda derecha, y rect.left y right en caso de arriba abajo para poder detectar mejor esas colisiones? Gracias de antemano.
Jonito11
 
Mensajes: 14
Registrado: Dom May 27, 2012 3:42 am

Re: Ayudaa

Notapor kiketom » Jue Jun 07, 2012 6:26 am

Si no quieres tener el efecto raro que comentas, no deberias dejar mover el tanque hasta que no llegara ha la posición central del tile hacia el que se está desplazando.
Digamos que tu pulsas hacia la derecha y el tanque cambia su estado a "Moviendo" y va incrementando su x hasta llegar al centro del tile de la derecha.
Una vez llegado al punto, cambia su estado a "Parado" y ya permite que le dés nuevas instrucciones.
Ahora si lo que quieres es un movimiento libre dentro de un tiledmap, eso es otra cosa.
Avatar de Usuario
kiketom
 
Mensajes: 82
Registrado: Lun Ene 03, 2011 3:01 pm
Ubicación: Valencia, España

Re: Ayudaa

Notapor Jonito11 » Jue Jun 07, 2012 4:18 pm

Claro, mi idea era un movimiento libre dentro de un tiledmap. Voy a implementar lo que me dijiste kike, y tambien, como ultima instancia, probar una alternativa de rieles que use en qbasic. Gracias por los consejos muchachos, voy a ver que encuentro sobre movimiento libre y si me conviene para mi tipo de juego. Cuando tenga mas noticias sobre el juego las publico, y en cuanto tenga el modelo listo lo subo para compartir.
Jonito11
 
Mensajes: 14
Registrado: Dom May 27, 2012 3:42 am

Re: Ayudaa

Notapor Jonito11 » Vie Jun 08, 2012 4:00 am

Bueno chicos, les escribo mas que nada para agredecer su dispocion y decirles que de traspasar las paredes por casi 10-15px perceptibles, ahora son entre 2-5px bastante disimulables. En el ejemplo del Mini RPG se encarga de revisar un punto especifico, lo cual me sirivio bastante de ayuda junto a sus opiniones y consejos. Lo que le agregue es que verifique otros 5 punto mas. Esos pocos px que disimulan, los voy a terminar reduciendo un poco el dibuje del tanque en si pero mateniendo las proporciones de su transpariencia.
Por ultimo les pido un consejo, desde el punto de vista artistico o diseño grafico mejor dicho, el tanque no debe tener el mismo ancho y largo que los tiles? O depende de gustos?
Jonito11
 
Mensajes: 14
Registrado: Dom May 27, 2012 3:42 am

Re: Ayudaa

Notapor Jonito11 » Vie May 17, 2013 12:44 am

Bueno gente, se que este no es el lugar indicado pero queria que sepan que no me olvido de ustedes ni del foro, y el proyecto de Battle City sigue en pie junto a la idea de que una vez terminado quede para el foro. En todo este tiempo no di noticias porque la facultad me consume y como es un Final para una materia que todavia no molesta no le habia dedicado tiempo. Hace un mes lo retome, dedicandole una hora o dos por semana y la verdad que avance bastante. Quiero agradecerles por su ayuda, disposicion, ideas y ejemplos que me dieron.
Aca les dejo un video sobre como gestiona las escenas, usando el metodo que Kiketom explica en su blog.

No se asusten por el codigo :mrgreen: , ya estoy corrigiendo y modularizando mejor las cosas. Si bien recomiendan tener todo en ingles, hice todo en español y comentado cada cosa para que sea mas entendible para gente recien iniciada como yo. Se que no giran los tanques :mrgreen: pero es porque me dedique en los detalles mas grandes que en los pequeños o faciles de implementar.
El video ya es algo viejito, segui avanzando de a poco, los tanques disparan, se rompen las paredes, por ahora tengo dos tipos de inteligencia artificial implementada: Algoritmo Estrella, y una pseudo aleatoria que hice en la que el tanque se mueve aleatoriamente y en cada cruce analice mi posicion para saber a donde moverse; la idea es hacer otro tipos de inteligencias para dotar de mayor variedad.
Ahora le estoy dedicando mas tiempo a lo que es gestion de escenas y de menu, y segun la resolucion del juego o la posicion del mapa en pantalla, me adapte los tiles, los escale y los ubique donde corresponde. Quizas el estilo engine rpg no es lo mas conveniente para este tipo de juegos, pero si el mas convienente para el algoritmo estrella que utilizo. Voy a seguir adaptando mejor las cosas para que las colisiones no dependan tanto de la matriz del mapa sino de un grupo de sprites en si.
En cuantos a los tiles sprites, decidi una vez terminado el juego empezar con el dibujado a mano y digitalizacion para que tenga un estilo "papel" como el Paper Mario. Estuve probando bocetos y tengo algunos inconvenientes con la pixelizacion y detalles pero vamos por buen camino.
Esto es todo por ahora, una vez que tenga mas practica con el manejo del lenguaje y del paradigma de objetos, la idea es añadirle un creador de mapas. Es dificil, pero me gustan los retos :mrgreen:

PD: Por si no se ve el video, aca les dejo el link http://www.youtube.com/watch?v=aIDJnIzsZFY No se como acer que se vea con las etiquetas de youtube :?:

Saludos Gente! Gracias Nuevamente
Jonito11
 
Mensajes: 14
Registrado: Dom May 27, 2012 3:42 am


Volver a Ejemplos

¿Quién está conectado?

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