class Game(object): def __init__(self): # Set up our middleware which will handle messages from the client. middleware = ControllerMiddleware(game_server=self) # Our "middleware" will populate this dictionary with legal directional # events from the client when they are received. self.network_events = {"left": False, "right": False, "up": False, "down": False} # Create a Neteria server instance and start listening. self.server = NeteriaServer(middleware) self.server.listen() # Set up and configure PyGame. pygame.init() self.screen = pygame.display.set_mode((800, 600)) pygame.display.set_caption("Neteria Server") self.clock = pygame.time.Clock() # Create a player sprite that we can move around. self.sprite = pygame.image.load("assets/player.png").convert_alpha() self.sprite_position = [(self.screen.get_width() / 2) - self.sprite.get_width() / 2, (self.screen.get_height() / 2) - self.sprite.get_height() / 2] def start(self): # Set up our main game loop. while True: self.clock.tick(60) # Loop through all of our PyGame events. for event in pygame.event.get(): if event.type == pygame.QUIT: return elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: return if self.network_events["left"]: self.sprite_position[0] -= 1 if self.network_events["right"]: self.sprite_position[0] += 1 if self.network_events["up"]: self.sprite_position[1] -= 1 if self.network_events["down"]: self.sprite_position[1] += 1 self.screen.fill((0,0,0)) self.screen.blit(self.sprite, self.sprite_position) if len(self.server.registry) > 0: pygame.display.set_caption("Neteria Server (Client Registered!)") pygame.display.flip()
class Control(object): """Control class for entire project. Contains the game loop, and contains the event_loop which passes events to States as needed. Logic for flipping states is also found here. :param caption: The window caption to use for the game itself. :type caption: String :rtype: None :returns: None """ def __init__(self, caption): self.screen = pg.display.get_surface() self.caption = caption self.done = False self.clock = pg.time.Clock() self.fps = 60.0 self.show_fps = True self.current_time = 0.0 self.keys = pg.key.get_pressed() self.key_events = [] self.state_dict = {} self.state_name = None self.state = None if NeteriaServer and Controller: self.network_events = [] self.server = NeteriaServer(Controller(self)) self.server.listen() else: self.server = None # Set up our game's configuration from the prepare module. from core import prepare self.imports = { "prepare": prepare, "ai": ai, "rumble": rumble, "db": db, "monster": monster, "player": player, "item": item, "map": maps, "pyganim": pyganim } self.config = prepare.CONFIG # Set up our game's event engine which executes actions based on # conditions defined in map files. self.event_engine = event.EventEngine() self.event_conditions = {} self.event_actions = {} self.event_persist = {} # Set up a variable that will keep track of currently playing music. self.current_music = {"status": "stopped", "song": None} # Keep track of animations that we will play. self.animations = {} # Create these Pygame event objects to simulate KEYDOWN and KEYUP # events for all the directional keys self.keyboard_events = {} self.keyboard_events["KEYDOWN"] = {} self.keyboard_events["KEYDOWN"]["up"] = pg.event.Event( pg.KEYDOWN, {'scancode': 111, 'key': 273, 'unicode': u'', 'mod': 4096}) self.keyboard_events["KEYDOWN"]["down"] = pg.event.Event( pg.KEYDOWN, {'scancode': 116, 'key': 274, 'unicode': u'', 'mod': 4096}) self.keyboard_events["KEYDOWN"]["left"] = pg.event.Event( pg.KEYDOWN, {'scancode': 113, 'key': 276, 'unicode': u'', 'mod': 4096}) self.keyboard_events["KEYDOWN"]["right"] = pg.event.Event( pg.KEYDOWN, {'scancode': 114, 'key': 275, 'unicode': u'', 'mod': 4096}) self.keyboard_events["KEYDOWN"]["enter"] = pg.event.Event( pg.KEYDOWN, {'scancode': 36, 'key': 13, 'unicode': u'\r', 'mod': 4096}) self.keyboard_events["KEYDOWN"]["escape"] = pg.event.Event( pg.KEYDOWN, {'scancode': 9, 'key': 27, 'unicode': u'\x1b', 'mod': 4096}) self.keyboard_events["KEYUP"] = {} self.keyboard_events["KEYUP"]["up"] = pg.event.Event( pg.KEYUP, {'scancode': 111, 'key': 273, 'mod': 4096}) self.keyboard_events["KEYUP"]["down"] = pg.event.Event( pg.KEYUP, {'scancode': 116, 'key': 274, 'mod': 4096}) self.keyboard_events["KEYUP"]["left"] = pg.event.Event( pg.KEYUP, {'scancode': 113, 'key': 276, 'mod': 4096}) self.keyboard_events["KEYUP"]["right"] = pg.event.Event( pg.KEYUP, {'scancode': 114, 'key': 275, 'mod': 4096}) self.keyboard_events["KEYUP"]["enter"] = pg.event.Event( pg.KEYUP, {'scancode': 36, 'key': 13, 'mod': 4096}) self.keyboard_events["KEYUP"]["escape"] = pg.event.Event( pg.KEYUP, {'scancode': 9, 'key': 27, 'mod': 4096}) # Set up the command line. This provides a full python shell for # troubleshooting. You can view and manipulate any variables in # the game. self.exit = False # Allow exit from the CLI if self.config.cli: self.cli = cli.CommandLine(self) # Controller overlay if self.config.controller_overlay == "1": self.controller = controller.Controller(self) self.controller.load() # Keep track of what buttons have been pressed when the overlay # controller is enabled. self.overlay_pressed = { "up": False, "down": False, "left": False, "right": False, "a": False, "b": False } # Set up rumble support for gamepads self.rumble_manager = rumble.RumbleManager() self.rumble = self.rumble_manager.rumbler def setup_states(self, state_dict, start_state): """Given a dictionary of States and a State to start in, builds the self.state_dict. :param state_dict: A dictionary of core.tools._State objects. :param start_state: A string of the starting state. E.g. "START" :type state_dict: Dictionary :type start_state: String :rtype: None :returns: None **Examples:** >>> state_dict {'COMBAT': <core.states.combat.Combat object at 0x7f681d736590>, 'START': <core.states.start.StartScreen object at 0x7f68230f5150>, 'WORLD': <core.states.world.World object at 0x7f68230f54d0>} >>> start_state "START" """ self.state_dict = state_dict self.state_name = start_state self.state = self.state_dict[self.state_name] def update(self, dt): """Checks if a state is done or has called for a game quit. State is flipped if neccessary and State.update is called. This also calls the currently active state's "update" function each frame. :param dt: Time delta - Amount of time passed since last frame. :type dt: Float :rtype: None :returns: None **Example:** >>> dt 0.031 """ self.current_time = pg.time.get_ticks() if self.state.quit: self.done = True self.exit = True elif self.state.done: self.flip_state() self.state.update(self.screen, self.keys, self.current_time, dt) if self.config.controller_overlay == "1": self.controller.draw(self) def flip_state(self): """When a State changes to "done" necessary startup and cleanup functions are called and the current State is changed. In addition, the state specified in self.state.next is loaded. :param None: :rtype: None :returns: None """ previous, self.state_name = self.state_name, self.state.next persist = self.state.cleanup() self.state = self.state_dict[self.state_name] self.state.startup(self.current_time, persist) self.state.previous = previous def event_loop(self): """Process all events and pass them down to current State. The F5 key globally turns on/off the display of FPS in the caption :param None: :rtype: None :returns: None """ # Loop through our pygame events and pass them to the current state. self.key_events = [] self.keys = list(pg.key.get_pressed()) for event in pg.event.get(): self.key_events.append(event) if event.type == pg.QUIT: self.done = True self.exit = True elif event.type == pg.KEYDOWN: self.toggle_show_fps(event.key) # Loop through our controller overlay events and pass them to the current state. if self.config.controller_overlay == "1": self.mouse_pos = pg.mouse.get_pos() contr_events = self.controller_event_loop(event) if contr_events: for contr_event in contr_events: self.key_events.append(contr_event) self.state.get_event(contr_event) # Loop through our joystick events and pass them to the current state. joy_events = self.joystick_event_loop(event) if joy_events: for joy_event in joy_events: self.key_events.append(joy_event) self.state.get_event(joy_event) self.state.get_event(event) # Loop through our network events and pass them to the current state. if self.server: net_events = self.network_event_loop() if net_events: for net_event in net_events: self.key_events.append(net_event) self.state.get_event(net_event) def network_event_loop(self): """Process all network events from the mobile controller and pass them down to current State. All network events are converted to keyboard events for compatibility. :param None: :rtype: None :returns: None """ events = [] for event_data in self.network_events: if event_data == "KEYDOWN:up": self.keys[pg.K_UP] = 1 event = self.keyboard_events["KEYDOWN"]["up"] elif event_data == "KEYUP:up": self.keys[pg.K_UP] = 0 event = self.keyboard_events["KEYUP"]["up"] elif event_data == "KEYDOWN:down": self.keys[pg.K_DOWN] = 1 event = self.keyboard_events["KEYDOWN"]["down"] elif event_data == "KEYUP:down": self.keys[pg.K_DOWN] = 0 event = self.keyboard_events["KEYUP"]["down"] elif event_data == "KEYDOWN:left": self.keys[pg.K_LEFT] = 1 event = self.keyboard_events["KEYDOWN"]["left"] elif event_data == "KEYUP:left": self.keys[pg.K_LEFT] = 0 event = self.keyboard_events["KEYUP"]["left"] elif event_data == "KEYDOWN:right": self.keys[pg.K_RIGHT] = 1 event = self.keyboard_events["KEYDOWN"]["right"] elif event_data == "KEYUP:right": self.keys[pg.K_RIGHT] = 0 event = self.keyboard_events["KEYUP"]["right"] elif event_data == "KEYDOWN:enter": self.keys[pg.K_RETURN] = 1 event = self.keyboard_events["KEYDOWN"]["enter"] elif event_data == "KEYUP:enter": self.keys[pg.K_RETURN] = 0 event = self.keyboard_events["KEYUP"]["enter"] elif event_data == "KEYDOWN:esc": self.keys[pg.K_ESCAPE] = 1 event = self.keyboard_events["KEYDOWN"]["escape"] elif event_data == "KEYUP:esc": self.keys[pg.K_ESCAPE] = 0 event = self.keyboard_events["KEYUP"]["escape"] else: print "Unknown network event." event = None if event: events.append(event) self.network_events = [] return events def controller_event_loop(self, event): """Process all events from the controller overlay and pass them down to current State. All controller overlay events are converted to keyboard events for compatibility. This is primarily used for the mobile version of Tuxemon. :param event: A Pygame event object from pg.event.get() :type event: pygame.event.Event :rtype: None :returns: None """ events = [] if (event.type == pg.MOUSEBUTTONDOWN and event.button == 1): if self.controller.dpad["rect"]["up"].collidepoint(self.mouse_pos): events.append( self.keyboard_events["KEYDOWN"]["up"]) self.keys[pg.K_UP] = 1 self.overlay_pressed["up"] = True if self.controller.dpad["rect"]["down"].collidepoint(self.mouse_pos): events.append( self.keyboard_events["KEYDOWN"]["down"]) self.keys[pg.K_DOWN] = 1 self.overlay_pressed["down"] = True if self.controller.dpad["rect"]["left"].collidepoint(self.mouse_pos): events.append( self.keyboard_events["KEYDOWN"]["left"]) self.keys[pg.K_LEFT] = 1 self.overlay_pressed["left"] = True if self.controller.dpad["rect"]["right"].collidepoint(self.mouse_pos): events.append( self.keyboard_events["KEYDOWN"]["right"]) self.keys[pg.K_RIGHT] = 1 self.overlay_pressed["right"] = True if self.controller.a_button["rect"].collidepoint(self.mouse_pos): events.append( self.keyboard_events["KEYDOWN"]["enter"]) self.keys[pg.K_RETURN] = 1 self.overlay_pressed["a"] = True if self.controller.b_button["rect"].collidepoint(self.mouse_pos): events.append( self.keyboard_events["KEYDOWN"]["escape"]) self.keys[pg.K_ESCAPE] = 1 self.overlay_pressed["b"] = True if (event.type == pg.MOUSEBUTTONUP) and (event.button == 1): if self.overlay_pressed["up"]: events.append(self.keyboard_events["KEYUP"]["up"]) self.overlay_pressed["up"] = False if self.overlay_pressed["down"]: events.append(self.keyboard_events["KEYUP"]["down"]) self.overlay_pressed["down"] = False if self.overlay_pressed["left"]: events.append(self.keyboard_events["KEYUP"]["left"]) self.overlay_pressed["left"] = False if self.overlay_pressed["right"]: events.append(self.keyboard_events["KEYUP"]["right"]) self.overlay_pressed["right"] = False if self.overlay_pressed["a"]: events.append(self.keyboard_events["KEYUP"]["enter"]) self.overlay_pressed["a"] = False self.keys[pg.K_RETURN] = 0 if self.overlay_pressed["b"]: events.append(self.keyboard_events["KEYUP"]["escape"]) self.overlay_pressed["b"] = False return events def joystick_event_loop(self, event): """Process all events from a joystick and pass them down to current State. All joystick events are converted to keyboard events for compatibility. :param event: A Pygame event object from pg.event.get() :type event: pygame.event.Event :rtype: None :returns: None """ from core import prepare # Handle joystick events if we detected one events = [] if len(prepare.JOYSTICKS) > 0: # Xbox 360 Controller buttons: # A = 0 Start = 7 D-Up = 13 # B = 1 Back = 6 D-Down = 14 # X = 2 D-Left = 11 # Y = 3 D-Right = 12 # if event.type == pg.JOYBUTTONDOWN: if event.button == 0: events.append( self.keyboard_events["KEYDOWN"]["enter"]) self.keys[pg.K_RETURN] = 1 if (event.button == 1 or event.button == 7 or event.button == 6): events.append( self.keyboard_events["KEYDOWN"]["escape"]) self.keys[pg.K_ESCAPE] = 1 if event.button == 13: events.append( self.keyboard_events["KEYDOWN"]["up"]) self.keys[pg.K_UP] = 1 if event.button == 14: events.append( self.keyboard_events["KEYDOWN"]["down"]) self.keys[pg.K_DOWN] = 1 if event.button == 11: events.append( self.keyboard_events["KEYDOWN"]["left"]) self.keys[pg.K_LEFT] = 1 if event.button == 12: events.append( self.keyboard_events["KEYDOWN"]["right"]) self.keys[pg.K_RIGHT] = 1 elif event.type == pg.JOYBUTTONUP: if event.button == 0: events.append( self.keyboard_events["KEYUP"]["enter"]) if (event.button == 1 or event.button == 7 or event.button == 6): events.append( self.keyboard_events["KEYUP"]["escape"]) if event.button == 13: events.append(self.keyboard_events["KEYUP"]["up"]) if event.button == 14: events.append( self.keyboard_events["KEYUP"]["down"]) if event.button == 11: events.append( self.keyboard_events["KEYUP"]["left"]) if event.button == 12: events.append( self.keyboard_events["KEYUP"]["right"]) # Handle left joystick movement as well. # Axis 1 - up = negative, down = positive # Axis 0 - left = negative, right = positive if event.type == pg.JOYAXISMOTION and False: # Disabled until input manager is implemented # Handle the left/right axis if event.axis == 0: if event.value >= 0.5: events.append( self.keyboard_events["KEYDOWN"]["right"]) self.keys[pg.K_RIGHT] = 1 elif event.value <= -0.5: events.append( self.keyboard_events["KEYDOWN"]["left"]) self.keys[pg.K_LEFT] = 1 else: events.append( self.keyboard_events["KEYUP"]["left"]) events.append( self.keyboard_events["KEYUP"]["right"]) # Handle the up/down axis if event.axis == 1: if event.value >= 0.5: events.append( self.keyboard_events["KEYDOWN"]["down"]) self.keys[pg.K_DOWN] = 1 elif event.value <= -0.5: events.append( self.keyboard_events["KEYDOWN"]["up"]) self.keys[pg.K_LEFT] = 1 else: events.append( self.keyboard_events["KEYUP"]["up"]) events.append( self.keyboard_events["KEYUP"]["down"]) return events def toggle_show_fps(self, key): """Press f5 to turn on/off displaying the framerate in the caption. :param key: A pygame key event from pygame.event.get() :type key: PyGame Event :rtype: None :returns: None """ if key == pg.K_F5: self.show_fps = not self.show_fps if not self.show_fps: pg.display.set_caption(self.caption) def main(self): """Initiates the main game loop. Since we are using Asteria networking to handle network events, we pass this core.tools.Control instance to networking which in turn executes the "main_loop" method every frame. This leaves the networking component responsible for the main loop. :param None: :rtype: None :returns: None """ # This sets up Asteria networking to handle executing the game loop #listen(Controller(self), self, port=8000, game_loop=True) while not self.exit: self.main_loop() def main_loop(self): """Main loop for entire game. This method gets execute every frame by Asteria Networking's "listen()" function. Every frame we get the amount of time that has passed each frame, check game conditions, and draw the game to the screen. :param None: :rtype: None :returns: None """ # Android-specific check for pause if android: if android.check_pause(): android.wait_for_resume() # Get the amount of time that has passed since the last frame. time_delta = self.clock.tick(self.fps)/1000.0 self.time_passed_seconds = time_delta self.event_loop() # Run our event engine which will check to see if game conditions # are met and run an action associated with that condition. self.event_data = {} self.event_engine.check_conditions(self, time_delta) logger.debug("Event Data:" + str(self.event_data)) # Draw and update our display self.update(time_delta) pg.display.update() if self.show_fps: fps = self.clock.get_fps() with_fps = "{} - {:.2f} FPS".format(self.caption, fps) pg.display.set_caption(with_fps) if self.exit: self.done = True
#!/usr/bin/python import logging import sys import time from neteria.server import NeteriaServer from neteria.tools import _Middleware # Create a middleware object that will echo events. "event_execute" is # executed for every legal event message. class EchoMiddleware(_Middleware): def event_legal(self, cuuid, euuid, event_data): return True def event_execute(self, cuuid, euuid, event_data): print event_data # Create a client instance. server = NeteriaServer(EchoMiddleware()) server.listen() print "Server started. Press CTRL+C to quit." while True: time.sleep(1)
class Control(object): """Control class for entire project. Contains the game loop, and contains the event_loop which passes events to States as needed. Logic for flipping states is also found here. :param caption: The window caption to use for the game itself. :type caption: String :rtype: None :returns: None """ def __init__(self, caption): self.screen = pg.display.get_surface() self.caption = caption self.done = False self.clock = pg.time.Clock() self.fps = 60.0 self.show_fps = True self.current_time = 0.0 self.keys = pg.key.get_pressed() self.key_events = [] self.state_dict = {} self.state_name = None self.state = None if NeteriaServer and Controller: self.network_events = [] self.server = NeteriaServer(Controller(self)) self.server.listen() else: self.server = None # Set up our game's configuration from the prepare module. from core import prepare self.imports = { "prepare": prepare, "ai": ai, "rumble": rumble, "db": db, "monster": monster, "player": player, "item": item, "map": maps, "pyganim": pyganim } self.config = prepare.CONFIG # Set up our game's event engine which executes actions based on # conditions defined in map files. self.event_engine = event.EventEngine() self.event_conditions = {} self.event_actions = {} self.event_persist = {} # Set up a variable that will keep track of currently playing music. self.current_music = {"status": "stopped", "song": None} # Keep track of animations that we will play. self.animations = {} # Create these Pygame event objects to simulate KEYDOWN and KEYUP # events for all the directional keys self.keyboard_events = {} self.keyboard_events["KEYDOWN"] = {} self.keyboard_events["KEYDOWN"]["up"] = pg.event.Event( pg.KEYDOWN, { 'scancode': 111, 'key': 273, 'unicode': u'', 'mod': 4096 }) self.keyboard_events["KEYDOWN"]["down"] = pg.event.Event( pg.KEYDOWN, { 'scancode': 116, 'key': 274, 'unicode': u'', 'mod': 4096 }) self.keyboard_events["KEYDOWN"]["left"] = pg.event.Event( pg.KEYDOWN, { 'scancode': 113, 'key': 276, 'unicode': u'', 'mod': 4096 }) self.keyboard_events["KEYDOWN"]["right"] = pg.event.Event( pg.KEYDOWN, { 'scancode': 114, 'key': 275, 'unicode': u'', 'mod': 4096 }) self.keyboard_events["KEYDOWN"]["enter"] = pg.event.Event( pg.KEYDOWN, { 'scancode': 36, 'key': 13, 'unicode': u'\r', 'mod': 4096 }) self.keyboard_events["KEYDOWN"]["escape"] = pg.event.Event( pg.KEYDOWN, { 'scancode': 9, 'key': 27, 'unicode': u'\x1b', 'mod': 4096 }) self.keyboard_events["KEYUP"] = {} self.keyboard_events["KEYUP"]["up"] = pg.event.Event( pg.KEYUP, { 'scancode': 111, 'key': 273, 'mod': 4096 }) self.keyboard_events["KEYUP"]["down"] = pg.event.Event( pg.KEYUP, { 'scancode': 116, 'key': 274, 'mod': 4096 }) self.keyboard_events["KEYUP"]["left"] = pg.event.Event( pg.KEYUP, { 'scancode': 113, 'key': 276, 'mod': 4096 }) self.keyboard_events["KEYUP"]["right"] = pg.event.Event( pg.KEYUP, { 'scancode': 114, 'key': 275, 'mod': 4096 }) self.keyboard_events["KEYUP"]["enter"] = pg.event.Event( pg.KEYUP, { 'scancode': 36, 'key': 13, 'mod': 4096 }) self.keyboard_events["KEYUP"]["escape"] = pg.event.Event( pg.KEYUP, { 'scancode': 9, 'key': 27, 'mod': 4096 }) # Set up the command line. This provides a full python shell for # troubleshooting. You can view and manipulate any variables in # the game. self.exit = False # Allow exit from the CLI if self.config.cli: self.cli = cli.CommandLine(self) # Controller overlay if self.config.controller_overlay == "1": self.controller = controller.Controller(self) self.controller.load() # Keep track of what buttons have been pressed when the overlay # controller is enabled. self.overlay_pressed = { "up": False, "down": False, "left": False, "right": False, "a": False, "b": False } # Set up rumble support for gamepads self.rumble_manager = rumble.RumbleManager() self.rumble = self.rumble_manager.rumbler def setup_states(self, state_dict, start_state): """Given a dictionary of States and a State to start in, builds the self.state_dict. :param state_dict: A dictionary of core.tools._State objects. :param start_state: A string of the starting state. E.g. "START" :type state_dict: Dictionary :type start_state: String :rtype: None :returns: None **Examples:** >>> state_dict {'COMBAT': <core.states.combat.Combat object at 0x7f681d736590>, 'START': <core.states.start.StartScreen object at 0x7f68230f5150>, 'WORLD': <core.states.world.World object at 0x7f68230f54d0>} >>> start_state "START" """ self.state_dict = state_dict self.state_name = start_state self.state = self.state_dict[self.state_name] def update(self, dt): """Checks if a state is done or has called for a game quit. State is flipped if neccessary and State.update is called. This also calls the currently active state's "update" function each frame. :param dt: Time delta - Amount of time passed since last frame. :type dt: Float :rtype: None :returns: None **Example:** >>> dt 0.031 """ self.current_time = pg.time.get_ticks() if self.state.quit: self.done = True self.exit = True elif self.state.done: self.flip_state() self.state.update(self.screen, self.keys, self.current_time, dt) if self.config.controller_overlay == "1": self.controller.draw(self) def flip_state(self): """When a State changes to "done" necessary startup and cleanup functions are called and the current State is changed. In addition, the state specified in self.state.next is loaded. :param None: :rtype: None :returns: None """ previous, self.state_name = self.state_name, self.state.next persist = self.state.cleanup() self.state = self.state_dict[self.state_name] self.state.startup(self.current_time, persist) self.state.previous = previous def event_loop(self): """Process all events and pass them down to current State. The F5 key globally turns on/off the display of FPS in the caption :param None: :rtype: None :returns: None """ # Loop through our pygame events and pass them to the current state. self.key_events = [] self.keys = list(pg.key.get_pressed()) for event in pg.event.get(): self.key_events.append(event) if event.type == pg.QUIT: self.done = True self.exit = True elif event.type == pg.KEYDOWN: self.toggle_show_fps(event.key) # Loop through our controller overlay events and pass them to the current state. if self.config.controller_overlay == "1": self.mouse_pos = pg.mouse.get_pos() contr_events = self.controller_event_loop(event) if contr_events: for contr_event in contr_events: self.key_events.append(contr_event) self.state.get_event(contr_event) # Loop through our joystick events and pass them to the current state. joy_events = self.joystick_event_loop(event) if joy_events: for joy_event in joy_events: self.key_events.append(joy_event) self.state.get_event(joy_event) self.state.get_event(event) # Loop through our network events and pass them to the current state. if self.server: net_events = self.network_event_loop() if net_events: for net_event in net_events: self.key_events.append(net_event) self.state.get_event(net_event) def network_event_loop(self): """Process all network events from the mobile controller and pass them down to current State. All network events are converted to keyboard events for compatibility. :param None: :rtype: None :returns: None """ events = [] for event_data in self.network_events: if event_data == "KEYDOWN:up": self.keys[pg.K_UP] = 1 event = self.keyboard_events["KEYDOWN"]["up"] elif event_data == "KEYUP:up": self.keys[pg.K_UP] = 0 event = self.keyboard_events["KEYUP"]["up"] elif event_data == "KEYDOWN:down": self.keys[pg.K_DOWN] = 1 event = self.keyboard_events["KEYDOWN"]["down"] elif event_data == "KEYUP:down": self.keys[pg.K_DOWN] = 0 event = self.keyboard_events["KEYUP"]["down"] elif event_data == "KEYDOWN:left": self.keys[pg.K_LEFT] = 1 event = self.keyboard_events["KEYDOWN"]["left"] elif event_data == "KEYUP:left": self.keys[pg.K_LEFT] = 0 event = self.keyboard_events["KEYUP"]["left"] elif event_data == "KEYDOWN:right": self.keys[pg.K_RIGHT] = 1 event = self.keyboard_events["KEYDOWN"]["right"] elif event_data == "KEYUP:right": self.keys[pg.K_RIGHT] = 0 event = self.keyboard_events["KEYUP"]["right"] elif event_data == "KEYDOWN:enter": self.keys[pg.K_RETURN] = 1 event = self.keyboard_events["KEYDOWN"]["enter"] elif event_data == "KEYUP:enter": self.keys[pg.K_RETURN] = 0 event = self.keyboard_events["KEYUP"]["enter"] elif event_data == "KEYDOWN:esc": self.keys[pg.K_ESCAPE] = 1 event = self.keyboard_events["KEYDOWN"]["escape"] elif event_data == "KEYUP:esc": self.keys[pg.K_ESCAPE] = 0 event = self.keyboard_events["KEYUP"]["escape"] else: print "Unknown network event." event = None if event: events.append(event) self.network_events = [] return events def controller_event_loop(self, event): """Process all events from the controller overlay and pass them down to current State. All controller overlay events are converted to keyboard events for compatibility. This is primarily used for the mobile version of Tuxemon. :param event: A Pygame event object from pg.event.get() :type event: pygame.event.Event :rtype: None :returns: None """ events = [] if (event.type == pg.MOUSEBUTTONDOWN and event.button == 1): if self.controller.dpad["rect"]["up"].collidepoint(self.mouse_pos): events.append(self.keyboard_events["KEYDOWN"]["up"]) self.keys[pg.K_UP] = 1 self.overlay_pressed["up"] = True if self.controller.dpad["rect"]["down"].collidepoint( self.mouse_pos): events.append(self.keyboard_events["KEYDOWN"]["down"]) self.keys[pg.K_DOWN] = 1 self.overlay_pressed["down"] = True if self.controller.dpad["rect"]["left"].collidepoint( self.mouse_pos): events.append(self.keyboard_events["KEYDOWN"]["left"]) self.keys[pg.K_LEFT] = 1 self.overlay_pressed["left"] = True if self.controller.dpad["rect"]["right"].collidepoint( self.mouse_pos): events.append(self.keyboard_events["KEYDOWN"]["right"]) self.keys[pg.K_RIGHT] = 1 self.overlay_pressed["right"] = True if self.controller.a_button["rect"].collidepoint(self.mouse_pos): events.append(self.keyboard_events["KEYDOWN"]["enter"]) self.keys[pg.K_RETURN] = 1 self.overlay_pressed["a"] = True if self.controller.b_button["rect"].collidepoint(self.mouse_pos): events.append(self.keyboard_events["KEYDOWN"]["escape"]) self.keys[pg.K_ESCAPE] = 1 self.overlay_pressed["b"] = True if (event.type == pg.MOUSEBUTTONUP) and (event.button == 1): if self.overlay_pressed["up"]: events.append(self.keyboard_events["KEYUP"]["up"]) self.overlay_pressed["up"] = False if self.overlay_pressed["down"]: events.append(self.keyboard_events["KEYUP"]["down"]) self.overlay_pressed["down"] = False if self.overlay_pressed["left"]: events.append(self.keyboard_events["KEYUP"]["left"]) self.overlay_pressed["left"] = False if self.overlay_pressed["right"]: events.append(self.keyboard_events["KEYUP"]["right"]) self.overlay_pressed["right"] = False if self.overlay_pressed["a"]: events.append(self.keyboard_events["KEYUP"]["enter"]) self.overlay_pressed["a"] = False self.keys[pg.K_RETURN] = 0 if self.overlay_pressed["b"]: events.append(self.keyboard_events["KEYUP"]["escape"]) self.overlay_pressed["b"] = False return events def joystick_event_loop(self, event): """Process all events from a joystick and pass them down to current State. All joystick events are converted to keyboard events for compatibility. :param event: A Pygame event object from pg.event.get() :type event: pygame.event.Event :rtype: None :returns: None """ from core import prepare # Handle joystick events if we detected one events = [] if len(prepare.JOYSTICKS) > 0: # Xbox 360 Controller buttons: # A = 0 Start = 7 D-Up = 13 # B = 1 Back = 6 D-Down = 14 # X = 2 D-Left = 11 # Y = 3 D-Right = 12 # if event.type == pg.JOYBUTTONDOWN: if event.button == 0: events.append(self.keyboard_events["KEYDOWN"]["enter"]) self.keys[pg.K_RETURN] = 1 if (event.button == 1 or event.button == 7 or event.button == 6): events.append(self.keyboard_events["KEYDOWN"]["escape"]) self.keys[pg.K_ESCAPE] = 1 if event.button == 13: events.append(self.keyboard_events["KEYDOWN"]["up"]) self.keys[pg.K_UP] = 1 if event.button == 14: events.append(self.keyboard_events["KEYDOWN"]["down"]) self.keys[pg.K_DOWN] = 1 if event.button == 11: events.append(self.keyboard_events["KEYDOWN"]["left"]) self.keys[pg.K_LEFT] = 1 if event.button == 12: events.append(self.keyboard_events["KEYDOWN"]["right"]) self.keys[pg.K_RIGHT] = 1 elif event.type == pg.JOYBUTTONUP: if event.button == 0: events.append(self.keyboard_events["KEYUP"]["enter"]) if (event.button == 1 or event.button == 7 or event.button == 6): events.append(self.keyboard_events["KEYUP"]["escape"]) if event.button == 13: events.append(self.keyboard_events["KEYUP"]["up"]) if event.button == 14: events.append(self.keyboard_events["KEYUP"]["down"]) if event.button == 11: events.append(self.keyboard_events["KEYUP"]["left"]) if event.button == 12: events.append(self.keyboard_events["KEYUP"]["right"]) # Handle left joystick movement as well. # Axis 1 - up = negative, down = positive # Axis 0 - left = negative, right = positive if event.type == pg.JOYAXISMOTION and False: # Disabled until input manager is implemented # Handle the left/right axis if event.axis == 0: if event.value >= 0.5: events.append(self.keyboard_events["KEYDOWN"]["right"]) self.keys[pg.K_RIGHT] = 1 elif event.value <= -0.5: events.append(self.keyboard_events["KEYDOWN"]["left"]) self.keys[pg.K_LEFT] = 1 else: events.append(self.keyboard_events["KEYUP"]["left"]) events.append(self.keyboard_events["KEYUP"]["right"]) # Handle the up/down axis if event.axis == 1: if event.value >= 0.5: events.append(self.keyboard_events["KEYDOWN"]["down"]) self.keys[pg.K_DOWN] = 1 elif event.value <= -0.5: events.append(self.keyboard_events["KEYDOWN"]["up"]) self.keys[pg.K_LEFT] = 1 else: events.append(self.keyboard_events["KEYUP"]["up"]) events.append(self.keyboard_events["KEYUP"]["down"]) return events def toggle_show_fps(self, key): """Press f5 to turn on/off displaying the framerate in the caption. :param key: A pygame key event from pygame.event.get() :type key: PyGame Event :rtype: None :returns: None """ if key == pg.K_F5: self.show_fps = not self.show_fps if not self.show_fps: pg.display.set_caption(self.caption) def main(self): """Initiates the main game loop. Since we are using Asteria networking to handle network events, we pass this core.tools.Control instance to networking which in turn executes the "main_loop" method every frame. This leaves the networking component responsible for the main loop. :param None: :rtype: None :returns: None """ # This sets up Asteria networking to handle executing the game loop #listen(Controller(self), self, port=8000, game_loop=True) while not self.exit: self.main_loop() def main_loop(self): """Main loop for entire game. This method gets execute every frame by Asteria Networking's "listen()" function. Every frame we get the amount of time that has passed each frame, check game conditions, and draw the game to the screen. :param None: :rtype: None :returns: None """ # Android-specific check for pause if android: if android.check_pause(): android.wait_for_resume() # Get the amount of time that has passed since the last frame. time_delta = self.clock.tick(self.fps) / 1000.0 self.time_passed_seconds = time_delta self.event_loop() # Run our event engine which will check to see if game conditions # are met and run an action associated with that condition. self.event_data = {} self.event_engine.check_conditions(self, time_delta) logger.debug("Event Data:" + str(self.event_data)) # Draw and update our display self.update(time_delta) pg.display.update() if self.show_fps: fps = self.clock.get_fps() with_fps = "{} - {:.2f} FPS".format(self.caption, fps) pg.display.set_caption(with_fps) if self.exit: self.done = True
def run(self): server = NeteriaServer(EchoMiddleware()) server.listen() while(True): time.sleep(1)