class World(EventListenerBase): """World holds the data needed by fife to render the engine The engine keeps a copy of this class""" def __init__(self, engine): """Constructor for engine @type engine: fife.Engine @param engine: A fife.Engine instance @return: None""" super(World, self).__init__(engine, reg_mouse=True, reg_keys=True) # self.engine is a fife.Engine object, not an Engine object self.engine = engine self.event_manager = engine.getEventManager() self.quitFunction = None # self.data is an engine.Engine object, but is set in run.py self.data = None self.mouseCallback = None # self.map is a Map object, set to none here self.active_map = None self.maps = {} self.action_number = 1 # init the sound self.sounds = SoundEngine(engine) # don't force restart if skipping to new section if TDS.readSetting("PlaySounds") == "1": if not self.sounds.music_init: self.sounds.playMusic("/music/preciouswasteland.ogg") # The current highlighted object self.highlight_obj = None # Last saved mouse coords self.last_mousecoords = None # faded objects in top layer self.faded_objects = set() # current map scroll velocity vector self.scroll_vect = [0.0, 0.0] # scroll speed - should be moved to settings self.scroll_speed = 1 def initHud(self): """Initialize the hud member @return: None""" hud_callbacks = { 'saveGame': self.saveGame, 'loadGame': self.loadGame, 'quitGame': self.quitGame, } self.hud = hud.Hud(self.engine, TDS, self.data, hud_callbacks) def quitGame(self): """Quits the game @return: None""" self.quitFunction() def saveGame(self, *args, **kwargs): """Saves the game state, delegates call to engine.Engine @return: None""" self.data.save(*args, **kwargs) def loadGame(self, *args, **kwargs): """Loads the game state, delegates call to engine.Engine @return: None""" self.data.load(*args, **kwargs) def loadMap(self, map_name, filename): """Loads a map and stores it under the given name in the maps list. @type map_name: String @param map_name: The name of the map to load @type filename: String @param filename: File which contains the map to be loaded @return: None""" if not map_name in self.maps: map = Map(self.engine, self.data) self.maps[map_name] = map map.load(filename) else: self.setActiveMap(map_name) def setActiveMap(self, map_name): """Sets the active map that is to be rendered. @type map_name: String @param map_name: The name of the map to load @return: None""" # Turn off the camera on the old map before we turn on the camera # on the new map. self.active_map.cameras[self.active_map.my_cam_id].setEnabled(False) # Make the new map active. self.active_map = self.maps[map_name] self.active_map.makeActive() def displayObjectText(self, obj, text): """Display on screen the text of the object over the object. @type obj: fife.instance @param obj: object to draw over @type text: String @param text: text to display over object @return: None""" obj.say(str(text), 1000) def keyPressed(self, evt): """Whenever a key is pressed, fife calls this routine. @type evt: fife.event @param evt: The event that fife caught @return: None""" key = evt.getKey() key_val = key.getValue() if(key_val == key.Q): # we need to quit the game self.hud.quitGame() if(key_val == key.T): self.active_map.toggleRenderer('GridRenderer') if(key_val == key.F1): # display the help screen and pause the game self.hud.displayHelp() if(key_val == key.F5): self.active_map.toggleRenderer('CoordinateRenderer') if(key_val == key.F7): # F7 saves a screenshot to fife/clients/parpg/screenshots t = "screenshots/screen-%s-%s.png" % \ (date.today().strftime('%Y-%m-%d'),\ time.strftime('%H-%M-%S')) print "PARPG: Saved:",t self.engine.getRenderBackend().captureScreen(t) if(key_val == key.F10): # F10 shows/hides the console self.engine.getGuiManager().getConsole().toggleShowHide() if(key_val == key.I): # I opens and closes the inventory self.hud.toggleInventory() if(key_val == key.A): # A adds a test action to the action box # The test actions will follow this format: Action 1, # Action 2, etc. self.hud.addAction("Action " + str(self.action_number)) self.action_number += 1 if(key_val == key.ESCAPE): # Escape brings up the main menu self.hud.displayMenu() # Hide the quit menu self.hud.quit_window.hide() if(key_val == key.M): self.sounds.toggleMusic() if(key_val == key.PAUSE): # Pause pause/unpause the game self.togglePause() # map scrolling if key_val == key.UP: self.startMapScroll(0, -1) if key_val == key.DOWN: self.startMapScroll(0, 1) if key_val == key.LEFT: self.startMapScroll(-1, 0) if key_val == key.RIGHT: self.startMapScroll(1, 0) def keyReleased(self, evt): """Whenever a key is pressed, fife calls this routine. @type evt: fife.event @param evt: The event that fife caught @return: None""" key = evt.getKey() key_val = key.getValue() # map scrolling if key_val == key.UP: self.stopMapScroll(0, -1) if key_val == key.DOWN: self.stopMapScroll(0, 1) if key_val == key.LEFT: self.stopMapScroll(-1, 0) if key_val == key.RIGHT: self.stopMapScroll(1, 0) def mouseReleased(self, evt): """If a mouse button is released, fife calls this routine. We want to wait until the button is released, because otherwise pychan captures the release if a menu is opened. @type evt: fife.event @param evt: The event that fife caught @return: None""" self.hud.hideContextMenu() scr_point = fife.ScreenPoint(evt.getX(), evt.getY()) if(evt.getButton() == fife.MouseEvent.LEFT): self.data.handleMouseClick(self.getCoords(scr_point)) elif(evt.getButton() == fife.MouseEvent.RIGHT): # is there an object here? instances = self.active_map.cameras[self.active_map.my_cam_id].\ getMatchingInstances(scr_point, \ self.active_map.agent_layer) info = None for inst in instances: # check to see if this is an active item if(self.data.objectActive(inst.getId())): # yes, get the data info = self.data.getItemActions(inst.getId()) break # take the menu items returned by the engine or show a # default menu if no items data = info or \ [["Walk", "Walk here", self.onWalk, self.getCoords(scr_point)]] # show the menu self.hud.showContextMenu(data, (scr_point.x, scr_point.y)) def onWalk(self, click): """Callback sample for the context menu.""" self.hud.hideContainer() self.data.game_state.PC.run(click) def refreshTopLayerInstanceTransparencies(self): """Fade or unfade TopLayer instances if the PC is under them.""" # get the PC's screen coordinates camera = self.active_map.cameras[self.active_map.my_cam_id] point = self.data.game_state.PC.behaviour.agent.getLocation() scr_coords = camera.toScreenCoordinates(point.getMapCoordinates()) # find all instances on TopLayer that fall on those coordinates instances = camera.getMatchingInstances(scr_coords, self.active_map.top_layer) instance_ids = [ instance.getId() for instance in instances ] faded_objects = self.faded_objects # fade instances for instance_id in instance_ids: if instance_id not in faded_objects: faded_objects.add(instance_id) instance.get2dGfxVisual().setTransparency(128) # unfade previously faded instances for instance_id in faded_objects.copy(): if instance_id not in instance_ids: faded_objects.remove(instance_id) self.active_map.top_layer.getInstance(instance_id).\ get2dGfxVisual().setTransparency(0) def teleport(self, position): """Called when a door is used that moves a player to a new location on the same map. the setting of position may want to be created as its own method down the road. @type position: String Tuple @param position: X,Y coordinates passed from engine.changeMap @return: fife.Location """ print position coord = fife.DoublePoint3D(float(position[0]), float(position[1]), 0) location = fife.Location(self.active_map.agent_layer) location.setMapCoordinates(coord) self.data.game_state.PC.teleport(location) def mouseMoved(self, evt): """Called when the mouse is moved @type evt: fife.event @param evt: The event that fife caught @return: None""" self.last_mousecoords = fife.ScreenPoint(evt.getX(), evt.getY()) self.highlightFrontObject() def highlightFrontObject(self): """Highlights the object that is at the current mouse coordinates""" if self.last_mousecoords: front_obj = self.getObjectAtCoords(self.last_mousecoords) if front_obj != None: if self.highlight_obj == None or front_obj.getId() != self.highlight_obj.getId(): if self.highlight_obj: self.displayObjectText(self.highlight_obj,"") self.active_map.outline_render.removeAllOutlines() self.highlight_obj = front_obj self.active_map.outline_render.addOutlined(self.highlight_obj, 0, \ 137, 255, 2) # get the text item = self.data.objectActive(self.highlight_obj.getId()) if item is not None: self.displayObjectText(self.highlight_obj, item.name) else: if self.highlight_obj: self.displayObjectText(self.highlight_obj,"") self.active_map.outline_render.removeAllOutlines() self.highlight_obj = None def getObjectAtCoords(self, coords): """Get the object which is at the given coords @type coords: fife.Screenpoint @param coords: Coordinates where to check for an object @rtype: fife.Object @return: An object or None""" i=self.active_map.cameras[self.active_map.my_cam_id].\ getMatchingInstances(coords, self.active_map.agent_layer) # no object returns an empty tuple if(i != ()): front_y = 0 for obj in i: # check to see if this in our list at all if(self.data.objectActive(obj.getId())): # check if the object is on the foreground obj_map_coords = \ obj.getLocation().getMapCoordinates() obj_screen_coords = self.active_map.\ cameras[self.active_map.my_cam_id]\ .toScreenCoordinates(obj_map_coords) if obj_screen_coords.y > front_y: #Object on the foreground front_y = obj_screen_coords.y return obj else: return None else: return None def getCoords(self, click): """Get the map location x, y coordinates from the screen coordinates @type click: fife.ScreenPoint @param click: Screen coordinates @rtype: fife.Location @return: The map coordinates""" coord = self.active_map.cameras[self.active_map.my_cam_id].\ toMapCoordinates(click, False) coord.z = 0 location = fife.Location(self.active_map.agent_layer) location.setMapCoordinates(coord) return location def togglePause(self): """ Pause/Unpause the game. @return: nothing""" self.active_map.togglePause() def deleteMaps(self): """Clear all currently loaded maps from FIFE as well as clear our local map cache @return: nothing""" self.engine.getView().clearCameras() self.engine.getModel().deleteMaps() self.engine.getModel().deleteObjects() self.maps = {} def startMapScroll(self, vx, vy): # ignore doubled or contrary requests if self.scroll_vect[0] == 0.0: self.scroll_vect[0] = sign(vx)*self.scroll_speed if self.scroll_vect[1] == 0.0: self.scroll_vect[1] = sign(vy)*self.scroll_speed def stopMapScroll(self, vx, vy): pass # ignore contrary requests if sign(self.scroll_vect[0]) == sign(vx): self.scroll_vect[0] = 0.0 if sign(self.scroll_vect[1]) == sign(vy): self.scroll_vect[1] = 0.0 def scrollMap(self): """Routine applies scroll_vect to camera position in screen space""" camera = self.active_map.cameras[self.active_map.my_cam_id] map_coords = camera.getLocationRef().getMapCoordinates() screen_coords = camera.toScreenCoordinates(map_coords) delta_time = self.engine.getTimeManager().getTimeDelta() cell_dim = camera.getCellImageDimensions() aspect = cell_dim.x / cell_dim.y screen_coords += fife.Point3D(int(self.scroll_vect[0]*delta_time), int(self.scroll_vect[1]*delta_time*aspect)) map_coords = camera.toMapCoordinates(screen_coords, True) map_coords.z = 0 camera.getLocationRef().setMapCoordinates(map_coords) camera.refresh() def pump(self): """Routine called during each frame. Our main loop is in ./run.py""" # uncomment to instrument # t0 = time.time() self.highlightFrontObject() self.refreshTopLayerInstanceTransparencies() # print "%05f" % (time.time()-t0,) self.scrollMap()
class World(EventListenerBase): """World holds the data needed by fife to render the engine The engine keeps a copy of this class""" def __init__(self, engine): """Constructor for engine @type engine: fife.Engine @param engine: A fife.Engine instance @return: None""" super(World, self).__init__(engine, regMouse = True, regKeys = True) # self.engine is a fife.Engine object, not an Engine object self.engine = engine self.eventmanager = engine.getEventManager() self.quitFunction = None # self.data is an engine.Engine object, but is set in run.py self.data = None self.mouseCallback = None self.obj_hash={} # self.map is a Map object, set to none here self.activeMap = None self.maps = {} self.hud = hud.Hud(self.engine, self, TDS) self.action_number = 1 # setup the inventory # make slot 'A1' and 'A3' container daggers inv_data = {'A1':'dagger01', 'A3':'dagger01'} self.inventory = inventory.Inventory(self.engine, inv_data, self.hud.refreshReadyImages, self.hud.toggleInventoryButton) self.hud.refreshReadyImages() self.boxOpen = False self.boxCreated = False # init the sound self.sounds = SoundEngine(engine) # don't force restart if skipping to new section if (TDS.readSetting("PlaySounds") == "1"): if(self.sounds.music_init == False): self.sounds.playMusic("/music/preciouswasteland.ogg") def saveFunction(self, *args, **kwargs): """Callback for save game @return: None""" self.data.save(*args, **kwargs) def loadFunction(self, *args, **kwargs): """Callback for load game @return: None""" self.data.load(*args, **kwargs) def loadMap(self, mapname, filename): """Loads a map an stores it under the given name in the maps list. """ map = Map(self.engine, self.data) """Need to set active map before we load it because the map loader uses call backs that expect to find an active map. This needs to be reworked. """ self.maps[mapname] = map self.setActiveMap(mapname) map.load(filename) def setActiveMap(self, mapname): """Sets the active map that is to be rendered. """ self.activeMap = self.maps[mapname] self.activeMap.makeActive() def displayObjectText(self, obj, text): """Display on screen the text of the object over the object. @type obj: fife.instance @param obj: object to draw over @type text: text @param text: text to display over object @return: None""" obj.say(str(text), 1000) # all key / mouse event handling routines go here def keyPressed(self, evt): """Whenever a key is pressed, fife calls this routine. @type evt: fife.event @param evt: The event that fife caught @return: None""" key = evt.getKey() keyval = key.getValue() if(keyval == key.Q): # we need to quit the game self.hud.quitGame() if(keyval == key.T): self.activeMap.toggle_renderer('GridRenderer') if(keyval == key.F1): # display the help screen and pause the game self.hud.displayHelp() if(keyval == key.F5): # logic would say we use similar code to above and toggle # logic here does not work, my friend :-( self.cord_render.setEnabled(not self.cord_render.isEnabled()) if(keyval == key.F7): # F7 saves a screenshot to fife/clients/parpg/screenshots t = "screenshots/screen-%s-%s.png" % (date.today().strftime('%Y-%m-%d'), time.strftime('%H-%M-%S')) print "PARPG: Saved:",t self.engine.getRenderBackend().captureScreen(t) if(keyval == key.F10): # F10 shows/hides the console self.engine.getGuiManager().getConsole().toggleShowHide() if(keyval == key.I): # I opens and closes the inventory self.hud.displayInventory(callFromHud=False) if(keyval == key.A): # A adds a test action to the action box # The test actions will follow this format: Action 1, Action 2, etc. self.hud.addAction("Action " + str(self.action_number)) self.action_number += 1 if(keyval == key.ESCAPE): # Escape brings up the main menu self.hud.displayMenu() if(keyval == key.M): self.sounds.toggleMusic() def mouseReleased(self, evt): """If a mouse button is released, fife calls this routine. We want to wait until the button is released, because otherwise pychan captures the release if a menu is opened. @type evt: fife.event @param evt: The event that fife caught @return: None""" self.hud.context_menu.hide() # hide the context menu in case it is displayed scr_point = fife.ScreenPoint(evt.getX(), evt.getY()) if(evt.getButton() == fife.MouseEvent.LEFT): self.data.handleMouseClick(self.getCoords(scr_point)) elif(evt.getButton() == fife.MouseEvent.RIGHT): # is there an object here? instances = self.activeMap.cameras['main'].getMatchingInstances(scr_point, self.activeMap.agent_layer) info = None for inst in instances: # check to see if this is an active item if(self.data.objectActive(inst.getId())): # yes, get the data info = self.data.getItemActions(inst.getId()) break # take the menu items returned by the engine or show a default menu if no items data = info or [["Walk", "Walk here", self.onWalk, self.getCoords(scr_point)]] # show the menu self.hud.showContextMenu(data, (scr_point.x, scr_point.y)) def onWalk(self, click): """Callback sample for the context menu. """ self.hud.context_menu.hide() self.data.gameState.PC.run(click) def mouseMoved(self, evt): """Called when the mouse is moved @type evt: fife.event @param evt: The event that fife caught @return: None""" click = fife.ScreenPoint(evt.getX(), evt.getY()) i=self.activeMap.cameras['main'].getMatchingInstances(click, self.activeMap.agent_layer) # no object returns an empty tuple if(i != ()): for obj in i: # check to see if this in our list at all if(self.data.objectActive(obj.getId())): # yes, so outline self.activeMap.outline_render.addOutlined(obj, 0, 137, 255, 2) # get the text item = self.data.objectActive(obj.getId()) if(item): self.displayObjectText(obj, item.name) else: # erase the outline self.activeMap.outline_render.removeAllOutlines() def getCoords(self, click): """Get the map location x, y cords from the screen co-ords @type click: fife.ScreenPoint @param click: Screen co-ords @rtype: fife.Location @return: The map co-ords""" coord = self.activeMap.cameras["main"].toMapCoordinates(click, False) coord.z = 0 location = fife.Location(self.activeMap.agent_layer) location.setMapCoordinates(coord) return location def createBoxGUI(self, title): """ Creates a window to display the contents of a box @type title: string @param title: The title for the window @return: None """ if ((self.boxCreated == True) and (self.boxOpen == False)): # if it has already been created, just show it self.box_container.showContainer() self.boxOpen = True else: # otherwise create it then show it data = ["dagger01", "empty", "empty", "empty", "empty", "empty", "empty", "empty", "empty"] self.box_container = ContainerGUI(self.engine, unicode(title), data) def close_and_delete(): self.box_container.hideContainer() self.boxOpen = False events = {'takeAllButton':close_and_delete, 'closeButton':close_and_delete} self.box_container.container_gui.mapEvents(events) self.box_container.showContainer() self.boxOpen = True self.boxCreated = True def createExamineBox(self, title, desc): self.examineBox = ExaminePopup(self.engine, title, desc) self.examineBox.showPopUp() def pump(self): """Routine called during each frame. Our main loop is in ./run.py We ignore this main loop (but FIFE complains if it is missing).""" pass
class World(EventListenerBase): """World holds the data needed by fife to render the engine The engine keeps a copy of this class""" def __init__(self, engine): """Constructor for engine @type engine: fife.Engine @param engine: A fife.Engine instance @return: None""" super(World, self).__init__(engine, reg_mouse=True, reg_keys=True) # self.engine is a fife.Engine object, not an Engine object self.engine = engine self.event_manager = engine.getEventManager() self.quitFunction = None # self.data is an engine.Engine object, but is set in run.py self.data = None self.mouseCallback = None self.obj_hash={} # self.map is a Map object, set to none here self.active_map = None self.maps = {} # setup the inventory model # make slot 'A1' and 'A3' container daggers inv_model = {'A1':'dagger01', 'A3':'dagger01'} hud_callbacks = { 'saveGame': self.saveGame, 'loadGame': self.loadGame, 'quitGame': self.quitGame, } self.hud = hud.Hud(self.engine, TDS, inv_model, hud_callbacks) self.action_number = 1 # init the sound self.sounds = SoundEngine(engine) # don't force restart if skipping to new section if (TDS.readSetting("PlaySounds") == "1"): if(self.sounds.music_init == False): self.sounds.playMusic("/music/preciouswasteland.ogg") def quitGame(self): """Quits the game @return: None""" self.quitFunction() def saveGame(self, *args, **kwargs): """Saves the game state @return: None""" self.data.save(*args, **kwargs) def loadGame(self, *args, **kwargs): """Loads the game state @return: None""" self.data.load(*args, **kwargs) def loadMap(self, map_name, filename): """Loads a map and stores it under the given name in the maps list. @type map_name: text @param map_name: The name of the map to load @type filename: text @param filename: File which contains the map to be loaded @return: None """ if not map_name in self.maps: """Need to set active map before we load it because the map loader uses call backs that expect to find an active map. This needs to be reworked. """ map = Map(self.engine, self.data) self.maps[map_name] = map self.setActiveMap(map_name) map.load(filename) def setActiveMap(self, map_name): """Sets the active map that is to be rendered. @type map_name: text @param map_name: The name of the map to load @return: None """ self.active_map = self.maps[map_name] self.active_map.makeActive() def displayObjectText(self, obj, text): """Display on screen the text of the object over the object. @type obj: fife.instance @param obj: object to draw over @type text: text @param text: text to display over object @return: None""" obj.say(str(text), 1000) # all key / mouse event handling routines go here def keyPressed(self, evt): """Whenever a key is pressed, fife calls this routine. @type evt: fife.event @param evt: The event that fife caught @return: None""" key = evt.getKey() key_val = key.getValue() if(key_val == key.Q): # we need to quit the game self.hud.quitGame() if(key_val == key.T): self.active_map.toggle_renderer('GridRenderer') if(key_val == key.F1): # display the help screen and pause the game self.hud.displayHelp() if(key_val == key.F5): # logic would say we use similar code to above and toggle # logic here does not work, my friend :-( self.cord_render.setEnabled(not self.cord_render.isEnabled()) if(key_val == key.F7): # F7 saves a screenshot to fife/clients/parpg/screenshots t = "screenshots/screen-%s-%s.png" % \ (date.today().strftime('%Y-%m-%d'),\ time.strftime('%H-%M-%S')) print "PARPG: Saved:",t self.engine.getRenderBackend().captureScreen(t) if(key_val == key.F10): # F10 shows/hides the console self.engine.getGuiManager().getConsole().toggleShowHide() if(key_val == key.I): # I opens and closes the inventory self.hud.toggleInventory() if(key_val == key.A): # A adds a test action to the action box # The test actions will follow this format: Action 1, # Action 2, etc. self.hud.addAction("Action " + str(self.action_number)) self.action_number += 1 if(key_val == key.ESCAPE): # Escape brings up the main menu self.hud.displayMenu() # Hide the quit menu self.hud.quit_window.hide() if(key_val == key.M): self.sounds.toggleMusic() def mouseReleased(self, evt): """If a mouse button is released, fife calls this routine. We want to wait until the button is released, because otherwise pychan captures the release if a menu is opened. @type evt: fife.event @param evt: The event that fife caught @return: None""" self.hud.hideContextMenu() scr_point = fife.ScreenPoint(evt.getX(), evt.getY()) if(evt.getButton() == fife.MouseEvent.LEFT): self.data.handleMouseClick(self.getCoords(scr_point)) elif(evt.getButton() == fife.MouseEvent.RIGHT): # is there an object here? instances = self.active_map.cameras['main'].\ getMatchingInstances(scr_point, \ self.active_map.agent_layer) info = None for inst in instances: # check to see if this is an active item if(self.data.objectActive(inst.getId())): # yes, get the data info = self.data.getItemActions(inst.getId()) break # take the menu items returned by the engine or show a # default menu if no items data = info or \ [["Walk", "Walk here", self.onWalk, self.getCoords(scr_point)]] # show the menu self.hud.showContextMenu(data, (scr_point.x, scr_point.y)) def onWalk(self, click): """Callback sample for the context menu.""" self.hud.hideContainer() self.data.game_state.PC.run(click) def teleport(self, position): """Called when a door is used that moves a player to a new location on the same map. the setting of position may want to be created as its own method down the road. @type position: String Tuple @param position: X,Y coordinates passed from enigine.changeMap @return: fife.Location """ coord = fife.DoublePoint3D(float(position[0]), float(position[1]), 0) location = fife.Location(self.active_map.agent_layer) location.setMapCoordinates(coord) self.data.game_state.PC.teleport(location) def mouseMoved(self, evt): """Called when the mouse is moved @type evt: fife.event @param evt: The event that fife caught @return: None""" click = fife.ScreenPoint(evt.getX(), evt.getY()) i=self.active_map.cameras['main'].getMatchingInstances(click, \ self.active_map.agent_layer) # no object returns an empty tuple if(i != ()): for obj in i: # check to see if this in our list at all if(self.data.objectActive(obj.getId())): # yes, so outline self.active_map.outline_render.addOutlined(obj, 0, \ 137, 255, 2) # get the text item = self.data.objectActive(obj.getId()) if(item is not None): self.displayObjectText(obj, item.name) else: # erase the outline self.active_map.outline_render.removeAllOutlines() def getCoords(self, click): """Get the map location x, y cords from the screen co-ords @type click: fife.ScreenPoint @param click: Screen co-ords @rtype: fife.Location @return: The map co-ords""" coord = self.active_map.cameras["main"].toMapCoordinates(click, False) coord.z = 0 location = fife.Location(self.active_map.agent_layer) location.setMapCoordinates(coord) return location def pump(self): """Routine called during each frame. Our main loop is in ./run.py We ignore this main loop (but FIFE complains if it is missing).""" pass