Logo Search packages:      
Sourcecode: castle-combat version File versions  Download package

gamephases.py

import pygame
from pygame.locals import *
from Numeric import *

import common
from game import get_game
from state import State, IgnoreEvent

class GameState(State):

      def handle_keypress(self, event):
            if event.type == KEYDOWN:
                  if event.key == K_ESCAPE:
                        self.quit()
                        raise IgnoreEvent
            if common.debug and event.type == KEYDOWN:
                  if event.key == K_BACKSPACE:
                        get_game().server_call('next_phase')      
                        raise IgnoreEvent
                  if event.key == K_EQUALS:
                        try:
                              import cannon
                              reload(cannon)
                              print "reload successful"
                        except:
                              print "WARNING: Module reload failed!"
                              import traceback
                              traceback.print_exc() 
      
      def quit(self):
            # allow GameState to quit event if it's not the topmost state
            State.stack[-1].quit()
            State.quit(self)

      persistent_events = {
            KEYDOWN: handle_keypress,
      }


class Phase(State):

      def __init__(self):
            State.__init__(self)
            for player in get_game().players:
                  player.init_phase(self.phase_name)

            self.time_left = self.duration
            self.clock = pygame.time.Clock()
            self.clock.tick()

      def handle(self):
            if self.phase_end():
                  get_game().server_call('next_phase')      
            else:
                  passed_milliseconds = min(self.clock.tick(), 500)
                  # handle redraws and other actions that occur each frame
                  self.actions(passed_milliseconds)
                  for player in get_game().players:
                        player.handle_movement(passed_milliseconds)
                        player.draw_cursor()
                  self.time_left -= passed_milliseconds * 0.001
                  get_game().print_time()
                  common.update()
      
      def handle_keypress(self, event):
            for player in get_game().players:
                  if player.local:
                        player.handle_event(event)

      events = {
            KEYDOWN: handle_keypress,
            KEYUP: handle_keypress,
      }
            
00075 class AnnouncePhase(State):
      """Shows the 'Phase X begins' messages"""

      box_pic = common.load_image('box.png', alpha=True)
      phase_name = 'announce'

      def __init__(self, next_phase):
            State.__init__(self)
            if next_phase == BuildPhase:
                  self.make_announce_surface(
                              "Repair your walls!",
                              "Enclose at least one castle to survive.",
                              "Place block / Rotate Block"
                  )
            elif next_phase == PlacePhase:
                  self.make_announce_surface(
                              "Place your cannons!",
                              "Position new cannons inside your walls.",
                              "Place cannon / Select cannon"
                  )
            elif next_phase == BattlePhase:
                  self.make_announce_surface(
                              "Shoot at your enemey's walls!",
                              "You can also destroy the cannons.",
                              "Shoot / Accelerate movement"
                  )
            elif next_phase == SelectPhase:
                  self.make_announce_surface(
                              "Select your Castle!",
                              "Choose one castle to be your home castle.",
                              "Select Castle / No Action"
                  )
            common.blit(
                  self.announce_surface, 
                  divide(
                        subtract(common.screen.get_size(), self.announce_surface.get_size()),
                        2
                  )
            )
            common.update()
            self.start_time = pygame.time.get_ticks()
            self.next_phase = next_phase
      
      def proceed_if_waited_long_enough(self, event):
            print "a"
            if pygame.time.get_ticks() > self.start_time + 500:
                  get_game().server_call('next_phase')      
                  raise IgnoreEvent

      events = {
            KEYDOWN: proceed_if_waited_long_enough,
      }

      def cleanup(self):
            pass
      
      def make_announce_surface(self, title, instructions, buttons):
            self.announce_surface = self.box_pic.convert_alpha()
            title_pic = common.font.render(title, True, (0,0,0))
            instructions_pic = common.small_font.render(instructions, True, (0,0,0))
            buttons_pic = common.small_font.render("Buttons: " + buttons, True, (0,0,0))
            if get_game().server:
                  continue_string = "< Press any button to continue >"
            else:
                  continue_string = "< Waiting for Server to continue >"
            continue_pic = common.small_font.render(continue_string, True, (0,0,0))
            self.announce_surface.blit(
                        title_pic,
                        ((self.announce_surface.get_width() - title_pic.get_width()) / 2, 15)
            )
            self.announce_surface.blit(instructions_pic, (30, 65))
            self.announce_surface.blit(buttons_pic, (30, 90))
            self.announce_surface.blit(
                        continue_pic,
                        ((self.announce_surface.get_width() - continue_pic.get_width()) / 2, 160)
            )
      
