Calificación:
  • 0 voto(s) - 0 Media
  • 1
  • 2
  • 3
  • 4
  • 5
Problema con movimiento en pygame
#1
Question 
Hola, tengo el siguiente problema, yo estoy tratando de simular, con un codigo sencillo usando pygame, el movimiento de una pelota

Quiero que una pelota se mueva a mi gusto, pero que si la dejo se quede parada (hay amortiguamientos de la velocidad).

El hecho es que al dejarla reposar (luego de sacarle el reposo inicial) termina iniciando un movimiento lento hacia la ultima pared que haya tocado... Alguien podria ayudarme a identificar porque pasa esto ultimo?


Código:
import numpy as np
import pygame,sys
from pygame.locals import *


def data():
    #print(x)
    #print(vx)
    #print(deltax)
    #print(y)
    #print(vy)
    #print(ay)
    #print(deltay)
    print(pygame.key.get_pressed())



alto = 500
ancho = 1000
A=200
h0=0
h0x=0
phi=0
X0=ancho/2
Y0=alto-30
vx=0
vy=0
ay=20
h=0
l=0
x=X0
y=Y0
taupiso=0.75
tau=0.9995
piso=alto-30
usoKEYUP=False
usoKEYDOWN=False
usoKEYRIGHT=False
usoKEYLEFT=False
ck1=0
ck2=0
ck3=0
ck4=0
d=(((piso-y)**2)**(1/2))
intervalo=200




pygame.init()
screen = pygame.display.set_caption("spaceinvader")
ventana = pygame.display.set_mode((ancho, alto))
imagen = pygame.image.load("spaceinvader.png")
rectanguloimg = imagen.get_rect()
deltax=(((x-rectanguloimg.top)**2)**(1/2))
deltay=(((y-rectanguloimg.top)**2)**(1/2))

jugando = True
while jugando:
    
    h=h+1
    if (((vx)**2)**(1/2))<0.01:
        vx=0
    else:    
        vx=vx*tau

    if 0>x:
        vx=(-1)*vx
        h0x=h-1
        X0=x
        print("pared1")
    if x>ancho-30:
        vx=(-1)*vx
        h0x=h-1
        X0=x
        print("pared2")      

    if y>piso:
        Y0=piso
        #if (((vy)**2)**(1/2))<0.25:
        #    vy=0
        #else:
        vy=(-1)*(vy*taupiso)
        h0=h-1

        print("piso")          
    
    #teclado()

    if vy==0:
        if d==0:
            Y0=piso
            h0=h-1
    y=int(ay*(((h-h0)/100)**2)+vy*((h-h0)/100)+Y0)
    x=int(vx*((h-h0x)/100)+X0)

    rectanguloimg.left = x
    rectanguloimg.top = y
    ventana.fill((0,0,0))
    ventana.blit(imagen, rectanguloimg)
    pygame.display.flip()
    #data()
    pygame.time.wait(1)
    


    if ck1>0:
        ck1=ck1-1
    else:
        ck1=0
        usoKEYUP=False
    if ck2>0:
        ck2=ck2-1
    else:
        ck2=0
        usoKEYRIGHT=False
    if ck3>0:
        ck3=ck3-1
    else:
        ck3=0
        usoKEYLEFT=False
    if ck4>0:
        ck4=ck4-1
    else:
        ck4=0
        usoKEYDOWN=False

    for event in pygame.event.get():
        print(event)
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
        elif event.type == pygame.KEYDOWN:
            
            if event.key==K_UP:
                if usoKEYUP==True:
                    print("Debes esperar para empujarte denuevo")
                else:    
                    vy=vy-100
                    usoKEYUP=True
                    ck1=intervalo
                    h0=h-1
                    Y0=y
            elif event.key==K_RIGHT:
                if usoKEYRIGHT==True:
                    print("Debes esperar para empujarte denuevo")
                else:    
                    vx=vx+100
                    usoKEYRIGHT=True
                    ck2=intervalo
                    h0x=h-1
                    X0=x

            elif event.key == K_LEFT:
                if usoKEYLEFT==True:
                    print("Debes esperar para empujarte denuevo")
                else:    
                    vx=vx-100
                    usoKEYLEFT=True
                    ck3=intervalo
                    h0x=h-1
                    X0=x

            elif event.key == K_DOWN:
                if y>460:
                    print("no space down")
                else:
                    vy=vy+100
                    usoKEYDOWN=True
                    ck4=intervalo
                    h0=h-1
                    Y0=y

   
