data/tools.py (view raw)
1__author__ = 'justinarmstrong'
2
3import os, random
4import pygame as pg
5from . import constants as c
6
7class Control(object):
8 """
9 Control class for entire project. Contains the game loop, and contains
10 the event_loop which passes events to States as needed. Logic for flipping
11 states is also found here.
12 """
13 def __init__(self, caption):
14 self.screen = pg.display.get_surface()
15 self.done = False
16 self.clock = pg.time.Clock()
17 self.caption = caption
18 self.fps = 60
19 self.show_fps = False
20 self.current_time = 0.0
21 self.keys = pg.key.get_pressed()
22 self.state_dict = {}
23 self.state_name = None
24 self.state = None
25
26 def setup_states(self, state_dict, start_state):
27 self.state_dict = state_dict
28 self.state_name = start_state
29 self.state = self.state_dict[self.state_name]
30 self.set_music()
31
32 def update(self):
33 self.current_time = pg.time.get_ticks()
34 if self.state.quit:
35 self.done = True
36 elif self.state.done:
37 self.flip_state()
38 self.state.update(self.screen, self.keys, self.current_time)
39
40 def flip_state(self):
41 previous, self.state_name = self.state_name, self.state.next
42 previous_music = self.state.music_title
43 persist = self.state.cleanup()
44 self.state = self.state_dict[self.state_name]
45 self.state.previous = previous
46 self.state.previous_music = previous_music
47 self.state.startup(self.current_time, persist)
48 self.set_music()
49
50 def set_music(self):
51 """
52 Set music for the new state.
53 """
54 if self.state.music_title == self.state.previous_music:
55 pass
56 elif self.state.music:
57 pg.mixer.music.load(self.state.music)
58 pg.mixer.music.set_volume(self.state.volume)
59 pg.mixer.music.play(-1)
60
61 def event_loop(self):
62 self.events = pg.event.get()
63
64 for event in self.events:
65 if event.type == pg.QUIT:
66 self.done = True
67 elif event.type == pg.KEYDOWN:
68 if event.key == pg.K_ESCAPE:
69 self.done = True
70 self.keys = pg.key.get_pressed()
71 self.toggle_show_fps(event.key)
72 self.state.get_event(event)
73 elif event.type == pg.KEYUP:
74 self.keys = pg.key.get_pressed()
75 self.state.get_event(event)
76
77 def toggle_show_fps(self, key):
78 if key == pg.K_F5:
79 self.show_fps = not self.show_fps
80 if not self.show_fps:
81 pg.display.set_caption(self.caption)
82
83 def main(self):
84 """Main loop for entire program"""
85 while not self.done:
86 self.event_loop()
87 self.update()
88 pg.display.update()
89 self.clock.tick(self.fps)
90 if self.show_fps:
91 fps = self.clock.get_fps()
92 with_fps = "{} - {:.2f} FPS".format(self.caption, fps)
93 pg.display.set_caption(with_fps)
94
95
96class _State(object):
97 """Base class for all game states"""
98 def __init__(self):
99 self.start_time = 0.0
100 self.current_time = 0.0
101 self.done = False
102 self.quit = False
103 self.next = None
104 self.previous = None
105 self.game_data = {}
106 self.music = None
107 self.music_title = None
108 self.previous_music = None
109
110 def get_event(self, event):
111 pass
112
113 def startup(self, current_time, game_data):
114 self.game_data = game_data
115 self.start_time = current_time
116
117 def cleanup(self):
118 self.done = False
119 return self.game_data
120
121 def update(self, surface, keys, current_time):
122 pass
123
124
125def load_all_gfx(directory, colorkey=(255,0,255), accept=('.png', 'jpg', 'bmp')):
126 graphics = {}
127 for pic in os.listdir(directory):
128 name, ext = os.path.splitext(pic)
129 if ext.lower() in accept:
130 img = pg.image.load(os.path.join(directory, pic))
131 if img.get_alpha():
132 img = img.convert_alpha()
133 else:
134 img = img.convert()
135 img.set_colorkey(colorkey)
136 graphics[name] = img
137 return graphics
138
139
140def load_all_music(directory, accept=('.wav', '.mp3', '.ogg', '.mdi')):
141 songs = {}
142 for song in os.listdir(directory):
143 name, ext = os.path.splitext(song)
144 if ext.lower() in accept:
145 songs[name] = os.path.join(directory, song)
146 return songs
147
148
149def load_all_fonts(directory, accept=('.ttf')):
150 return load_all_music(directory, accept)
151
152
153def load_all_tmx(directory, accept=('.tmx')):
154 return load_all_music(directory, accept)
155
156
157def load_all_sfx(directory, accept=('.wav','.mp3','.ogg','.mdi')):
158 effects = {}
159 for fx in os.listdir(directory):
160 name, ext = os.path.splitext(fx)
161 if ext.lower() in accept:
162 effects[name] = pg.mixer.Sound(os.path.join(directory, fx))
163 return effects
164
165
166def get_image(x, y, width, height, sprite_sheet):
167 """Extracts image from sprite sheet"""
168 image = pg.Surface([width, height])
169 rect = image.get_rect()
170
171 image.blit(sprite_sheet, (0, 0), (x, y, width, height))
172 image.set_colorkey(c.BLACK)
173
174 return image
175
176def get_tile(x, y, tileset, width=16, height=16, scale=1):
177 """Gets the surface and rect for a tile"""
178 surface = get_image(x, y, width, height, tileset)
179 surface = pg.transform.scale(surface, (int(width*scale), int(height*scale)))
180 rect = surface.get_rect()
181
182 tile_dict = {'surface': surface,
183 'rect': rect}
184
185 return tile_dict
186
187def notify_observers(self, event):
188 """
189 Notify all observers of events.
190 """
191 for each_observer in self.observers:
192 each_observer.on_notify(event)
193
194def create_game_data_dict():
195 """Create a dictionary of persistant values the player
196 carries between states"""
197
198 player_items = {'GOLD': dict([('quantity',100),
199 ('value',0)]),
200 'Healing Potion': dict([('quantity',2),
201 ('value',15)]),
202 'Ether Potion': dict([('quantity',1),
203 ('value', 15)]),
204 'Rapier': dict([('quantity', 1),
205 ('value', 50),
206 ('power', 9)]),
207 'equipped weapon': 'Rapier',
208 'equipped armor': []}
209
210 player_health = {'current': 0,
211 'maximum': 70}
212
213 player_magic = {'current': 70,
214 'maximum': 70}
215
216 player_stats = {'health': player_health,
217 'Level': 1,
218 'experience to next level': 30,
219 'magic': player_magic,
220 'attack points': 10,
221 'Defense Points': 10}
222
223
224 data_dict = {'last location': None,
225 'last state': None,
226 'last direction': 'down',
227 'king item': 'GOLD',
228 'old man item': {'ELIXIR': dict([('value',1000),
229 ('quantity',1)])},
230 'player inventory': player_items,
231 'player stats': player_stats,
232 'battle counter': random.randint(50, 255),
233 'treasure1': True,
234 'treasure2': True,
235 'treasure3': True,
236 'treasure4': True,
237 'treasure5': True,
238 'talked to king': False,
239 'brother quest complete': False,
240 'talked to sick brother': False,
241 'has brother elixir': False,
242 'elixir received': False,
243 'old man gift': '',
244 'battle type': '',
245 'crown quest': False,
246 'delivered crown': False,
247 'brother item': 'ELIXIR'
248 }
249
250 return data_dict
251
252
253
254
255
256
257