all repos — Legends-RPG @ 680235e09a98538dcc6f7165b3f8186889ed6ba5

A fantasy mini-RPG built with Python and Pygame.

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