Foros del Web » Programando para Internet » Python »

Tiro parabolico con pygame

Estas en el tema de Tiro parabolico con pygame en el foro de Python en Foros del Web. Aquí dejo un pequeño código, donde simulo el tiro parabólico: Las teclas son: Arriba -> Aumentar el ángulo Abajo -> Disminuir el ángulo Izquierda -> ...
  #1 (permalink)  
Antiguo 27/12/2008, 17:40
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 9 meses
Puntos: 1360
Tiro parabolico con pygame

Aquí dejo un pequeño código, donde simulo el tiro parabólico:
Las teclas son:

Arriba -> Aumentar el ángulo
Abajo -> Disminuir el ángulo

Izquierda -> Aumentar la velocidad inicial
Derecha -> Disminuir la velocidad inicial

Barra espaciadora -> Empezar la animacion
Escape -> Salir
Código python:
Ver original
  1. #!/usr/bin/env python
  2. #coding: UTF-8
  3.  
  4. def printos(surface, text, x, y, color, font):
  5.     text_in_lines = text.split('\n')
  6.     for line in text_in_lines:
  7.         new = font.render(line, 1, color)
  8.         surface.blit(new, (x, y))
  9.         y += new.get_height()
  10.  
  11. def arrow(screen, color, x, y, ang):
  12.     pygame.draw.line(screen, color, (x, y), (x + 20*math.cos(math.radians(ang + 150.0)), y - 20*math.sin(math.radians(ang + 150.0))))
  13.     pygame.draw.line(screen, color, (x, y), (x + 20*math.cos(math.radians(ang + 210.0)), y - 20*math.sin(math.radians(ang + 210.0))))
  14.  
  15. def vector(screen, color, x, y, ang):
  16.     w, z = x + v0*10*math.cos(math.radians(ang)), y - v0*10*math.sin(math.radians(ang))
  17.     x, y, w, z = int(x), int(y), int(w), int(z)
  18.     arrow(screen, color, w, z, ang)
  19.     pygame.draw.line(screen, blue, (x, y), (w, z))
  20.    
  21.  
  22. import pygame, math
  23. pygame.init()
  24.  
  25. size = width, height = 640, 480
  26.  
  27. black = (0, 0, 0)
  28. blue = (0, 0, 255)
  29. green = (0, 255, 0)
  30. background = (200, 200, 200)
  31.  
  32. screen = pygame.display.set_mode(size)
  33. pygame.display.set_caption("Inicializar")
  34.  
  35.  
  36. radio = 10
  37. x = 10
  38. y = height - radio
  39.  
  40. pygame.font.init()
  41. font = pygame.font.Font(None, 30)
  42.  
  43. clock = pygame.time.Clock()
  44.  
  45. t = 0.0
  46. dt = 0.5
  47.  
  48. v0 = 25.0
  49. a = 1.0
  50. ang = 45.0
  51.  
  52. vx = 0
  53. vy = 0
  54.  
  55. lock = True
  56. lock1 = False
  57. second = False
  58. while 1:
  59.     screen.fill(background)
  60.     for event in pygame.event.get():
  61.         if event.type == pygame.QUIT:
  62.             exit()
  63.     teclado = pygame.key.get_pressed()
  64.     if(tuple(set(teclado)) == (0,1) and lock):
  65.         if (teclado[pygame.K_UP]):
  66.             ang += 1
  67.             if(ang >= 90):
  68.                 ang = 90
  69.         if (teclado[pygame.K_DOWN]):
  70.             ang -= 1
  71.             if(ang < 0):
  72.                 ang = 0
  73.         if (teclado[pygame.K_RIGHT] and v0 < 100):
  74.             v0 += 1
  75.         if (teclado[pygame.K_LEFT] and v0 > 1):
  76.             v0 -= 1
  77.         if (teclado[pygame.K_SPACE]):
  78.             lock = False
  79.             lock1 = True
  80.             vy0 = v0*math.sin(math.radians(ang))
  81.     if (teclado[pygame.K_ESCAPE]):
  82.         break
  83.     vx0 = v0*math.cos(math.radians(ang))
  84.     vy = a*t - v0*math.sin(math.radians(ang))
  85.     if(lock1):
  86.         y = (height - radio) - vy0*t + .5*a*(t**2)
  87.         x = radio + vx0*t
  88.         t += dt
  89.         if(y > (height - radio)):
  90.             y = height - radio
  91.             t = 0
  92.             lock1 = False
  93.             second = True
  94.     if(second):
  95.         printos(screen, "Continue? Y/N", 0, 60, green, font)
  96.         if(teclado[pygame.K_y]):
  97.             lock = True
  98.             second = False
  99.             x = radio
  100.         elif(teclado[pygame.K_n]):
  101.             break
  102.  
  103.     printos(screen, "x = %d y = %d ang = %d v0 = %d vx = %d vy = %d"%(x - radio, height - radio - y, ang, v0, vx0, vy), 0, 0, green, font)
  104.     pygame.draw.circle(screen, blue, (int(x), int(y)), radio)
  105.     vector(screen, blue, x, y, ang)
  106.     pygame.display.flip()
  107.     clock.tick(30)
  #2 (permalink)  
