Example #1
0
class CPUSpinnerController(object):
    """Controls the game clock -- generating an Event for each game tick, and throttling
		the game to limit CPU usage"""
    def __init__(self, maxfps=40):
        self.evManager = EventManager()
        self.evManager.RegisterListener(self)

        self.keepGoing = 1
        self.clock = pygame.time.Clock()
        self.maxfps = maxfps

    def Run(self):
        """Start the game by telling the game clock to go!"""
        while self.keepGoing:
            event = TickEvent(pygame.time.get_ticks(),
                              self.clock.tick(self.maxfps))
            self.evManager.Notify(event)

    def Notify(self, event):
        """handled events:
		Quit Event:
			Stop the clock from ticking (the app will then close)
		"""
        if isinstance(event, QuitEvent):
            #this will stop the while loop from running
            self.keepGoing = 0
Example #2
0
class Game(object):
    """Responsible for setting the stage:
    Namely, making sure that the appropriate Actors exist and know the appropriate things
    """
    __metaclass__ = SingletonType

    STATE_PREPARING = 0
    STATE_RUNNING = 1
    STATE_PAUSED = 2
    STATE_GAMEOVER = 3

    def __init__(self):
        self.evManager = EventManager()
        self.evManager.RegisterListener(self)

        self.state = Game.STATE_PREPARING
        self.heroes = {}
        self.enemies = {}
        self.enemyCount = 0
        self.problem = (0, 0)
        self.time = 0
        self.solutionWait = 5000  #milliseconds
        self.solEndTime = 0

    def Start(self):
        """starts the game action -- spawning any Actors needed, setting required variables
            and generating the GameStartedEvent"""
        self.SpawnHero()
        self.SpawnEnemy()

        self.state = Game.STATE_RUNNING
        self.evManager.Notify(GameStartedEvent(self))

    def SpawnHero(self):
        self.heroes["hero"] = HeroModel("hero", self.enemies)
        self.evManager.Notify(SpawnHeroEvent(self.heroes["hero"].evID))

    def SpawnEnemy(self):
        self.enemyCount += 1
        enemyID = "enemy%s" % self.enemyCount
        self.enemies[enemyID] = EnemyModel(enemyID, self.heroes, self.time)
        self.evManager.Notify(SpawnEnemyEvent(enemyID))

    def myOpponents(self, actor):
        if isinstance(actor, Hero):
            return self.enemies
        elif isinstance(actor, Enemy):
            return self.heroes

    def Notify(self, event):
        """Handled events:
        TickEvent:
            progress the game action by one game tick (currently just starts game
                if it's not already set up)
        DieEvent:
            Actor has died.  If hero, game is over, if (last) enemy, victory is achieved
        NextBattleEvent:
            Player has requested next battle, so spawn an enemy
        """
        if self.state == Game.STATE_GAMEOVER:
            return  #don't do anything if the game is over
        elif self.state == Game.STATE_PREPARING:
            if isinstance(event, TickEvent):
                self.Start()

        if isinstance(event, TickEvent):
            self.time = event.time

        if self.state == Game.STATE_RUNNING:
            if isinstance(event, DieEvent):
                if event.subject in self.heroes.keys():
                    self.state = Game.STATE_GAMEOVER
                    self.evManager.Notify(GameOverEvent())
                    #del self.heroes[event.subject]
                elif event.subject in self.enemies.keys():
                    self.evManager.Notify(VictoryEvent())
                    del self.enemies[event.subject]
            elif isinstance(event, NextBattleEvent):
                self.SpawnEnemy()
Example #3
0
class KeyboardController(object):
    """Takes input from the keboard and translates that into game Events to trigger action
		in the rest of the system"""
    STATE_ACTION = 0
    STATE_SOLVE = 1
    STATE_VICTORY = 2

    def __init__(self):
        self.evManager = EventManager()
        self.evManager.RegisterListener(self)
        self.state = KeyboardController.STATE_ACTION
        self.solution = ""
        self.solveTime = 0

    def Notify(self, event):
        """Takes mostly keyboard inputs and generates events based on state.
		STATE_ACTION: Generic state -- basically just waiting for player to attack
			RequestSolutionEvent:
				Change state to STATE_SOLVE
			TickEvent:
				Check to see if game is quit or attack is requested based on key presses
		STATE_VICTORY: Player has defeated all enemies (waiting for next battle)
		STATE_SOLVE: Player has attacked, and is in the process of entering the solution
			SolveEvent:
				Attack has completed, change state back to STATE_ACTION and reset solution
			TickEvent:
				Listen for any key presses (quit, numbers, delete, submit) and update appropriately
		"""
        events = []  #events to be raised at the end if necessary

        #always quit (regardless of state)
        if isinstance(event, TickEvent):
            pgEventList = pygame.event.get()
            for pgEvent in pgEventList:
                if pgEvent.type == QUIT:
                    events.append(QuitEvent())
                elif pgEvent.type == KEYDOWN:
                    if pgEvent.key == K_ESCAPE:
                        events.append(QuitEvent())
        #always switch to victory state (regardless of current state)
        elif isinstance(event, VictoryEvent):
            print "controller victory"
            self.state = KeyboardController.STATE_VICTORY

        if self.state == KeyboardController.STATE_ACTION:
            if isinstance(event, RequestSolutionEvent):
                self.state = KeyboardController.STATE_SOLVE
            elif isinstance(event, TickEvent):
                #Handle Input Events
                for pgEvent in pgEventList:
                    if pgEvent.type == KEYDOWN:
                        if pgEvent.key == K_SPACE:
                            events.append(RequestAttackEvent())

        elif self.state == KeyboardController.STATE_SOLVE:
            if isinstance(event, SolveEvent):
                self.state = KeyboardController.STATE_ACTION
                self.solution = ""
            elif isinstance(event, TickEvent):
                for pgEvent in pgEventList:
                    if pgEvent.type == KEYDOWN:
                        if pgEvent.unicode in u'0123456789':  #typed a digit
                            self.solution += pgEvent.unicode
                            events.append(SolutionUpdateEvent(self.solution))
                        elif pgEvent.key == K_BACKSPACE:
                            self.solution = self.solution[:-1]
                            events.append(SolutionUpdateEvent(self.solution))
                        elif pgEvent.key in (K_RETURN, K_KP_ENTER):
                            events.append(SolveEvent(self.solution))

        elif self.state == KeyboardController.STATE_VICTORY:
            if isinstance(event, TickEvent):
                for pgEvent in pgEventList:
                    if pgEvent.type == KEYDOWN:
                        if pgEvent.key == K_SPACE:
                            events.append(NextBattleEvent())
                            self.state = KeyboardController.STATE_ACTION
        for ev in events:
            self.evManager.Notify(ev)
