Desactivar key_repeat selectivamente (pygame)

Agrupa todas las consultas sobre los lenguajes de programacion como C, C++, Python, Java ...

Desactivar key_repeat selectivamente (pygame)

Notapor algarafa » Mié Sep 29, 2010 5:49 pm

Hola a todos los losersdevelopers :D :

Estoy haciendo un minijuego con una navecita. No se muy bien como enfocaré el juego, pero lo que si es seguro es que constará de dos elementos, navecita y misiles. Así que, mientras que me pienso que habrá que hacer para ganar y eso he programado ya las dos clases correspondientes. El caso es que al hacer el misil me encuentro un problema. Tengo activada la repetición de teclas para que sea más sencillo mover la nave, pero al pulsar la tecla espacio (asignada para lanzar misil) me lanza una ráfaga de ellos que no veas. Adjuntos dos capturas y el código.

Así está ahora:
Imagen

Y así quiero que esté:
Imagen

Código: Seleccionar todo
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ------------------------------
# Autor: Rafael Álvarez García
# e-mail: algarafa@gmail.com
# ------------------------------

# ------------------------------
# Importación de módulos
# ------------------------------

import pygame
from pygame.locals import *
import sys
import os

# ------------------------------
# Constantes
# ------------------------------

SCREEN_WIDTH = 400
SCREEN_HEIGHT = 600
IMG_DIR = 'images'

# ------------------------------
# Funciones y clases
# ------------------------------

# Creamos la función para cargar imágenes.
def load_image(name, dir, alpha = False):
   # Unimos la ruta de la imágen.
   ruta = os.path.join(dir, name)
   # Probamos a cargarla y si no devolvemos error.
   try:
      image = pygame.image.load(ruta)
      print 'Cargando imagen', ruta, '...¡éxito!'
      
   except:
      print 'No se pudo cargar la imagen', ruta
      sys.exit(1)
      
   # Comprobamos si hay alpha.
   if alpha:
      image = image.convert_alpha()
   else:
      image = image.convert()
      
   return image

# Clase para la nave.
class Nave(pygame.sprite.Sprite):
   
   def __init__(self):
      pygame.sprite.Sprite.__init__(self)
      self.image = load_image('nave.png', IMG_DIR, alpha = True)
      self.rect = self.image.get_rect()
      self.rect.centerx = SCREEN_WIDTH / 2
      self.rect.centery = SCREEN_HEIGHT - 60
      self.speed = [0, 0]
      
   def update(self):
      # Hacemos que no salga de la pantalla.
      if self.rect.top < 0:
         self.rect.top = 0
         self.speed[1] = 0
      elif self.rect.bottom > SCREEN_HEIGHT + 1:
         self.rect.bottom = SCREEN_HEIGHT
         self.speed[1] = 0
      elif self.rect.left < -1:
         self.rect.left = 0
         self.speed[0] = 0
      elif self.rect.right > SCREEN_WIDTH + 1:
         self.rect.right = SCREEN_WIDTH
         self.speed[0] = 0
         
      self.rect.move_ip(self.speed)
      
# Clase para el misil.
class Misil(pygame.sprite.Sprite):
   
   def __init__(self, initial_pos):
      pygame.sprite.Sprite.__init__(self)
      self.image = load_image('misil.png', IMG_DIR, alpha = True)
      self.rect = self.image.get_rect()
      self.rect.midbottom = initial_pos
      self.speed = [0, -4]
      
   # Si se sale de pantalla lo matamos, si no lo movemos.
   def update(self):
      if self.rect.bottom < 0:
         self.kill
      else:
         self.rect.move_ip(self.speed)

# ------------------------------
# Función principal
# ------------------------------