pygame.quit()


(edite un poco por el aspecto actual del problema)

Gracias.
Saludos!
Responder
#2
Hola, bienvenido.

¿Podés volver a pegar el código procurando que no se pierda la sangría? Porque si no es imposible probarlo. Acá explico cómo hacer que se muestre con resaltado de sintaxis: https://foro.recursospython.com/showthre...76#pid1476.

También te pido que subas los sprites necesarios para ejecutar el código.

Saludos
Responder
#3
(24-06-2020, 09:54 PM)Francisco escribió: Hola, bienvenido.

¿Podés volver a pegar el código procurando que no se pierda la sangría? Porque si no es imposible probarlo. Acá explico cómo  hacer que se muestre con resaltado de sintaxis: https://foro.recursospython.com/showthread.php?tid=18&pid=1476#pid1476.

También te pido que subas los sprites necesarios para ejecutar el código.

Saludos

Gracias por avisarme, ahi lo cambie, y actualize un poco el problema como perdur ahora.
Responder
#4
Bueno, habría que entender bien la lógica del programa, pero en principio, la posición en X del sprite está definida como:

  1. x=int(vx*((h-h0x)/100)+X0)


Y esa vx como:

  1. vx=vx*tau


tau es 0.9995, por ende, multiplicar vx por 0.9995 va a achicar progresivamente el número, y si la posición en X depende de vx, va a variar constantemente y el sprite nunca se va a quedar quieto.

Saludos
Responder
#5
(25-06-2020, 02:10 AM)Francisco escribió: Bueno, habría que entender bien la lógica del programa, pero en principio, la posición en X del sprite está definida como:

  1. x=int(vx*((h-h0x)/100)+X0)


Y esa vx como:

  1. vx=vx*tau


tau es 0.9995, por ende, multiplicar vx por 0.9995 va a achicar progresivamente el número, y si la posición en X depende de vx, va a variar constantemente y el sprite nunca se va a quedar quieto.

Saludos

Claro, entiendo que no se qude quieto, pues la velocidad nunca llega a 0 realmente (salvo imponiendo una condicion que si |vx|<0.001: vx=0, x ej) pero aca con la velocidad vx/100 del orden de 0.4 empieza a avanzar en sentido contrario a la velocidad... nose me extraña. Actualmente puse como condicion que si |vx/100| < 0.4 se detiene forzosamente, lo que es algo incomodo y podria generar errores futuros.
Responder
#6
Bueno gracias pr las respuestas, creo haber entendido el problema, de tanto mirar el codigo.

1) la funcion  x= vx(h-h)+ X0      logicamente tiende a X0 cuando vx tiende a 0