class BuildPhase(Phase):

      phase_name = "build"
      duration = 18
      
      def __init__(self):

            def build_actions(passed_milliseconds):
                  pygame.time.delay(1)

            pygame.time.set_timer(USEREVENT, 500)
            self.actions = build_actions
            self.next_phase = lambda: AnnouncePhase(PlacePhase)
            Phase.__init__(self)

      def phase_end(self):
            return self.time_left <= 0
      
      def cleanup(self):
            def clean_walls():
                  from field import Field
                  for player in get_game().players:
                        player_id = player.player_id
                        field = get_game().field.array

                        # count how many walls are adjecent to each wall
                        adj_walls = zeros(common.field_size)
                        adj_walls[1:, :] += where(field[:-1 ,:] == player_id, 1, 0)
                        adj_walls[:-1, :] += where(field[1: ,:] == player_id, 1, 0)
                        adj_walls[:, 1:] += where(field[:, :-1] == player_id, 1, 0)
                        adj_walls[:, :-1] += where(field[:, 1:] == player_id, 1, 0)
                        
                        # delete all lonely walls
                        mask = logical_and(where(adj_walls == 0, 1, 0), where(field == player_id, 1, 0))
                        putmask(field, mask, (Field.EMPTY, ))

                        # delete every fourth wall with only one adjacent wall
                        mask = logical_and(where(adj_walls == 1, 1, 0), where(field == player_id, 1, 0))
                        putmask(field, mask, (Field.EMPTY, ) + (player_id, )*3 )

                        get_game().field.look_for_secured_areas(player)
                  get_game().field.draw_backbuffer()
                  
            clean_walls()
            get_game().field.add_houses(5)
            pygame.time.set_timer(USEREVENT, 0)


class PlacePhase(Phase):

      phase_name = "place"
      duration = 15

      def __init__(self):

            def place_actions(passed_milliseconds):
                  pygame.time.delay(1)
      
            pygame.time.set_timer(USEREVENT, 500)
            self.actions = place_actions
            self.next_phase = lambda: AnnouncePhase(BattlePhase)
            Phase.__init__(self)
            
            # This must be called later, otherwise it would freeze for everyone until
            # the server player clicked OK
            from twisted.internet import reactor
            reactor.callLater(0, get_game().end_test) 
            
      def phase_end(self):
            return self.time_left <= 0 or not filter(lambda player: player.place_player.new_cannons > 0, get_game().players)

      def cleanup(self):
            pygame.time.set_timer(USEREVENT, 0)


class BattlePhase(Phase):

      phase_name = "battle"
      duration = 10

      def __init__(self):

            def battle_actions(passed_milliseconds):
                  from cannon import Shot
                  for can in get_game().cannons:
                        can.blit()
                  for shot in get_game().shots:
                        shot.handle(passed_milliseconds)
                        shot.draw()
                  from field import Grunt
                  for grunt in Grunt.instances:
                        grunt.handle(passed_milliseconds)

            def remove_garbage():
                  from field import Field
                  get_game().field.array += logical_and (
                              where(get_game().field.array >= Field.GARBAGE_NEW, 1, 0),
                              where(get_game().field.array <= Field.GARBAGE_OLD, 1, 0)
                  )
                  
            self.actions = battle_actions
            self.next_phase = lambda: AnnouncePhase(BuildPhase)
            remove_garbage()
            self.announce_surface = common.font.render("Shoot at your enemey's walls!", True, (0,0,0))
            Phase.__init__(self)
            get_game().field.draw_backbuffer(draw_cannons=False)
            
      def phase_end(self):
            from cannon import Shot
            return self.time_left <= 0 and not get_game().shots

      def cleanup(self):
            get_game().field.draw_backbuffer()


class SelectPhase(Phase):

      phase_name = "select"
      duration = 20

      def __init__(self):

            def select_actions(passed_milliseconds):
                  pygame.time.delay(1)

            self.actions = select_actions
            self.next_phase = lambda: AnnouncePhase(PlacePhase)
            Phase.__init__(self)
            
      def phase_end(self):
            return self.time_left <= 0 or not filter(lambda player: not player.select_player.finished, get_game().players)

      def cleanup(self):
            for player in get_game().players:
                  if not player.select_player.finished:
                        player.select_player.remote_confirm_select()



Generated by  Doxygen 1.6.0   Back to index