AUXILIO! :(, como muevo un sprite!

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

AUXILIO! :(, como muevo un sprite!

Notapor shackra » Vie Ene 08, 2010 10:51 pm

hola otra vez! :D.
esta vez mi problema es con los sprites!, estube probando como podia mover un sencillo sprite por la pantalla en cuatro direcciones.
ese era elprimer paso, luego era cambiar las imagenes del sprite para realizar un efecto de animacion mientras el sprite se mueve por la pantalla... pero en vistas de que siquiera se movia decidi dejar la animacion de lado para intentar moverlo.

me fije en varios ejemplos que vienen en el pygame, pero son bastantes extensos y no me es sencillo seguirlos para aprender a mover un sprite con entrada por teclado... aqui el codigo:

fichero completo descargable desde 4share.com, modulo Sprites.tar.bz2

main_2.py:
Código: Seleccionar todo
import sys
import pygame
from pygame.locals import *

class Test(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        #ojo aqui!, cambien la ubicacion para ver una imagen!
        self.image = pygame.image.load("/home/jorge/Dreams To Games/DEMOS/pruebas con pygame/modulo Sprites/datos/graph/b0.png")
        self.screen = pygame.display.get_surface()
        self.area = self.screen.get_rect()
        self.rect = self.image.get_rect()

    def update(self, posx, posy):
        nueva_pos = self.rect.move(posx,posy)
        print nueva_pos
        if self.area.contains(nueva_pos):
            self.rect.move_ip(posx, posy)
            if self.rect.left > self.area.left:
                self.rect.left = self.area.left
            if self.rect.right > self.area.right:
                self.rect.right = self.area.right

def main():
    pygame.init()
    pantalla = pygame.display.set_mode((800, 600))
    pygame.display.set_caption("Prueba con Sprites")
    pygame.mouse.set_visible(0)

    bicho_posx = 0
    bicho_posy = 0

    blanco = (255, 255, 255, 255)
    pantalla.fill(blanco)
    pygame.display.flip()

    bicho = Test()
    todos = pygame.sprite.RenderPlain(bicho)
    clock = pygame.time.Clock()

    while 1:
        clock.tick(60)
        key = pygame.key.get_pressed()

        for evento in pygame.event.get():
            if evento.type == QUIT:
                sys.exit(0)
            if evento.type == KEYDOWN and evento.key == K_ESCAPE:
                sys.exit(0)
            if evento.type == KEYDOWN:
                if key[K_UP]:
                    bicho_posx += 10
                if key[K_DOWN]:
                    bicho_posx -= 10
                if key[K_LEFT]:
                    bicho_posy -= 10
                if key[K_RIGHT]:
                    bicho_posy += 10

        todos.update(bicho_posx, bicho_posy)
        pantalla.fill(blanco)
        todos.draw(pantalla)
        pygame.display.flip()
        pygame.time.wait(10)
       
if __name__ == "__main__":
    main()
Avatar de Usuario
shackra
 
Mensajes: 308
Registrado: Lun Jun 15, 2009 4:10 pm
Ubicación: Costa Rica

Notapor Juanxo » Sab Ene 09, 2010 1:26 am

Buenas shackra:

te comento varias cosas que veo a primera vista:
1. En el tema de los sprites, se puede decir que hay tres funciones basicas: el init, el update y el draw(esta ultima te falta)

2.En mi opinion, creo que es innecesario almacenar una "pantalla" para cada clase, ya que fijate que en todos.draw(pantalla), que es el método que te faltaria implementar ya estas pasando la pantalla como parametro

3.Fijate en el update(). self.rect.move no te lo mueve a una posicion global, sino que te lo mueve la cantidad de pixeles que le digas a partir de donde este en ese momento.
Veamos el problema: tu inicializas posx y posy a 0 los dos. Luego, en funcion de las teclas, sumas o restas. Vale, ahora piensa que pasaría si pulsases muchas veces la tecla "derecha". Al principio no se movería. Luego, la primera vez que pulsases, se pondría posx a +10, por lo que "cada frame" se movería 10 pixels a la derecha. La segunda vez que pulsases, sumarías 10 a posx, que pasaría a ser 20. No se si ves a donde lleva esto.
Pista(tras muchas pulsaciones, el movimiento por frame sería de varias centenas de pixels xD).

Siguiendo con update, el tema de calcular la nueva pos y luego ver si esta contenida no esta mal, pero un apunte: para que compruebas si va a estar contenida en la pantalla, si luego haces lo del if self.rect.left > .... que es basicamente lo mismo. Ademas las comprobaciones estan mal hechas. Fijate: si el lado izquierdo del rectangulo esta a la derecha del limite de la pantalla (vamos, que esta en la pantalla) lo tratas como malo y lo pones a la izquierda de la pantalla. El de la derecha esta bien.
Conclusion: quita lo de contains y nueva pos y deja el resto, pero corrijiendo la comparacion y añadiendo los choques con los bordes verticales

Ahora vamos con el draw:
la funcion sería def draw(self, pantalla):
y aqui dentro lo unico que tendrías que hacer sería el pantalla.blit(self.imagen........)

Por ultimo, un consejo sobre el tratamiento del teclado(bueno un par):
Hay teclas que se anulan: si tu tienes pulsada la tecla derecha, no tiene sentido que tambien entre en el if de la tecla izquierda (lo mismo con arriba/abajo) por lo tanto un if teclaDerecha: ..... else if teclaIzqu quedaría mejor.

Luego, en este mismo sitio vuelves a mezclar métodos: para la entrada de teclado se suelen utilizar dos métodos: o bien por eventos, o bien accediendo directamente al estado del teclado. Usas los dos.
Algo mejor sería:

Código: Seleccionar todo
for evento in pygame.event.get():
       
            if evento.type == KEYDOWN:
                if evento.key == K_RIGHT:
                    bicho_posx = 10
                elif evento.key == K_LEFT:
                    bicho_posx = -10
                if evento.key == K_UP:
                    bicho_posy = -10
                elif evento.key == K_DOWN:
                    bicho_posy = 10


Así creo yo que es más correcto. Además, te faltaría tratar si el evento es de KEYUP(soltar la tecla) para volver a establecer las velocidades a 0.

Y creo que más o menos eso es todo. He preferido postearte consejos a directamente el codigo porque creo que asi se te quedara mejor. Si hay cualquier duda, dimelo
Avatar de Usuario
Juanxo
 
Mensajes: 437
Registrado: Sab Ene 31, 2009 2:34 am
Ubicación: Madrid(España)

Notapor shackra » Sab Ene 09, 2010 9:44 pm

para serte sincero... no comprendo con exactitud los errores, no me hables español!, mejor python :D. se que hay que quitar algunas cosas y arreglar otras, pero te agradeceria si podrias poner pedazos de codigo en aquellas areas que son necesarias (como un antes y un despues).

y si... lo de las centenas de pixeles ya lo venia sospechando! xD
Avatar de Usuario
shackra
 
Mensajes: 308
Registrado: Lun Jun 15, 2009 4:10 pm
Ubicación: Costa Rica

Notapor Juanxo » Sab Ene 09, 2010 11:01 pm

[EDITADO***: habia un fallo en el update, en las colisiones con las bandas]

buenas shackra:

aqui va la solucion

Código: Seleccionar todo

# -*- coding: utf-8 -*-
import sys
import pygame
from pygame.locals import *

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600

class Test(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("test.bmp")
        self.rect = self.image.get_rect()

    def update(self, velx, vely):
        self.rect.move_ip(velx, vely)

        if self.rect.left <0> SCREEN_WIDTH:
            self.rect.right = SCREEN_WIDTH
        if self.rect.top <0> SCREEN_HEIGHT:
            self.rect.bottom = SCREEN_HEIGHT

    def draw(pantalla):
        pantalla.blit(self.image, self.rect)

def main():
    pygame.init()
    pantalla = pygame.display.set_mode((800, 600))
    pygame.display.set_caption("Prueba con Sprites")
    pygame.mouse.set_visible(0)

    blanco = (255, 255, 255, 255)


    #no hace falta que crees un objeto y luego lo añadas
    #puedes crearlo dentro del grupo directamente
    todos = pygame.sprite.RenderPlain(Test())
    clock = pygame.time.Clock()

    while 1:
        clock.tick(60)
       
        #he cambiado los ifs por if..elif. Para que te preguntarás:
        #El tema es que un evento solo puede pertenecer a un tipo a la vez,
        #cosa lógica. Por lo tanto, una vez que encuentra al tipo al que pertenece,
        #debería saltarse los demás, que es lo que conseguimos con el elif.
        #En este caso no ganamos mucho, pero siempre hay que pensar a lo grande
        for evento in pygame.event.get():
            if evento.type == QUIT:
                sys.exit(0)
            elif evento.type == KEYDOWN:
                if evento.key == K_ESCAPE:
                    sys.exit(0)

        key = pygame.key.get_pressed()
        velx = 0
        vely = 0
       
        if key[K_RIGHT]:
            velx = 10
        elif key[K_LEFT]:
            velx = -10
        if key[K_DOWN]:
            vely = 10
        elif key[K_UP]:
            vely = -10

        todos.update(velx, vely)
        pantalla.fill(blanco)
        todos.draw(pantalla)
        pygame.display.flip()
       
if __name__ == "__main__":
    main()

[/b]
Última edición por Juanxo el Dom Ene 17, 2010 2:32 am, editado 1 vez en total
Avatar de Usuario
Juanxo
 
Mensajes: 437
Registrado: Sab Ene 31, 2009 2:34 am
Ubicación: Madrid(España)

Notapor shackra » Sab Ene 16, 2010 7:11 pm

gracias por la guia!, lo estudiare con mas detenimiento en mi casa, lo pruebo y luego vengo con mas dudas!
Avatar de Usuario
shackra
 
Mensajes: 308
Registrado: Lun Jun 15, 2009 4:10 pm
Ubicación: Costa Rica


Volver a General

¿Quién está conectado?

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

cron