Antiguo 09/01/2009, 07:17
Avatar de dmassive  
Fecha de Ingreso: febrero-2002
Ubicación: Paraná - Entre Ríos - Argentina
Mensajes: 279
Antigüedad: 22 años, 9 meses
Puntos: 7
De acuerdo Respuesta: Tiro parabolico con pygame

Gracias por el aporte estaba utilizando algo similar para intentar entender las formulas matemáticas que intervienen en este tipo de juegos.

¿Te gustaria explicar como funcionan las formulas matematicas de la parabola? porque en base a esto luego le podria aplicar un parametro mas como por ejemplo el viento en el caso que el tiro tenga angulo y fuerza.

Muchas Gracias!
__________________
Blümchen... einfach die rave Prinzessin
http://www.dmassive.com.ar/
  #3 (permalink)  
Antiguo 09/01/2009, 15:47
AlvaroG
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Tiro parabolico con pygame

¿fórmulas matemáticas? solamente hay una: y = ax^2 + bx + c
¿o te referís al fundamento físico? cosas como
- si no hay rozamiento la velocidad de salida es igual a la de llegada
- el punto con altura máxima no tiene velocidad vertical
- la velocidad es constante en sentido horizontal
- la aceleración vertical en la trayectoria es -g hacia abajo

Sabiendo eso, suponiendo un rozamiento en el aire tendrás que incluir una fuerza de tipo F = -b.v opuesta a la velocidad horizontal, donde b es la constante (si no recuerdo mal, llamada "constante de viscosidad" del aire). Ya con el viento sería diferente...

Explicate un poco más


Saludos.
  #4 (permalink)  
Antiguo 14/01/2009, 19:27
 
Fecha de Ingreso: mayo-2008
Mensajes: 499
Antigüedad: 16 años, 7 meses
Puntos: 1
Respuesta: Tiro parabolico con pygame

oye como consigo hacer un cuadro en pygame¿!?
  #5 (permalink)  
Antiguo 16/01/2009, 12:46
AlvaroG
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Tiro parabolico con pygame

En otro mensaje se había puesto este enlace: Cuadrado en PyGame
  #6 (permalink)  
Antiguo 22/01/2009, 16:09
 
Fecha de Ingreso: enero-2009
Mensajes: 2
Antigüedad: 15 años, 11 meses
Puntos: 2
Respuesta: Tiro parabolico con pygame

Estaba buscando en google documentacion sobre pygame.K_UP, y encontre este post. Lo curioso es que estoy escribiendo un programita de tiro parabolico!

En fin, decidi unirme al foro para opinar sobre el tiro parabolico.

Alguien preguntaba sobre las ecuaciones, asi que pense en dar un poco mas de detalles. En el caso más simple, solamente la gravedad actua sobre la bala. Recuerden que la aceleracion de la gravedad es constante, por lo que tenemos un problema de aceleracion constante. La solucion fisica a este problema es en general:

Código:
x(t) = x0 + vx0 * t + 1/2 * ax * t^2
y(t) = y0 + vy0 * t + 1/2 * ay * t^2
Es decir, la posicion (x,y) de la particula, en cualquier instante t del tiempo, esta dada por esas formulas, donde:

(x0, y0): posicion inicial de la particula
(vx0, vy0): velocidad inicial de la particula
(ax, ay): aceleracion que experimenta la particula (debe ser constante!)
t: tiempo

Si lo aplicamos al problema del tiro parabolico, la aceleracion es la de la gravedad, que solo actua en direccion vertical (y hacia abajo): ax = 0, ay = -g. Las ecuaciones se simplifican entonces a:

Código:
x(t) = x0 + vx0 * t
y(t) = y0 + vy0 * t - 1/2 * g * t^2
donde g = 9.81 es el valor de la aceleracion de la gravedad.

Agregar fricion (por ejemplo para incluir viento) es un poco mas complicado, ya que como indica alvlin, es necesario introducir una fuerza adicional, por ejemplo F = -b * v. El problema es que al hacerlo, la aceleracion de la particula deja de ser constante, y entonces la solucion general que puse arriba ya no es valida - se tienen que resolver las ecuaciones fisicas de forma distinta. De hecho, dependiendo de como se modele la friccion (es decir, que formula usemos para la fuerza), es posible que no se pueda encontrar una solucion exacta a las ecuaciones fisicas. En esos casos se utiliza una filosofia distinta para modelar la fisica.

Última edición por Meithan; 22/01/2009 a las 21:32
  #7 (permalink)  
Antiguo 22/01/2009, 21:41
 
Fecha de Ingreso: enero-2009
Mensajes: 2
Antigüedad: 15 años, 11 meses
Puntos: 2
Respuesta: Tiro parabolico con pygame

Aqui posteo el codigo medio terminado. Ya tiene forma de jueguito. A ver que les parece.

Código python:
Ver original
  1. # ################ #
  2. #   ballistix.py   #
  3. # ################ #
  4. # by Meithan West  #
  5. # 22 / Jan / 2009  #
  6. # ################ #
  7.  
  8. # Game instructions:
  9. # Shoot the squares that appear on the screen
  10. # LEFT/RIGHT: change turrent angle
  11. # UP/DOWN: increase/decrease power
  12. # SPACE: fire!
  13. # ESCAPE: quit
  14.  
  15. # If the game runs too slow/fast, tweak the variable 'speed'
  16. # in the 'Settings' section below
  17.  
  18. from __future__ import division
  19. from math import *
  20. import pygame
  21. import random
  22. pygame.init()
  23.  
  24. # Definitions
  25. black = (0, 0, 0)
  26. white = (255, 255, 255)
  27. blue = (0, 0, 255)
  28. green = (0, 255, 0)
  29. red = (255, 0, 0)
  30. yellow = (255, 255, 0)
  31. purple = (255, 0, 255)
  32. pi = 3.14159
  33. g = 9.8
  34.  
  35. # Settings
  36. width = 800
  37. height = 550
  38. bgcolor = blue
  39. speed = 1000
  40.  
  41. # ###################### #
  42. # Cannon class definition #
  43. # ###################### #
  44. class Cannon:
  45.  
  46.   # Constructor
  47.   def __init__(self, surface):
  48.     self.surface = surface
  49.     self.x = 15
  50.     self.y = 65
  51.     self.alpha = 30
  52.     self.size = 30
  53.     self.power = 70
  54.     self.fired = False
  55.     self.score = 0
  56.     self.shots = 0
  57.     self.charge = 1000
  58.     self.draw(1)
  59.  
  60.   # Cannon shoots
  61.   def shoot(self):
  62.     self.fired = True
  63.     self.shots += 1
  64.     self.charge = 0
  65.  
  66.   # Keyboard input handler
  67.   def key_event(self,event):
  68.     if event.key == pygame.K_LEFT:
  69.       if self.alpha < 90:
  70.         self.draw(0)
  71.         self.alpha += 1
  72.         self.draw(1)
  73.     elif event.key == pygame.K_RIGHT:
  74.       if self.alpha > 0:
  75.         self.draw(0)
  76.         self.alpha -= 1
  77.         self.draw(1)
  78.     elif event.key == pygame.K_DOWN:
  79.       if self.power > 40:
  80.         self.power -= 1
  81.     elif event.key == pygame.K_UP:
  82.       if self.power < 120:
  83.         self.power += 1
  84.  
  85.   # Drawing function"
  86.   def draw(self,mode):
  87.     size = self.size
  88.     # base
  89.     x1 = scrx(self.x-size/2)
  90.     y1 = scry(self.y+size/2)
  91.     x2 = scrx(self.x-size/2)
  92.     y2 = scry(self.y)
  93.     if mode == 0: color = bgcolor
  94.     else: color = white
  95.     pygame.draw.arc(self.surface, color, (x1,y1,size,size),0,3.2,1)
  96.     pygame.draw.rect(self.surface, color, (x2,y2,size+1,size/2),1)
  97.     # barrel
  98.     x1 = scrx(self.x)
  99.     y1 = scry(self.y)
  100.     x2 = scrx(self.x + size*cos(self.alpha*pi/180))
  101.     y2 = scry(self.y + size*sin(self.alpha*pi/180))
  102.     if mode == 0: color = bgcolor
  103.     else: color = yellow
  104.     pygame.draw.line(self.surface, color, (x1,y1),(x2,y2),1)
  105.  
  106. # ###################### #
  107. # Shell class definition #
  108. # ###################### #
  109. class Shell:
  110.  
  111.   # Constructor
  112.   def __init__(self,surface,alpha,power):
  113.     self.surface = surface
  114.     self.size = 3
  115.     # kinematics
  116.     self.x0 = cannon.x + cannon.size*cos(alpha*pi/180)*1.1
  117.     self.y0 = cannon.y + cannon.size*sin(alpha*pi/180)*1.1
  118.     self.vx0 = power*cos(alpha*pi/180)
  119.     self.vy0 = power*sin(alpha*pi/180)
  120.     self.t0 = t
  121.     self.x = self.x0
  122.     self.y = self.y0
  123.     self.vx = self.vx0
  124.     self.vy = self.vy0
  125.  
  126.   # Function to move the shell
  127.   # Uses exact solutions to the kinematic equations
  128.   def move(self):
  129.     self.undraw()
  130.     self.x = self.x0 + self.vx0*(t-self.t0)
  131.     self.y = self.y0 + self.vy0*(t-self.t0) - g/2*(t-self.t0)**2
  132.     self.vx = self.vx0
  133.     self.vy = self.vy0 - g*(t-self.t0)
  134.     if not self.destroyed(): self.draw()
  135.  
  136.   # Check if shell is out of the playing area
  137.   def destroyed(self):
  138.     sx = self.x
  139.     sy = height-self.y
  140.     if sx > width or sy > height-55-self.size:
  141.       return True
  142.     else:
  143.       return False
  144.  
  145.   # Drawing function
  146.   def draw(self):
  147.     # shell
  148.     sx = scrx(self.x)
  149.     sy = scry(self.y)
  150.     pygame.draw.circle(self.surface,red,(sx,sy),self.size,0)
  151.     # trail
  152.     alpha = atan(self.vy/self.vx)
  153.     cosa = cos(alpha)
  154.     sina = sin(alpha)
  155.     sx = scrx(self.x-self.size*cosa*1.3)
  156.     sy = scry(self.y-self.size*sina*1.3)
  157.     self.surface.set_at((sx,sy),red)
  158.  
  159.   # Erasing function
  160.   def undraw(self):
  161.     sx = scrx(self.x)
  162.     sy = scry(self.y)
  163.     pygame.draw.circle(self.surface,bgcolor,(sx,sy),self.size,0)
  164.  
  165.   # Utility function to return the shell position
  166.   def pos(self):
  167.     return self.x, self.y
  168.  
  169. # ####################### #
  170. # Target class definition #
  171. # ####################### #
  172.  
  173. class Target:
  174.  
  175.   # Constructor
  176.   def __init__(self,surface):
  177.     self.x = random.randint(50, width-10)
  178.     self.y = random.randint(10, height-50)
  179.     self.size = 10
  180.     self.surface = surface
  181.     self.draw()
  182.    
  183.   # Drawing function
  184.   def draw(self):
  185.     sx = scrx(self.x)
  186.     sy = scry(self.y)
  187.     pygame.draw.rect(self.surface,yellow,(sx,sy,self.size,self.size),0)
  188.  
  189.   # Erasing function
  190.   def undraw(self):
  191.     sx = scrx(self.x)
  192.     sy = scry(self.y)
  193.     pygame.draw.rect(self.surface,bgcolor,(sx,sy,self.size,self.size),0)
  194.  
  195.   # Checks if the target was hit by a shell
  196.   def hit(self,(x,y),rad):
  197.     if x > (self.x-rad) and \
  198.        x < (self.x+self.size+rad) and \
  199.        y > (self.y-self.size-rad) and \
  200.        y < (self.y+rad):
  201.       return True
  202.     else: return False
  203.  
  204. # ###################### #
  205. # Miscelaneous functions #
  206. # ###################### #
  207.  
  208. # Draws the scoring board
  209. def drawboard():
  210.   pygame.draw.rect(screen,bgcolor,(0,height-49,width,49),0)
  211.   printos(screen, "Power = " + str(cannon.power), 2, height-40, white, font)
  212.   printos(screen, "Angle = " + str(cannon.alpha), 2, height-20, white, font)
  213.   printos(screen, "Score = " + str(cannon.score), width/2-20, height-40, white, font)
  214.   printos(screen, "Score = " + str(cannon.score), width/2-20, height-40, white, font)
  215.   if cannon.shots == 0:
  216.     printos(screen, "Accuracy = 0%", width/2-20, height-20, white, font)
  217.   else:
  218.     printos(screen, "Accuracy = " + str(int(cannon.score/cannon.shots*100)) + "%", width/2-20, height-20, white, font)
  219.   # Reload indicator
  220.   if cannon.charge == 1000:
  221.     printos(screen, "Cannon: ", 100, height-40, white, font)
  222.     printos(screen, "Ready", 160, height-40, green, font)
  223.     pygame.draw.rect(screen,white,(100,height-21,100,10),1)
  224.     pygame.draw.rect(screen,green,(101,height-20,cannon.charge/10-2,8),0)
  225.   else:
  226.     printos(screen, "Cannon: ", 100, height-40, white, font)
  227.     printos(screen, "Reloading", 160, height-40, red, font)
  228.     pygame.draw.rect(screen,white,(100,height-21,100,10),1)
  229.     pygame.draw.rect(screen,red,(101,height-20,cannon.charge/10-2,8),0)
  230.  
  231. # Functions to convert game coordinates to screen coordinates
  232. def scrx(x):
  233.   return int(x)
  234. def scry(y):
  235.   return int(height-y)
  236.  
  237. # Generic screen printing function
  238. def printos(surface, text, x, y, color, font):
  239.   new = font.render(text, 1, color)
  240.   surface.blit(new, (x, y))
  241.  
  242. # ################## #
  243. # Main program start #
  244. # ################## #
  245.  
  246. # Initialization
  247. screen = pygame.display.set_mode((width,height))
  248. clock = pygame.time.Clock()
  249. pygame.key.set_repeat(25)
  250. pygame.font.init()
  251. font = pygame.font.Font(None, 20)
  252. screen.fill(bgcolor)
  253. pygame.draw.line(screen, white, (0,height-50),(width,height-50), 1)
  254. t=0
  255. cannon = Cannon(screen)
  256. target = Target(screen)
  257. shell_list = []
  258. drawboard()
  259. running = True
  260.  
  261. # Main game loop
  262. while running:
  263.  
  264.   # Event handler
  265.   for event in pygame.event.get():
  266.     if event.type == pygame.QUIT:
  267.       print "Thanks for playing!"
  268.       running = False
  269.     # Keyboard input
  270.     elif event.type == pygame.KEYDOWN:
  271.       # ESCAPE exits the game
  272.       if event.key == pygame.K_ESCAPE:
  273.         print "Thanks for playing!"
  274.         running = False
  275.       # SPACE shoots
  276.       elif event.key == pygame.K_SPACE:
  277.         if cannon.charge == 1000:
  278.           cannon.shoot()
  279.           shell_list.append(Shell(screen,cannon.alpha,cannon.power))
  280.       # All other key events are handled by the Cannon class
  281.       else:
  282.         cannon.key_event(event)
  283.  
  284.   # For each shell
  285.   if len(shell_list) > 0:
  286.     for index,shell in enumerate(shell_list):
  287.       shell.move()
  288.       if shell.destroyed():
  289.         shell_list.pop(index)
  290.       if target.hit(shell.pos(),shell.size):
  291.         cannon.score += 1
  292.         shell.undraw()
  293.         shell_list.pop(index)
  294.         target.undraw()
  295.         target = Target(screen)
  296.  
  297.   # Recharge cannon
  298.   if cannon.charge < 1000: cannon.charge+=2
  299.  
  300.   # Draw frame
  301.   drawboard()
  302.   pygame.display.flip()
  303.  
  304.   # Update time
  305.   t += 0.01
  306.   clock.tick(speed)
  #8 (permalink)  
Antiguo 26/01/2009, 16:33
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 9 meses
Puntos: 1360
Respuesta: Tiro parabolico con pygame

Para ser sincero me costo mas hacer las flechitas que el tiro parabolico. Por que involucra muchas funciones trigonometricas y trastaciones de ejes.

Excelente codigo Meithan

Proximamento posteo otro codigo ;D

Etiquetas: pygame
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 21:14.