all repos — Legends-RPG @ 1cff6e4fd351db22b6f34a35606ee230eef7ccd5

A fantasy mini-RPG built with Python and Pygame.

data/states/battle.py (view raw)

  1"""This is the state that handles battles against
  2monsters"""
  3
  4import random
  5import pygame as pg
  6from .. import tools, battlegui, observer
  7from .. components import person, attack, attackitems
  8from .. import constants as c
  9
 10
 11
 12class Battle(tools._State):
 13    def __init__(self):
 14        super(Battle, self).__init__()
 15
 16    def startup(self, current_time, game_data):
 17        """Initialize state attributes"""
 18        self.current_time = current_time
 19        self.allow_input = False
 20        self.allow_info_box_change = False
 21        self.game_data = game_data
 22        self.background = self.make_background()
 23        self.enemy_group, self.enemy_pos_list = self.make_enemies()
 24        self.player = self.make_player()
 25        self.attack_animations = pg.sprite.Group()
 26        self.info_box = battlegui.InfoBox(game_data)
 27        self.arrow = battlegui.SelectArrow(self.enemy_pos_list,
 28                                           self.info_box)
 29        self.select_box = battlegui.SelectBox()
 30        self.player_health = battlegui.PlayerHealth(self.select_box.rect,
 31                                                    self.game_data)
 32        self.sword = attackitems.Sword(self.player)
 33        self.attacked_enemy = None
 34        self.attacking_enemy = None
 35        self.state = c.SELECT_ACTION
 36        self.select_action_state_dict = self.make_selection_state_dict()
 37        self.name = 'battle'
 38        self.next = game_data['last state']
 39        self.observer = observer.Battle(self)
 40        self.player.observer = self.observer
 41
 42    def make_background(self):
 43        """Make the blue/black background"""
 44        background = pg.sprite.Sprite()
 45        surface = pg.Surface(c.SCREEN_SIZE).convert()
 46        surface.fill(c.BLACK_BLUE)
 47        background.image = surface
 48        background.rect = background.image.get_rect()
 49        background_group = pg.sprite.Group(background)
 50
 51        return background_group
 52
 53    def make_enemies(self):
 54        """Make the enemies for the battle. Return sprite group"""
 55        pos_list  = []
 56
 57        for column in range(3):
 58            for row in range(3):
 59                x = (column * 100) + 100
 60                y = (row * 100) + 100
 61                pos_list.append([x,y])
 62
 63        enemy_group = pg.sprite.Group()
 64
 65        for enemy in range(random.randint(1, 6)):
 66            enemy_group.add(person.Person('devil', 0, 0,
 67                                          'down', 'battle resting'))
 68
 69        for i, enemy in enumerate(enemy_group):
 70            enemy.rect.topleft = pos_list[i]
 71            enemy.image = pg.transform.scale2x(enemy.image)
 72
 73        return enemy_group, pos_list[0:len(enemy_group)]
 74
 75    def make_player(self):
 76        """Make the sprite for the player's character"""
 77        player = person.Player('left', 630, 220, 'battle resting', 1)
 78        player.image = pg.transform.scale2x(player.image)
 79
 80        return player
 81
 82    def make_selection_state_dict(self):
 83        """
 84        Make a dictionary of states with arrow coordinates as keys.
 85        """
 86        pos_list = self.arrow.make_select_action_pos_list()
 87        state_list = [c.SELECT_ENEMY, c.SELECT_ITEM, c.SELECT_MAGIC, c.RUN_AWAY]
 88        return dict(zip(pos_list, state_list))
 89
 90    def update(self, surface, keys, current_time):
 91        """Update the battle state"""
 92        self.check_input(keys)
 93        self.check_if_battle_won()
 94        self.enemy_group.update(current_time)
 95        self.player.update(keys, current_time)
 96        self.attack_animations.update()
 97        self.info_box.update()
 98        self.arrow.update(keys)
 99
100        self.draw_battle(surface)
101
102    def check_input(self, keys):
103        """
104        Check user input to navigate GUI.
105        """
106        if self.allow_input:
107            if keys[pg.K_RETURN]:
108                self.notify(c.END_BATTLE)
109
110            elif keys[pg.K_SPACE]:
111                if self.state == c.SELECT_ACTION:
112                    self.state = self.select_action_state_dict[
113                        self.arrow.rect.topleft]
114                    self.notify(self.state)
115
116                elif self.state == c.SELECT_ENEMY:
117                    self.state = c.PLAYER_ATTACK
118                    self.notify(self.state)
119
120                elif self.state == c.PLAYER_ATTACK:
121                    self.state = c.ENEMY_DEAD
122                    self.info_box.state = c.ENEMY_DEAD
123
124                elif self.state == c.ENEMY_DEAD:
125                    self.state = c.SELECT_ACTION
126                    self.notify(self.state)
127
128                elif self.state == c.SELECT_ITEM or self.state == c.SELECT_MAGIC:
129                    if self.arrow.index == (len(self.arrow.pos_list) - 1):
130                        self.state = c.SELECT_ACTION
131                        self.notify(self.state)
132
133            self.allow_input = False
134
135        if keys[pg.K_RETURN] == False and keys[pg.K_SPACE] == False:
136            self.allow_input = True
137
138    def check_if_battle_won(self):
139        """
140        Check if state is SELECT_ACTION and there are no enemies left.
141        """
142        if self.state == c.SELECT_ACTION:
143            if len(self.enemy_group) == 0:
144                self.notify(c.BATTLE_WON)
145
146    def notify(self, event):
147        """
148        Notify observer of event.
149        """
150        self.observer.on_notify(event)
151
152    def end_battle(self):
153        """
154        End battle and flip back to previous state.
155        """
156        self.game_data['last state'] = self.name
157        self.done = True
158
159    def attack_enemy(self):
160        enemy = self.player.attacked_enemy
161
162        if enemy:
163            enemy.kill()
164            posx = enemy.rect.x - 32
165            posy = enemy.rect.y - 64
166            fire_sprite = attack.Fire(posx, posy)
167            self.attack_animations.add(fire_sprite)
168            self.player.attacked_enemy = None
169
170    def draw_battle(self, surface):
171        """Draw all elements of battle state"""
172        self.background.draw(surface)
173        self.enemy_group.draw(surface)
174        self.attack_animations.draw(surface)
175        surface.blit(self.player.image, self.player.rect)
176        surface.blit(self.info_box.image, self.info_box.rect)
177        surface.blit(self.select_box.image, self.select_box.rect)
178        surface.blit(self.arrow.image, self.arrow.rect)
179        self.player_health.draw(surface)
180        self.sword.draw(surface)
181
182