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