def main():
   pygame.init()
   print 'Iniciando juego...'
   
   # Creamos la ventana e indicamos nombre e icono.
   screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
   pygame.display.set_caption('Provisional')
   icon = pygame.image.load('images/nave.png').convert_alpha()
   pygame.display.set_icon(icon)
   print 'Creando ventana... ¡éxito!'
   
   # Cargamos e imprimimos el fondo.
   fondo = load_image('background.jpg', IMG_DIR)
   screen.blit(fondo, (0, 0))
   
   # Cremoas el frupo de sprites.
   sprites = pygame.sprite.Group()
   
   # Creamos la nave y la añadimos al grupo sprites.
   nave = Nave()
   sprites.add(nave)
   
   # Creamos el reloj.
   clock = pygame.time.Clock()
   # Activamos la repetición de teclas.
   pygame.key.set_repeat(1, 25)
   # Hacemos el ratón invisible.
   pygame.mouse.set_visible(False)
   
   # Bucle principal.
   while True:
      clock.tick(60)
      
      # Comprobamos los eventos.
      for event in pygame.event.get():
         if event.type == pygame.QUIT:
            print 'Cerrando juego...'
            sys.exit()
            
         if event.type == pygame.KEYDOWN:
            if event.key == K_UP:
               nave.speed[1] -= 0.3
            elif event.key == K_DOWN:
               nave.speed[1] += 0.3
            elif event.key == K_LEFT:
               nave.speed[0] -= 0.3
            elif event.key == K_RIGHT:
               nave.speed[0] += 0.3
            elif event.key == K_SPACE:
               misil = Misil(nave.rect.midtop)
               
               sprites.add(misil)
               
            elif event.key == K_ESCAPE:
               print 'Cerrando juego...'
               sys.exit()
      
      # Actualizamos los sprites.
      sprites.update()
            
      # Actualizamos la pantalla.
      sprites.clear(screen, fondo)
      sprites.draw(screen)
      pygame.display.flip()
   
if __name__ == "__main__":
   main()


¡Muchas gracias! :wink:
http://liberatumundo.wordpress.com/
Avatar de Usuario
algarafa
 
Mensajes: 135
Registrado: Lun Oct 27, 2008 6:12 pm
Ubicación: España

Re: Desactivar key_repeat selectivamente (pygame)

Notapor Juanxo » Mié Sep 29, 2010 6:54 pm

Código: Seleccionar todo
#clase Nave
def update(self):
      key = pygame.key.get_pressed()
      vel_x = 0
      vel_y = 0
      if (key[K_UP])
   vel_y = -VELOCIDAD_NAVE
      elif (key[K_DOWN])
   vel_y = VELOCIDAD_NAVE
      if (key[K_LEFT])
   vel_x = -VELOCIDAD_NAVE
      if (key[K_RIGHT])
   vel_x = VELOCIDAD_NAVE
         
      self.rect.move_ip(vel_x, vel_y)


Otra opcion:

Código: Seleccionar todo
#inicializacion
nave.speed= [0,0]

#dentro del bucle principal
if event.type == pygame.KEYDOWN:
    if event.key == K_UP:
       nave.speed[1]  = -0.3
    elif event.key == K_DOWN:
       nave.speed[1]  = 0.3
    elif event.key == K_LEFT:
       nave.speed[0] =  -0.3
    elif event.key == K_RIGHT:
       nave.speed[0] = 0.3
    elif event.key == K_SPACE:
       misil = Misil(nave.rect.midtop)
       
       sprites.add(misil)
       
    elif event.key == K_ESCAPE:
       print 'Cerrando juego...'
       sys.exit()
if event.type == pygame.KEYUP:
    if event.key == K_UP or event.key == K_DOWN:
       nave.speed[1] = 0.0
    if event.key == K_LEFT or event.key == K_RIGHT:
       nave.speed[0] = 0.0


El tema es que de esta manera no tienes que manejar nada de repeticiones de teclas ni nada parecido, asi que no tendrás problemas con los misiles
Avatar de Usuario
Juanxo
 
Mensajes: 437
Registrado: Sab Ene 31, 2009 2:34 am
Ubicación: Madrid(España)

Re: Desactivar key_repeat selectivamente (pygame)

Notapor hugoruscitti » Mié Sep 29, 2010 7:57 pm

