Commits

Dominic Kexel committed 992d393 Draft

show ruins

Comments (0)

Files changed (1)

 import pygame
 import pymunk
 import random
-from itertools import product, starmap
+import operator
+from itertools import product, starmap, chain, repeat
+from math import sqrt
 
 from scene import Scene
 from constants import *
 +################
 """
 
+ruin = \
+"""
+                 
+                 
+                 
+                 
+                 
+                 
+ +##             
+++###           #
++#####     +# +##
++# ## ## +  ### #
++################
++################
+"""
 
-def _city_surface(tick):
+#TODO cache this image
+def _city_surface(tick, img=city):
   size = 3
-  splitted = city.split('\n')[1:-1]
+  splitted = img.split('\n')[1:-1]
   width = len(splitted[0])
   height = len(splitted)
   _city_surf = pygame.surface.Surface((width * size, height * size), pygame.SRCALPHA, 32)
 
 class Explosion(Actor):
   
-  def __init__(self, speed=2, size=40, shrapnels=True, **kwargs):
+  def __init__(self, speed=2, size=40, shrapnels=True, kills=False, **kwargs):
     super(Explosion, self).__init__(**kwargs)
     self._start = kwargs['start_pos']
     self._radius = 0
     self._max_radius = size
     self._speed = speed
     self._alpha = 0
+    self._kills = kills
     
     if shrapnels:
       l = [1,1,1,1,1,1,1,1,2,2,2,3,3]
       for _ in xrange(20):
         Shrapnel(scene=self.scene, start_pos=self._start, size=random.choice(l))
-        
+
+  def _in_range(self, rocket):
+    x1, y1 = self._start
+    x2, y2 = rocket._current
+    return abs(sqrt((x2 - x1)**2 + (y2 - y1)**2)) <= self._radius
+          
   def update(self):
     self._radius += self._speed
+
+    if self._kills:
+      rockets = (a for a in self.scene._actors if isinstance(a, Rocket) and self._in_range(a))
+      for a in rockets:
+        a.die()
+    
     self._alpha = 255 - int(1.0 * self._radius / self._max_radius * 255)
     if self._radius >= self._max_radius:
       self.die()
 
 class Rocket(Actor):
   
-  def __init__(self, **kwargs):
+  def __init__(self, speed=1, **kwargs):
     super(Rocket, self).__init__(**kwargs)
     self._start = kwargs['start_pos']
     self._current = kwargs['start_pos']
     self._target = kwargs['target']
-    self._vector = [e*0.2 for e in kwargs['vector']]
+    self._vector = list(starmap(operator.mul, zip(kwargs['vector'], repeat(speed*0.2))))
+    
     self._moving = True
     self.z = -1
 
   def update(self):
     if not self._moving: return
-
+    
     self._current = [e for e in add(self._current, self._vector)]
 
     c = map(int, self._current)
     x, y = map(int, self._target)
+
     r = 3
     if c in starmap(lambda a,b: [x+a, y+b], product(xrange(-r, r+1), xrange(-r, r+1))):
       self._moving = False
       Explosion(start_pos=c, speed=18, size=300, shrapnels=False, scene=self.scene)
-      Explosion(start_pos=c, speed=3, size=40, scene=self.scene)
+      Explosion(start_pos=c, speed=3, size=40, scene=self.scene, kills=True)
       self.die()
       
   def draw(self, screen):
     super(City, self).__init__(**kwargs)
     self._inx = kwargs['inx']
     self.hit = False
-  
+    self._surf = _city_surface(self.scene._game.tick)
+
+  @property
+  def pos(self):
+    center = (SCREEN_WIDTH / 10) * (self._inx + (2 if self._inx <= 2 else 3))
+    pos = center - self._surf.get_width() / 2, SCREEN_HEIGHT - self._surf.get_height()
+    return pos
+    
+  @property
+  def center_pos(self):
+    center = (SCREEN_WIDTH / 10) * (self._inx + (2 if self._inx <= 2 else 3))
+    pos = center, SCREEN_HEIGHT - self._surf.get_height()
+    return pos
+    
   def draw(self, screen):
-    center = (SCREEN_WIDTH / 10) * (self._inx + (2 if self._inx <= 2 else 3))
-    surf = _city_surface(self.scene._game.tick)
-    pos = center - surf.get_width() / 2, SCREEN_HEIGHT - surf.get_height()
-    screen.blit(surf, pos)
+    self._surf = _city_surface(self.scene._game.tick, ruin if self.hit else city)
+    screen.blit(self._surf, self.pos)
 
 class Silo(Actor):
   
     return self._get_silo_pos(self.inx)
   
   @property
+  def center_pos(self):
+    return map(sum, zip(self._get_silo_pos(self.inx), (0, -20)))
+  
+  @property
   def firing_vetor(self):
     return self._get_firing_vetor(self.inx)
   
     return v
       
   def draw(self, screen):
-    cpos = self._get_silo_pos(self._inx)
-    if self.rockets:
-      v = [e*22 for e in self._get_firing_vetor(self._inx)]
-      pygame.draw.line(screen, RED, cpos, add(cpos, v), 2)
-    r = 20
-    pygame.draw.circle(screen, HIGHLAND, cpos, r, 0)
-
+    if not self.hit:
+      cpos = self._get_silo_pos(self._inx)
+      if self.rockets:
+        v = [e*22 for e in self._get_firing_vetor(self._inx)]
+        pygame.draw.line(screen, RED, cpos, add(cpos, v), 2)
+      r = 20
+      pygame.draw.circle(screen, HIGHLAND, cpos, r, 0)
+    else:
+      surf = _city_surface(self.scene._game.tick, ruin)
+      screen.blit(surf, map(sum, zip(self.pos, (0, -20))))
+      
   def fire(self):
     if not self.rockets: return
     self.rockets -= 1
 
-    v = [e*25 for e in self.firing_vetor]
     Rocket(start_pos=self.pos, 
            target=pygame.mouse.get_pos(), 
-           vector=v, 
+           vector=self.firing_vetor, 
+           speed=25,
            scene=self.scene)
 
 class Battle(Scene):
     self._event_handler = {pygame.MOUSEBUTTONUP: self._fire_rocket}
     self._background = pygame.transform.scale(pygame.image.load('back.jpg'), (SCREEN_WIDTH, SCREEN_HEIGHT)).convert()
     self._silos = {}
+    self._cities = {}
+    self._initialized = False
+    self._enemy_timeout = r(10, 300)
+
+  def enter(self):
+    if self._initialized: return
     for inx, city in enumerate(self._state.cities):
-      City(scene=self, inx=inx)
+      self._cities[inx] = City(scene=self, inx=inx)
     for inx, silo in enumerate(self._state.silos):
       self._silos[inx] = Silo(scene=self, inx=inx)
+    self._initialized = True
 
   def destroy(self, actor):
-    self._actors.remove(actor)
+    if actor in self._actors:
+      self._actors.remove(actor)
     return actor
     
   def create(self, actor):
-    self._actors.append(actor)
+    if not actor in self._actors:
+      self._actors.append(actor)
     return actor
 
   def _fire_rocket(self, event):
   
   def update_state(self):
     super(Battle, self).update_state()
+    self._enemy_timeout -= 1
+    if not self._enemy_timeout:
+      self._enemy_timeout = r(10, 300)
+      
+      pos = random.randrange(0, SCREEN_WIDTH + 1), 0
+      target = random.choice(list(self._cities.values()) + list(self._silos.values()))
+
+      ro = None
+      def destroy_obj():
+        if ro._moving: return
+        target.hit = True
+
+      ro = Rocket(start_pos=pos, 
+                 speed=5,
+                 on_die=destroy_obj,
+                 target=target.center_pos, 
+                 vector=normalize(sub(target.center_pos, pos)), 
+                 scene=self)
+    
     space.step(1/50.0)