def setupInput(self): # Create the inputManager using the supplied renderWindow windowHnd = self.renderWindow.getCustomAttributeInt("WINDOW") paramList = [("WINDOW", str(windowHnd)), \ ("w32_mouse", "DISCL_FOREGROUND"), \ ("w32_mouse", "DISCL_NONEXCLUSIVE"), \ ("w32_keyboard", "DISCL_FOREGROUND"), \ ("w32_keyboard", "DISCL_NONEXCLUSIVE"),] # @todo: add mac/linux parameters self.inputManager = OIS.createPythonInputSystem(paramList) # Attempt to get the mouse/keyboard input device objects. try: self.mouse = self.inputManager.createInputObjectMouse( OIS.OISMouse, True) self.keyboard = self.inputManager.createInputObjectKeyboard( OIS.OISKeyboard, True) except Exception: # Unable to obtain mouse/keyboard input raise # Use an InputHandler object to handle the callback functions. self.inputHandler = InputHandler(mouse=self.mouse, keyboard=self.keyboard, scene=self, player=self.player) self.mouse.setEventCallback(self.inputHandler) self.keyboard.setEventCallback(self.inputHandler)
def __init__(self, sceneManager): # Initialize the various listener classes we are a subclass from ogre.FrameListener.__init__(self) ogre.WindowEventListener.__init__(self) self.renderWindow = ogre.Root.getSingleton().getAutoCreatedWindow() self.sceneManager = sceneManager self.camera = self.sceneManager.getCamera("PrimaryCamera") self.cameraNode = self.sceneManager.getSceneNode("PrimaryCamera") self.viewport = self.camera.getViewport() # Create an empty list of nodes self.nodes = [] # Create an empty list of GUI elements. self.gui_elements = [] # Set up the overlay for the GUI. self.setupOverlay() # Set up the scene. self.setupScene() # Set up the GUI. self.setupGUI() # Create the inputManager using the supplied renderWindow windowHnd = self.renderWindow.getCustomAttributeInt("WINDOW") paramList = [("WINDOW", str(windowHnd)), \ ("w32_mouse", "DISCL_FOREGROUND"), \ ("w32_mouse", "DISCL_NONEXCLUSIVE"), \ ("w32_keyboard", "DISCL_FOREGROUND"), \ ("w32_keyboard", "DISCL_NONEXCLUSIVE"),] # @todo: add mac/linux parameters self.inputManager = OIS.createPythonInputSystem(paramList) # Attempt to get the mouse/keyboard input device objects. try: self.mouse = self.inputManager.createInputObjectMouse(OIS.OISMouse, True) self.keyboard = self.inputManager.createInputObjectKeyboard(OIS.OISKeyboard, True) except Exception: # Unable to obtain mouse/keyboard input raise # Use an InputHandler object to handle the callback functions. self.inputHandler = InputHandler(mouse=self.mouse, keyboard=self.keyboard, scene=self, player=self.player) self.mouse.setEventCallback(self.inputHandler) self.keyboard.setEventCallback(self.inputHandler) # Set up initial window size. self.windowResized(self.renderWindow) # Set this to True when we get an event to exit the application self.quit = False # Listen for any events directed to the window manager's close button ogre.WindowEventUtilities.addWindowEventListener(self.renderWindow, self)
def __init__(self, spawn_x=100, spawn_y=100, entity=[]): Person.__init__(self, spawn_x, spawn_y, '0.png', 'player\\default') self.inputhandler = InputHandler() self.admin = self.physics = self.parkour = False self.add_basic_movement() self.add_physics() self.add_parkour() self.add_stats(entity)
def handle_input(thread, screen): if thread == None or not running(thread): inp = InputHandler(renderer.screen) inp.daemon = True inp.start() return inp # return thread else: return thread
def __init__(self,spawn_x=100,spawn_y=100,entity = []): Person.__init__(self,spawn_x,spawn_y,'0.png', 'player\\default') self.inputhandler = InputHandler() self.admin = self.physics = self.parkour = False self.add_basic_movement() self.add_physics() self.add_parkour() self.add_stats(entity)
def __init__(self, spawn_x=100, spawn_y=100, entity=[]): Person.__init__(self, spawn_x, spawn_y, '0.png', 'player\\default') self.inputhandler = InputHandler() self.admin = self.physics = self.parkour = False self.add_basic_movement() self.add_physics() self.add_parkour() self.add_stats(entity) self.state = 'idle' self.stage = 0 self.next_stage = False self.brightness = 50 #temporary self.stamina_regen = True self.direc = 1 #right
def __init__(self,spawn_x=100,spawn_y=100,entity = []): Person.__init__(self,spawn_x,spawn_y,'0.png', 'player\\default') self.inputhandler = InputHandler() self.admin = self.physics = self.parkour = False self.add_basic_movement() self.add_physics() self.add_parkour() self.add_stats(entity) self.state = 'idle' self.stage = 0 self.next_stage = False self.brightness = 50 #temporary self.stamina_regen= True self.direc = 1 #right
def setupInput(self): # Create the inputManager using the supplied renderWindow windowHnd = self.renderWindow.getCustomAttributeInt("WINDOW") paramList = [("WINDOW", str(windowHnd)), \ ("w32_mouse", "DISCL_FOREGROUND"), \ ("w32_mouse", "DISCL_NONEXCLUSIVE"), \ ("w32_keyboard", "DISCL_FOREGROUND"), \ ("w32_keyboard", "DISCL_NONEXCLUSIVE"),] # @todo: add mac/linux parameters self.inputManager = OIS.createPythonInputSystem(paramList) # Attempt to get the mouse/keyboard input device objects. try: self.mouse = self.inputManager.createInputObjectMouse(OIS.OISMouse, True) self.keyboard = self.inputManager.createInputObjectKeyboard(OIS.OISKeyboard, True) except Exception: # Unable to obtain mouse/keyboard input raise # Use an InputHandler object to handle the callback functions. self.inputHandler = InputHandler(self.mouse, self.keyboard, self) self.mouse.setEventCallback(self.inputHandler) self.keyboard.setEventCallback(self.inputHandler)
class PlayScene(ogre.FrameListener, ogre.WindowEventListener): """ This class represents the game's main scene - the play scene. This class sets up the initial scene and acts as the main game loop (via frameStarted()). """ def __init__(self, sceneManager, address, port): # Initialize the various listener classes we are a subclass from ogre.FrameListener.__init__(self) ogre.WindowEventListener.__init__(self) self.address = address self.port = port self.renderWindow = ogre.Root.getSingleton().getAutoCreatedWindow() self.sceneManager = sceneManager self.camera = self.sceneManager.getCamera("PrimaryCamera") self.cameraNode = self.sceneManager.getSceneNode("PrimaryCamera") # Create an empty list of nodes self.nodes = [] # Set up the scene. self.setupScene() # Init attributes. self.player = None self.last_update = None # Create the inputManager using the supplied renderWindow windowHnd = self.renderWindow.getCustomAttributeInt("WINDOW") paramList = [("WINDOW", str(windowHnd)), \ ("w32_mouse", "DISCL_FOREGROUND"), \ ("w32_mouse", "DISCL_NONEXCLUSIVE"), \ ("w32_keyboard", "DISCL_FOREGROUND"), \ ("w32_keyboard", "DISCL_NONEXCLUSIVE"),] # @todo: add mac/linux parameters self.inputManager = OIS.createPythonInputSystem(paramList) # Attempt to get the mouse/keyboard input device objects. try: self.mouse = self.inputManager.createInputObjectMouse(OIS.OISMouse, True) self.keyboard = self.inputManager.createInputObjectKeyboard(OIS.OISKeyboard, True) except Exception: # Unable to obtain mouse/keyboard input raise # Use an InputHandler object to handle the callback functions. self.inputHandler = InputHandler(self.mouse, self.keyboard, self) self.mouse.setEventCallback(self.inputHandler) self.keyboard.setEventCallback(self.inputHandler) # Set up initial window size. self.windowResized(self.renderWindow) # Set this to True when we get an event to exit the application self.quit = False # Listen for any events directed to the window manager's close button ogre.WindowEventUtilities.addWindowEventListener(self.renderWindow, self) def __del__ (self ): # Clean up OIS self.inputManager.destroyInputObjectKeyboard(self.keyboard) self.inputManager.destroyInputObjectMouse(self.mouse) OIS.InputManager.destroyInputSystem(self.inputManager) self.inputManager = None ogre.WindowEventUtilities.removeWindowEventListener(self.renderWindow, self) self.windowClosed(self.renderWindow) def setupScene(self): ## Load the level. # @todo: Remove .scene dependancy and move to external file (format?). # Load some data from the .scene file sceneLoader = SceneLoader.DotSceneLoader("media/testtilescene.scene", self.sceneManager) sceneLoader.parseDotScene() # Create the world. self.world = gamestate.world.World() # Create the client and set listeners. self.client = net.client.GameClient(self.world, self.address, self.port) self.client.connected += self.on_client_connected # Start the netclient and connect. self.client_thread = threading.Thread(target=self.client.go) self.client_thread.start() # Attach a handler to world.object_added self.world.object_added += self.on_world_object_added # Set up the TestScene self.scene = gamestate.scenes.TestScene(self.world) # Setup camera self.camera.nearClipDistance = 1 self.camera.farClipDistance = 500 self.camera.setProjectionType(ogre.PT_ORTHOGRAPHIC) # THIS SPECIFIES THE HEIGHT OF THE ORTHOGRAPHIC WINDOW # the width will be recalculated based on the aspect ratio # in ortho projection mode, decreasing the size of the window # is equivalent to zooming in, increasing is the equivalent of # zooming out. self.camera.setOrthoWindowHeight(200) # Setup camera node self.cameraNode.position = (0, 100, 100) self.cameraNode.pitch(ogre.Degree(-45)) def frameStarted(self, event): """ Called before a frame is displayed, handles events (also those via callback functions, as you need to call capture() on the input objects) Returning False here exits the application (render loop stops) """ dt = event.timeSinceLastFrame # Get buffered input from server and process it. while not self.client.input.empty(): packet = self.client.input.get_nowait() self.process_packet(packet) # Capture any buffered events (and fire any callbacks). self.inputHandler.capture() # Update the game state world. self.world.update(dt) # Send an PlayerUpdate packet to the server if appropriate. self._send_update() # Send buffered output to server. reactor.callFromThread(self.client.send) # Add time to animations. for node in self.nodes: node.animations_addtime(dt) # Neatly close our FrameListener if our renderWindow has been shut down # or we are quitting. if self.renderWindow.isClosed() or self.quit: return False return True ## Net event callbacks & helpers def _send_update(self): """ Sends a PlayerUpdate packet to the server if appropriate. """ if self.player is None: return update = self._get_update() if self.last_update is not None: update_time, last_update = self.last_update # Don't send if we've sent in the last 0.1s. if update_time + 0.05 > self.world.time: return # Don't send if info hasn't changed since the last update. if last_update.x == update.x and last_update.z == update.z and \ last_update.rotation == update.rotation and \ last_update.move_speed == update.move_speed and \ last_update.move_direction == update.move_direction: return print "Sending player update to server." self.client.output.put_nowait(update) self.last_update = (self.world.time, update) def _get_update(self): """ Returns a PlayerUpdate packet based on the current player state. """ update = packets.PlayerUpdate() update.x, update.z = self.player.position update.rotation = self.player.rotation if self.player.is_moving: update.move_speed = self.player.move_speed update.move_direction = self.player.move_direction else: update.move_speed = 0 update.move_direction = 0 return update def process_packet(self, packet): ptype = type(packet) print "Processing packet=%s: %s from server." % (packet.id, ptype.__name__) # JoinResponse if ptype is packets.JoinResponse: # @todo: handle deny # Add a player to the world and set it as our active player. print "Creating player in world with id=%s." % packet.player_id self.player = gamestate.objects.Player(self.world) self.world.add_object(self.player, packet.player_id) # Listen to the player's position change event so we can mvoe the # camera with the player. self.player.position_changed += self.on_player_position_changed # ObjectInit elif ptype is packets.ObjectInit: if packet.object_type == "player": object = gamestate.objects.Player(self.world) else: raise Exception("Invalid object_type") # @todo: implement name, owner_id, ttl self.world.add_object(object, packet.object_id) # ObjectUpdate elif ptype is packets.ObjectUpdate: if not self.world.objects_hash.has_key(packet.object_id): return object = self.world.objects_hash[packet.object_id] print "Updating object id=%s." % object.object_id object.rotation = packet.rotation try: if packet.move_speed > 0: diff_vector = ogre.Vector3(packet.x - object.position[0], 0, packet.z - object.position[1]) move_vector = ogre.Vector3(packet.move_speed * math.cos(packet.rotation), 0, packet.move_speed * math.sin(packet.rotation)) resultant = diff_vector + move_vector angle = math.atan2(resultant.z, resultant.x) object.move_speed = packet.move_speed object.rotation = angle object.move_direction = 0 object.is_moving = True else: object.position = (packet.x, packet.z) object.is_moving = False except: object.position = (packet.x, packet.z) def on_client_connected(self): packet = packets.JoinRequest() # @todo: Get player_name from somewhere. packet.player_name = "Player1" self.client.output.put_nowait(packet) ## Game event callbacks def on_world_object_added(self, gameObject): if gameObject.type == "player": self.nodes.append(nodes.PlayerNode(self.sceneManager, gameObject)) def on_player_position_changed(self, mobileObject, position): self.cameraNode.position = (position[0], 100, position[1] + 100) ## Window event listener callbacks def windowResized(self, renderWindow): self.mouse.getMouseState().width = renderWindow.width self.mouse.getMouseState().height = renderWindow.height vp = self.camera.getViewport() self.camera.aspectRatio = vp.actualWidth / vp.actualHeight # @todo: Scale the image so viewable area remains the same. def windowClosed(self, renderWindow): # Only close for window that created OIS if(renderWindow == self.renderWindow): del self
class Player(Person): def __init__(self,spawn_x=100,spawn_y=100,entity = []): Person.__init__(self,spawn_x,spawn_y,'0.png', 'player\\default') self.inputhandler = InputHandler() self.admin = self.physics = self.parkour = False self.add_basic_movement() self.add_physics() self.add_parkour() self.add_stats(entity) def add_animation(self): pass def add_basic_movement(self): self.jumping = self.onGround = self.running = False self.inputhandler.add_button('right') self.inputhandler.add_button('left') self.inputhandler.add_button('up') self.inputhandler.add_button('sprint') self.inputhandler.add_button('down') self.inputhandler.add_button('jump') def add_parkour(self): self.parkour = True self.hanging = self.onWall_R = self.onWall_L = self.climb = False def reset(self,entity): Person.reset(self,entity) self.status['health'].set(100) self.dead = False self.add_physics() self.add_parkour() def add_physics(self): self.physics = True self.acc = 1 self.speed_limit = 4 self.walk_limit = 2 self.run_limit = 4 self.sprint_limit = 8 self.fall_time = 0 self.fall_limit = 20 self.wall_slide_limit = 25 self.wall_slide_time = 0 self.control = True def add_stats(self,entity): self.status = {} #health self.status.update({'health':Health()}) #exp self.exp = None #self.status.append(self.exp) #hunger self.hunger = None #self.status.append(self.hunger) #stamina self.status.update({'stamina':Stamina()}) #money self.money = 0 #danger self.danger = 0 def get_button(self,button): return self.inputhandler.button_list[button] def set_button(self,button,state): self.inputhandler.button_list[button] = state def admin_tick(self): #allows the player to float around self.xvel = self.yvel = 0 if self.get_button('right'): self.xvel = 5 if self.get_button('left'): self.xvel = -5 if self.get_button('up'): self.yvel = -5 if self.get_button('down'): self.yvel = 5 self.rect.left += self.xvel self.rect.top += self.yvel def x_movement(self): if self.physics: if self.get_button('right') and not self.get_button('left') and self.control: if self.xvel <= self.speed_limit: self.xvel += self.acc else: self.xvel -= self.acc elif self.get_button('left') and not self.get_button('right') and self.control: if self.xvel >= -self.speed_limit: self.xvel -= self.acc else: self.xvel += self.acc elif (self.get_button('left') and self.get_button('right') and self.control) or \ (not self.get_button('left') and not self.get_button('right') and self.control): if self.xvel != 0: self.xvel /= 2 if -1< self.xvel < 1: self.xvel = 0 #allows a player to run if self.status['stamina'].state: if self.get_button('sprint'): self.speed_limit = self.sprint_limit elif self.running: self.speed_limit = self.run_limit else: self.speed_limit = self.walk_limit else: self.speed_limit = self.walk_limit else: if self.get_button('right') and not self.get_button('left'): self.xvel = self.run_limit elif not self.get_button('right') and self.get_button('left'): self.xvel = -self.run_limit else: self.xvel = 0 if self.get_button('sprint'): self.xvel *=2 def wall_movement(self): if self.onWall and self.wall_slide_limit > self.wall_slide_time: #wall slide if self.yvel > 0: self.yvel = 2 self.wall_slide_time += 1 #if on ground, do nothing elif self.yvel==0 and not self.hanging: return self.jumping = True #wall jump if self.get_button('jump'): if self.status['stamina'].cost(20): if self.onWall_R and self.get_button('right') and not self.get_button('left'): self.yvel = -15 self.xvel = -5 elif self.onWall_L and not self.get_button('right') and self.get_button('left'): self.yvel = -15 self.xvel = 5 #climb if self.get_button('up') and self.hanging: if self.status['stamina'].cost(10): self.climb = True self.yvel = -15 self.xvel = 0 elif not self.onWall or self.hanging: self.wall_slide_time = 0 elif self.wall_slide_limit <= self.wall_slide_time: self.onWall_L = self.onWall_R = self.onWall = False def tick(self,platforms,entity): #check if the character is dead or not if self.status['health'].current <= 0: self.dead = True self.onWall = self.onWall_L or self.onWall_R #make sure the charater has the control at certain point if not self.jumping or self.onWall or self.hanging or self.climb: self.control = True else: self.control = False #all the x-component movements self.x_movement() #apply gravity self.gravity.apply(self) #all wall-related movements self.wall_movement() #all the y-component movements if self.onGround: self.jumping = self.climb = False if self.get_button('jump') and self.onGround: if self.status['stamina'].cost(20): self.yvel = -15 self.set_button('jump',False) self.jumping = True Person.tick(self,platforms) if self.yvel > 2 and not self.onWall: self.fall_time+=1 elif self.onWall and self.fall_time > 0: self.fall_time-=1 elif self.onGround: self.status['health'].current -= int(self.fall_time/self.fall_limit) * 20 if self.yvel <= 0: self.fall_time = 0 #stamina calculation if self.onGround: if abs(self.xvel) > self.run_limit: self.status['stamina'].cost(.5) elif abs(self.xvel) <= self.run_limit: self.status['stamina'].recover(1) #make sure status stays updated for s in self.status.values(): s.update()
class Player(Person): def __init__(self, spawn_x=100, spawn_y=100, entity=[]): Person.__init__(self, spawn_x, spawn_y, '0.png', 'player\\default') self.inputhandler = InputHandler() self.admin = self.physics = self.parkour = False self.add_basic_movement() self.add_physics() self.add_parkour() self.add_stats(entity) self.state = 'idle' self.stage = 0 self.next_stage = False self.brightness = 50 #temporary self.stamina_regen = True self.direc = 1 #right #self.add_animation() def add_animation(self): self.motion = 'default' def set_spawn(self, x, y): self.spawn_x = x self.spawn_y = y def reset_basic_movement(self): self.inputhandler = InputHandler() self.add_basic_movement() def add_basic_movement(self): self.jumping = self.onGround = self.running = False self.inputhandler.add_button('right') self.inputhandler.add_button('left') self.inputhandler.add_button('up') self.inputhandler.add_button('sprint') self.inputhandler.add_button('down') self.inputhandler.add_button('jump') def add_parkour(self): self.parkour = True self.hanging = self.onWall_R = self.onWall_L = self.climb = False def place(self, entity): Person.reset(self, entity) self.reset_basic_movement() def stamina_reset(self): self.status['stamina'].reset() def reset(self, entity): Person.reset(self, entity) self.status['health'].set(self.status['health'].maximum) self.status['stamina'].set(self.status['stamina'].maximum) self.dead = False self.add_physics() self.add_parkour() def add_physics(self): self.physics = True self.acc = 1 self.speed_limit = 4 self.walk_limit = 2 self.run_limit = 4 self.sprint_limit = 8 self.fall_time = 0 self.fall_limit = 20 self.wall_slide_limit = 25 self.wall_slide_time = 0 self.control = True def add_stats(self, entity): self.status = {} #health self.status.update({'health': Health()}) #exp self.exp = None #self.status.append(self.exp) #hunger self.hunger = None #self.status.append(self.hunger) #stamina self.status.update({'stamina': Stamina()}) #money self.status.update({'money': Money()}) #danger self.danger = 0 def get_button(self, button): return self.inputhandler.button_list[button] def set_button(self, button, state): self.inputhandler.button_list[button] = state def admin_tick(self): #allows the player to float around self.xvel = self.yvel = 0 if self.get_button('right'): self.xvel = 5 if self.get_button('left'): self.xvel = -5 if self.get_button('up'): self.yvel = -5 if self.get_button('down'): self.yvel = 5 self.rect.left += self.xvel self.rect.top += self.yvel def x_movement(self): if self.physics: if self.get_button( 'right') and not self.get_button('left') and self.control: if self.xvel <= self.speed_limit: self.xvel += self.acc else: self.xvel -= self.acc elif self.get_button( 'left') and not self.get_button('right') and self.control: if self.xvel >= -self.speed_limit: self.xvel -= self.acc else: self.xvel += self.acc elif (self.get_button('left') and self.get_button('right') and self.control) or \ (not self.get_button('left') and not self.get_button('right') and self.control): if self.xvel != 0: self.xvel /= 2 if -1 < self.xvel < 1: self.xvel = 0 #allows a player to run if self.get_button('sprint'): self.speed_limit = self.sprint_limit elif self.running: self.speed_limit = self.run_limit else: self.speed_limit = self.walk_limit else: if self.get_button('right') and not self.get_button('left'): self.xvel = self.run_limit elif not self.get_button('right') and self.get_button('left'): self.xvel = -self.run_limit else: self.xvel = 0 if self.get_button('sprint'): self.xvel *= 2 def wall_movement(self): if self.onWall and self.wall_slide_limit > self.wall_slide_time: #wall slide if self.yvel > 0: self.yvel = 2 self.wall_slide_time += 1 #if on ground, do nothing elif self.yvel == 0 and not self.hanging: return self.jumping = True #wall jump if self.get_button('jump') and not self.onGround: if self.status['stamina'].cost(20): if self.onWall_R and self.get_button( 'right') and not self.get_button('left'): self.yvel = -15 self.xvel = -5 elif self.onWall_L and not self.get_button( 'right') and self.get_button('left'): self.yvel = -15 self.xvel = 5 #climb if self.get_button('up') and self.hanging: if self.status['stamina'].cost(10): self.climb = True self.yvel = -15 self.xvel = 0 elif not self.onWall or self.hanging: self.wall_slide_time = 0 elif self.wall_slide_limit <= self.wall_slide_time: self.onWall_L = self.onWall_R = self.onWall = False def tick(self, platforms, entity): if self.status['health'].current <= 0: self.dead = True if self.parkour: self.onWall = self.onWall_L or self.onWall_R else: self.onWall = self.hanging = self.climb = False #make sure the charater has the control at certain point if not self.jumping or self.onWall or self.hanging or self.climb: self.control = True else: self.control = False #all the x-component movements self.x_movement() #apply gravity self.gravity.apply(self) #all wall-related movements if self.parkour: self.wall_movement() #all the y-component movements if self.onGround: self.jumping = self.climb = False if self.get_button('jump') and self.onGround: if self.status['stamina'].cost(20): self.yvel = -15 + self.stage self.set_button('jump', False) self.jumping = True Person.tick(self, platforms) if self.yvel > 2 and not self.onWall: self.fall_time += 1 elif self.onWall and self.fall_time > 0: self.fall_time -= 1 elif self.onGround: self.status['health'].current -= int( self.fall_time / self.fall_limit) * 20 if self.yvel <= 0: self.fall_time = 0 #make sure status stays updated for s in self.status.values(): s.update()
def reset_basic_movement(self): self.inputhandler = InputHandler() self.add_basic_movement()
class PlayScene(ogre.FrameListener, ogre.WindowEventListener): """ This class represents the game's main scene - the play scene. This class sets up the initial scene and acts as the main game loop (via frameStarted()). """ def __init__(self, sceneManager): # Initialize the various listener classes we are a subclass from ogre.FrameListener.__init__(self) ogre.WindowEventListener.__init__(self) self.renderWindow = ogre.Root.getSingleton().getAutoCreatedWindow() self.sceneManager = sceneManager self.camera = self.sceneManager.getCamera("PrimaryCamera") self.cameraNode = self.sceneManager.getSceneNode("PrimaryCamera") # Create an empty list of nodes self.nodes = [] # Set up the scene. self.setupScene() # Create the inputManager using the supplied renderWindow windowHnd = self.renderWindow.getCustomAttributeInt("WINDOW") paramList = [("WINDOW", str(windowHnd)), \ ("w32_mouse", "DISCL_FOREGROUND"), \ ("w32_mouse", "DISCL_NONEXCLUSIVE"), \ ("w32_keyboard", "DISCL_FOREGROUND"), \ ("w32_keyboard", "DISCL_NONEXCLUSIVE"),] # @todo: add mac/linux parameters self.inputManager = OIS.createPythonInputSystem(paramList) # Attempt to get the mouse/keyboard input device objects. try: self.mouse = self.inputManager.createInputObjectMouse(OIS.OISMouse, True) self.keyboard = self.inputManager.createInputObjectKeyboard(OIS.OISKeyboard, True) except Exception: # Unable to obtain mouse/keyboard input raise # Use an InputHandler object to handle the callback functions. self.inputHandler = InputHandler(mouse=self.mouse, keyboard=self.keyboard, scene=self, player=self.player) self.mouse.setEventCallback(self.inputHandler) self.keyboard.setEventCallback(self.inputHandler) # Set up initial window size. self.windowResized(self.renderWindow) # Set this to True when we get an event to exit the application self.quit = False # Listen for any events directed to the window manager's close button ogre.WindowEventUtilities.addWindowEventListener(self.renderWindow, self) def __del__ (self ): # Clean up OIS self.inputManager.destroyInputObjectKeyboard(self.keyboard) self.inputManager.destroyInputObjectMouse(self.mouse) OIS.InputManager.destroyInputSystem(self.inputManager) self.inputManager = None ogre.WindowEventUtilities.removeWindowEventListener(self.renderWindow, self) self.windowClosed(self.renderWindow) def setupScene(self): ## Load the level. # @todo: Remove .scene dependancy and move to external file (format?). # Load some data from the .scene file sceneLoader = SceneLoader.DotSceneLoader("media/testtilescene.scene", self.sceneManager) sceneLoader.parseDotScene() # Create the world. self.world = gamestate.world.World() # Attach a handler to world.object_added self.world.object_added += self.on_world_object_added # Add a player to the world and set it as our active player. self.player = gamestate.objects.Player(self.world) self.world.add_object(self.player) # Add stationary NPC ninja... npc = gamestate.objects.Player(self.world) self.world.add_object(npc) npc.position = (45, 45) npc.isPassable = False # Add boundary lines for map walls. # @todo: move this out of here! # north wall boundary1 = gamestate.objects.GameObject(self.world) boundary1.position = (-90, -90) boundary1.isPassable = False boundary1.bounding_shape = gamestate.collision.BoundingLineSegment((-90, -90), (90, -90), (0, 1)) # south wall boundary2 = gamestate.objects.GameObject(self.world) boundary2.position = (-90, 90) boundary2.isPassable = False boundary2.bounding_shape = gamestate.collision.BoundingLineSegment((-90, 90), (90, 90), (0, -1)) # east wall boundary3 = gamestate.objects.GameObject(self.world) boundary3.position = (90, -90) boundary3.isPassable = False boundary3.bounding_shape = gamestate.collision.BoundingLineSegment((90, -90), (90, 90), (-1, 0)) # west wall boundary4 = gamestate.objects.GameObject(self.world) boundary4.position = (-90, -90) boundary4.isPassable = False boundary4.bounding_shape = gamestate.collision.BoundingLineSegment((-90, -90), (-90, 90), (1, 0)) # bounding rectangle for testing boundary5 = gamestate.objects.GameObject(self.world) boundary5.position = (-30, 0) boundary5.isPassable = False boundary5.bounding_shape = gamestate.collision.BoundingRectangle(40, 40, 45) self.world.add_object(boundary1) self.world.add_object(boundary2) self.world.add_object(boundary3) self.world.add_object(boundary4) self.world.add_object(boundary5) # Listen to the player's position change event so we can mvoe the # camera with the player. self.player.position_changed += self.on_player_position_changed # Setup camera self.camera.nearClipDistance = 1 self.camera.farClipDistance = 500 self.camera.setProjectionType(ogre.PT_ORTHOGRAPHIC) # THIS SPECIFIES THE HEIGHT OF THE ORTHOGRAPHIC WINDOW # the width will be recalculated based on the aspect ratio # in ortho projection mode, decreasing the size of the window # is equivalent to zooming in, increasing is the equivalent of # zooming out. self.camera.setOrthoWindowHeight(200) # Setup camera node self.cameraNode.position = (0, 100, 100) self.cameraNode.pitch(ogre.Degree(-45)) def frameStarted(self, event): """ Called before a frame is displayed, handles events (also those via callback functions, as you need to call capture() on the input objects) Returning False here exits the application (render loop stops) """ dt = event.timeSinceLastFrame # Capture any buffered events (and fire any callbacks). self.inputHandler.capture() # Update the game state world. self.world.update(dt) # Add time to animations. for node in self.nodes: node.animations_addtime(dt) # Neatly close our FrameListener if our renderWindow has been shut down # or we are quitting. if self.renderWindow.isClosed() or self.quit: return False return True ## Game event callbacks def on_world_object_added(self, gameObject): if gameObject.type == "player": self.nodes.append(nodes.PlayerNode(self.sceneManager, gameObject)) def on_player_position_changed(self, mobileObject, position): self.cameraNode.position = (position[0], 100, position[1] + 100) ## Window event listener callbacks def windowResized(self, renderWindow): self.mouse.getMouseState().width = renderWindow.width self.mouse.getMouseState().height = renderWindow.height vp = self.camera.getViewport() self.camera.aspectRatio = vp.actualWidth / vp.actualHeight # @todo: Scale the image so viewable area remains the same. def windowClosed(self, renderWindow): # Only close for window that created OIS if(renderWindow == self.renderWindow): del self
class PlayScene(ogre.FrameListener, ogre.WindowEventListener, SchedulerManager): """ This class represents the game's main scene - the play scene. This class sets up the initial scene and acts as the main game loop (via frameStarted()). """ def __init__(self, sceneManager, address, port, player_name): # Initialize the various listener classes we are a subclass from ogre.FrameListener.__init__(self) ogre.WindowEventListener.__init__(self) SchedulerManager.__init__(self) self.address = address self.port = port self.player_name = player_name self.is_round_active = False self.renderWindow = ogre.Root.getSingleton().getAutoCreatedWindow() self.sceneManager = sceneManager self.camera = self.sceneManager.getCamera("PrimaryCamera") self.cameraNode = self.sceneManager.getSceneNode("PrimaryCamera") self.viewport = self.camera.getViewport() self.player = None self.last_update = None self.scores = { } self.scores_changed = Event() self.game_nodes = { } self.players = { } # Come up with a non-static way of doing this. self.nodes = [] nodes.Node.node_created += self.on_node_created nodes.Node.node_destroyed += self.on_node_destroyed # Set up the scene. self.setupScene() # Load sounds. self.loadSceneSounds() # Set up the GUI. self.gui = PlaySceneGUI(self) self.gui.element_selected += self.on_gui_element_selected # Show a welcome message. self.gui.message.notice("Tides of the Elements") # Load scene music audio.set_background_music("media/sounds/Dispatches+Of+Humanity.wav") # Set up the input devices. self.setupInput() # Set up initial window size. self.windowResized(self.renderWindow) # Set this to True when we get an event to exit the application self.quit = False # Listen for any events directed to the window manager's close button ogre.WindowEventUtilities.addWindowEventListener(self.renderWindow, self) # Begin scene music audio.play_background_music() def __del__ (self ): # Clean up OIS self.inputManager.destroyInputObjectKeyboard(self.keyboard) self.inputManager.destroyInputObjectMouse(self.mouse) OIS.InputManager.destroyInputSystem(self.inputManager) self.inputManager = None ogre.WindowEventUtilities.removeWindowEventListener(self.renderWindow, self) self.windowClosed(self.renderWindow) def setupScene(self): ## Load the level. # Create the world. self.world = gamestate.world.World() # Load the scene into the Ogre world. # @todo: Remove .scene dependancy and move to external file (format?). sceneLoader = SceneLoader.DotSceneLoader("media/testtilescene.scene", self.sceneManager) sceneLoader.parseDotScene() # Attach a handler to world.object_added and removed self.world.object_added += self.on_world_object_added self.world.object_removed += self.on_world_object_removed # Load the scene into the game state. self.scene = gamestate.scenes.TestScene(self.world) # Create the client and set listeners. self.client = net.client.GameClient(self.world, self.address, self.port) self.client.connected += self.on_client_connected # Start the netclient and connect. self.client_thread = threading.Thread(target=self.client.go) self.client_thread.start() # Setup camera self.camera.nearClipDistance = 1 self.camera.farClipDistance = 500 self.camera.setProjectionType(ogre.PT_ORTHOGRAPHIC) # THIS SPECIFIES THE HEIGHT OF THE ORTHOGRAPHIC WINDOW # the width will be recalculated based on the aspect ratio # in ortho projection mode, decreasing the size of the window # is equivalent to zooming in, increasing is the equivalent of # zooming out. self.camera.setOrthoWindowHeight(200) # Setup camera node self.cameraNode.position = (0, 100, 100) self.cameraNode.pitch(ogre.Degree(-45)) def loadSceneSounds(self): # Air Sounds audio.load_source("airshot", "media/sounds/airshot.wav") audio.load_source("gustofwind", "media/sounds/gustofwind.wav") audio.load_source("windwhisk", "media/sounds/windwhisk.wav") audio.load_source("lightningbolt", "media/sounds/lightningbolt.wav") # Earth Sounds audio.load_source("earthquake", "media/sounds/earthquake.wav") audio.load_source("hook", "media/sounds/hook.wav") # Fire Sounds audio.load_source("flamerush", "media/sounds/flamerush.wav") audio.load_source("lavasplash", "media/sounds/lavasplash.wav") audio.load_source("ringoffire", "media/sounds/ringoffire.wav") # Water Sounds audio.load_source("iceshot", "media/sounds/iceshot.wav") audio.load_source("iceburst", "media/sounds/iceburst.wav") audio.load_source("tidalwave", "media/sounds/tidalwave.wav") audio.load_source("watergush", "media/sounds/watergush.wav") # General Sounds audio.load_source("weaponswing", "media/sounds/weaponswing.wav") audio.load_source("weaponswingmiss","media/sounds/weaponswingmiss.wav") audio.load_source("whiff", "media/sounds/whiff.wav") audio.load_source("impact", "media/sounds/impact.wav") def setupInput(self): # Create the inputManager using the supplied renderWindow windowHnd = self.renderWindow.getCustomAttributeInt("WINDOW") paramList = [("WINDOW", str(windowHnd)), \ ("w32_mouse", "DISCL_FOREGROUND"), \ ("w32_mouse", "DISCL_NONEXCLUSIVE"), \ ("w32_keyboard", "DISCL_FOREGROUND"), \ ("w32_keyboard", "DISCL_NONEXCLUSIVE"),] # @todo: add mac/linux parameters self.inputManager = OIS.createPythonInputSystem(paramList) # Attempt to get the mouse/keyboard input device objects. try: self.mouse = self.inputManager.createInputObjectMouse(OIS.OISMouse, True) self.keyboard = self.inputManager.createInputObjectKeyboard(OIS.OISKeyboard, True) except Exception: # Unable to obtain mouse/keyboard input raise # Use an InputHandler object to handle the callback functions. self.inputHandler = InputHandler(self.mouse, self.keyboard, self) self.mouse.setEventCallback(self.inputHandler) self.keyboard.setEventCallback(self.inputHandler) def frameStarted(self, event): """ Called before a frame is displayed, handles events (also those via callback functions, as you need to call capture() on the input objects) Returning False here exits the application (render loop stops) """ dt = event.timeSinceLastFrame # Get buffered input from server and process it. while not self.client.input.empty(): packet = self.client.input.get_nowait() self.process_packet(packet) # Add time to schedulers. SchedulerManager.update(self, dt) # Capture any buffered events (and fire any callbacks). self.inputHandler.capture() # Update our UI Elements self.gui.update(dt) # Update the game state world. self.world.update(dt) # Update the audio module so it can throw its events audio.update(dt) # Send an PlayerUpdate packet to the server if appropriate. self._send_update() # Send buffered output to server. reactor.callFromThread(self.client.send) # Add time to animations. for node in self.nodes: node.update(dt) # Neatly close our FrameListener if our renderWindow has been shut down # or we are quitting. if self.renderWindow.isClosed() or self.quit: return False return True def on_node_created(self, node): self.nodes.append(node) def on_node_destroyed(self, node): self.nodes.remove(node) ## Net event callbacks & helpers def _send_update(self, check_time=True): """ Sends a PlayerUpdate packet to the server if appropriate. """ if self.player is None or self.player.is_dead: return update = self._get_update() if self.last_update is not None: update_time, last_update = self.last_update # Don't send if we've sent in the last 0.1s. if check_time and update_time + 0.05 > self.world.time: return # Don't send if info hasn't changed since the last update. if last_update.x == update.x and last_update.z == update.z and \ last_update.rotation == update.rotation and \ last_update.move_speed == update.move_speed and \ last_update.move_direction == update.move_direction: return # print "Sending player update to server." self.client.output.put_nowait(update) self.last_update = (self.world.time, update) def _get_update(self): """ Returns a PlayerUpdate packet based on the current player state. """ update = packets.PlayerUpdate() update.x, update.z = self.player.position update.rotation = self.player.rotation if self.player.is_moving: update.move_speed = self.player.move_speed update.move_direction = self.player.move_direction else: update.move_speed = 0 update.move_direction = 0 return update def process_packet(self, packet): ptype = type(packet) # print "Processing packet=%s: %s from server." % (packet.id, ptype.__name__) # JoinResponse if ptype is packets.JoinResponse: # @todo: handle deny # Add a player to the world and set it as our active player. print "Creating player in world with id=%s." % packet.player_id self.player = gamestate.objects.Player(self.world) self.player.object_id = packet.player_id self.player.is_dead = True self.player.name = self.player_name self.players[self.player.object_id] = self.player self.scores[self.player.object_id] = 0 self.scores_changed(self.scores) # Listen to the player's position change event so we can mvoe the # camera with the player. self.player.position_changed += self.on_player_position_changed self.player.element_changed += self.on_player_element_changed self.player.ability_requested += self.on_player_ability_requested self.player.is_dead_changed += self.on_player_is_dead_changed self.gui.element_selection.show() # SpawnResponse if ptype is packets.SpawnResponse: self.player.change_element(packet.element_type) self.player.position = (packet.x, packet.z) self.world.add_object(self.player, self.player.object_id) self.gui.setup_player_gui(self.player) self.is_round_active = True # ObjectInit elif ptype is packets.ObjectInit: if packet.object_type == "player": object = gamestate.objects.Player(self.world) object.name = packet.name object.change_element(packet.element_type) # @todo: implement owner_id, ttl self.world.add_object(object, packet.object_id) self.players[packet.object_id] = object if not self.scores.has_key(packet.object_id): self.scores[packet.object_id] = 0 self.scores_changed(self.scores) else: raise Exception("Invalid object_type") # ObjectUpdate elif ptype is packets.ObjectUpdate: if not self.world.objects_hash.has_key(packet.object_id): # We don't know about this object yet, so we can't update it. print "Received ObjectUpdate for unnkown object id=%s" % packet.object_id else: object = self.world.objects_hash[packet.object_id] # print "Updating object id=%s." % object.object_id if packet.forced: object.position = (packet.x, packet.z) object.rotation = packet.rotation if packet.move_speed > 0: object.move_speed = packet.move_speed else: object.is_moving = False object.move_direction = packet.move_direction object.force_vector = (packet.force_x, packet.force_z) object.is_dead = packet.is_dead else: object.rotation = packet.rotation object.force_vector = (packet.force_x, packet.force_z) if object == self.player: # This is an update about the player. We want to deal with # this case differently so we don't overwrite some client # states such as position. object.is_dead = packet.is_dead if packet.move_speed > 0: object.move_speed = packet.move_speed diff_vector = ogre.Vector2(packet.x - object.position[0], packet.z - object.position[1]) # if diff_vector.squaredLength() > 500: # If the server tells us we're far from where we think # we are, then warp to the server's location. # object.position = (packet.x, packet.z) else: # This is an update for another game object. if packet.move_speed > 0: object.is_moving = True object.move_direction = packet.move_direction object.move_speed = packet.move_speed diff_vector = ogre.Vector3(packet.x - object.position[0], 0, packet.z - object.position[1]) if diff_vector.squaredLength() > 500: # If the server's location is far from where we # thinkt his player is, then, then don't smooth. object.position = (packet.x, packet.z) object.rotation = packet.rotation else: # Smooth the difference in locations. move_vector = ogre.Vector3(packet.move_speed * math.cos(packet.rotation + packet.move_direction), 0, packet.move_speed * math.sin(packet.rotation + packet.move_direction)) resultant = diff_vector + move_vector angle = math.atan2(resultant.z, resultant.x) object.rotation = angle - packet.move_direction else: object.position = (packet.x, packet.z) object.is_moving = False if object.type == "player": if packet.is_dead: object.is_dead = packet.is_dead # ObjectStatusUpdate elif ptype is packets.ObjectStatusUpdate: if self.world.objects_hash.has_key(packet.object_id): object = self.world.objects_hash[packet.object_id] object.health = packet.health object.power = packet.power else: print "Ignoring ObjectStatusUpdate because player is not in world." # ObjectRemove elif ptype is packets.ObjectRemove: object = self.world.objects_hash[packet.object_id] if object.type == "player" and object.is_dead: # This is a player that probably just died. We will delay the # object's removal from the world for a short moment so that # objects can still collide with it. This is a fix to the # killing ability not showing collision with the player. # @todo: Fix this bug another way - this is putting the client # (slightly) out of synch with the server by keeping the object # around in the world. self.schedule(.25, self.world.remove_object, object) else: self.world.remove_object(object) # AbilityUsed elif ptype is packets.AbilityUsed: # print "Using ability id=%s on player_id=%s" % (packet.ability_id, packet.object_id) player = self.world.objects_hash[packet.object_id] player.use_ability(packet.ability_id) # Message elif ptype is packets.Message: if packet.type == "error": self.gui.message.error(packet.message) elif packet.type == "notice": self.gui.message.notice(packet.message) elif packet.type == "death": self.gui.message.death(packet.message) elif packet.type == "success": self.gui.message.success(packet.message) elif packet.type == "system": self.gui.message.system(packet.message) else: self.gui.message.system(packet.message) # ScoreUpdate elif ptype is packets.ScoreUpdate: # @todo: Delete these at some point. player = self.players[packet.player_id] player.score = packet.score self.scores[player.object_id] = player.score self.scores_changed(self.scores) # RoundEnd elif ptype is packets.RoundEnd: self.is_round_active = False self.player.is_dead = True self.gui.element_selection.hide() # RoundStart elif ptype is packets.RoundStart: self.is_round_active = True self.gui.element_selection.show() # ClientDisconnect elif ptype is packets.ClientDisconnect: if self.game_nodes.has_key(packet.player_id): node = self.game_nodes[packet.player_id] del self.game_nodes[packet.player_id] node.destroy() if self.players.has_key(packet.player_id): del self.players[packet.player_id] if self.scores.has_key(packet.player_id): del self.scores[packet.player_id] self.scores_changed(self.scores) def on_client_connected(self): packet = packets.JoinRequest() # @todo: Get player_name from somewhere. packet.player_name = self.player_name self.client.output.put_nowait(packet) ## Game event callbacks def on_world_object_added(self, object): if object.type == "player": if self.game_nodes.has_key(object.object_id): # We already have a node for this game object, but it may be # represented by another object in memory. node = self.game_nodes[object.object_id] if node.object == object: # If it's the same object, we don't need a new node. if node.corpse is not None: node.corpse.destroy() node.corpse = None return # Otherwise, destroy the current node and create a new one. node.destroy() node = nodes.PlayerNode(self.sceneManager, object, "ninja.mesh") node.set_scale(.1) node.rotation -= math.pi/2 self.game_nodes[object.object_id] = node elif object.type == "volcano": v = nodes.GameNode(self.sceneManager, object) v.set_mesh("volcano.mesh") v.set_particle_system("VolcanoEruption", position_offset=(0, 15, -5), scale=10) def on_world_object_removed(self, object): # @todo: Remove nodes at some point for players no longer here. pass def on_player_position_changed(self, mobileObject, position): self.cameraNode.position = (position[0], 100, position[1] + 100) def on_player_element_changed(self, player): # Recreate the ability bar GUI. self.gui.setup_ability_bar(self.player) def on_player_ability_requested(self, player, ability_id): ar = packets.AbilityRequest() ar.object_id = player.object_id ar.ability_id = ability_id # Send a PlayerUpdate so the server has the most recent information # about us when using the ability. self._send_update(check_time=False) self.client.output.put_nowait(ar) def on_player_is_dead_changed(self, player): if self.player.is_dead and self.is_round_active: # Show the element selection screen after 3 seconds. self.schedule(3, self.gui.element_selection.show) ## GUI event handlers def on_gui_element_selected(self, element_type): request = packets.SpawnRequest() request.element_type = element_type self.client.output.put_nowait(request) self.gui.element_selection.hide() ## Window event listener callbacks def windowResized(self, renderWindow): self.mouse.getMouseState().width = renderWindow.width self.mouse.getMouseState().height = renderWindow.height vp = self.viewport self.camera.aspectRatio = vp.actualWidth / vp.actualHeight # @todo: Scale the image so viewable area remains the same. def windowClosed(self, renderWindow): # Only close for window that created OIS if(renderWindow == self.renderWindow): del self
class PlayScene(ogre.FrameListener, ogre.WindowEventListener): """ This class represents the game's main scene - the play scene. This class sets up the initial scene and acts as the main game loop (via frameStarted()). """ def __init__(self, sceneManager): # Initialize the various listener classes we are a subclass from ogre.FrameListener.__init__(self) ogre.WindowEventListener.__init__(self) self.renderWindow = ogre.Root.getSingleton().getAutoCreatedWindow() self.sceneManager = sceneManager self.camera = self.sceneManager.getCamera("PrimaryCamera") self.cameraNode = self.sceneManager.getSceneNode("PrimaryCamera") # Create an empty list of nodes self.nodes = [] # Set up the scene. self.setupScene() # Create the inputManager using the supplied renderWindow windowHnd = self.renderWindow.getCustomAttributeInt("WINDOW") paramList = [("WINDOW", str(windowHnd)), \ ("w32_mouse", "DISCL_FOREGROUND"), \ ("w32_mouse", "DISCL_NONEXCLUSIVE"), \ ("w32_keyboard", "DISCL_FOREGROUND"), \ ("w32_keyboard", "DISCL_NONEXCLUSIVE"),] # @todo: add mac/linux parameters self.inputManager = OIS.createPythonInputSystem(paramList) # Attempt to get the mouse/keyboard input device objects. try: self.mouse = self.inputManager.createInputObjectMouse( OIS.OISMouse, True) self.keyboard = self.inputManager.createInputObjectKeyboard( OIS.OISKeyboard, True) except Exception: # Unable to obtain mouse/keyboard input raise # Use an InputHandler object to handle the callback functions. self.inputHandler = InputHandler(mouse=self.mouse, keyboard=self.keyboard, scene=self, player=self.player) self.mouse.setEventCallback(self.inputHandler) self.keyboard.setEventCallback(self.inputHandler) # Set up initial window size. self.windowResized(self.renderWindow) # Set this to True when we get an event to exit the application self.quit = False # Listen for any events directed to the window manager's close button ogre.WindowEventUtilities.addWindowEventListener( self.renderWindow, self) def __del__(self): # Clean up OIS self.inputManager.destroyInputObjectKeyboard(self.keyboard) self.inputManager.destroyInputObjectMouse(self.mouse) OIS.InputManager.destroyInputSystem(self.inputManager) self.inputManager = None ogre.WindowEventUtilities.removeWindowEventListener( self.renderWindow, self) self.windowClosed(self.renderWindow) def setupScene(self): ## Load the level. # @todo: Remove .scene dependancy and move to external file (format?). # Load some data from the .scene file sceneLoader = SceneLoader.DotSceneLoader("media/testtilescene.scene", self.sceneManager) sceneLoader.parseDotScene() # Create the world. self.world = gamestate.world.World() # Attach a handler to world.object_added self.world.object_added += self.on_world_object_added # Add a player to the world and set it as our active player. self.player = gamestate.objects.Player(self.world) self.world.add_object(self.player) # Add stationary NPC ninja... npc = gamestate.objects.Player(self.world) self.world.add_object(npc) npc.position = (45, 45) npc.isPassable = False # Add boundary lines for map walls. # @todo: move this out of here! # north wall boundary1 = gamestate.objects.GameObject(self.world) boundary1.position = (-90, -90) boundary1.isPassable = False boundary1.bounding_shape = gamestate.collision.BoundingLineSegment( (-90, -90), (90, -90), (0, 1)) # south wall boundary2 = gamestate.objects.GameObject(self.world) boundary2.position = (-90, 90) boundary2.isPassable = False boundary2.bounding_shape = gamestate.collision.BoundingLineSegment( (-90, 90), (90, 90), (0, -1)) # east wall boundary3 = gamestate.objects.GameObject(self.world) boundary3.position = (90, -90) boundary3.isPassable = False boundary3.bounding_shape = gamestate.collision.BoundingLineSegment( (90, -90), (90, 90), (-1, 0)) # west wall boundary4 = gamestate.objects.GameObject(self.world) boundary4.position = (-90, -90) boundary4.isPassable = False boundary4.bounding_shape = gamestate.collision.BoundingLineSegment( (-90, -90), (-90, 90), (1, 0)) # bounding rectangle for testing boundary5 = gamestate.objects.GameObject(self.world) boundary5.position = (-30, 0) boundary5.isPassable = False boundary5.bounding_shape = gamestate.collision.BoundingRectangle( 40, 40, 45) self.world.add_object(boundary1) self.world.add_object(boundary2) self.world.add_object(boundary3) self.world.add_object(boundary4) self.world.add_object(boundary5) # Listen to the player's position change event so we can mvoe the # camera with the player. self.player.position_changed += self.on_player_position_changed # Setup camera self.camera.nearClipDistance = 1 self.camera.farClipDistance = 500 self.camera.setProjectionType(ogre.PT_ORTHOGRAPHIC) # THIS SPECIFIES THE HEIGHT OF THE ORTHOGRAPHIC WINDOW # the width will be recalculated based on the aspect ratio # in ortho projection mode, decreasing the size of the window # is equivalent to zooming in, increasing is the equivalent of # zooming out. self.camera.setOrthoWindowHeight(200) # Setup camera node self.cameraNode.position = (0, 100, 100) self.cameraNode.pitch(ogre.Degree(-45)) def frameStarted(self, event): """ Called before a frame is displayed, handles events (also those via callback functions, as you need to call capture() on the input objects) Returning False here exits the application (render loop stops) """ dt = event.timeSinceLastFrame # Capture any buffered events (and fire any callbacks). self.inputHandler.capture() # Update the game state world. self.world.update(dt) # Add time to animations. for node in self.nodes: node.animations_addtime(dt) # Neatly close our FrameListener if our renderWindow has been shut down # or we are quitting. if self.renderWindow.isClosed() or self.quit: return False return True ## Game event callbacks def on_world_object_added(self, gameObject): if gameObject.type == "player": self.nodes.append(nodes.PlayerNode(self.sceneManager, gameObject)) def on_player_position_changed(self, mobileObject, position): self.cameraNode.position = (position[0], 100, position[1] + 100) ## Window event listener callbacks def windowResized(self, renderWindow): self.mouse.getMouseState().width = renderWindow.width self.mouse.getMouseState().height = renderWindow.height vp = self.camera.getViewport() self.camera.aspectRatio = vp.actualWidth / vp.actualHeight # @todo: Scale the image so viewable area remains the same. def windowClosed(self, renderWindow): # Only close for window that created OIS if (renderWindow == self.renderWindow): del self
from kivy.app import App from lanedisplay import LaneDisplay from lanesliders import LaneSliders from lanecanvas import LaneCanvas from gearshift import GearShift from speedyawadjust import SpeedYawAdjust from lanecenteringstatus import LaneCenteringStatus from sliderinput import SliderInput from inputhandler import InputHandler input_handler = InputHandler() class MockUIApp(App): def __init__(self, **kwargs): super(MockUIApp, self).__init__(**kwargs)
class PlayScene(ogre.FrameListener, ogre.WindowEventListener): """ This class represents the game's main scene - the play scene. This class sets up the initial scene and acts as the main game loop (via frameStarted()). """ def __init__(self, sceneManager, address, port): # Initialize the various listener classes we are a subclass from ogre.FrameListener.__init__(self) ogre.WindowEventListener.__init__(self) self.address = address self.port = port self.renderWindow = ogre.Root.getSingleton().getAutoCreatedWindow() self.sceneManager = sceneManager self.camera = self.sceneManager.getCamera("PrimaryCamera") self.cameraNode = self.sceneManager.getSceneNode("PrimaryCamera") # Create an empty list of nodes self.nodes = [] # Set up the scene. self.setupScene() # Init attributes. self.player = None self.last_update = None # Create the inputManager using the supplied renderWindow windowHnd = self.renderWindow.getCustomAttributeInt("WINDOW") paramList = [("WINDOW", str(windowHnd)), \ ("w32_mouse", "DISCL_FOREGROUND"), \ ("w32_mouse", "DISCL_NONEXCLUSIVE"), \ ("w32_keyboard", "DISCL_FOREGROUND"), \ ("w32_keyboard", "DISCL_NONEXCLUSIVE"),] # @todo: add mac/linux parameters self.inputManager = OIS.createPythonInputSystem(paramList) # Attempt to get the mouse/keyboard input device objects. try: self.mouse = self.inputManager.createInputObjectMouse( OIS.OISMouse, True) self.keyboard = self.inputManager.createInputObjectKeyboard( OIS.OISKeyboard, True) except Exception: # Unable to obtain mouse/keyboard input raise # Use an InputHandler object to handle the callback functions. self.inputHandler = InputHandler(self.mouse, self.keyboard, self) self.mouse.setEventCallback(self.inputHandler) self.keyboard.setEventCallback(self.inputHandler) # Set up initial window size. self.windowResized(self.renderWindow) # Set this to True when we get an event to exit the application self.quit = False # Listen for any events directed to the window manager's close button ogre.WindowEventUtilities.addWindowEventListener( self.renderWindow, self) def __del__(self): # Clean up OIS self.inputManager.destroyInputObjectKeyboard(self.keyboard) self.inputManager.destroyInputObjectMouse(self.mouse) OIS.InputManager.destroyInputSystem(self.inputManager) self.inputManager = None ogre.WindowEventUtilities.removeWindowEventListener( self.renderWindow, self) self.windowClosed(self.renderWindow) def setupScene(self): ## Load the level. # @todo: Remove .scene dependancy and move to external file (format?). # Load some data from the .scene file sceneLoader = SceneLoader.DotSceneLoader("media/testtilescene.scene", self.sceneManager) sceneLoader.parseDotScene() # Create the world. self.world = gamestate.world.World() # Create the client and set listeners. self.client = net.client.GameClient(self.world, self.address, self.port) self.client.connected += self.on_client_connected # Start the netclient and connect. self.client_thread = threading.Thread(target=self.client.go) self.client_thread.start() # Attach a handler to world.object_added self.world.object_added += self.on_world_object_added # Set up the TestScene self.scene = gamestate.scenes.TestScene(self.world) # Setup camera self.camera.nearClipDistance = 1 self.camera.farClipDistance = 500 self.camera.setProjectionType(ogre.PT_ORTHOGRAPHIC) # THIS SPECIFIES THE HEIGHT OF THE ORTHOGRAPHIC WINDOW # the width will be recalculated based on the aspect ratio # in ortho projection mode, decreasing the size of the window # is equivalent to zooming in, increasing is the equivalent of # zooming out. self.camera.setOrthoWindowHeight(200) # Setup camera node self.cameraNode.position = (0, 100, 100) self.cameraNode.pitch(ogre.Degree(-45)) def frameStarted(self, event): """ Called before a frame is displayed, handles events (also those via callback functions, as you need to call capture() on the input objects) Returning False here exits the application (render loop stops) """ dt = event.timeSinceLastFrame # Get buffered input from server and process it. while not self.client.input.empty(): packet = self.client.input.get_nowait() self.process_packet(packet) # Capture any buffered events (and fire any callbacks). self.inputHandler.capture() # Update the game state world. self.world.update(dt) # Send an PlayerUpdate packet to the server if appropriate. self._send_update() # Send buffered output to server. reactor.callFromThread(self.client.send) # Add time to animations. for node in self.nodes: node.animations_addtime(dt) # Neatly close our FrameListener if our renderWindow has been shut down # or we are quitting. if self.renderWindow.isClosed() or self.quit: return False return True ## Net event callbacks & helpers def _send_update(self): """ Sends a PlayerUpdate packet to the server if appropriate. """ if self.player is None: return update = self._get_update() if self.last_update is not None: update_time, last_update = self.last_update # Don't send if we've sent in the last 0.1s. if update_time + 0.05 > self.world.time: return # Don't send if info hasn't changed since the last update. if last_update.x == update.x and last_update.z == update.z and \ last_update.rotation == update.rotation and \ last_update.move_speed == update.move_speed and \ last_update.move_direction == update.move_direction: return print "Sending player update to server." self.client.output.put_nowait(update) self.last_update = (self.world.time, update) def _get_update(self): """ Returns a PlayerUpdate packet based on the current player state. """ update = packets.PlayerUpdate() update.x, update.z = self.player.position update.rotation = self.player.rotation if self.player.is_moving: update.move_speed = self.player.move_speed update.move_direction = self.player.move_direction else: update.move_speed = 0 update.move_direction = 0 return update def process_packet(self, packet): ptype = type(packet) print "Processing packet=%s: %s from server." % (packet.id, ptype.__name__) # JoinResponse if ptype is packets.JoinResponse: # @todo: handle deny # Add a player to the world and set it as our active player. print "Creating player in world with id=%s." % packet.player_id self.player = gamestate.objects.Player(self.world) self.world.add_object(self.player, packet.player_id) # Listen to the player's position change event so we can mvoe the # camera with the player. self.player.position_changed += self.on_player_position_changed # ObjectInit elif ptype is packets.ObjectInit: if packet.object_type == "player": object = gamestate.objects.Player(self.world) else: raise Exception("Invalid object_type") # @todo: implement name, owner_id, ttl self.world.add_object(object, packet.object_id) # ObjectUpdate elif ptype is packets.ObjectUpdate: if not self.world.objects_hash.has_key(packet.object_id): return object = self.world.objects_hash[packet.object_id] print "Updating object id=%s." % object.object_id object.rotation = packet.rotation try: if packet.move_speed > 0: diff_vector = ogre.Vector3(packet.x - object.position[0], 0, packet.z - object.position[1]) move_vector = ogre.Vector3( packet.move_speed * math.cos(packet.rotation), 0, packet.move_speed * math.sin(packet.rotation)) resultant = diff_vector + move_vector angle = math.atan2(resultant.z, resultant.x) object.move_speed = packet.move_speed object.rotation = angle object.move_direction = 0 object.is_moving = True else: object.position = (packet.x, packet.z) object.is_moving = False except: object.position = (packet.x, packet.z) def on_client_connected(self): packet = packets.JoinRequest() # @todo: Get player_name from somewhere. packet.player_name = "Player1" self.client.output.put_nowait(packet) ## Game event callbacks def on_world_object_added(self, gameObject): if gameObject.type == "player": self.nodes.append(nodes.PlayerNode(self.sceneManager, gameObject)) def on_player_position_changed(self, mobileObject, position): self.cameraNode.position = (position[0], 100, position[1] + 100) ## Window event listener callbacks def windowResized(self, renderWindow): self.mouse.getMouseState().width = renderWindow.width self.mouse.getMouseState().height = renderWindow.height vp = self.camera.getViewport() self.camera.aspectRatio = vp.actualWidth / vp.actualHeight # @todo: Scale the image so viewable area remains the same. def windowClosed(self, renderWindow): # Only close for window that created OIS if (renderWindow == self.renderWindow): del self
class PlayScene(ogre.FrameListener, ogre.WindowEventListener): """ This class represents the game's main scene - the play scene. This class sets up the initial scene and acts as the main game loop (via frameStarted()). """ def __init__(self, sceneManager): # Initialize the various listener classes we are a subclass from ogre.FrameListener.__init__(self) ogre.WindowEventListener.__init__(self) self.renderWindow = ogre.Root.getSingleton().getAutoCreatedWindow() self.sceneManager = sceneManager self.camera = self.sceneManager.getCamera("PrimaryCamera") self.cameraNode = self.sceneManager.getSceneNode("PrimaryCamera") self.viewport = self.camera.getViewport() # Create an empty list of nodes self.nodes = [] # Create an empty list of GUI elements. self.gui_elements = [] # Set up the overlay for the GUI. self.setupOverlay() # Set up the scene. self.setupScene() # Set up the GUI. self.setupGUI() # Create the inputManager using the supplied renderWindow windowHnd = self.renderWindow.getCustomAttributeInt("WINDOW") paramList = [("WINDOW", str(windowHnd)), \ ("w32_mouse", "DISCL_FOREGROUND"), \ ("w32_mouse", "DISCL_NONEXCLUSIVE"), \ ("w32_keyboard", "DISCL_FOREGROUND"), \ ("w32_keyboard", "DISCL_NONEXCLUSIVE"),] # @todo: add mac/linux parameters self.inputManager = OIS.createPythonInputSystem(paramList) # Attempt to get the mouse/keyboard input device objects. try: self.mouse = self.inputManager.createInputObjectMouse(OIS.OISMouse, True) self.keyboard = self.inputManager.createInputObjectKeyboard(OIS.OISKeyboard, True) except Exception: # Unable to obtain mouse/keyboard input raise # Use an InputHandler object to handle the callback functions. self.inputHandler = InputHandler(mouse=self.mouse, keyboard=self.keyboard, scene=self, player=self.player) self.mouse.setEventCallback(self.inputHandler) self.keyboard.setEventCallback(self.inputHandler) # Set up initial window size. self.windowResized(self.renderWindow) # Set this to True when we get an event to exit the application self.quit = False # Listen for any events directed to the window manager's close button ogre.WindowEventUtilities.addWindowEventListener(self.renderWindow, self) def __del__ (self ): # Clean up OIS self.inputManager.destroyInputObjectKeyboard(self.keyboard) self.inputManager.destroyInputObjectMouse(self.mouse) OIS.InputManager.destroyInputSystem(self.inputManager) self.inputManager = None ogre.WindowEventUtilities.removeWindowEventListener(self.renderWindow, self) self.windowClosed(self.renderWindow) def setupScene(self): ## Load the level. # @todo: Remove .scene dependancy and move to external file (format?). # Load some data from the .scene file sceneLoader = SceneLoader.DotSceneLoader("media/testtilescene.scene", self.sceneManager) sceneLoader.parseDotScene() # Create the world. self.world = gamestate.world.World() # Attach a handler to world.object_added self.world.object_added += self.on_world_object_added # Add a player to the world and set it as our active player. self.player = gamestate.objects.Player(self.world) self.world.add_object(self.player) # Add stationary NPC ninja... npc = gamestate.objects.Player(self.world) self.world.add_object(npc) npc.position = (-500, 0) npc.isPassable = False # Add boundary lines for map walls. self.setup_level_boundaries("media/levelbounds.bounds") # Listen to player events. self.player.position_changed += self.on_player_position_changed self.player.element_changed += self.on_player_element_changed # Setup camera self.camera.nearClipDistance = 1 self.camera.farClipDistance = 500 self.camera.setProjectionType(ogre.PT_ORTHOGRAPHIC) # THIS SPECIFIES THE HEIGHT OF THE ORTHOGRAPHIC WINDOW # the width will be recalculated based on the aspect ratio # in ortho projection mode, decreasing the size of the window # is equivalent to zooming in, increasing is the equivalent of # zooming out. self.camera.setOrthoWindowHeight(200) # Setup camera node self.cameraNode.position = (0, 100, 100) self.cameraNode.pitch(ogre.Degree(-45)) def setupGUI(self): # Set up health and power bars health_bar_rect = ogre.Rectangle() health_bar_rect.left = self.viewport.actualWidth / 2 - 128 health_bar_rect.top = self.viewport.actualHeight - 84 health_bar_rect.right = health_bar_rect.left + 256 health_bar_rect.bottom = health_bar_rect.top + 10 health_bar = gui.StatusBar("UI/StatusBars/Health", health_bar_rect, self.player.max_health) health_bar.name = "Health" power_bar_rect = ogre.Rectangle() power_bar_rect.left = health_bar_rect.left power_bar_rect.top = health_bar_rect.bottom power_bar_rect.right = health_bar_rect.right power_bar_rect.bottom = power_bar_rect.top + 10 power_bar = gui.StatusBar("UI/StatusBars/Power", power_bar_rect, self.player.max_power) power_bar.name = "Power" # Add the gui elements to the element list. self.gui_elements.append(health_bar) self.gui_elements.append(power_bar) # Add listeners to player's health and power changed events. self.player.health_changed += health_bar.on_value_changed self.player.power_changed += power_bar.on_value_changed # Create an FPS label. fpslabel = gui.FPSLabel("UI/FPSLabel") self.gui_elements.append(fpslabel) # Set up the ability bar. self.setupGUIAbilityBar() def setupGUIAbilityBar(self): player = self.player # Set up ability cooldown displays ability_keys = player.element.ability_keys ability_cooldowns = player.element.ability_cooldowns ability1_cooldown = ability_cooldowns[ability_keys[1]] ability2_cooldown = ability_cooldowns[ability_keys[2]] ability3_cooldown = ability_cooldowns[ability_keys[3]] ability4_cooldown = ability_cooldowns[ability_keys[4]] # Set up ability icons. if player.element.type == "fire": # Fire ability1_icon_mat = "FireIconAbility1" ability2_icon_mat = "FireIconAbility2" ability3_icon_mat = "FireIconAbility3" ability4_icon_mat = "FireIconAbility4" elif player.element.type == "earth": # Earth ability1_icon_mat = "EarthIconAbility1" ability2_icon_mat = "EarthIconAbility2" ability3_icon_mat = "EarthIconAbility3" ability4_icon_mat = "EarthIconAbility4" elif player.element.type == "air": # Air ability1_icon_mat = "AirIconAbility1" ability2_icon_mat = "AirIconAbility2" ability3_icon_mat = "AirIconAbility3" ability4_icon_mat = "AirIconAbility4" elif player.element.type == "water": # Water ability1_icon_mat = "WaterIconAbility1" ability2_icon_mat = "WaterIconAbility2" ability3_icon_mat = "WaterIconAbility3" ability4_icon_mat = "WaterIconAbility4" # Create UI Elements ability1_cdd_rect = ogre.Rectangle() ability1_cdd_rect.left = self.viewport.actualWidth / 2 - 128 ability1_cdd_rect.top = self.viewport.actualHeight - 64 ability1_cdd_rect.right = ability1_cdd_rect.left + 64 ability1_cdd_rect.bottom = ability1_cdd_rect.top + 64 ability1_cooldown_display = gui.AbilityCooldownDisplay("UI/AbilityBar/Ability1", ability1_cdd_rect, 1, ability1_cooldown) ability1_cooldown_display.overlay.setMaterialName(ability1_icon_mat) ability2_cdd_rect = ogre.Rectangle() ability2_cdd_rect.left = ability1_cdd_rect.right ability2_cdd_rect.top = ability1_cdd_rect.top ability2_cdd_rect.right = ability2_cdd_rect.left + 64 ability2_cdd_rect.bottom = ability2_cdd_rect.top + 64 ability2_cooldown_display = gui.AbilityCooldownDisplay("UI/AbilityBar/Ability2", ability2_cdd_rect, 2, ability2_cooldown) ability2_cooldown_display.overlay.setMaterialName(ability2_icon_mat) ability3_cdd_rect = ogre.Rectangle() ability3_cdd_rect.left = ability2_cdd_rect.right ability3_cdd_rect.top = ability2_cdd_rect.top ability3_cdd_rect.right = ability3_cdd_rect.left + 64 ability3_cdd_rect.bottom = ability3_cdd_rect.top + 64 ability3_cooldown_display = gui.AbilityCooldownDisplay("UI/AbilityBar/Ability3", ability3_cdd_rect, 3, ability3_cooldown) ability3_cooldown_display.overlay.setMaterialName(ability3_icon_mat) ability4_cdd_rect = ogre.Rectangle() ability4_cdd_rect.left = ability3_cdd_rect.right ability4_cdd_rect.top = ability3_cdd_rect.top ability4_cdd_rect.right = ability4_cdd_rect.left + 64 ability4_cdd_rect.bottom = ability4_cdd_rect.top + 64 ability4_cooldown_display = gui.AbilityCooldownDisplay("UI/AbilityBar/Ability4", ability4_cdd_rect, 4, ability4_cooldown) ability4_cooldown_display.overlay.setMaterialName(ability4_icon_mat) # Add the gui elements to the element list. self.gui_elements.append(ability1_cooldown_display) self.gui_elements.append(ability2_cooldown_display) self.gui_elements.append(ability3_cooldown_display) self.gui_elements.append(ability4_cooldown_display) # Listen to player events (why isn't this the same as how # StatusBar listens to its events?): ability1_cooldown_display.set_player_listener(self.player) ability2_cooldown_display.set_player_listener(self.player) ability3_cooldown_display.set_player_listener(self.player) ability4_cooldown_display.set_player_listener(self.player) def setupOverlay(self): pOver = ogre.OverlayManager.getSingleton().getByName("UI") pOver.show() def setup_level_boundaries(self, filepath): """ Takes an xml-style file that specifies all of the level's static boundinglinesegments, and creates those bounds in the world. """ xml_data = minidom.parse(filepath) docRoot = xml_data.getElementsByTagName('segments')[0].childNodes for segmentNode in docRoot: if segmentNode.nodeType == Node.ELEMENT_NODE and segmentNode.nodeName == 'segment': point1_data = self.getXMLNode(segmentNode, "point1").attributes point2_data = self.getXMLNode(segmentNode, "point2").attributes normal_data = self.getXMLNode(segmentNode, "normal").attributes point1 = (float(point1_data["x"].nodeValue), -float(point1_data["z"].nodeValue)) point2 = (float(point2_data["x"].nodeValue), -float(point2_data["z"].nodeValue)) normal = (float(normal_data["x"].nodeValue), float(normal_data["z"].nodeValue)) boundary_wall = gamestate.objects.GameObject(self.world) boundary_wall.isPassable = False boundary_wall.position = point1 boundary_wall.bounding_shape = gamestate.collision.BoundingLineSegment(point1, point2, normal) self.world.add_object(boundary_wall) def getXMLNode(self, base, name): """ This function basically doubles as both a test for element existence and a getter for that element node... used with setup_level_boundaries() """ if base.hasChildNodes: baseChildNodes = base.childNodes for node in baseChildNodes: if node.nodeType == Node.ELEMENT_NODE and node.nodeName == name: return node return False def frameStarted(self, event): """ Called before a frame is displayed, handles events (also those via callback functions, as you need to call capture() on the input objects) Returning False here exits the application (render loop stops) """ dt = event.timeSinceLastFrame # Capture any buffered events (and fire any callbacks). self.inputHandler.capture() # Update our UI Elements for element in self.gui_elements: element.update(dt) # Update the game state world. self.world.update(dt) # Add time to animations. for node in self.nodes: node.animations_addtime(dt) # Neatly close our FrameListener if our renderWindow has been shut down # or we are quitting. if self.renderWindow.isClosed() or self.quit: return False return True ## Game event callbacks def on_world_object_added(self, gameObject): if gameObject.type == "player": newPlayerNode = nodes.PlayerNode(self.sceneManager, gameObject, "ninja.mesh") newPlayerNode.set_scale(.1) self.nodes.append(newPlayerNode) def on_player_position_changed(self, mobileObject, position): self.cameraNode.position = (position[0], 100, position[1] + 100) def on_player_element_changed(self, player): # Remove all current gui.AbilityCooldownDisplay from the current gui. self.gui_elements = [element for element in self.gui_elements if type(element) is not gui.AbilityCooldownDisplay] # Recreate the ability bar GUI. self.setupGUIAbilityBar() def on_static_node_expired(self, static_node): print static_node.unique_scene_node_name self.sceneManager.destroySceneNode(static_node.unique_scene_node_name) ## Window event listener callbacks def windowResized(self, renderWindow): self.mouse.getMouseState().width = renderWindow.width self.mouse.getMouseState().height = renderWindow.height vp = self.viewport self.camera.aspectRatio = vp.actualWidth / vp.actualHeight # @todo: Scale the image so viewable area remains the same. def windowClosed(self, renderWindow): # Only close for window that created OIS if(renderWindow == self.renderWindow): del self
def signal_handler(signum, frame): exit(0) clear() title = 'Arsatum v0.0.1' os.system(f'title {title}') world = World(WIDTH, HEIGHT) world.init() # clear() # print(f'''Welcome to {title}''') # print('''-------------------''') # text = ''' # movement windows actions # 789 \\|/ i - inventory p - pick up item # 4.6 -.- e - charecter window space - descend/ascend stairs # 123 /|\\ l - message log num 5 - pass turn # j - journal # n - achievements # '''.strip() # print(text) # input('Press [enter] to start.') InputHandler(world).start() world.update(False) signal.signal(signal.SIGINT, signal_handler) time.sleep(99999)
class PlayScene(ogre.FrameListener, ogre.WindowEventListener): """ This class represents the game's main scene - the play scene. This class sets up the initial scene and acts as the main game loop (via frameStarted()). """ def __init__(self, sceneManager): # Initialize the various listener classes we are a subclass from ogre.FrameListener.__init__(self) ogre.WindowEventListener.__init__(self) self.renderWindow = ogre.Root.getSingleton().getAutoCreatedWindow() self.sceneManager = sceneManager self.camera = self.sceneManager.getCamera("PrimaryCamera") self.cameraNode = self.sceneManager.getSceneNode("PrimaryCamera") self.viewport = self.camera.getViewport() # Create an empty list of nodes self.nodes = [] # Create an empty list of GUI elements. self.gui_elements = [] # Set up the overlay for the GUI. self.setupOverlay() # Set up the scene. self.setupScene() # Set up the GUI. self.setupGUI() # Create the inputManager using the supplied renderWindow windowHnd = self.renderWindow.getCustomAttributeInt("WINDOW") paramList = [("WINDOW", str(windowHnd)), \ ("w32_mouse", "DISCL_FOREGROUND"), \ ("w32_mouse", "DISCL_NONEXCLUSIVE"), \ ("w32_keyboard", "DISCL_FOREGROUND"), \ ("w32_keyboard", "DISCL_NONEXCLUSIVE"),] # @todo: add mac/linux parameters self.inputManager = OIS.createPythonInputSystem(paramList) # Attempt to get the mouse/keyboard input device objects. try: self.mouse = self.inputManager.createInputObjectMouse( OIS.OISMouse, True) self.keyboard = self.inputManager.createInputObjectKeyboard( OIS.OISKeyboard, True) except Exception: # Unable to obtain mouse/keyboard input raise # Use an InputHandler object to handle the callback functions. self.inputHandler = InputHandler(mouse=self.mouse, keyboard=self.keyboard, scene=self, player=self.player) self.mouse.setEventCallback(self.inputHandler) self.keyboard.setEventCallback(self.inputHandler) # Set up initial window size. self.windowResized(self.renderWindow) # Set this to True when we get an event to exit the application self.quit = False # Listen for any events directed to the window manager's close button ogre.WindowEventUtilities.addWindowEventListener( self.renderWindow, self) def __del__(self): # Clean up OIS self.inputManager.destroyInputObjectKeyboard(self.keyboard) self.inputManager.destroyInputObjectMouse(self.mouse) OIS.InputManager.destroyInputSystem(self.inputManager) self.inputManager = None ogre.WindowEventUtilities.removeWindowEventListener( self.renderWindow, self) self.windowClosed(self.renderWindow) def setupScene(self): ## Load the level. # @todo: Remove .scene dependancy and move to external file (format?). # Load some data from the .scene file sceneLoader = SceneLoader.DotSceneLoader("media/testtilescene.scene", self.sceneManager) sceneLoader.parseDotScene() # Create the world. self.world = gamestate.world.World() # Attach a handler to world.object_added self.world.object_added += self.on_world_object_added # Add a player to the world and set it as our active player. self.player = gamestate.objects.Player(self.world) self.world.add_object(self.player) # Add stationary NPC ninja... npc = gamestate.objects.Player(self.world) self.world.add_object(npc) npc.position = (-500, 0) npc.isPassable = False # Add boundary lines for map walls. self.setup_level_boundaries("media/levelbounds.bounds") # Listen to player events. self.player.position_changed += self.on_player_position_changed self.player.element_changed += self.on_player_element_changed # Setup camera self.camera.nearClipDistance = 1 self.camera.farClipDistance = 500 self.camera.setProjectionType(ogre.PT_ORTHOGRAPHIC) # THIS SPECIFIES THE HEIGHT OF THE ORTHOGRAPHIC WINDOW # the width will be recalculated based on the aspect ratio # in ortho projection mode, decreasing the size of the window # is equivalent to zooming in, increasing is the equivalent of # zooming out. self.camera.setOrthoWindowHeight(200) # Setup camera node self.cameraNode.position = (0, 100, 100) self.cameraNode.pitch(ogre.Degree(-45)) def setupGUI(self): # Set up health and power bars health_bar_rect = ogre.Rectangle() health_bar_rect.left = self.viewport.actualWidth / 2 - 128 health_bar_rect.top = self.viewport.actualHeight - 84 health_bar_rect.right = health_bar_rect.left + 256 health_bar_rect.bottom = health_bar_rect.top + 10 health_bar = gui.StatusBar("UI/StatusBars/Health", health_bar_rect, self.player.max_health) health_bar.name = "Health" power_bar_rect = ogre.Rectangle() power_bar_rect.left = health_bar_rect.left power_bar_rect.top = health_bar_rect.bottom power_bar_rect.right = health_bar_rect.right power_bar_rect.bottom = power_bar_rect.top + 10 power_bar = gui.StatusBar("UI/StatusBars/Power", power_bar_rect, self.player.max_power) power_bar.name = "Power" # Add the gui elements to the element list. self.gui_elements.append(health_bar) self.gui_elements.append(power_bar) # Add listeners to player's health and power changed events. self.player.health_changed += health_bar.on_value_changed self.player.power_changed += power_bar.on_value_changed # Create an FPS label. fpslabel = gui.FPSLabel("UI/FPSLabel") self.gui_elements.append(fpslabel) # Set up the ability bar. self.setupGUIAbilityBar() def setupGUIAbilityBar(self): player = self.player # Set up ability cooldown displays ability_keys = player.element.ability_keys ability_cooldowns = player.element.ability_cooldowns ability1_cooldown = ability_cooldowns[ability_keys[1]] ability2_cooldown = ability_cooldowns[ability_keys[2]] ability3_cooldown = ability_cooldowns[ability_keys[3]] ability4_cooldown = ability_cooldowns[ability_keys[4]] # Set up ability icons. if player.element.type == "fire": # Fire ability1_icon_mat = "FireIconAbility1" ability2_icon_mat = "FireIconAbility2" ability3_icon_mat = "FireIconAbility3" ability4_icon_mat = "FireIconAbility4" elif player.element.type == "earth": # Earth ability1_icon_mat = "EarthIconAbility1" ability2_icon_mat = "EarthIconAbility2" ability3_icon_mat = "EarthIconAbility3" ability4_icon_mat = "EarthIconAbility4" elif player.element.type == "air": # Air ability1_icon_mat = "AirIconAbility1" ability2_icon_mat = "AirIconAbility2" ability3_icon_mat = "AirIconAbility3" ability4_icon_mat = "AirIconAbility4" elif player.element.type == "water": # Water ability1_icon_mat = "WaterIconAbility1" ability2_icon_mat = "WaterIconAbility2" ability3_icon_mat = "WaterIconAbility3" ability4_icon_mat = "WaterIconAbility4" # Create UI Elements ability1_cdd_rect = ogre.Rectangle() ability1_cdd_rect.left = self.viewport.actualWidth / 2 - 128 ability1_cdd_rect.top = self.viewport.actualHeight - 64 ability1_cdd_rect.right = ability1_cdd_rect.left + 64 ability1_cdd_rect.bottom = ability1_cdd_rect.top + 64 ability1_cooldown_display = gui.AbilityCooldownDisplay( "UI/AbilityBar/Ability1", ability1_cdd_rect, 1, ability1_cooldown) ability1_cooldown_display.overlay.setMaterialName(ability1_icon_mat) ability2_cdd_rect = ogre.Rectangle() ability2_cdd_rect.left = ability1_cdd_rect.right ability2_cdd_rect.top = ability1_cdd_rect.top ability2_cdd_rect.right = ability2_cdd_rect.left + 64 ability2_cdd_rect.bottom = ability2_cdd_rect.top + 64 ability2_cooldown_display = gui.AbilityCooldownDisplay( "UI/AbilityBar/Ability2", ability2_cdd_rect, 2, ability2_cooldown) ability2_cooldown_display.overlay.setMaterialName(ability2_icon_mat) ability3_cdd_rect = ogre.Rectangle() ability3_cdd_rect.left = ability2_cdd_rect.right ability3_cdd_rect.top = ability2_cdd_rect.top ability3_cdd_rect.right = ability3_cdd_rect.left + 64 ability3_cdd_rect.bottom = ability3_cdd_rect.top + 64 ability3_cooldown_display = gui.AbilityCooldownDisplay( "UI/AbilityBar/Ability3", ability3_cdd_rect, 3, ability3_cooldown) ability3_cooldown_display.overlay.setMaterialName(ability3_icon_mat) ability4_cdd_rect = ogre.Rectangle() ability4_cdd_rect.left = ability3_cdd_rect.right ability4_cdd_rect.top = ability3_cdd_rect.top ability4_cdd_rect.right = ability4_cdd_rect.left + 64 ability4_cdd_rect.bottom = ability4_cdd_rect.top + 64 ability4_cooldown_display = gui.AbilityCooldownDisplay( "UI/AbilityBar/Ability4", ability4_cdd_rect, 4, ability4_cooldown) ability4_cooldown_display.overlay.setMaterialName(ability4_icon_mat) # Add the gui elements to the element list. self.gui_elements.append(ability1_cooldown_display) self.gui_elements.append(ability2_cooldown_display) self.gui_elements.append(ability3_cooldown_display) self.gui_elements.append(ability4_cooldown_display) # Listen to player events (why isn't this the same as how # StatusBar listens to its events?): ability1_cooldown_display.set_player_listener(self.player) ability2_cooldown_display.set_player_listener(self.player) ability3_cooldown_display.set_player_listener(self.player) ability4_cooldown_display.set_player_listener(self.player) def setupOverlay(self): pOver = ogre.OverlayManager.getSingleton().getByName("UI") pOver.show() def setup_level_boundaries(self, filepath): """ Takes an xml-style file that specifies all of the level's static boundinglinesegments, and creates those bounds in the world. """ xml_data = minidom.parse(filepath) docRoot = xml_data.getElementsByTagName('segments')[0].childNodes for segmentNode in docRoot: if segmentNode.nodeType == Node.ELEMENT_NODE and segmentNode.nodeName == 'segment': point1_data = self.getXMLNode(segmentNode, "point1").attributes point2_data = self.getXMLNode(segmentNode, "point2").attributes normal_data = self.getXMLNode(segmentNode, "normal").attributes point1 = (float(point1_data["x"].nodeValue), -float(point1_data["z"].nodeValue)) point2 = (float(point2_data["x"].nodeValue), -float(point2_data["z"].nodeValue)) normal = (float(normal_data["x"].nodeValue), float(normal_data["z"].nodeValue)) boundary_wall = gamestate.objects.GameObject(self.world) boundary_wall.isPassable = False boundary_wall.position = point1 boundary_wall.bounding_shape = gamestate.collision.BoundingLineSegment( point1, point2, normal) self.world.add_object(boundary_wall) def getXMLNode(self, base, name): """ This function basically doubles as both a test for element existence and a getter for that element node... used with setup_level_boundaries() """ if base.hasChildNodes: baseChildNodes = base.childNodes for node in baseChildNodes: if node.nodeType == Node.ELEMENT_NODE and node.nodeName == name: return node return False def frameStarted(self, event): """ Called before a frame is displayed, handles events (also those via callback functions, as you need to call capture() on the input objects) Returning False here exits the application (render loop stops) """ dt = event.timeSinceLastFrame # Capture any buffered events (and fire any callbacks). self.inputHandler.capture() # Update our UI Elements for element in self.gui_elements: element.update(dt) # Update the game state world. self.world.update(dt) # Add time to animations. for node in self.nodes: node.animations_addtime(dt) # Neatly close our FrameListener if our renderWindow has been shut down # or we are quitting. if self.renderWindow.isClosed() or self.quit: return False return True ## Game event callbacks def on_world_object_added(self, gameObject): if gameObject.type == "player": newPlayerNode = nodes.PlayerNode(self.sceneManager, gameObject, "ninja.mesh") newPlayerNode.set_scale(.1) self.nodes.append(newPlayerNode) def on_player_position_changed(self, mobileObject, position): self.cameraNode.position = (position[0], 100, position[1] + 100) def on_player_element_changed(self, player): # Remove all current gui.AbilityCooldownDisplay from the current gui. self.gui_elements = [ element for element in self.gui_elements if type(element) is not gui.AbilityCooldownDisplay ] # Recreate the ability bar GUI. self.setupGUIAbilityBar() def on_static_node_expired(self, static_node): print static_node.unique_scene_node_name self.sceneManager.destroySceneNode(static_node.unique_scene_node_name) ## Window event listener callbacks def windowResized(self, renderWindow): self.mouse.getMouseState().width = renderWindow.width self.mouse.getMouseState().height = renderWindow.height vp = self.viewport self.camera.aspectRatio = vp.actualWidth / vp.actualHeight # @todo: Scale the image so viewable area remains the same. def windowClosed(self, renderWindow): # Only close for window that created OIS if (renderWindow == self.renderWindow): del self