Las imágenes que se utilizan son las siguientes. Para descargarlas: botón derecho del ratón y a "guardar imagen como..." en la misma carpeta que esté el código. Son libres (de copia, modificación y distribución), siendo yo el creador.
 
  
Las imágenes tiene la característica de que donde estaría el eje de rotación se sitúa en el centro de la imagen.
- Código: Seleccionar todo
- # -*- coding: utf-8 -*-
 #
 # Autor: David Ramírez
 # Licencia: GPL 3
 import pygame
 from pygame import *
 from math import *
 resolucion = (500, 300)
 color = (255, 240, 220)
 class Antiaereo ( sprite.Sprite):
 def __init__(self, centro):
 #El antiaéreo se compone por un cañón que gira sobre el eje de una base
 sprite.Sprite.__init__(self)
 
 # Se crea la imagen de la base y su rectángulo
 self.img_base = pygame.image.load("base.png").convert()
 color_transparente = self.img_base.get_at((0,0))
 self.img_base.set_colorkey(color_transparente)
 self.rect_base = self.img_base.get_rect()
 
 # Se crea la imagen del cañón y su rectángulo
 self.img_canyon = pygame.image.load("cañon.png").convert()
 color_transparente = self.img_canyon.get_at((0, 0))
 self.img_canyon.set_colorkey(color_transparente)
 self.rect_canyon = self.img_canyon.get_rect()
 
 # Se crea la imagen del antiaéreo, su rectángulo y se sitúa
 self.image = Surface((self.rect_canyon.width, self.rect_canyon.height)).convert()
 self.image.set_colorkey((255,0,255))
 self.rect = self.image.get_rect()
 self.rect.center = centro
 
 self.centro = float(centro[0]), float(centro[1])
 
 def update(self, pos_rat):
 # Se borra la imagen del antiaéreo y se dibuja, sobre ella, el cañón
 # girado y la base. Coincidiendo los 3 centros de las superficies en
 # la coordenada "centro"
 
 self.image.fill((255,0,255))
 
 self.canyon_g = self.mover_canyon(self.img_canyon, pos_rat)
 self.rect_canyon = self.canyon_g.get_rect()
 
 self.image.blit(self.img_base, ((self.rect.width / 2) - (self.rect_base.width / 2),
 (self.rect.height / 2) - (self.rect_base.height / 2)))
 self.image.blit(self.canyon_g, ((self.rect.width / 2) - (self.rect_canyon.width / 2),
 (self.rect.height / 2) - (self.rect_canyon.height / 2)))
 def mover_canyon(self, img_canyon, pos_rat):
 # Se devuelve la superficie del cañón girado, dependiendo de la
 # posición del ratón.
 # Para ello, hace falta saber el angulo exacto del centro a la posición
 # del ratón. Teniendo en cuenta que tan(ángulo) == tan(ángulo + pi).
 if (pos_rat[0] - self.centro[0]) == 0:
 if pos_rat[1] > self.centro[1]:
 a = pi / 2
 else:
 a = -pi / 2
 else:
 if pos_rat[0] > self.centro[0]:
 a = atan((self.centro[1] - pos_rat[1]) / (self.centro[0] - pos_rat[0]))
 else:
 a = pi + atan((self.centro[1] - pos_rat[1]) / (self.centro[0] - pos_rat[0]))
 
 canyon_girado = transform.rotate(img_canyon, degrees(-a))
 return canyon_girado
 
 def main():
 # Se crea la pantalla con la resolución determinada
 screen = pygame.display.set_mode(resolucion)
 # Se crea el conjunto de artillería y se añaden varios antiaéreos
 # en distintas posiciones.
 artilleria = pygame.sprite.Group()
 for a in range(1, 9):
 artilleria.add(Antiaereo(( -15 + a * 60, 60 + sin(a) * 40)))
 
 while True:
 for event in pygame.event.get():
 if event.type == QUIT:
 # Finaliza el programa si hay un evento de cerrar
 return
 screen.fill(color) # Se pinta la pantalla
 pos = mouse.get_pos() # Se obtiene la posición del ratón
 artilleria.update(pos) # Se actualizan la artillería dependiendo de "pos"
 artilleria.draw(screen) # Se dibuja la artillería
 display.update() # Se actualiza la pantalla
 if __name__ == '__main__':
 main()
Espero que disfrutéis con él. Lo siento si hay algún error, no he podido dedicarle mucho tiempo. En caso de ver alguno, agradecería un aviso para que lo pueda rectificar.
Saludos.