algarafa escribió:Estoy haciendo un minijuego con una navecita. No se muy bien como enfocaré el juego, pero lo que si es seguro es que constará de dos elementos, navecita y misiles. Así que, mientras que me pienso que habrá que hacer para ganar y eso he programado ya las dos clases correspondientes. El caso es que al hacer el misil me encuentro un problema. Tengo activada la repetición de teclas para que sea más sencillo mover la nave, pero al pulsar la tecla espacio (asignada para lanzar misil) me lanza una ráfaga de ellos que no veas.

Buenas, ¡que bien se ve el juego!.

Está muy bien que comiences por un prototipo, a mi
entender es una de las mejores forma de madurar
las ideas de desarrollo.

Con respecto a la lógica de los disparos, te sugiero
una mejora y una forma para implementar lo
de la repeticion de los disparos.

En donde capturas la pulsación de teclas es
mas sencillo enviarle un mensaje a la nave:

Código: Seleccionar todo
elif event.key == K_SPACE:
    nave.shoot()


Esto te permite encapsular es funcionalidad dentro de
la nave y hacer que el 'disparo' se vea mas sencillo
desde afuera.

Luego, para lograr que los disparos no se generen con
tanta frecuencia necesitarías un contador dentro de la
clase Nave.

Escribo acá solamente las lineas nuevas para agregar, el
resto de lo que tienes de código se tendría que dejar intacto:

Código: Seleccionar todo

class Nave(pygame.sprite.Sprite):

    def __init__(self, sprites):
        self.sprites = sprites     # necesita la lista de sprites para agregar disparos
        self.counter = 0

    def update(self):
        "Actualiza el contador para simular el tiempo que le lleva recargar municiones."
        if self.counter > 0:
            self.counter -= 1

    def shoot(self):
        if self.can_shoot():
            misil = Misil(self.rect.midtop)
            self.sprites.add(misil)
            self.counter = 10          # actualiza el contacto de municiones.

    def can_shoot(self):
        "Indica si la nave puede disparar o no"
        return self.counter < 1



Entonces con este cambio tu nave tiene un
método que sabe disparar, solamente que no lo hace
con tanta frecuencia, sino por lo que indica la variable 'counter':
cuanto mayor sea el valor que le asignas al contador cuando
dispara (en mi caso 10) mas lenta será la frecuencia de disparo.

El día de mañana, si la nave captura un item de
super potencia, o algo así, el valor de la variable
counter se puede ajustar, o incluso puede
disparar mas de un misíl a la vez, o supermisiles !!... etc

En fin, sería bueno que juegues con el valor de counter para
ver si se adapta bien a la frecuencia de disparos que
quieres tener, al menos para mí un buen enfoque
es colocar esa lógica en la nave, solo por conveniencia
digamos.

Saludos.
Avatar de Usuario
hugoruscitti
Site Admin
 
Mensajes: 1242
Registrado: Dom Jul 30, 2006 3:57 am
Ubicación: Buenos Aires, Argentina

Re: Desactivar key_repeat selectivamente (pygame)

Notapor algarafa » Vie Oct 01, 2010 3:56 pm

¡Muchas gracias a los dos por vuestras respuestas! Al final he cogido la solución de Hugo, ¡y funciona muy bien! Ahora me toca pensar en que voy a poner, si enemigos o algo así.

Respecto a lo de los Supermisiles, lo que se podría hacer es poner laser a la nave y que tuviera una frecuencia de disparo muy alta pero bajara muy poca vida, y que los misiles se pudieran disparar pocos pero muy destructivos. Luego todavía podría haber un bonificador que te diera 3 supermisiles o algo... no sé, ya se verá. ¡De momento un obstáculo menos!

¡Gracias a los dos de nuevo! :D
http://liberatumundo.wordpress.com/
Avatar de Usuario
algarafa
 
Mensajes: 135
Registrado: Lun Oct 27, 2008 6:12 pm
Ubicación: España


Volver a Sobre lenguajes de programación

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado