def __init__(self): self.loader = AssetLoader('images') self.control_loader = AssetLoader(join('images', 'controls')) self.background_img = self.loader.load_image('background.png') self.title_surf = self.loader.load_image_alpha( ControlSettings.TITLE_IMAGE_PATH) self.title_rect = self.title_surf.get_rect() self.title_rect.centerx = Globals.WIDTH / 2 self.title_rect.top = ControlSettings.TITLE_MARGIN_TOP self.arrows_top = self.title_rect.bottom + \ ControlSettings.TITLE_ARROW_MARGIN self.arrows_x_center = int(Globals.WIDTH / 4) self.text_top = self.title_rect.bottom + \ ControlSettings.TITLE_TEXT_MARGIN self.surf_rect_pairs = [ SurfRectPair() for i in range(0, ControlSettings.NUM_OPTIONS) ] self.surf_index = [ ControlSettings.SURF_INDEX_NORMAL for i in range(0, ControlSettings.NUM_OPTIONS) ] self.last_surf_index = [ ControlSettings.SURF_INDEX_NORMAL for i in range(0, ControlSettings.NUM_OPTIONS) ] self.ignore_index = [0 for i in range(0, ControlSettings.NUM_OPTIONS)] self.load_control_images() self.selection = 0 self.set_selection(0)
def __init__(self, definition_path, map_path, globals=Globals, in_game=False): self.globals = globals self.actions = list() self.browser = None self.message_time = 0 self.message_surf = None self.message_rect = None self.key_code = None self.mouse_down = False self.info_mode = False self.delete_mode = False self.in_game = in_game loader = AssetLoader(join("images", "tiles")) TileType.create_empty(loader) self.base_image = loader.load_image("transparent.png") self.base_rect = self.base_image.get_rect() self.definition_path = definition_path self.map_path = map_path self.tile_engine = TileEngine(self.definition_path, self.map_path) self.combo_tile_manager = TileManager(LevelEditor.COMBO_DEF_PATH, None) self.tile_rect = self.tile_engine.get_tile_rect() self.right_padding = self.tile_rect.width * \ LevelEditor.RIGHT_PADDING_FACTOR self.shift_factor = self.tile_rect.width self.init_camera() self.init_highlight() self.init_title() self.init_browser() self.init_second_title() self.init_combo_browser() self.in_combo = False
def __init__(self): self.loader = AssetLoader('images') self.control_loader = AssetLoader(join('images', 'controls')) self.background_img = self.loader.load_image('background.png') self.title_surf = self.loader.load_image_alpha( ControlSettings.TITLE_IMAGE_PATH) self.title_rect = self.title_surf.get_rect() self.title_rect.centerx = Globals.WIDTH / 2 self.title_rect.top = ControlSettings.TITLE_MARGIN_TOP self.arrows_top = self.title_rect.bottom + \ ControlSettings.TITLE_ARROW_MARGIN self.arrows_x_center = int(Globals.WIDTH / 4) self.text_top = self.title_rect.bottom + \ ControlSettings.TITLE_TEXT_MARGIN self.surf_rect_pairs = [SurfRectPair() for i in range(0, ControlSettings.NUM_OPTIONS)] self.surf_index = [ControlSettings.SURF_INDEX_NORMAL for i in range( 0, ControlSettings.NUM_OPTIONS)] self.last_surf_index = [ ControlSettings.SURF_INDEX_NORMAL for i in range(0, ControlSettings.NUM_OPTIONS)] self.ignore_index = [0 for i in range(0, ControlSettings.NUM_OPTIONS)] self.load_control_images() self.selection = 0 self.set_selection(0)
def loadResources(self): loader = AssetLoader('images') if BossEnemy.walking_images[Enemy.INDEX_DOWN] is None: path = os.path.join( BossEnemy.WALKING_PATH, BossEnemy.WALKING_DOWN_PATH) prefix_path = os.path.join( BossEnemy.PREFIX_PATH, BossEnemy.WALKING_DOWN_PATH) fM = FileManager(path, file_ext='.png', create_dir=False) BossEnemy.walking_images[Enemy.INDEX_DOWN] = \ loader.load_images(fM.get_files(prefix_path=prefix_path)) if BossEnemy.walking_images[Enemy.INDEX_UP] is None: path = os.path.join( BossEnemy.WALKING_PATH, BossEnemy.WALKING_UP_PATH) prefix_path = os.path.join( BossEnemy.PREFIX_PATH, BossEnemy.WALKING_UP_PATH) fM = FileManager(path, file_ext='.png', create_dir=False) BossEnemy.walking_images[Enemy.INDEX_UP] = \ loader.load_images(fM.get_files(prefix_path=prefix_path)) if BossEnemy.walking_images[Enemy.INDEX_LEFT] is None: path = os.path.join( BossEnemy.WALKING_PATH, BossEnemy.WALKING_LEFT_PATH) prefix_path = os.path.join( BossEnemy.PREFIX_PATH, BossEnemy.WALKING_LEFT_PATH) fM = FileManager(path, file_ext='.png', create_dir=False) BossEnemy.walking_images[Enemy.INDEX_LEFT] = \ loader.load_images(fM.get_files(prefix_path=prefix_path)) if BossEnemy.walking_images[Enemy.INDEX_RIGHT] is None: path = os.path.join( BossEnemy.WALKING_PATH, BossEnemy.WALKING_RIGHT_PATH) prefix_path = os.path.join( BossEnemy.PREFIX_PATH, BossEnemy.WALKING_RIGHT_PATH) fM = FileManager(path, file_ext='.png', create_dir=False) BossEnemy.walking_images[Enemy.INDEX_RIGHT] = \ loader.load_images(fM.get_files(prefix_path=prefix_path))
def load(self): self.mapCursor = [0, 0] loader = AssetLoader() self.maps = {} self.mapsData = {} areasConfig = loader.getConfig(Globals.AreasConfigPath) for area in areasConfig: self.maps[area] = loader.getMap(areasConfig[area]['inAreaMap']) self.mapsData[area] = {} roomsConfig = loader.getConfig(areasConfig[area]['roomsConfig']) for room in roomsConfig: # mapsData maps string area id * string room id -> # [0] string readable name of room # [1] string description of room # [2] int row number of room's tile on map # [3] int col number of room's tile on map # [4] string conditional if conditions must be fulfilled to show room, else None self.mapsData[area][room] = ( roomsConfig[room]['mapName'] if 'mapName' in roomsConfig[room] \ else roomsConfig[room]['name'], roomsConfig[room]['description'], roomsConfig[room]['r'], roomsConfig[room]['c'], roomsConfig[room]['showIf'] if 'showIf' in roomsConfig[room] else None, )
def __init__(self, container, max_value=100, value=None): self.container = container self.max_value = max_value self.value = value if value is not None else self.max_value self.loader = AssetLoader('images') self.init_slider() self.init_arrows() self.selected = False
def play_menu_sound(): if Globals.MENU_SOUND is None: loader = AssetLoader(sound_path_start='sounds') Globals.MENU_SOUND = loader.load_sound('menu_music.ogg') if Globals.PLAYING_MENU_SOUND: return Globals.MENU_SOUND.play(loops=-1) Globals.PLAYING_MENU_SOUND = True
def __init__(self, image_surf, list_index, return_state): self.list_index = list_index self.return_state = return_state self.image_surf = image_surf self.loader = AssetLoader('images') self.image_rect = self.image_surf.get_rect() self.image_rect.center = Globals.SCREEN.get_rect().center self.init_images()
def refreshOptions(self): # Check if New Game or Load Game options are visible self.freeFileInd = AssetLoader().freeSaveFileInd() self.blockedOptions = [] if self.freeFileInd < 0: self.blockedOptions.append(0) # remove 'new game' if AssetLoader().lenSaveFiles() == 0: self.blockedOptions.append(1) # remove 'load game' self.resetCursor()
def initAssets(self): AssetLoader().loadAssets() AssetLoader().loadSaves() AssetLoader().loadSettings() # send events for loaded settings if AssetLoader().getSettings() is not None: for setting in AssetLoader().getSettings(): GameState().onSettingChange(setting[0], setting[1]) self.windowManager.load() GameState().unlockGameMode()
def draw(self): self.clear() # draw the header text header = 'Select which file?' if not self.inDeleteMode else 'Delete which file?' rHeader = 1 cHeader = (self.width - len(header)) // 2 for c, ch in enumerate(header): self.pixels[rHeader][cHeader + c] = ch # draw the option text cOption = (self.width - len(self.otherOptions[0])) // 2 for i, optionText in enumerate(self.otherOptions): row = self.height - self.marginRows + i text = optionText if optionText == 'Delete File': # the delete option changes text text = 'Delete File' if not self.inDeleteMode else 'Cancel Delete' for c, ch in enumerate(text): self.pixels[row][cOption + c] = ch # draw the loaded file info cFile = self.width // 4 for i, finfo in enumerate(self.fileinfo): if finfo is None: continue name = finfo['name'] playtime = int(finfo['playtime']) ind = finfo['activeProtagonistInd'] substate = finfo['subStates'][ind] areasConfig = AssetLoader().getConfig(Globals.AreasConfigPath) roomsConfig = AssetLoader().getConfig(areasConfig[substate['areaId']]['roomsConfig']) timeStr = '{:02}:{:02}:{:02}'.format(playtime // 3600, (playtime % 3600) // 60, (playtime % 60)) progressStr = '{}.{}.{}'.format('Lore' if ind == 0 else 'Kipp', areasConfig[substate['areaId']]['name'], roomsConfig[substate['roomId']]['mapName'] \ if 'mapName' in roomsConfig[substate['roomId']] else roomsConfig[substate['roomId']]['name']) infoStr = name + (' ' * (16 - len(name))) \ + timeStr + (' ' * (16 - len(timeStr))) \ + progressStr for j, ch in enumerate(infoStr): self.pixels[self.rowNum(i)][cFile + j] = ch # add strikethrough for deletion if self.inDeleteMode and i == self.pointingTo: self.formatting = [('overstrike', (self.rowNum(i)*self.width + cFile, self.rowNum(i)*self.width + cFile + len(infoStr) - 1))] # draw the cursor if self.pointingTo < len(self.fileinfo): cursorCol = cFile - 2 self.pixels[self.rowNum(self.pointingTo)][cursorCol] = ">" else: row = self.height - self.marginRows + self.pointingTo - len(self.fileinfo) cursorCol = cOption - 2 self.pixels[row][cursorCol] = ">" return self.pixels
def __init__(self, width, height): super().__init__(width, height) mapslst = Globals.MapsPaths loader = AssetLoader() self.maps = [] self.colorMasks = [] self.travelMasks = [] # TODO move to a load method for threetup in mapslst: self.maps.append(loader.getMap(threetup[0]).splitlines()) self.colorMasks.append(loader.getMap(threetup[1]).splitlines()) self.travelMasks.append(loader.getMap(threetup[2]).splitlines())
def load(self): artslst = Globals.InAreaPaths loader = AssetLoader() self.maps = [] self.details = [] self.names = [] for element in artslst: self.maps.append(loader.getMap(element[0])) self.details.append( loader.getConfig(os.path.join('rooms', element[1]))) for item in self.details[0]: self.names.append(item)
def _enterAreaHandler(*args, **kwargs): # run the startup script for an area (_, areaId), (_, roomId), fromWorldMap = args[0], args[1], args[2] startupverb = '_enter' if fromWorldMap else '_awake' areasConfig = AssetLoader().getConfig(Globals.AreasConfigPath) roomsConfig = AssetLoader().getConfig( areasConfig[areaId]['roomsConfig']) roomScript = AssetLoader().getScript(roomsConfig[roomId]['script']) for verb, action, _ in roomScript: if verb == startupverb: self.interpreter.executeAction(action) break
def __init__(self): Globals.INTRO_SOUND_PLAYED = False self.file_name = "" self.error_message = None self.loader = AssetLoader('images') self.setup_text() self.show_extra = False self.extra_time = 0 Globals.play_menu_sound() self.background_img = self.loader.load_image('background.png') self.file_manager = FileManager( path=CustomLevelNameInput.CUSTOM_MAP_PATH, file_ext=CustomLevelNameInput.MAP_FILE_EXT)
def __init__(self): self.loader = AssetLoader('images') self.background_img = self.loader.load_image('background.png') Globals.play_menu_sound() self.title_surf = self.loader.load_image_alpha( SettingsState.TITLE_IMAGE_PATH) self.title_rect = self.title_surf.get_rect() self.title_rect.centerx = Globals.WIDTH / 2 self.title_rect.top = SettingsState.TITLE_MARGIN_TOP self.control_index = 0 self.init_labels() self.init_sliders() self.selected = 0
def bootstrap(): """Perform all processes needed to start up the game""" AssetLoader().loadAssets() # TODO do in separate thread # TODO move out of bootstrap from game_state import GameState, GameMode from lang_interpreter import Interpreter GameState().areaId = 'aspire' GameState().roomId = 'townCenter' GameState().gameMode = GameMode.inAreaCommand Interpreter().executeAction(AssetLoader().getScript('aspire/Rooms/town center.txt')[0][1]) GameState().refreshCommandList() GameDriver().mainloop()
def init_images(self): self.loader = AssetLoader('images') self.background_img = self.loader.load_image('background.png') self.title_surf = self.loader.load_image_alpha( CustomLevelPicker.TITLE_IMAGE_PATH) self.title_rect = self.title_surf.get_rect() self.title_rect.center = Globals.SCREEN.get_rect().center self.title_rect.top = CustomLevelPicker.TITLE_MARGIN_TOP self.arrow_down_surf = self.loader.load_image_alpha('arrow_down.png') self.arrow_down_rect = self.arrow_down_surf.get_rect() self.arrow_up_surf = self.loader.load_image_alpha('arrow_up.png') self.arrow_up_rect = self.arrow_up_surf.get_rect() self.arrow_up_rect.centerx = Globals.WIDTH / 2 self.arrow_down_rect.centerx = Globals.WIDTH / 2
def load(self): settings = AssetLoader().getSettings() if settings is not None: for setting in settings: if setting[0] == 'fontSize': self.optionIndices[0] = setting[1] elif setting[0] == 'scrollSpeed': self.optionIndices[1] = setting[1] elif setting[0] == 'styledText': self.optionIndices[2] = setting[1] for row, (option, values) in enumerate(self.options): col = self.startCol # Draw the option names (eg Font size) for char in option + ': ': self.pixels[self.rowNum(row)][col] = char col += 1 self.optionPositions.append([]) # Draw the individual option values for value in values: self.optionPositions[row].append(col) for char in value + ' ': self.pixels[self.rowNum(row)][col] = char col += 1 footer = '[Return] to exit' for c, ch in enumerate(footer): self.pixels[self.height - self.marginRows][(self.width - len(footer)) // 2 + c] = ch
def update(self, timestep, keypresses): def updateCursor(delta): while True: self.pointingTo = (self.pointingTo + delta) % ( len(self.fileinfo) + len(self.otherOptions)) if self.pointingTo >= len(self.fileinfo) or self.fileinfo[ self.pointingTo] is not None: break for key in keypresses: if key == "Up": updateCursor(-1) elif key == "Down": updateCursor(1) elif key == "Return": if self.pointingTo < len(self.fileinfo): if not self.inDeleteMode: GameState().load(self.fileinfo[self.pointingTo]) GameState().saveId = self.pointingTo GameState().gameMode = GameMode.inAreaCommand else: AssetLoader().deleteSave(self.pointingTo) self.fileinfo[self.pointingTo] = None self.inDeleteMode = False updateCursor(1) else: option = self.otherOptions[self.pointingTo - len(self.fileinfo)] if option == 'Delete File': self.inDeleteMode = not self.inDeleteMode self.resetCursor() elif option == 'Go Back': GameState().gameMode = GameMode.titleScreen break
def __init__(self, x, y, left, left_img_path, right_img_path): super(Syringe, self).__init__() self.health_effect = 0 self.left = left self.velocity = Syringe.VELOCITY # if random.random() <= Syringe.BURST_PROB: # self.velocity = Syringe.BURST_VELOCITY if self.left: self.velocity *= -1 self.loader = AssetLoader("images") self.is_dead = False if left: self.image = self.loader.load_image_alpha(left_img_path) else: self.image = self.loader.load_image_alpha(right_img_path) self.init_rect(self.image.get_rect(), x, y)
def __init__(self, definition_path, map_path, init_music_path=None, music_path=None, music_loops=-1, has_timer=True, should_fade_in=True, mid=0): self.has_timer = has_timer self.keyCode = None self.definition_path = definition_path self.map_path = map_path self.tile_engine = TileEngine( join(Level.MAP_BASE, definition_path), join(Level.MAP_BASE, map_path) ) self.camera = Camera(self.tile_engine, pygame.Rect( 0, 0, Globals.WIDTH, Globals.HEIGHT)) self.tile_rect = self.tile_engine.get_tile_rect() self.enemySprites = pygame.sprite.Group() self.playerSprites = pygame.sprite.Group() self.turrets = list() self.lights = list() self.init_player() self.init_enemies() self.timer = None if Globals.HEALTH_BAR is None: Globals.HEALTH_BAR = HealthBar() if Globals.HUD_MANAGER is None: Globals.HUD_MANAGER = HUDManager() self.black_surf = pygame.Surface( (Globals.WIDTH, Globals.HEIGHT)).convert() self.black_surf.fill((0, 0, 0)) self.fade_in = False self.fade_out = False self.showing_subtitle = False self.alpha_factor = 300 self.should_fade_in = should_fade_in self.pausing = False self.going_back = False self.score_counted = False self.respawn_coords = [-1, -1] self.timer = None self.first_occur = True self.find_respawn() self.loader = AssetLoader('images', 'sounds') self.switch_sound = self.loader.load_sound(Level.SWITCH_SOUND_PATH) self.channel = None self.music_loops = music_loops self.music_handle = None if music_path is not None: self.background_music_handle = self.loader.load_sound(music_path) self.music_handle = self.background_music_handle else: self.background_music_handle = None if init_music_path is not None: self.init_music_handle = self.loader.load_sound(init_music_path) self.music_handle = self.init_music_handle else: self.init_music_handle = None self.time_init = 0 self.start_on_stop = True self.switched_sound = False self.music_end_id = Level.MUSIC_END_ID_BASE + mid self.can_open_doors = True
def update(self, timestep, keypresses): """ sends update signal to Windows in the active group """ # scan for the fullscreen key to change the mode for key in keypresses: if key == 'F11': self.fullScreen = 1 - self.fullScreen GameState().onSettingChange('fullScreen', self.fullScreen) # if in transition mode, freeze update calls if self.isTransitioning: self.transitionTimer += timestep if self.transitionTimer >= self.transitionThreshold: self.transitionTimer = 0.0 self.isTransitioning = False self.alphaLevel = 0 self.clear() if self.resetOnTransitionComplete: # reload save files AssetLoader().loadSaves() self.refresh() self.resetOnTransitionComplete = False return # update the playtime clock GameState().incPlaytime(timestep) # update is only sent to activeWindowGroups[-1], so the foreground windows for winind in self.windowGroups[self.activeWindowGroups[-1]]: self.windowList[winind].update(timestep, keypresses)
def update(self, timestep, keypresses): def camelCase(s): x = ''.join([word.capitalize() for word in s.split()]) return x[0].lower() + x[1:] def packSettings(): obj = [] for i in range(len(self.options)): obj.append( (camelCase(self.options[i][0]), self.optionIndices[i])) return obj def changeSetting(delta): self.optionIndices[self.pointingTo] = (self.optionIndices[self.pointingTo] + delta) \ % len(self.options[self.pointingTo][1]) option = camelCase(self.options[self.pointingTo][0]) GameState().onSettingChange(option, self.optionIndices[self.pointingTo]) for key in keypresses: if key == "Up": self.pointingTo = (self.pointingTo - 1) % len(self.options) elif key == "Down": self.pointingTo = (self.pointingTo + 1) % len(self.options) elif key == "Left": changeSetting(-1) elif key == "Right": changeSetting(1) elif key in [" ", "Return", "BackSpace"]: AssetLoader().writeSettings(packSettings()) # creates a file GameState().gameMode = GameMode.titleScreen
class Syringe(pygame.sprite.Sprite): NEGATIVE_MARGIN = 10 VELOCITY = 200 BURST_VELOCITY = 300 BURST_PROB = .2 def __init__(self, x, y, left, left_img_path, right_img_path): super(Syringe, self).__init__() self.health_effect = 0 self.left = left self.velocity = Syringe.VELOCITY # if random.random() <= Syringe.BURST_PROB: # self.velocity = Syringe.BURST_VELOCITY if self.left: self.velocity *= -1 self.loader = AssetLoader("images") self.is_dead = False if left: self.image = self.loader.load_image_alpha(left_img_path) else: self.image = self.loader.load_image_alpha(right_img_path) self.init_rect(self.image.get_rect(), x, y) def init_rect(self, rect, x, y): self.rect = rect if self.left: self.rect.right = x + Syringe.NEGATIVE_MARGIN else: self.rect.left = x - Syringe.NEGATIVE_MARGIN self.rect.centery = y def move(self, x_delta, y_delta): self.rect.x += x_delta self.rect.y += y_delta def kill(self): self.is_dead = True def update(self, time, camera): self.rect.x += time * self.velocity radius = max(self.rect.size) * 1.5 solid_tiles = camera.get_solid_tiles(self.rect.center, radius) solid_rects = [pair.rect for pair in solid_tiles] collide_rects = self.rect.collidelistall(solid_rects) if len(collide_rects) > 0: self.kill()
class Syringe (pygame.sprite.Sprite): NEGATIVE_MARGIN = 10 VELOCITY = 200 BURST_VELOCITY = 300 BURST_PROB = .2 def __init__(self, x, y, left, left_img_path, right_img_path): super(Syringe, self).__init__() self.health_effect = 0 self.left = left self.velocity = Syringe.VELOCITY # if random.random() <= Syringe.BURST_PROB: # self.velocity = Syringe.BURST_VELOCITY if self.left: self.velocity *= -1 self.loader = AssetLoader("images") self.is_dead = False if left: self.image = self.loader.load_image_alpha(left_img_path) else: self.image = self.loader.load_image_alpha(right_img_path) self.init_rect(self.image.get_rect(), x, y) def init_rect(self, rect, x, y): self.rect = rect if self.left: self.rect.right = x + Syringe.NEGATIVE_MARGIN else: self.rect.left = x - Syringe.NEGATIVE_MARGIN self.rect.centery = y def move(self, x_delta, y_delta): self.rect.x += x_delta self.rect.y += y_delta def kill(self): self.is_dead = True def update(self, time, camera): self.rect.x += time * self.velocity radius = max(self.rect.size) * 1.5 solid_tiles = camera.get_solid_tiles(self.rect.center, radius) solid_rects = [pair.rect for pair in solid_tiles] collide_rects = self.rect.collidelistall(solid_rects) if len(collide_rects) > 0: self.kill()
def load(self): self.fileinfo = [] for path in Globals.SavePaths: obj = AssetLoader().getSave(path) if obj: self.fileinfo.append(obj) else: self.fileinfo.append(None) self.resetCursor()
def __init__(self, definitionPath, mapPath): self.loader = AssetLoader(path.join("images", "tiles")) # self.tileDefinitions = list() self.definitionPath = definitionPath self.mapPath = mapPath self.tileDefinitions = dict() self.tileMap = list() self.readTileDefinitions() self.readTileMap()
def __init__(self): GameState( ) # initialize singletons before threading to avoid race conditions AssetLoader() MusicPlayer() self.root = tk.Tk() self.windowManager = WindowManager() self.display = Display(self.root, self.windowManager) self.inputHandler = InputHandler(self.display.widget)
def __init__(self): Globals.INTRO_SOUND_PLAYED = False if Globals.PLAYER_NAME is None: Globals.PLAYER_NAME = "" self.error_message = None self.loader = AssetLoader('images') self.setup_text() self.show_extra = False self.extra_time = 0 Globals.play_menu_sound()
def __init__(self, return_state, escape_state=None): self.return_state = return_state self.escape_state = escape_state if escape_state is not None else \ Menu.Menu() self.loader = AssetLoader('images') self.background_img = self.loader.load_image('background.png') self.pause_image = self.loader.load_image_alpha('game-paused.png') Globals.play_menu_sound() # self.title_surf = PauseScreen.TITLE_FONT.render( # PauseScreen.TITLE_TEXT, True, PauseScreen.TITLE_COLOR) # self.title_rect = self.title_surf.get_rect() # self.title_rect.center = Globals.SCREEN.get_rect().center self.black_surf = pygame.Surface( (Globals.WIDTH, Globals.HEIGHT)).convert() self.black_surf.fill((0, 0, 0)) self.fade_in = False self.fade_out = False self.alpha_factor = 300 self.start_fade_in()
def _settingsChangeHandler(*args, **kwargs): if args[0] == 'backgroundMusic': self.isEnabled = True if args[1] == 0 else False if self.isEnabled: if self.currentSong != '': self.playNext(self.currentSong) else: self.playNext(AssetLoader().getMusicPath('title')) else: mixer.music.stop()
def update(self, timestep, keypresses): gs = GameState() if gs.gameMode == GameMode.inAreaChoice: for key in keypresses: if key == 'Up': self.choiceInd = (self.choiceInd - 1) % len(gs.choices) elif key == 'Down': self.choiceInd = (self.choiceInd + 1) % len(gs.choices) elif key == 'Return': self.interpreter.resume(self.choiceInd) elif gs.gameMode == GameMode.inAreaCommand or gs.gameMode == GameMode.inAreaInput: for key in keypresses: # key is printable -> add it to buffer if len(key) == 1: if len(gs.cmdBuffer) == 0 and key == ' ': continue # ignore 1st char spaces as that is used to advance text gs.appendCmdBuffer(key) # key is backspace -> pop one char from buffer elif key == 'BackSpace': gs.popCmdBuffer() # key is return -> commit command elif key == 'Return': if gs.gameMode == GameMode.inAreaInput: self.interpreter.resume(gs.cmdBuffer.strip()) else: # GameMode.inAreaCommand val = gs.traverseCmdMap() if isinstance(val, BodyNode): # valid normal command # special logic for go to - change room ID TODO refactor if gs.cmdBuffer.strip('. ')[0:5] == 'go to': roomId = AssetLoader().reverseRoomLookup(gs.cmdBuffer.strip('. ')[5:].strip(), gs.areaId) gs.enterRoom(roomId or gs.roomId) self.interpreter.executeAction(val) elif isinstance(val, str): # valid metacommand if val == 'view inventory': gs.gameMode = GameMode.inAreaInventory elif val == 'view map': gs.gameMode = GameMode.inAreaMap elif val == 'save game': # write the save file in a separate thread and wait with loading screen def writeFileFunc(): gs.writeFile(Globals.SavePaths[gs.saveId]) gs.pushMessage('Game saved to ' + Globals.SavePaths[gs.saveId] + '.') gs.unlockGameMode() gs.lockGameMode(GameMode.isLoading) t = threading.Thread(target=writeFileFunc) t.daemon = True t.start() elif val == 'exit game': gs.gameMode = GameMode.titleScreen else: # tuple or None - invalid command if len(gs.cmdBuffer.strip('. ')) > 0: gs.pushMessage('Command not recognized.') gs.clearCmdBuffer()
def load(self): self.maps = [] self.colorMasks = [] self.travelMasks = [] mapslst = Globals.MapsPaths loader = AssetLoader() for threetup in mapslst: self.maps.append(loader.getMap(threetup[0])) self.colorMasks.append(loader.getMap(threetup[1])) self.travelMasks.append(loader.getMap(threetup[2])) self.entrances = ([], []) self.areaInfo = {} areaConfig = loader.getConfig(Globals.AreasConfigPath) for area in areaConfig: entranceList = areaConfig[area]['entrances'] mapId = areaConfig[area]['mapId'] for entrance in entranceList: roomId = entrance['roomId'] r = entrance['r'] c = entrance['c'] # self.entrances has two lists, one per world, with tuples formatted as # [0] int row of tile with entrance # [1] int col of tile with entrance # [2] string area id # [3] string room id self.entrances[mapId].append((r, c, area, roomId)) # self.areaInfo maps area id -> (string title, string subtitle) self.areaInfo[area] = (areaConfig[area]['name'], areaConfig[area]['subtitle'] \ if 'subtitle' in areaConfig[area] else '')
class HUDManager(object): KEY_IMAGE_PATH = 'key.png' SPECIAL_KEY_IMAGE_PATH = 'special_key.png' MARGIN_BOTTOM = 10 MARGIN_RIGHT = 10 PADDING_NEXT = 5 def __init__(self): self.num_keys = 0 self.num_special_keys = 0 self.loader = AssetLoader('images') self.init_images() self.update_surface() def init_images(self): self.key_surf = self.loader.load_image_alpha(HUDManager.KEY_IMAGE_PATH) self.key_rect = self.key_surf.get_rect() self.special_key_surf = self.loader.load_image_alpha( HUDManager.SPECIAL_KEY_IMAGE_PATH) self.special_key_rect = self.special_key_surf.get_rect() # assuming images are the same size self.image_width = self.key_rect.width self.image_height = self.key_rect.height def update_surface(self): num_obj = self.num_keys + self.num_special_keys surf_width = num_obj * (self.image_width + HUDManager.PADDING_NEXT) surf_height = self.image_height self.surface = pygame.Surface((surf_width, surf_height), pygame.SRCALPHA, 32).convert_alpha() self.rect = self.surface.get_rect() self.rect.bottom = Globals.HEIGHT - HUDManager.MARGIN_BOTTOM self.rect.right = Globals.WIDTH - HUDManager.MARGIN_RIGHT self.blit_images() def blit_images(self): curr_x = self.rect.width - self.image_width for i in range(0, self.num_keys): self.surface.blit(self.key_surf, (curr_x, 0)) curr_x -= self.image_width + HUDManager.PADDING_NEXT for i in range(0, self.num_special_keys): self.surface.blit(self.special_key_surf, (curr_x, 0)) curr_x -= self.image_width + HUDManager.PADDING_NEXT def render(self, screen): self.blit_images() screen.blit(self.surface, self.rect) def add_key(self): self.num_keys += 1 self.update_surface() def add_special_key(self): self.num_special_keys += 1 self.update_surface() def has_key(self): return self.num_keys > 0 def has_special_key(self): return self.num_special_keys > 0 def use_key(self): if self.has_key(): self.num_keys -= 1 self.update_surface() return True return False def use_special_key(self): if self.has_special_key(): self.num_special_keys -= 1 self.update_surface() return True return False
def __init__(self): self.num_keys = 0 self.num_special_keys = 0 self.loader = AssetLoader('images') self.init_images() self.update_surface()
class SettingsSlider(object): BASE_HEIGHT_PERCENT = .5 BASE_COLOR = (0, 229, 255) BASE_HIGHLIGHT_COLOR = pygame.color.Color('yellow') BASE_BORDER_COLOR = pygame.color.Color('black') BASE_BORDER_WIDTH = 4 INDICATOR_WIDTH_PERCENT = .4 INDICATOR_BORDER_PERCENT = .6 INDICATOR_BORDER_COLOR = pygame.color.Color('black') INDICATOR_INNER_COLOR = pygame.color.Color('gray') ARROW_MARGIN = 15 VELOCITY = 300 def __init__(self, container, max_value=100, value=None): self.container = container self.max_value = max_value self.value = value if value is not None else self.max_value self.loader = AssetLoader('images') self.init_slider() self.init_arrows() self.selected = False def init_slider(self): self.init_indicator() self.init_base() def init_indicator(self): indicator_height = self.container.height indicator_width = indicator_height * \ SettingsSlider.INDICATOR_WIDTH_PERCENT self.indicator_surf = pygame.Surface( (indicator_width, indicator_height)).convert() self.indicator_surf.fill(SettingsSlider.INDICATOR_INNER_COLOR) self.indicator_rect = self.indicator_surf.get_rect() pygame.draw.rect( self.indicator_surf, SettingsSlider.INDICATOR_BORDER_COLOR, self.indicator_rect, int(indicator_width * SettingsSlider.INDICATOR_BORDER_PERCENT)) self.indicator_rect.top = self.container.top self.target_x = self.container.left + \ self.container.width * self.get_percentage() self.indicator_rect.centerx = self.target_x def init_arrows(self): self.arrow_left_surf = self.loader.load_image_alpha('arrow_left.png') self.arrow_right_surf = self.loader.load_image_alpha('arrow_right.png') self.arrow_left_rect = self.arrow_left_surf.get_rect() self.arrow_right_rect = self.arrow_right_surf.get_rect() self.arrow_left_rect.centery = self.container.centery self.arrow_right_rect.centery = self.container.centery self.arrow_left_rect.right = self.container.left - \ SettingsSlider.ARROW_MARGIN self.arrow_right_rect.left = self.container.right + \ SettingsSlider.ARROW_MARGIN def init_base(self): base_height = self.container.height * \ SettingsSlider.BASE_HEIGHT_PERCENT self.base_surf = pygame.Surface( (self.container.width, base_height)).convert() self.base_rect = self.base_surf.get_rect() self.base_rect.topleft = self.container.topleft self.base_rect.top += (self.container.height - base_height) / 2 self.fill_base() def fill_base(self, base_color=BASE_COLOR): self.base_surf.fill(base_color) area = self.base_surf.get_rect() pygame.draw.rect( self.base_surf, SettingsSlider.BASE_BORDER_COLOR, area, SettingsSlider.BASE_BORDER_WIDTH) def select(self): self.fill_base(SettingsSlider.BASE_HIGHLIGHT_COLOR) self.selected = True def deselect(self): self.fill_base() self.selected = False def change_value(self, delta): self.set_value(self.value + delta) def set_value(self, value): self.value = value if self.value < 0: self.value = 0 elif self.value > self.max_value: self.value = self.max_value self.target_x = self.container.left + \ self.container.width * self.get_percentage() def get_percentage(self): return self.value / self.max_value def render(self, screen): screen.blit(self.base_surf, self.base_rect) screen.blit(self.indicator_surf, self.indicator_rect) if self.selected: if self.value > 0: screen.blit(self.arrow_left_surf, self.arrow_left_rect) if self.value < self.max_value: screen.blit(self.arrow_right_surf, self.arrow_right_rect) def update(self, time): if self.indicator_rect.centerx < self.target_x: self.indicator_rect.centerx = min( self.indicator_rect.centerx + SettingsSlider.VELOCITY * time, self.target_x) elif self.indicator_rect.centerx > self.target_x: self.indicator_rect.centerx = max( self.indicator_rect.centerx - SettingsSlider.VELOCITY * time, self.target_x)
class Level(GameState): MAP_BASE = "maps" MAX_OFFSET_X = 150 MAX_OFFSET_Y = 75 FACTOR = 10 ALPHA_FACTOR = 550 MIN_ALPHA = 0 MAX_ALPHA = 255 SUBTITLE_BACKGROUND = pygame.color.Color("black") SUBTITLE_PADDING = 5 SUBTITLE_COLOR = pygame.color.Color("white") SUBTITLE_FONT = pygame.font.Font(None, 32) SUBTITLE_MARGIN = 20 POTION_CURED_SUBTITLE = 'You have been cured' POTION_CURED_SUBTITLE_LOOPS = 5 ANTIDOTE_HINT = 'Press the action key to use' ANTIDOTE_TILE_LOOPS = 1 ACTION_TILE_HINT = 'Press the action key to use' ACTION_TILE_LOOPS = 1 LOCKED_TILE_HINT = 'This is locked' LOCKED_TILE_LOOPS = 1 GAUNTLET_TILE_HINT = 'Pick up to enable punching' GAUNTLET_TILE_LOOPS = 1 HEALTH_PICKUP = 10 DAMAGE_TRAP = -1 POTION_PICKUP_DISORIENTED = 5 POTION_PICKUP = 10 PUNCHING_INFLATE = .2 MUSIC_END_ID_BASE = pygame.USEREVENT SOUND_FADE_TIME = 500 SWITCH_SOUND_PATH = 'switch.ogg' IGNORE_TIME = .5 def __init__(self, definition_path, map_path, init_music_path=None, music_path=None, music_loops=-1, has_timer=True, should_fade_in=True, mid=0): self.has_timer = has_timer self.keyCode = None self.definition_path = definition_path self.map_path = map_path self.tile_engine = TileEngine( join(Level.MAP_BASE, definition_path), join(Level.MAP_BASE, map_path) ) self.camera = Camera(self.tile_engine, pygame.Rect( 0, 0, Globals.WIDTH, Globals.HEIGHT)) self.tile_rect = self.tile_engine.get_tile_rect() self.enemySprites = pygame.sprite.Group() self.playerSprites = pygame.sprite.Group() self.turrets = list() self.lights = list() self.init_player() self.init_enemies() self.timer = None if Globals.HEALTH_BAR is None: Globals.HEALTH_BAR = HealthBar() if Globals.HUD_MANAGER is None: Globals.HUD_MANAGER = HUDManager() self.black_surf = pygame.Surface( (Globals.WIDTH, Globals.HEIGHT)).convert() self.black_surf.fill((0, 0, 0)) self.fade_in = False self.fade_out = False self.showing_subtitle = False self.alpha_factor = 300 self.should_fade_in = should_fade_in self.pausing = False self.going_back = False self.score_counted = False self.respawn_coords = [-1, -1] self.timer = None self.first_occur = True self.find_respawn() self.loader = AssetLoader('images', 'sounds') self.switch_sound = self.loader.load_sound(Level.SWITCH_SOUND_PATH) self.channel = None self.music_loops = music_loops self.music_handle = None if music_path is not None: self.background_music_handle = self.loader.load_sound(music_path) self.music_handle = self.background_music_handle else: self.background_music_handle = None if init_music_path is not None: self.init_music_handle = self.loader.load_sound(init_music_path) self.music_handle = self.init_music_handle else: self.init_music_handle = None self.time_init = 0 self.start_on_stop = True self.switched_sound = False self.music_end_id = Level.MUSIC_END_ID_BASE + mid self.can_open_doors = True def start_music(self, end_id=None): if end_id is None: end_id = self.music_end_id if self.channel or self.music_handle is None: return if not self.switched_sound: l = 0 else: l = self.music_loops self.channel = self.music_handle.play( loops=l, fade_ms=Level.SOUND_FADE_TIME) self.channel.set_endevent(end_id) self.start_on_stop = True # if self.channel: # return # self.channel = self.background_music_handle.play( # loops=self.music_loops, fade_ms=Level.SOUND_FADE_TIME) # self.channel.set_endevent(Level.MUSIC_END_ID) def pause_music(self): if self.channel: self.channel.pause() self.start_on_stop = True def resume_music(self): if self.channel: self.channel.unpause() self.start_on_stop = True def stop_music(self): if self.channel: self.channel.fadeout(Level.SOUND_FADE_TIME) self.channel = None self.start_on_stop = False self.music_handle = self.background_music_handle def find_respawn(self): tile_map = self.tile_engine.tileMap for row_num in range(0, len(tile_map)): for col_num in range(0, len(tile_map[row_num])): if tile_map[row_num][col_num] is None: continue if TileType.RESPAWN_ATTR in \ tile_map[row_num][col_num].special_attr: if self.has_respawn_coords(): raise Exception( "There can only be one respawn point in the map" ) self.respawn_coords[0] = row_num self.respawn_coords[1] = col_num if self.has_respawn_coords(): tile_map[self.respawn_coords[0]][self.respawn_coords[1]] = \ self.tile_engine.get_tile_from_attr(TileType.BASE_ATTR) def has_respawn_coords(self): return self.respawn_coords[0] != -1 and self.respawn_coords[1] != -1 def got_current_state(self): diff = self.camera.initView() self.shift_non_player_objects(diff[0], diff[1]) self.player.rect.center = Globals.SCREEN.get_rect().center if self.should_fade_in: self.start_fade_in() if self.has_timer and self.timer is None: self.timer = ScoreTimer() elif self.timer is not None: self.timer.unpause() Globals.stop_menu_sound() self.start_music() self.first_occur = False def got_state_back(self): if self.has_respawn_coords(): diff = self.camera.set_viewpoint_with_coords( self.respawn_coords[0], self.respawn_coords[1]) center = Globals.SCREEN.get_rect().center self.player.stop_and_set_direction(Character.INDEX_DOWN) self.player.rect.left = center[0] - 16 self.player.rect.top = center[1] self.shift_non_player_objects(diff[0], diff[1]) self.start_fade_in() self.start_music() else: raise Exception( "A respawn point must be defined to return to the level") def shift_non_player_objects(self, x_delta, y_delta): if x_delta == 0 and y_delta == 0: return for enemy in self.enemySprites: enemy.rect.centerx += x_delta enemy.rect.centery += y_delta for turret in self.turrets: turret.move(x_delta, y_delta) def handle_stair_up(self): if not self.score_counted: self.score_counted = True Globals.PLAYER_SCORE += Globals.HEALTH_BAR.health if self.has_timer: time = self.timer.total_time / 1000 diff = max(300 - time, 0) Globals.PLAYER_SCORE += diff self.going_back = False self.pausing = False self.start_fade_out() def handle_stair_down(self): self.going_back = True self.start_fade_out() def handle_enemy_collision(self): pass def handle_special_collision(self, pair): self.replace_special_tile(pair) if TileType.TRAP_ATTR in pair.tile.special_attr: Globals.HEALTH_BAR.changeHealth(Level.DAMAGE_TRAP) self.player.show_damage() elif TileType.HEALTH_ATTR in pair.tile.special_attr: Globals.HEALTH_BAR.changeHealth(Level.HEALTH_PICKUP) elif TileType.KEY_ATTR in pair.tile.special_attr: Globals.HUD_MANAGER.add_key() elif TileType.POTION_ATTR in pair.tile.special_attr: if Globals.DISORIENTED: Globals.DISORIENTED = False self.show_subtitle(Level.POTION_CURED_SUBTITLE, Level.POTION_CURED_SUBTITLE_LOOPS) self.player.stop_and_set_direction(self.player.direction) Globals.HEALTH_BAR.changeHealth( Level.POTION_PICKUP_DISORIENTED) else: Globals.HEALTH_BAR.changeHealth(Level.POTION_PICKUP) def handle_finish_fade_out(self): self.stop_music() if not Globals.goto_next_level(): self.handle_last_level() def handle_last_level(self): manager = HighscoreManager() manager.add(Globals.PLAYER_NAME, Globals.PLAYER_SCORE) Globals.STATE = WinGame.WinGame() # for now def handle_finish_fade_in(self): if self.timer is not None: self.timer.unpause() def replace_special_tile(self, pair): if pair.tile.is_replaceable: row, col = self.camera.tileEngine.get_tile_pos(pair.coords[0], pair.coords[1]) base = self.camera.tileEngine.get_tile_from_attr( pair.tile.replace_attr) if base is None: base = self.camera.tileEngine.get_tile_from_attr( TileType.BASE_ATTR) self.camera.tileEngine.tileMap[row][col] = base self.camera.set_dirty() self.lights = [ l for l in self.lights if not l.rect.colliderect(self.player.rect)] def init_player(self): self.player = Player( Globals.WIDTH, Globals.HEIGHT, Globals.WIDTH / 2, Globals.HEIGHT / 2 ) self.playerSprites.add(self.player) def init_enemies(self): tile_map = self.tile_engine.tileMap base_tile = self.tile_engine.get_tile_from_attr(TileType.BASE_ATTR) for row_num in range(0, len(tile_map)): for col_num in range(0, len(tile_map[row_num])): if tile_map[row_num][col_num] is None: continue if TileType.SPAWN_ATTR in \ tile_map[row_num][col_num].special_attr: self.add_enemy(row_num, col_num) tile_map[row_num][col_num] = base_tile self.camera.set_dirty() elif TileType.CHASE_SPAWN_ATTR in \ tile_map[row_num][col_num].special_attr: self.add_enemy(row_num, col_num, chase_enemy=True) tile_map[row_num][col_num] = base_tile self.camera.set_dirty() elif TileType.BOSS_SPAWN in \ tile_map[row_num][col_num].special_attr: self.add_enemy(row_num, col_num, boss=True) tile_map[row_num][col_num] = base_tile self.camera.set_dirty() elif TileType.TURRET_LEFT in \ tile_map[row_num][col_num].special_attr: self.add_turret(row_num, col_num, True) elif TileType.TURRET_RIGHT in \ tile_map[row_num][col_num].special_attr: self.add_turret(row_num, col_num, False) elif TileType.LIGHT_REPLACE_ATTR in \ tile_map[row_num][col_num].special_attr: self.add_light(row_num, col_num) tile_map[row_num][col_num] = base_tile self.camera.set_dirty() elif TileType.LIGHT_ATTR in \ tile_map[row_num][col_num].special_attr: self.add_light(row_num, col_num) def add_light(self, row_num, col_num): y = self.tile_rect.height * (row_num - 1) - self.camera.viewpoint.top x = self.tile_rect.width * (col_num - 1) - self.camera.viewpoint.left self.lights.append(LightSource(x, y, self.tile_rect.width)) def add_enemy(self, row_num, col_num, chase_enemy=False, boss=False): y = self.tile_rect.height * row_num - self.camera.viewpoint.top x = self.tile_rect.width * col_num - self.camera.viewpoint.left if boss: enemy = BossEnemy(camera=self.camera, x=x, y=y) elif chase_enemy: enemy = ChaseEnemy(camera=self.camera, x=x, y=y) else: enemy = Enemy(Globals.WIDTH, Globals.HEIGHT, x=x, y=y) self.enemySprites.add(enemy) def add_turret(self, row_num, col_num, left): row_num += 1 if not left: col_num += 1 y = self.tile_rect.height * row_num - self.camera.viewpoint.top x = self.tile_rect.width * col_num - self.camera.viewpoint.left self.turrets.append(Turret(x, y, left)) def check_collisions(self): radius = max(self.player.rect.size) * 2 self.check_turret_collisions() self.check_punching_collisions() self.enemySprites = pygame.sprite.Group( [e for e in self.enemySprites if e.is_alive]) self.check_enemy_collisions() special_tiles = self.camera.get_special_tiles( self.player.rect.center, radius) self.check_stair_collisions(special_tiles) self.check_special_collisions(special_tiles) self.check_action_hints() def check_action_hints(self): if self.showing_subtitle: return temp_rect = self.player.rect.inflate( Player.ACTION_OFFSET, Player.ACTION_OFFSET) radius = max(temp_rect.size) * 2 special_tiles = self.camera.get_special_tiles( self.player.rect.center, radius) action_tiles = [pair for pair in special_tiles if TileType.ACTION_ATTR in pair.tile.special_attr and temp_rect.colliderect(pair.rect)] locked_tiles = [pair for pair in action_tiles if TileType.LOCKED_ATTR in pair.tile.special_attr] special_locked = [pair for pair in locked_tiles if TileType.SPECIAL_DOOR_ATTR in pair.tile.special_attr] antidote_tiles = [pair for pair in action_tiles if TileType.ANTIDOTE_ATTR in pair.tile.special_attr] if len(antidote_tiles) > 0: self.show_subtitle(Level.ANTIDOTE_HINT, Level.ANTIDOTE_TILE_LOOPS) return contains_red = self.camera.contains_attribute(TileType.REDBALL_ATTR) if len(action_tiles) > 0 and not self.can_open_doors: self.show_subtitle(Level.LOCKED_TILE_HINT, Level.LOCKED_TILE_LOOPS) elif len(special_locked) > 0 and contains_red: self.show_subtitle(Level.LOCKED_TILE_HINT, Level.LOCKED_TILE_LOOPS) elif len(special_locked) == 0 and len(locked_tiles) > 0 and \ not Globals.HUD_MANAGER.has_key(): self.show_subtitle(Level.LOCKED_TILE_HINT, Level.LOCKED_TILE_LOOPS) elif len(action_tiles) > 0 and (len(special_locked) == 0 or not contains_red): self.show_subtitle(Level.ACTION_TILE_HINT, Level.ACTION_TILE_LOOPS) def check_special_collisions(self, special_tiles): for pair in special_tiles: if self.player.rect.colliderect(pair.rect): self.handle_special_collision(pair) def check_stair_collisions(self, special_tiles): stair_up_rects = [pair.rect for pair in special_tiles if TileType.STAIR_UP_ATTR in pair.tile.special_attr] temp_rect = self.player.rect.inflate( -Player.STAIR_OFFSET, -Player.STAIR_OFFSET) num_up_stairs = len(temp_rect.collidelistall(stair_up_rects)) if num_up_stairs > 0: self.handle_stair_up() stair_down_rects = [pair.rect for pair in special_tiles if TileType.STAIR_DOWN_ATTR in pair.tile.special_attr] num_down_stairs = len(temp_rect.collidelistall(stair_down_rects)) if num_down_stairs > 0: self.handle_stair_down() def check_enemy_collisions(self): enemy_rects = [enemy.rect.inflate(-20, -20) for enemy in self.enemySprites] player_rect = self.player.rect.copy() if self.player.punching: # player_rect.inflate_ip( # -player_rect.width * Level.PUNCHING_INFLATE, # -player_rect.height * Level.PUNCHING_INFLATE) pass collided_indices = player_rect.collidelistall(enemy_rects) if len(collided_indices) > 0: self.handle_health_change(Enemy.HEALTH_EFFECT) def check_punching_collisions(self): if not self.player.punching: return punching_rect = self.player.get_punching_rect() for enemy in self.enemySprites: if punching_rect.colliderect(enemy.rect): enemy.handle_hit(self.camera, self.player) def check_turret_collisions(self): for turret in self.turrets: for syringe in turret.syringeSprites: if self.player.rect.colliderect(syringe): self.handle_health_change(syringe.health_effect) syringe.kill() def handle_health_change(self, health_effect): Globals.HEALTH_BAR.changeHealth(health_effect) if health_effect < 0: self.player.show_damage() def render(self): self.render_pre_fade() if self.fade_out or self.fade_in: Globals.SCREEN.blit(self.black_surf, (0, 0)) self.render_post_fade() # r = self.player.get_punching_rect() # if r is not None: # Globals.SCREEN.fill((255, 255, 255), r) def render_pre_fade(self): self.camera.render(Globals.SCREEN) self.render_lights() self.enemySprites.draw(Globals.SCREEN) for turret in self.turrets: turret.render(Globals.SCREEN) self.playerSprites.draw(Globals.SCREEN) self.render_overlay() if self.has_timer and not self.score_counted: self.timer.render(Globals.SCREEN) if self.showing_subtitle: Globals.SCREEN.blit(self.subtitle_surf, self.subtitle_rect) def render_lights(self): for light in self.lights: light.render(Globals.SCREEN) def render_overlay(self): if Globals.DISORIENTED: Globals.SCREEN.blit(Globals.get_disoriented_surf(), (0, 0), special_flags=pygame.BLEND_SUB) def render_post_fade(self): Globals.HEALTH_BAR.render(Globals.SCREEN) Globals.HUD_MANAGER.render(Globals.SCREEN) def update(self, time): if self.time_init < Level.IGNORE_TIME: self.time_init += time return if Globals.HEALTH_BAR.is_dead(): self.handle_lose_game() if self.fade_out or self.fade_in: self.update_alpha(time) return Globals.HEALTH_BAR.update(time) self.player.update(time, self.camera) self.enemySprites.update(time, self.camera, self.player) for turret in self.turrets: turret.update(time, self.camera) self.check_camera_position() self.check_collisions() self.update_subtitle(time) def handle_lose_game(self): self.stop_music() Globals.STATE = LoseGame.LoseGame() def update_subtitle(self, time): if not self.showing_subtitle: return old_alpha = self.subtitle_surf.get_alpha() if old_alpha == 0 or old_alpha == 255: self.alpha_factor *= -1 if self.subtitle_loops != -1: self.subtitle_loops -= 1 if self.subtitle_loops == 0: self.stop_subtitle() new_alpha = int(old_alpha + self.alpha_factor * time) if new_alpha < 0: new_alpha = 0 elif new_alpha > 255: new_alpha = 255 self.subtitle_surf.set_alpha(new_alpha) def update_alpha(self, time): if self.fade_out: old_alpha = self.black_surf.get_alpha() new_alpha = int(old_alpha + time * Level.ALPHA_FACTOR) if new_alpha >= Level.MAX_ALPHA: if self.pausing: self.handle_pause() elif self.going_back: self.handle_go_back() else: self.handle_finish_fade_out() self.fade_out = False self.black_surf.set_alpha(new_alpha) elif self.fade_in: old_alpha = self.black_surf.get_alpha() new_alpha = int(old_alpha - time * Level.ALPHA_FACTOR) if new_alpha <= Level.MIN_ALPHA: self.handle_finish_fade_in() self.fade_in = False self.black_surf.set_alpha(new_alpha) def start_fade_out(self): self.black_surf.set_alpha(Level.MIN_ALPHA) self.fade_out = True def start_fade_in(self): self.black_surf.set_alpha(Level.MAX_ALPHA) self.fade_in = True def handle_action_key(self): temp_rect = self.player.rect.inflate( Player.ACTION_OFFSET, Player.ACTION_OFFSET) radius = max(temp_rect.size) * 2 pairs = self.camera.get_special_tiles( self.player.rect.center, radius) special_tiles = [pair for pair in pairs if temp_rect.colliderect(pair.rect)] self.handle_sliding_doors(special_tiles) self.handle_action_switch(special_tiles) self.handle_antidote_check(special_tiles) def handle_antidote_check(self, special_tiles): for pair in special_tiles: if TileType.ANTIDOTE_ATTR in pair.tile.special_attr: row, col = self.camera.tileEngine.get_tile_pos( pair.coords[0], pair.coords[1] ) base = self.camera.tileEngine.get_tile_from_attr( TileType.ANTIDOTE_REPLACE) self.camera.tileEngine.tileMap[row][col] = base self.camera.set_dirty() self.handle_antidote() def handle_antidote(self): pass def handle_sliding_doors(self, special_tiles): if not self.can_open_doors: return base = self.camera.tileEngine.get_tile_from_attr( TileType.BASE_ATTR) was_special_door = False for pair in special_tiles: if TileType.SLIDING_DOOR_ATTR in pair.tile.special_attr: row, col = self.camera.tileEngine.get_tile_pos( pair.coords[0], pair.coords[1] ) doors = self.get_sliding_doors(row, col) for pos in doors: row, col = pos tile_map = self.camera.tileEngine.tileMap if TileType.SPECIAL_DOOR_ATTR in \ tile_map[row][col].special_attr: was_special_door = True tile_map[row][col] = base self.camera.set_dirty() if was_special_door: self.handle_special_door() def handle_special_door(self): pass def get_sliding_doors(self, row, col): init_num_keys = Globals.HUD_MANAGER.num_keys coords = list() use_key = True if TileType.LOCKED_ATTR in \ self.camera.tileEngine.tileMap[row][col].special_attr: if TileType.SPECIAL_DOOR_ATTR in \ self.camera.tileEngine.tileMap[row][col].special_attr: if self.camera.contains_attribute(TileType.REDBALL_ATTR): return list() elif not Globals.HUD_MANAGER.has_key(): return list() else: init_num_keys = -1 if use_key: Globals.HUD_MANAGER.use_key() coords.append([row, col]) result = self.get_doors_delta(row, col, init_num_keys, row_delta=-1) if result == -1: return list() coords.extend(result) result = self.get_doors_delta(row, col, init_num_keys, row_delta=1) if result == -1: return list() coords.extend(result) result = self.get_doors_delta(row, col, init_num_keys, col_delta=-1) if result == -1: return list() coords.extend(result) result = self.get_doors_delta(row, col, init_num_keys, col_delta=1) if result == -1: return list() coords.extend(result) return coords def get_doors_delta(self, row, col, init_num_keys, row_delta=0, col_delta=0): coords = list() tile_map = self.camera.tileEngine.tileMap row += row_delta col += col_delta while self.camera.tileEngine.is_coord_valid(row, col) and \ tile_map[row][col] is not None and \ TileType.SLIDING_DOOR_ATTR in tile_map[row][col].special_attr: if TileType.LOCKED_ATTR in tile_map[row][col].special_attr: if TileType.SPECIAL_DOOR_ATTR in \ self.camera.tileEngine.tileMap[row][col].special_attr: if self.camera.contains_attribute(TileType.REDBALL_ATTR): return -1 elif not Globals.HUD_MANAGER.has_key(): return -1 elif Globals.HUD_MANAGER.num_keys >= init_num_keys: Globals.HUD_MANAGER.use_key() coords.append([row, col]) row += row_delta col += col_delta return coords def handle_action_switch(self, special_tiles): for pair in special_tiles: if TileType.LEVER_LEFT_ATTR in pair.tile.special_attr: row, col = self.camera.tileEngine.get_tile_pos(pair.coords[0], pair.coords[1]) lever_right = self.camera.tileEngine.get_tile_from_attr( TileType.LEVER_RIGHT_ATTR) self.camera.tileEngine.tileMap[row][col] = lever_right self.camera.set_dirty() self.handle_lever_on() elif TileType.LEVER_RIGHT_ATTR in pair.tile.special_attr: row, col = self.camera.tileEngine.get_tile_pos(pair.coords[0], pair.coords[1]) lever_left = self.camera.tileEngine.get_tile_from_attr( TileType.LEVER_LEFT_ATTR) self.camera.tileEngine.tileMap[row][col] = lever_left self.camera.set_dirty() self.handle_lever_off() def handle_lever_on(self): self.switch_sound.play() for turret in self.turrets: turret.turn_off() def handle_lever_off(self): self.switch_sound.play() for turret in self.turrets: turret.turn_on() def event(self, event): if event.type == pygame.KEYDOWN: key = event.key if not Globals.DISORIENTED else \ self.invert_key(event.key) self.handle_keydown(key) elif event.type == pygame.KEYUP: key = event.key if not Globals.DISORIENTED else \ self.invert_key(event.key) self.handle_keyup(key) def handle_key_down(self, keydown): key = pygame.K_DOWN if not Globals.DISORIENTED else pygame.K_UP if keydown: self.handle_keydown(key) else: self.handle_keyup(key) def handle_key_up(self, keydown): key = pygame.K_UP if not Globals.DISORIENTED else pygame.K_DOWN if keydown: self.handle_keydown(key) else: self.handle_keyup(key) def handle_key_left(self, keydown): key = pygame.K_LEFT if not Globals.DISORIENTED else pygame.K_RIGHT if keydown: self.handle_keydown(key) else: self.handle_keyup(key) def handle_key_right(self, keydown): key = pygame.K_RIGHT if not Globals.DISORIENTED else pygame.K_LEFT if keydown: self.handle_keydown(key) else: self.handle_keyup(key) def handle_attack(self): self.player.handle_attack() def handle_raw_event(self, event): if event.type == pygame.KEYDOWN: key = event.key if key == pygame.K_1: self.handle_stair_up() elif key == pygame.K_2: delta = 100 - Globals.HEALTH_BAR.health Globals.HEALTH_BAR.changeHealth(delta) elif key == pygame.K_3: Globals.HUD_MANAGER.add_key() elif key == pygame.K_4: Globals.DISORIENTED = False elif key == pygame.K_5: self.replace_reds() elif event.type == self.music_end_id and not self.switched_sound: self.switched_sound = True self.stop_subtitle() self.music_handle = self.background_music_handle if self.start_on_stop: self.stop_music() self.start_music() def replace_reds(self): tile_map = self.camera.tileEngine.tileMap green_tile = self.camera.tileEngine.get_tile_from_attr( TileType.GREENBALL_ATTR) for row in range(0, len(tile_map)): for col in range(0, len(tile_map[row])): tile = tile_map[row][col] if tile is not None and \ TileType.REDBALL_ATTR in tile.special_attr: tile_map[row][col] = green_tile self.camera.set_dirty() def handle_keydown(self, key): self.keyCode = key for p in self.playerSprites: p.keyPressed(key) def handle_go_back(self): if Globals.goto_previous_level(): self.stop_music() self.timer.pause() self.player.stop_and_set_direction(Character.INDEX_UP) def start_pause_fade(self): if self.pausing: return self.pausing = True if self.has_timer: self.timer.pause() self.start_fade_out() def handle_pause(self): self.pausing = False if self.has_timer: self.timer.pause() self.pause_music() self.goto_pause() def goto_pause(self): Globals.STATE = PauseScreen(self) def handle_unpause(self): self.resume_music() if self.has_timer: self.timer.unpause() def handle_escape(self): # self.handle_pause() self.start_pause_fade() def handle_keyup(self, key): if key == self.keyCode: self.keyCode = None for p in self.playerSprites: p.keyReleased(key) def check_camera_position(self): dist_x = self.camera.container.centerx - self.player.rect.centerx dist_y = self.camera.container.centery - self.player.rect.centery if abs(dist_x) > Level.MAX_OFFSET_X: diff = abs(dist_x) - Level.MAX_OFFSET_X # player is to the right of center if dist_x < 0: pass # player is to the left of center else: diff *= -1 self.camera.move(diff, 0) self.player.rect.centerx -= diff for enemy in self.enemySprites: enemy.rect.centerx -= diff for turret in self.turrets: turret.move(-diff, 0) for light in self.lights: light.move(-diff, 0) if abs(dist_y) > Level.MAX_OFFSET_Y: diff = abs(dist_y) - Level.MAX_OFFSET_Y # player is below center if dist_y < 0: pass # player is above center else: diff *= -1 self.camera.move(0, diff) self.player.rect.centery -= diff for enemy in self.enemySprites: enemy.rect.centery -= diff for turret in self.turrets: turret.move(0, -diff) for light in self.lights: light.move(0, -diff) def init_subtitle(self, text): text_surf = Level.SUBTITLE_FONT.render( text, True, Level.SUBTITLE_COLOR) self.subtitle_rect = text_surf.get_rect() self.subtitle_rect.centerx = Globals.WIDTH / 2 self.subtitle_rect.bottom = \ Globals.HEIGHT - Level.SUBTITLE_MARGIN self.subtitle_rect.inflate_ip( Level.SUBTITLE_PADDING * 2, Level.SUBTITLE_PADDING * 2 ) self.subtitle_surf = pygame.Surface(self.subtitle_rect.size).convert() self.subtitle_surf.fill(Level.SUBTITLE_BACKGROUND) self.subtitle_surf.blit(text_surf, ( Level.SUBTITLE_PADDING, Level.SUBTITLE_PADDING )) self.subtitle_surf.set_alpha(255) def show_subtitle(self, text, loops=-1): self.subtitle_loops = loops if self.subtitle_loops != -1: self.subtitle_loops *= 2 self.init_subtitle(text) self.showing_subtitle = True def stop_subtitle(self): self.showing_subtitle = False
class ControlSettings(GameState): TITLE_IMAGE_PATH = 'control_settings.png' TITLE_MARGIN_TOP = 60 TITLE_TEXT_MARGIN = 40 TITLE_ARROW_MARGIN = 100 SURF_INDEX_NORMAL = 0 SURF_INDEX_HIT = 1 SURF_INDEX_SELECTED = 2 ARROW_PADDING = 10 KEY_PADDING = 30 RESET_MARGIN_BOTTOM = 20 INDEX_UP = 0 INDEX_DOWN = 2 INDEX_LEFT = 1 INDEX_RIGHT = 3 INDEX_ATTACK = 4 INDEX_ACTION = 5 INDEX_ESCAPE = 6 INDEX_RETURN = 7 INDEX_RESET = 8 NUM_OPTIONS = 9 def __init__(self): self.loader = AssetLoader('images') self.control_loader = AssetLoader(join('images', 'controls')) self.background_img = self.loader.load_image('background.png') self.title_surf = self.loader.load_image_alpha( ControlSettings.TITLE_IMAGE_PATH) self.title_rect = self.title_surf.get_rect() self.title_rect.centerx = Globals.WIDTH / 2 self.title_rect.top = ControlSettings.TITLE_MARGIN_TOP self.arrows_top = self.title_rect.bottom + \ ControlSettings.TITLE_ARROW_MARGIN self.arrows_x_center = int(Globals.WIDTH / 4) self.text_top = self.title_rect.bottom + \ ControlSettings.TITLE_TEXT_MARGIN self.surf_rect_pairs = [SurfRectPair() for i in range(0, ControlSettings.NUM_OPTIONS)] self.surf_index = [ControlSettings.SURF_INDEX_NORMAL for i in range( 0, ControlSettings.NUM_OPTIONS)] self.last_surf_index = [ ControlSettings.SURF_INDEX_NORMAL for i in range(0, ControlSettings.NUM_OPTIONS)] self.ignore_index = [0 for i in range(0, ControlSettings.NUM_OPTIONS)] self.load_control_images() self.selection = 0 self.set_selection(0) def set_selection(self, index): if self.selection != -1: if self.surf_index[self.selection] == \ ControlSettings.SURF_INDEX_HIT: self.last_surf_index[ self.selection] = ControlSettings.SURF_INDEX_NORMAL else: self.last_surf_index[ self.selection] = ControlSettings.SURF_INDEX_NORMAL self.surf_index[ self.selection] = ControlSettings.SURF_INDEX_NORMAL self.selection = index if self.surf_index[index] == ControlSettings.SURF_INDEX_HIT: self.last_surf_index[index] = ControlSettings.SURF_INDEX_SELECTED else: self.last_surf_index[index] = self.surf_index[index] self.surf_index[index] = ControlSettings.SURF_INDEX_SELECTED def change_selection(self, delta): index = self.selection + delta if index < 0 or index >= ControlSettings.NUM_OPTIONS: return self.set_selection(index) def select(self): if self.selection == -1: return if self.selection == ControlSettings.INDEX_RESET: SettingsManager.reset_controls() self.set_selection(0) return Globals.STATE = SetJoystickKeyState( self.surf_rect_pairs[self.selection].surf_arr[0], list_index=self.selection, return_state=self) def load_image_group(self, file_path): return self.control_loader.load_spritesheet_alpha( file_path, num_rows=3, num_cols=1) def set_surf_arr(self, index, file_path): self.surf_rect_pairs[index].surf_arr = self.load_image_group(file_path) self.surf_rect_pairs[index].rect = self.surf_rect_pairs[ index].surf_arr[0].get_rect() def get_surf(self, index): return self.surf_rect_pairs[index].surf_arr[self.surf_index[index]] def get_rect(self, index): return self.surf_rect_pairs[index].rect def load_control_images(self): self.load_arrows() self.set_surf_arr(ControlSettings.INDEX_ATTACK, 'attack_key.png') self.set_surf_arr(ControlSettings.INDEX_ACTION, 'action_key.png') self.set_surf_arr(ControlSettings.INDEX_ESCAPE, 'escape_key.png') self.set_surf_arr(ControlSettings.INDEX_RETURN, 'return_key.png') self.set_surf_arr(ControlSettings.INDEX_RESET, 'reset_controls.png') centerx = int((3 * Globals.WIDTH) / 4) attack_key_rect = self.get_rect(ControlSettings.INDEX_ATTACK) attack_key_rect.centerx = centerx attack_key_rect.top = self.text_top action_key_rect = self.get_rect(ControlSettings.INDEX_ACTION) action_key_rect.centerx = centerx action_key_rect.top = attack_key_rect.bottom + \ ControlSettings.KEY_PADDING escape_key_rect = self.get_rect(ControlSettings.INDEX_ESCAPE) escape_key_rect.centerx = centerx escape_key_rect.top = action_key_rect.bottom + \ ControlSettings.KEY_PADDING return_key_rect = self.get_rect(ControlSettings.INDEX_RETURN) return_key_rect.centerx = centerx return_key_rect.top = escape_key_rect.bottom + \ ControlSettings.KEY_PADDING reset_rect = self.get_rect(ControlSettings.INDEX_RESET) reset_rect.centerx = int(Globals.WIDTH / 2) reset_rect.bottom = Globals.HEIGHT - \ ControlSettings.RESET_MARGIN_BOTTOM def load_arrows(self): self.set_surf_arr(ControlSettings.INDEX_UP, 'arrow_up.png') self.set_surf_arr(ControlSettings.INDEX_DOWN, 'arrow_down.png') self.set_surf_arr(ControlSettings.INDEX_LEFT, 'arrow_left.png') self.set_surf_arr(ControlSettings.INDEX_RIGHT, 'arrow_right.png') arrow_up_rect = self.get_rect(ControlSettings.INDEX_UP) arrow_up_rect.centerx = self.arrows_x_center arrow_up_rect.top = self.arrows_top arrow_down_rect = self.get_rect(ControlSettings.INDEX_DOWN) arrow_down_rect.centerx = arrow_up_rect.centerx arrow_down_rect.top = arrow_up_rect.bottom + \ ControlSettings.ARROW_PADDING arrow_left_rect = self.get_rect(ControlSettings.INDEX_LEFT) arrow_left_rect.top = arrow_down_rect.top arrow_left_rect.right = arrow_down_rect.left - \ ControlSettings.ARROW_PADDING arrow_right_rect = self.get_rect(ControlSettings.INDEX_RIGHT) arrow_right_rect.top = arrow_down_rect.top arrow_right_rect.left = arrow_down_rect.right + \ ControlSettings.ARROW_PADDING def render(self): Globals.SCREEN.blit(self.background_img, (0, 0)) Globals.SCREEN.blit(self.title_surf, self.title_rect) for i, pair in enumerate(self.surf_rect_pairs): Globals.SCREEN.blit(pair.surf_arr[self.surf_index[i]], pair.rect) def handle_raw_event(self, event): if event.type == pygame.KEYDOWN: index = -1 if event in SettingsManager.EVENTS_UP: index = ControlSettings.INDEX_UP elif event in SettingsManager.EVENTS_DOWN: index = ControlSettings.INDEX_DOWN elif event in SettingsManager.EVENTS_LEFT: index = ControlSettings.INDEX_LEFT elif event in SettingsManager.EVENTS_RIGHT: index = ControlSettings.INDEX_RIGHT elif event in SettingsManager.EVENTS_ESCAPE: index = ControlSettings.INDEX_ESCAPE elif event in SettingsManager.EVENTS_ACTION: index = ControlSettings.INDEX_ACTION elif event in SettingsManager.EVENTS_ATTACK: index = ControlSettings.INDEX_ATTACK elif event in SettingsManager.EVENTS_RETURN: index = ControlSettings.INDEX_RETURN if index != -1: self.ignore_index[index] = 2 def quit(self): import SettingsState Globals.STATE = SettingsState.SettingsState() def check_hit(self, index, keydown=True): if not keydown: self.ignore_index[index] = 0 if self.surf_index[index] != ControlSettings.SURF_INDEX_SELECTED: self.set_last_state(index) return False if self.ignore_index[index] > 0: self.ignore_index[index] -= 1 if self.surf_index[index] != ControlSettings.SURF_INDEX_SELECTED: self.set_last_state(index) return False self.last_surf_index[index] = self.surf_index[index] self.surf_index[index] = ControlSettings.SURF_INDEX_HIT return True def set_last_state(self, index): if self.last_surf_index[index] == ControlSettings.SURF_INDEX_HIT: self.last_surf_index[index] = ControlSettings.SURF_INDEX_NORMAL self.surf_index[index] = self.last_surf_index[index] def handle_action_key(self, keydown=True): self.check_hit(ControlSettings.INDEX_ACTION, keydown) def handle_action_keyup(self): self.handle_action_key(False) def handle_attack(self, keydown=True): self.check_hit(ControlSettings.INDEX_ATTACK, keydown) def handle_attack_keyup(self): self.handle_attack(False) def handle_key_down(self, keydown): if keydown and self.ignore_index[ControlSettings.INDEX_DOWN] > 0: self.change_selection(1) self.check_hit(ControlSettings.INDEX_DOWN, keydown) def handle_key_up(self, keydown): if keydown and self.ignore_index[ControlSettings.INDEX_UP] > 0: self.change_selection(-1) self.check_hit(ControlSettings.INDEX_UP, keydown) def handle_key_left(self, keydown): if keydown and self.ignore_index[ControlSettings.INDEX_LEFT] > 0: self.change_selection(-1) self.check_hit(ControlSettings.INDEX_LEFT, keydown) def handle_key_right(self, keydown): if keydown and self.ignore_index[ControlSettings.INDEX_RIGHT] > 0: self.change_selection(1) self.check_hit(ControlSettings.INDEX_RIGHT, keydown) def handle_backspace(self): pass def handle_return(self, keydown=True): if keydown and self.ignore_index[ControlSettings.INDEX_RETURN] > 0: self.select() self.ignore_index[ControlSettings.INDEX_RETURN] = 0 else: self.check_hit(ControlSettings.INDEX_RETURN, keydown) def handle_return_keyup(self): self.handle_return(False) def handle_escape(self, keydown=True): if self.ignore_index[ControlSettings.INDEX_ESCAPE] > 0: self.quit() self.check_hit(ControlSettings.INDEX_ESCAPE, keydown) def handle_escape_keyup(self): self.handle_escape(False)
class SetJoystickKeyState(GameState): ALLOWED_TYPES = set( [pygame.JOYBUTTONDOWN, pygame.JOYAXISMOTION, pygame.JOYHATMOTION]) TITLE_IMAGE_PATH = 'set_key.png' TITLE_MARGIN_TOP = 60 def __init__(self, image_surf, list_index, return_state): self.list_index = list_index self.return_state = return_state self.image_surf = image_surf self.loader = AssetLoader('images') self.image_rect = self.image_surf.get_rect() self.image_rect.center = Globals.SCREEN.get_rect().center self.init_images() def init_images(self): self.background_img = self.loader.load_image('background.png') self.title_surf = self.loader.load_image_alpha( SetJoystickKeyState.TITLE_IMAGE_PATH) self.title_rect = self.title_surf.get_rect() self.title_rect.centerx = Globals.WIDTH / 2 self.title_rect.top = SetJoystickKeyState.TITLE_MARGIN_TOP def render(self): Globals.SCREEN.blit(self.background_img, (0, 0)) Globals.SCREEN.blit(self.title_surf, self.title_rect) Globals.SCREEN.blit(self.image_surf, self.image_rect) def handle_escape(self): Globals.STATE = self.return_state def set_event(self, event): pair = self.convert_event(event) SettingsManager.EVENTS_UP = [ a for a in SettingsManager.EVENTS_UP if a != event] SettingsManager.EVENTS_DOWN = [ a for a in SettingsManager.EVENTS_DOWN if a != event] SettingsManager.EVENTS_LEFT = [ a for a in SettingsManager.EVENTS_LEFT if a != event] SettingsManager.EVENTS_RIGHT = [ a for a in SettingsManager.EVENTS_RIGHT if a != event] SettingsManager.EVENTS_ATTACK = [ a for a in SettingsManager.EVENTS_ATTACK if a != event] SettingsManager.EVENTS_ACTION = [ a for a in SettingsManager.EVENTS_ACTION if a != event] SettingsManager.EVENTS_ESCAPE = [ a for a in SettingsManager.EVENTS_ESCAPE if a != event] SettingsManager.EVENTS_RETURN = [ a for a in SettingsManager.EVENTS_RETURN if a != event] SettingsManager.EVENTS_BACKSPACE = [ a for a in SettingsManager.EVENTS_BACKSPACE if a != event] self.get_event_list().append(pair) SettingsManager.save() self.handle_escape() def get_event_list(self): from ControlSettings import ControlSettings if self.list_index == ControlSettings.INDEX_ESCAPE: return SettingsManager.EVENTS_ESCAPE elif self.list_index == ControlSettings.INDEX_ATTACK: return SettingsManager.EVENTS_ATTACK elif self.list_index == ControlSettings.INDEX_ACTION: return SettingsManager.EVENTS_ACTION elif self.list_index == ControlSettings.INDEX_RETURN: return SettingsManager.EVENTS_RETURN elif self.list_index == ControlSettings.INDEX_UP: return SettingsManager.EVENTS_UP elif self.list_index == ControlSettings.INDEX_DOWN: return SettingsManager.EVENTS_DOWN elif self.list_index == ControlSettings.INDEX_LEFT: return SettingsManager.EVENTS_LEFT elif self.list_index == ControlSettings.INDEX_RIGHT: return SettingsManager.EVENTS_RIGHT else: return list() def convert_event(self, event): pair = EventPair(type=event.type) if event.type == pygame.JOYBUTTONDOWN: pair.value = event.button elif event.type == pygame.JOYAXISMOTION: if event.value < 0: pair.value = -1 elif event.value > 0: pair.value = 1 else: pair.value = 0 pair.axis = event.axis elif event.type == pygame.JOYHATMOTION: pair.hat = event.hat pair.value = event.value return pair def handle_raw_event(self, event): if event.type in SetJoystickKeyState.ALLOWED_TYPES and \ EventManager.is_keydown(event): self.set_event(event)
class CustomLevelPicker(GameState): MAP_FILE_EXT = 'txt' CUSTOM_MAP_PATH = join('maps', 'custom') PLAY_PATH = 'custom' SELECTION_FONT = pygame.font.Font(None, 70) SELECTION_COLOR = pygame.color.Color('white') CREATE_NEW_TEXT = 'Create New Level' SELECTION_TOP_MARGIN = 30 SELECTION_PADDING = 20 HIGHLIGHT_PADDING_HEIGHT = 30 HIGHLIGHT_PADDING_WIDTH = 70 HIGHLIGHT_COLOR = pygame.color.Color("black") HIGHLIGHT_ALPHA = 150 ARROW_MARGIN = 20 SUBTITLE_BACKGROUND = pygame.color.Color("black") SUBTITLE_PADDING = 10 CENTER_SUBTITLE_TEXT = "Press enter to play" LEFT_SUBTITLE_TEXT = "Press 'd' to delete" RIGHT_SUBTITLE_TEXT = "Press 'e' to edit" SUBTITLE_OFFSET = 40 NEW_SUBTITLE_TEXT = "Press enter" SUBTITLE_COLOR = pygame.color.Color("white") SUBTITLE_FONT = pygame.font.Font(None, 32) SUBTITLE_MARGIN_BOTTOM = 50 TITLE_IMAGE_PATH = 'customlevel.png' TITLE_MARGIN_TOP = 70 def __init__(self): self.init_images() self.file_manager = FileManager( path=CustomLevelPicker.CUSTOM_MAP_PATH, file_ext=CustomLevelPicker.MAP_FILE_EXT) self.file_names = self.file_manager.get_files(strip_ext=True) self.current_selection = 0 self.text_surf = None self.text_rect = None self.highlight_surf = None self.highlight_rect = None self.build_text() self.build_subtitles() Globals.play_menu_sound() def init_images(self): self.loader = AssetLoader('images') self.background_img = self.loader.load_image('background.png') self.title_surf = self.loader.load_image_alpha( CustomLevelPicker.TITLE_IMAGE_PATH) self.title_rect = self.title_surf.get_rect() self.title_rect.center = Globals.SCREEN.get_rect().center self.title_rect.top = CustomLevelPicker.TITLE_MARGIN_TOP self.arrow_down_surf = self.loader.load_image_alpha('arrow_down.png') self.arrow_down_rect = self.arrow_down_surf.get_rect() self.arrow_up_surf = self.loader.load_image_alpha('arrow_up.png') self.arrow_up_rect = self.arrow_up_surf.get_rect() self.arrow_up_rect.centerx = Globals.WIDTH / 2 self.arrow_down_rect.centerx = Globals.WIDTH / 2 def build_subtitles(self): self.left_subtitle_surf, self.left_subtitle_rect = self.init_subtitle( CustomLevelPicker.LEFT_SUBTITLE_TEXT, Globals.WIDTH / 4 - CustomLevelPicker.SUBTITLE_OFFSET) self.center_subtitle_surf, self.center_subtitle_rect = \ self.init_subtitle(CustomLevelPicker.CENTER_SUBTITLE_TEXT, Globals.WIDTH / 2) self.right_subtitle_surf, self.right_subtitle_rect = \ self.init_subtitle( CustomLevelPicker.RIGHT_SUBTITLE_TEXT, (3 * Globals.WIDTH) / 4 + CustomLevelPicker.SUBTITLE_OFFSET) self.new_subtitle_surf, self.new_subtitle_rect = \ self.init_subtitle(CustomLevelPicker.NEW_SUBTITLE_TEXT, Globals.WIDTH / 2) def init_subtitle(self, text, centerx): text_surf = CustomLevelPicker.SUBTITLE_FONT.render( text, True, CustomLevelPicker.SUBTITLE_COLOR) subtitle_rect = text_surf.get_rect() subtitle_rect.bottom = \ Globals.HEIGHT - CustomLevelPicker.SUBTITLE_MARGIN_BOTTOM subtitle_rect.centerx = centerx subtitle_rect.inflate_ip( CustomLevelPicker.SUBTITLE_PADDING * 2, CustomLevelPicker.SUBTITLE_PADDING * 2 ) subtitle_surf = pygame.Surface(subtitle_rect.size).convert() subtitle_surf.fill(CustomLevelPicker.SUBTITLE_BACKGROUND) subtitle_surf.blit(text_surf, ( CustomLevelPicker.SUBTITLE_PADDING, CustomLevelPicker.SUBTITLE_PADDING )) return subtitle_surf, subtitle_rect def render(self): Globals.SCREEN.blit(self.background_img, (0, 0)) Globals.SCREEN.blit(self.title_surf, self.title_rect) Globals.SCREEN.blit(self.highlight_surf, self.highlight_rect) Globals.SCREEN.blit(self.text_surf, self.text_rect) if self.current_selection == 0: Globals.SCREEN.blit(self.new_subtitle_surf, self.new_subtitle_rect) else: Globals.SCREEN.blit( self.left_subtitle_surf, self.left_subtitle_rect) Globals.SCREEN.blit( self.center_subtitle_surf, self.center_subtitle_rect) Globals.SCREEN.blit( self.right_subtitle_surf, self.right_subtitle_rect) if len(self.file_names) > 0: Globals.SCREEN.blit(self.arrow_down_surf, self.arrow_down_rect) Globals.SCREEN.blit(self.arrow_up_surf, self.arrow_up_rect) def build_text(self): self.text_surf = CustomLevelPicker.SELECTION_FONT.render( self.get_selection_name(), True, CustomLevelPicker.SELECTION_COLOR) self.text_rect = self.text_surf.get_rect() self.text_rect.center = Globals.SCREEN.get_rect().center self.text_rect.top += CustomLevelPicker.SELECTION_TOP_MARGIN self.highlight_rect = self.text_rect.inflate( CustomLevelPicker.HIGHLIGHT_PADDING_WIDTH, CustomLevelPicker.HIGHLIGHT_PADDING_HEIGHT) self.highlight_surf = pygame.Surface(self.highlight_rect.size) self.highlight_surf.fill(CustomLevelPicker.HIGHLIGHT_COLOR) self.highlight_surf.set_alpha(CustomLevelPicker.HIGHLIGHT_ALPHA) self.arrow_up_rect.bottom = self.highlight_rect.top - \ CustomLevelPicker.ARROW_MARGIN self.arrow_down_rect.top = self.highlight_rect.bottom + \ CustomLevelPicker.ARROW_MARGIN def get_selection_name(self): if self.current_selection == 0: return CustomLevelPicker.CREATE_NEW_TEXT else: return self.file_names[self.current_selection - 1] def handle_change(self, delta): self.current_selection = (self.current_selection + delta) % \ (len(self.file_names) + 1) self.build_text() def handle_selection(self): if self.current_selection != 0: file_path = self.file_manager.fix_ext( self.file_names[self.current_selection - 1]) level = CustomLevel(join(CustomLevelPicker.PLAY_PATH, file_path)) level.got_current_state() Globals.STATE = level else: Globals.STATE = CustomLevelNameInput() def handle_edit_selection(self): if self.current_selection != 0: file_path = self.file_manager.fix_ext( self.file_names[self.current_selection - 1]) Globals.STATE = LevelEditor( join('maps', 'map_def.txt'), join(CustomLevelPicker.CUSTOM_MAP_PATH, file_path), globals=Globals, in_game=True) else: Globals.STATE = CustomLevelNameInput() def handle_delete(self): if self.current_selection != 0: full_name = self.file_manager.fix_ext( self.file_names[self.current_selection - 1]) full_path = join(CustomLevelPicker.CUSTOM_MAP_PATH, full_name) try: os.remove(full_path) self.file_names = self.file_manager.get_files(strip_ext=True) self.handle_change(-1) except Exception as e: print 'An error occured while deleting "' + full_path + '"' print e def handle_escape(self): Globals.STATE = Menu.Menu() def handle_return(self): self.handle_selection() def handle_raw_event(self, event): if event.type == pygame.KEYDOWN: if event.key == pygame.K_e: self.handle_edit_selection() elif event.key == pygame.K_d: self.handle_delete() def handle_key_up(self, keydown): if keydown: self.handle_change(-1) def handle_key_down(self, keydown): if keydown: self.handle_change(1)
class SettingsState(GameState): SLIDER_SIZE = (400, 50) SLIDER_DELTA = 10 MIN_BRIGHTNESS = 30 TITLE_IMAGE_PATH = 'settings.png' CONTROL_IMAGE_PATH = 'control_settings_small.png' VOLUME_IMAGE_PATH = 'volume.png' BRIGHTNESS_IMAGE_PATH = 'brightness.png' TITLE_MARGIN_TOP = 60 TITLE_MARGIN_BOTTOM = 50 LABEL_SLIDER_MARGIN = 5 SLIDER_MARGIN = 10 LABEL_FONT = pygame.font.Font(None, 60) LABEL_COLOR = pygame.color.Color('white') def __init__(self): self.loader = AssetLoader('images') self.background_img = self.loader.load_image('background.png') Globals.play_menu_sound() self.title_surf = self.loader.load_image_alpha( SettingsState.TITLE_IMAGE_PATH) self.title_rect = self.title_surf.get_rect() self.title_rect.centerx = Globals.WIDTH / 2 self.title_rect.top = SettingsState.TITLE_MARGIN_TOP self.control_index = 0 self.init_labels() self.init_sliders() self.selected = 0 def init_labels(self): self.volume_label_surf = self.loader.load_image_alpha( SettingsState.VOLUME_IMAGE_PATH) self.volume_label_rect = self.volume_label_surf.get_rect() self.volume_label_rect.centerx = Globals.WIDTH / 2 self.volume_label_rect.top = self.title_rect.bottom + \ SettingsState.TITLE_MARGIN_BOTTOM self.brightness_label_surf = self.loader.load_image_alpha( SettingsState.BRIGHTNESS_IMAGE_PATH) self.brightness_label_rect = self.brightness_label_surf.get_rect() self.brightness_label_rect.centerx = Globals.WIDTH / 2 self.brightness_label_rect.top = self.volume_label_rect.bottom + \ SettingsState.LABEL_SLIDER_MARGIN + \ SettingsState.SLIDER_SIZE[1] + SettingsState.SLIDER_MARGIN self.control_surfs = self.loader.load_spritesheet_alpha( SettingsState.CONTROL_IMAGE_PATH, num_rows=2, num_cols=1) self.control_rect = self.control_surfs[0].get_rect() self.control_rect.centerx = Globals.WIDTH / 2 self.control_rect.top = self.brightness_label_rect.bottom + \ SettingsState.LABEL_SLIDER_MARGIN + \ SettingsState.SLIDER_SIZE[1] + SettingsState.SLIDER_MARGIN def init_sliders(self): volume_slider_rect = pygame.Rect((0, 0), SettingsState.SLIDER_SIZE) volume_slider_rect.centerx = Globals.WIDTH / 2 volume_slider_rect.top = self.volume_label_rect.bottom + \ SettingsState.LABEL_SLIDER_MARGIN self.volume_slider = SettingsSlider( volume_slider_rect, max_value=100, value=SettingsManager.VOLUME) self.volume_slider.select() brightness_slider_rect = pygame.Rect((0, 0), SettingsState.SLIDER_SIZE) brightness_slider_rect.centerx = Globals.WIDTH / 2 brightness_slider_rect.top = self.brightness_label_rect.bottom + \ SettingsState.LABEL_SLIDER_MARGIN self.brightness_slider = SettingsSlider( brightness_slider_rect, max_value=(100 - SettingsState.MIN_BRIGHTNESS), value=(SettingsManager.BRIGHTNESS - SettingsState.MIN_BRIGHTNESS)) def render(self): Globals.SCREEN.blit(self.background_img, (0, 0)) Globals.SCREEN.blit(self.title_surf, self.title_rect) Globals.SCREEN.blit(self.volume_label_surf, self.volume_label_rect) Globals.SCREEN.blit(self.brightness_label_surf, self.brightness_label_rect) Globals.SCREEN.blit(self.control_surfs[self.control_index], self.control_rect) self.volume_slider.render(Globals.SCREEN) self.brightness_slider.render(Globals.SCREEN) def update(self, time): self.volume_slider.update(time) self.brightness_slider.update(time) def change_selection(self, delta): self.selected = (self.selected + delta) % 3 if self.selected == 0: self.control_index = 0 self.volume_slider.select() self.brightness_slider.deselect() if self.selected == 1: self.control_index = 0 self.volume_slider.deselect() self.brightness_slider.select() elif self.selected == 2: self.control_index = 1 self.brightness_slider.deselect() self.volume_slider.deselect() def change_value(self, factor=1): if self.selected == 0: self.volume_slider.change_value( SettingsState.SLIDER_DELTA * factor) Globals.set_volume(self.volume_slider.value) elif self.selected == 1: self.brightness_slider.change_value( SettingsState.SLIDER_DELTA * factor) Globals.set_brightness(SettingsState.MIN_BRIGHTNESS + self.brightness_slider.value) def handle_escape(self): Globals.STATE = Menu.Menu() def handle_return(self): if self.selected == 2: Globals.STATE = ControlSettings() def handle_key_left(self, keydown): if keydown: self.change_value(-1) def handle_key_right(self, keydown): if keydown: self.change_value(1) def handle_key_up(self, keydown): if keydown: self.change_selection(-1) def handle_key_down(self, keydown): if keydown: self.change_selection(1)
class PauseScreen(GameState): UNPAUSE_KEYS = [pygame.K_p, pygame.K_RETURN] TITLE_FONT = pygame.font.Font(None, 100) TITLE_TEXT = 'Game Paused' TITLE_COLOR = pygame.color.Color('white') ALPHA_FACTOR = 550 MIN_ALPHA = 0 MAX_ALPHA = 255 def __init__(self, return_state, escape_state=None): self.return_state = return_state self.escape_state = escape_state if escape_state is not None else \ Menu.Menu() self.loader = AssetLoader('images') self.background_img = self.loader.load_image('background.png') self.pause_image = self.loader.load_image_alpha('game-paused.png') Globals.play_menu_sound() # self.title_surf = PauseScreen.TITLE_FONT.render( # PauseScreen.TITLE_TEXT, True, PauseScreen.TITLE_COLOR) # self.title_rect = self.title_surf.get_rect() # self.title_rect.center = Globals.SCREEN.get_rect().center self.black_surf = pygame.Surface( (Globals.WIDTH, Globals.HEIGHT)).convert() self.black_surf.fill((0, 0, 0)) self.fade_in = False self.fade_out = False self.alpha_factor = 300 self.start_fade_in() def render(self): Globals.SCREEN.blit(self.background_img, (0, 0)) # Globals.SCREEN.blit(self.title_surf, self.title_rect) Globals.SCREEN.blit(self.pause_image, [175, Globals.HEIGHT / 3]) if self.fade_out or self.fade_in: Globals.SCREEN.blit(self.black_surf, (0, 0)) def update(self, time): if self.fade_out: old_alpha = self.black_surf.get_alpha() new_alpha = int(old_alpha + time * PauseScreen.ALPHA_FACTOR) if new_alpha >= PauseScreen.MAX_ALPHA: self.handle_finish_fade_out() self.fade_out = False self.black_surf.set_alpha(new_alpha) elif self.fade_in: old_alpha = self.black_surf.get_alpha() new_alpha = int(old_alpha - time * PauseScreen.ALPHA_FACTOR) if new_alpha <= PauseScreen.MIN_ALPHA: self.fade_in = False self.black_surf.set_alpha(new_alpha) def start_fade_out(self): if self.fade_out: return self.black_surf.set_alpha(PauseScreen.MIN_ALPHA) self.fade_out = True def start_fade_in(self): self.black_surf.set_alpha(PauseScreen.MAX_ALPHA) self.fade_in = True def handle_finish_fade_out(self): fn = getattr(self.return_state, "handle_unpause", None) if callable(fn): fn() Globals.STATE = self.return_state def handle_escape(self): Globals.STATE = self.escape_state def handle_return(self): Globals.stop_menu_sound() self.start_fade_out() def handle_action_key(self): Globals.stop_menu_sound() self.start_fade_out() def handle_raw_event(self, event): if EventManager.is_keyboard_event(event.type) and \ event not in SettingsManager.EVENTS_ESCAPE and \ event not in SettingsManager.EVENTS_RETURN and \ event not in SettingsManager.EVENTS_ACTION: self.handle_return()