Como X0 toma su ultimo valor al golpear con la pared, X0 es la posicion en la pared. 
Para hacerlo bien deberia encontrar la aceleracion para ese movimiento, pero prefiero definir una nueva condicion:
(reemplaze a y b de aca:   
a- if (((vx)**2)**(1/2))<0.01:  #(((vx)**2)**(1/2)) = |vx|
b-        vx=0
    else:    
        vx=vx*tau

por:

if |vx| < 0.4:
   vx=0
   h0x=h-1
   X0=x

De modo que cuando pasa por esa velocidad crítica se frena directamente.

bueno nose queda cerrado esto como hago?

Dejo el codigo mas terminado aca.

Código:
import numpy as np
import pygame,sys
from pygame.locals import *


def data():
    #print(x)
    #print(vx)
    #print(y)
    #print(vy)
    print(deltax)
    print(dvx)
    #print(ay)
    #print(deltay)
    #print(pygame.key.get_pressed())



alto = 500
ancho = 1000
A=200
h0=0
h0x=0
phi=0
X0=ancho/2
Y0=alto-30
vx=0
vy=0
ay=50
h=0
l=0
x=X0
y=Y0
taupiso=0.75
tau=0.9995
piso=alto-30
usoKEYUP=False
usoKEYDOWN=False
usoKEYRIGHT=False
usoKEYLEFT=False
ck1=0
ck2=0
ck3=0
ck4=0
d=(((piso-y)**2)**(1/2))
intervalo=200
modvx=0.
modvy=0.
dvx=0.
minvxExperimental=0.4



pygame.init()
screen = pygame.display.set_caption("spaceinvader")
ventana = pygame.display.set_mode((ancho, alto))


imagen1 = pygame.image.load("spaceinvader.png")
rectanguloimg = imagen1.get_rect()

jugando = True
while jugando:
    
    h=h+1
    
    vx=vx*tau

    vy=vy*tau
    if modvy<0.0001:
        vy=0
        h0=h-1
        Y0=y
    if modvx<0.0001:
        vx=0
        h0x=h-1
        X0=x

    if 0>x:
        vx=(-1)*vx
        h0x=h-1
        X0=x
        print("pared1")

    if x>ancho-30:
        vx=(-1)*vx
        h0x=h-1
        X0=x
        print("pared2")      

    if y>piso:
        Y0=piso
        vy=(-1)*(vy*taupiso)
        h0=h-1
        print("piso")          
    
    #teclado()

    #if modvy<0.0001:
    #    if d==0:
    #        vy=0
    #        Y0=piso
    #        h0=h-1
    y=int(ay*(((h-h0)/100)**2)+vy*((h-h0)/100)+Y0)
    x=int(vx*((h-h0x)/100)+X0)

    deltax=(((vx*((h-h0x)/100)+X0-(vx*((h-1-h0x)/100)+X0))**2)**(1/2))
    dvx=vx/100
    if deltax<minvxExperimental:
        vx=0
        h0x=h-1
        X0=x
        x=int(vx*((h-h0x)/100)+X0)
        print("froz")
    #deltay=(((y-rectanguloimg.top)**2)**(1/2))        


    rectanguloimg.left = x
    rectanguloimg.top = y

    
    ventana.fill((0,0,0))
    ventana.blit(imagen1, rectanguloimg)
    pygame.display.flip()
    data()
    pygame.time.wait(1)
    


    if ck1>0:
        ck1=ck1-1
    else:
        ck1=0
        usoKEYUP=False

    if ck2>0:
        ck2=ck2-1
    else:
        ck2=0
        usoKEYRIGHT=False

    if ck3>0:
        ck3=ck3-1
    else:
        ck3=0
        usoKEYLEFT=False

    if ck4>0:
        ck4=ck4-1
    else:
        ck4=0
        usoKEYDOWN=False

    for event in pygame.event.get():
        print(event)
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
        elif event.type == pygame.KEYDOWN:
            
            if event.key==K_UP:
                if usoKEYUP==True:
                    print("Debes esperar para empujarte denuevo")
                else:    
                    vy=vy-100
                    usoKEYUP=True
                    ck1=intervalo
                    h0=h-1
                    Y0=y
            elif event.key==K_RIGHT:
                if usoKEYRIGHT==True:
                    print("Debes esperar para empujarte denuevo")
                else:    
                    vx=vx+300
                    usoKEYRIGHT=True
                    ck2=intervalo
                    h0x=h-1
                    X0=x

            elif event.key == K_LEFT:
                if usoKEYLEFT==True:
                    print("Debes esperar para empujarte denuevo")
                else:    
                    vx=vx-300
                    usoKEYLEFT=True
                    ck3=intervalo
                    h0x=h-1
                    X0=x

            elif event.key == K_DOWN:
                if y>468:
                    print("no space down")
                else:
                    vy=vy+100
                    usoKEYDOWN=True
                    ck4=intervalo
                    h0=h-1
                    Y0=y

    modvx=(((vx)**2)**(1/2))
    modvy=(((vy)**2)**(1/2))        

   
pygame.quit() 
Responder
#7
Me alegro de que lo hayas podido solucionar.

Gracias por el código, saludos.
Responder


Salto de foro:


Usuarios navegando en este tema: 2 invitado(s)