source: trunk/game/scripts/gamescenecontroller.py @ 600

Revision 600, 13.3 KB checked in by beliar, 10 years ago (diff)

Patch by Beliar.

  • Dropping items menu action now only shows when right-clicking on an item in the players inventory
  • Actions that are supposed to happen when a key is pressed now work again.
Line 
1#!/usr/bin/env python
2
3#   This file is part of PARPG.
4
5#   PARPG is free software: you can redistribute it and/or modify
6#   it under the terms of the GNU General Public License as published by
7#   the Free Software Foundation, either version 3 of the License, or
8#   (at your option) any later version.
9
10#   PARPG is distributed in the hope that it will be useful,
11#   but WITHOUT ANY WARRANTY; without even the implied warranty of
12#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13#   GNU General Public License for more details.
14
15#   You should have received a copy of the GNU General Public License
16#   along with PARPG.  If not, see <http://www.gnu.org/licenses/>.
17
18from controllerbase import ControllerBase
19from datetime import datetime
20from fife import fife
21from scripts.gui.hud import Hud
22import random
23import glob
24import os
25from objects.action import ChangeMapAction, ExamineAction, OpenBoxAction, \
26                           UnlockBoxAction, LockBoxAction, TalkAction, \
27                           PickUpAction
28
29class GameSceneController(ControllerBase):
30    '''
31    This controller handles inputs when the game is in "scene" state.
32    "Scene" state is when the player can move around and interact
33    with objects. Like, talking to a npc or examining the contents of a box.
34    '''
35
36
37    def __init__(self, engine, view, model, application):
38        '''
39        Constructor
40        @param engine: Instance of the active fife engine
41        @type engine: fife.Engine
42        @param view: Instance of a GameSceneView
43        @param type: scripts.GameSceneView
44        @param model: The model that has the current gamestate
45        @type model: scripts.GameModel
46        @param application: The application that created this controller
47        @type application: scripts.PARPGApplication
48        @param settings: The current settings of the application
49        @type settings: fife.extensions.fife_settings.Setting
50        '''
51        super(GameSceneController, self).__init__(engine,
52                                                  view,
53                                                  model,
54                                                  application,
55                                                  reg_mouse=True, 
56                                                  reg_keys=True)
57        # Last saved mouse coords       
58        self.last_mousecoords = None
59        self.action_number = 1
60
61        self.mouse_callback = None
62
63        if model.settings.get("FIFE",  "PlaySounds"):
64            if not self.view.sounds.music_init:
65                music_file = random.choice(glob.glob(os.path.join(
66                                                                  "music", 
67                                                                  "*.ogg")))
68                self.view.sounds.playMusic(music_file) 
69
70
71    def initHud(self):
72        """Initialize the hud member
73        @return: None"""
74        hud_callbacks = {
75            'saveGame': self.saveGame,
76            'loadGame': self.loadGame,
77            'quitGame': self.quitGame,
78        }
79        self.view.hud = Hud(self, 
80                            self.model.settings, 
81                            hud_callbacks)
82
83    def keyPressed(self, evt):
84        """Whenever a key is pressed, fife calls this routine.
85           @type evt: fife.event
86           @param evt: The event that fife caught
87           @return: None"""
88        key = evt.getKey()
89        key_val = key.getValue()
90
91        if(key_val == key.Q):
92            # we need to quit the game
93            self.view.hud.quitGame()
94        if(key_val == key.T):
95            self.model.active_map.toggleRenderer('GridRenderer')
96        if(key_val == key.F1):
97            # display the help screen and pause the game
98            self.view.hud.displayHelp()
99        if(key_val == key.F5):
100            self.model.active_map.toggleRenderer('CoordinateRenderer')
101        if(key_val == key.F7):
102            # F7 saves a screenshot to fife/clients/parpg/screenshots
103           
104            screenshot_file = "screenshots/screen-%s.png" % \
105                    (datetime.now().strftime('%Y-%m-%d-%H-%M-%S'))
106            print "PARPG: Saved:", screenshot_file
107            self.engine.getRenderBackend().captureScreen(screenshot_file)
108        if(key_val == key.F10):
109            # F10 shows/hides the console
110            self.engine.getGuiManager().getConsole().toggleShowHide()
111        if(key_val == key.I):
112            # I opens and closes the inventory
113            self.view.hud.toggleInventory()
114        if(key_val == key.A):
115            # A adds a test action to the action box
116            # The test actions will follow this format: Action 1,
117            # Action 2, etc.
118            self.view.hud.addAction("Action " + str(self.action_number))
119            self.action_number += 1
120        if(key_val == key.ESCAPE):
121            # Escape brings up the main menu
122            self.view.hud.displayMenu()
123            # Hide the quit menu
124            self.view.hud.quit_window.hide()
125        if(key_val == key.M):
126            self.view.sounds.toggleMusic()
127        if(key_val == key.PAUSE):
128            # Pause pause/unpause the game
129            self.view.togglePause()
130
131    def mouseReleased(self, evt):
132        """If a mouse button is released, fife calls this routine.
133           We want to wait until the button is released, because otherwise
134           pychan captures the release if a menu is opened.
135           @type evt: fife.event
136           @param evt: The event that fife caught
137           @return: None"""
138        self.view.hud.hideContextMenu()
139        scr_point = fife.ScreenPoint(evt.getX(), evt.getY())
140        if(evt.getButton() == fife.MouseEvent.LEFT):
141            self.model.movePlayer(self.model.getCoords(scr_point))
142        elif(evt.getButton() == fife.MouseEvent.RIGHT):
143            # is there an object here?
144            tmp_active_map = self.model.active_map
145            instances = tmp_active_map.cameras[tmp_active_map.my_cam_id].\
146                            getMatchingInstances(scr_point,
147                                                 tmp_active_map.agent_layer)
148            info = None
149            for inst in instances:
150                # check to see if this is an active item
151                if(self.model.objectActive(inst.getId())):
152                    # yes, get the model
153                    info = self.getItemActions(inst.getId())
154                    break
155
156            # take the menu items returned by the engine or show a
157            # default menu if no items
158            data = info or \
159                [["Walk", "Walk here", self.view.onWalk, 
160                  self.model.getCoords(scr_point)]]
161            # show the menu
162            self.view.hud.showContextMenu(data, (scr_point.x, scr_point.y))
163
164    def mouseMoved(self, evt):
165        """Called when the mouse is moved
166           @type evt: fife.event
167           @param evt: The event that fife caught
168           @return: None"""
169        self.last_mousecoords = fife.ScreenPoint(evt.getX(), evt.getY())
170        self.view.highlightFrontObject(self.last_mousecoords)       
171
172    def handleCommands(self):
173        """Check if a command is to be executed
174        """
175        if self.model.map_change:
176            if self.model.active_map:
177                player_agent = self.model.active_map.\
178                                    agent_layer.getInstance("PlayerCharacter")
179                self.model.active_map.agent_layer.deleteInstance(player_agent)
180                player_char = self.model.game_state.player_character
181                self.model.game_state.player_character = None
182                pc_agent = self.model.agents[self.model.ALL_AGENTS_KEY]\
183                                                ["PlayerCharacter"] 
184                pc_agent["Map"] = self.model.target_map_name
185                pc_agent["Position"] = self.model.target_position
186                pc_agent["Inventory"] = player_char.inventory.serializeInventory()
187            self.model.loadMap(self.model.target_map_name)
188            self.model.setActiveMap(self.model.target_map_name)         
189            self.model.readAgentsOfMap(self.model.target_map_name)
190            self.model.placeAgents()
191            self.model.placePC()
192            self.model.map_change = False
193            # The PlayerCharacter has an inventory, and also some
194            # filling of the ready slots in the HUD.
195            # At this point we sync the contents of the ready slots
196            # with the contents of the inventory.
197            self.view.hud.inventory = None
198            self.view.hud.initializeInventory()         
199                       
200    def nullFunc(self, userdata):
201        """Sample callback for the context menus."""
202        print userdata   
203
204    def initTalk(self, npc_info):
205        """ Starts the PlayerCharacter talking to an NPC. """
206        # TODO: work more on this when we get NPCData and HeroData straightened
207        # out
208        npc = self.model.game_state.getObjectById(npc_info.ID,
209                                            self.model.game_state.\
210                                                current_map_name)
211        self.model.game_state.player_character.approach([npc.getLocation().\
212                                     getLayerCoordinates().x,
213                                     npc.getLocation().\
214                                     getLayerCoordinates().y],
215                                    TalkAction(self, npc))
216
217    def getItemActions(self, obj_id):
218        """Given the objects ID, return the text strings and callbacks.
219           @type obj_id: string
220           @param obj_id: ID of object
221           @rtype: list
222           @return: List of text and callbacks"""
223        actions = []
224        # note: ALWAYS check NPC's first!
225        obj = self.model.game_state.\
226                        getObjectById(obj_id,
227                                      self.model.game_state.current_map_name)
228       
229        if obj is not None:
230            if obj.trueAttr("NPC"):
231                # keep it simple for now, None to be replaced by callbacks
232                actions.append(["Talk", "Talk", self.initTalk, obj])
233                actions.append(["Attack", "Attack", self.nullFunc, obj])
234            else:
235                actions.append(["Examine", "Examine",
236                                self.model.game_state.player_character.approach, 
237                                [obj.X, obj.Y],
238                                ExamineAction(self, obj.name, obj.text)])
239                # is it a Door?
240                if obj.trueAttr("door"):
241                    actions.append(["Change Map", "Change Map",
242                       self.model.game_state.player_character.approach, 
243                       [obj.X, obj.Y],
244                       ChangeMapAction(self, obj.target_map_name,
245                                       obj.target_pos)])
246                # is it a container?
247                if obj.trueAttr("container"):
248                    actions.append(["Open", "Open", 
249                                    self.model.game_state.\
250                                        player_character.approach,
251                                    [obj.X, obj.Y],
252                                    OpenBoxAction(self, obj)])
253                    actions.append(["Unlock", "Unlock", 
254                                    self.model.game_state.\
255                                        player_character.approach,
256                                    [obj.X, obj.Y],
257                                    UnlockBoxAction(self, obj)])
258                    actions.append(["Lock", "Lock", 
259                                    self.model.game_state.\
260                                        player_character.approach,
261                                    [obj.X, obj.Y],
262                                    LockBoxAction(self, obj)])
263                # can you pick it up?
264                if obj.trueAttr("carryable"):
265                    actions.append(["Pick Up", "Pick Up", 
266                                    self.model.game_state.\
267                                        player_character.approach,
268                                    [obj.X, obj.Y],
269                                    PickUpAction(self, obj)])
270
271        return actions
272   
273    def saveGame(self, *args, **kwargs):
274        """Saves the game state, delegates call to engine.Engine
275           @return: None"""
276        self.model.save(*args, **kwargs)
277
278    def loadGame(self, *args, **kwargs):
279        """Loads the game state, delegates call to engine.Engine
280           @return: None"""
281        # Remove all currently loaded maps so we can start fresh
282        self.model.deleteMaps()
283        self.view.hud.inventory = None
284
285        self.model.load(*args, **kwargs)
286        self.view.hud.initializeInventory()         
287
288    def quitGame(self):
289        """Quits the game
290           @return: None"""
291        self.application.listener.quitGame()
292
293    def pump(self):
294        """Routine called during each frame. Our main loop is in ./run.py"""
295        # uncomment to instrument
296        # t0 = time.time()
297        if self.model.active_map:
298            self.view.highlightFrontObject(self.last_mousecoords)
299            self.view.refreshTopLayerTransparencies()
300        self.handleCommands()
301        # print "%05f" % (time.time()-t0,)
Note: See TracBrowser for help on using the repository browser.