Example #4
0
class ActorModel(object):
    """Generic class for anything 'alive' -- namely anything that can be involved in combat
    Tracks the following data:
        * Current state of Actor (Waiting, Attacking, Defending, Hurting or Dead)
        * The amount of time that should be spent in the various states
        * The current and maximum amount of health the Actor has
    """
    STATE_WAITING = 0
    STATE_ATTACKING = 1
    STATE_DEFENDING = 2
    STATE_HURTING = 3
    STATE_DEAD = 4

    def __init__(self, evID, opponents):
        self.evManager = EventManager()
        self.evManager.RegisterListener(self)
        self.evID = evID
        self.opponents = opponents
        self.victim = None

        self.state = ActorModel.STATE_WAITING

        self.AttackWait = 300  #milliseconds
        self.HurtWait = 200  #milliseconds
        self.time = 0
        self.AttackEndTime = self.time
        self.HurtEndTime = self.time

        self.maxHealth = 100
        self.health = self.maxHealth

        self.attackPower = 0  # to be defined in subclasses

    def Wait(self):
        """Sets Actor's current state to waiting (neutral)"""
        self.state = ActorModel.STATE_WAITING
        event = WaitEvent(self.evID)
        self.evManager.Notify(event)

    def nextVictim(self):
        """Determines next victim from list of known opponents"""
        victims = self.opponents.keys()
        Debug("available victims: %s" % victims, 5)
        if len(victims) == 0 or self.victim not in victims:
            self.victim = None
        for a in (
                1, 2
        ):  #search list twice to wrap, since current victim might be last opponent in list
            for v in victims:
                if self.victim == None:
                    self.victim = v
                    return
                if v == self.victim:
                    self.victim = None  #will set victim and return on next go-round

    def Attack(self, damage):
        """Sets Actor's current state to attacking -- and hurts victim based on given damage value"""
        if self.state == ActorModel.STATE_WAITING:
            self.state = ActorModel.STATE_ATTACKING
            self.AttackEndTime = self.time + self.AttackWait

            self.nextVictim(
            )  #currently there is no targeting system -- so just pick the next opponent in line
            Debug("victim %s has been chosen" % self.victim, 5)
            event = AttackEvent(self.evID, self.victim, damage)
            self.evManager.Notify(event)

    def Defend(self):
        """Sets Actor's current state do defending (not yet used)"""
        if self.state == ActorModel.STATE_WAITING:
            self.state = ActorModel.STATE_DEFENDING
            event = DefendEvent(self.evID)
            self.evManager.Notify(event)

    def Hurt(self, damage):
        """Sets Actors current state to hurting and deducts damage from health"""
        self.state = ActorModel.STATE_HURTING
        self.HurtEndTime = self.time + self.HurtWait

        if self.health >= 0:
            self.health -= damage
        if self.health < 0:
            self.health = 0

        event = HurtEvent(self.evID, 1.0 * self.health / self.maxHealth)
        self.evManager.Notify(event)

        if self.health == 0:
            self.Die()

    def Die(self):
        """Sets Actor's current state to dead"""
        self.state = ActorModel.STATE_DEAD

        event = DieEvent(self.evID)
        self.evManager.Notify(event)
        self.evManager.UnregisterListener(self)

    def Notify(self, event):
        """Handles the following events:
        TickEvent:
            verify whether actor is currently still attacking or hurting based on 
                duration values for these states
        HurtEvent:
            if this actor is being attacked, call hurt
        """
        if isinstance(event, TickEvent):
            self.time = event.time
            #ready to stop attacking
            if self.state == ActorModel.STATE_ATTACKING and self.AttackEndTime <= self.time:
                self.Wait()
            if self.state == ActorModel.STATE_HURTING and self.HurtEndTime <= self.time:
                self.Wait()
        elif isinstance(event, AttackEvent) and event.object == self.evID:
            self.Hurt(event.damage)