class GameEngine(Client): """ The main game client: The game engine sends GLUT events to a gamestate class that manages what is happening on the screen. It also handles server communication. """ def __init__(self): """ Initializes the game client """ # since our game client is a client... Client.__init__(self) self.setsMgr = SettingsManager() self.res = self.setsMgr.screenRes self._InitGLUT_() self._InitGL_() # Make a screen object - we want to make the first here # so that we can ensure the size is set appropriately. # All other objects using the screen-singleton will assume # it is has already been sized and, thus, won't call setSize. self.screen = Screen() self.screen.setSize( self.res ) # be the first entity to create the managers self.rsrcMgr = TextureManager() self.fontMgr = FontManager() self.connected = False self.serverOwner = False self.serverName = "default" # the gameworld is mostly undefined at this point self.gameWorld = GameWorld() # this variable denotes for certain game states whether # the user 'start'-ed or 'join'-ed a server so they know # which state to return to when the user pushes 'back' self.statePath = None # create the initial game state self.gState = TitleScreenState(self) #self.gState = EngineState(self) def _InitGLUT_(self): """Initialize GLUT""" glutInit() #*# Create/Initialize the Window glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA) glutInitWindowPosition( 0,0 ) glutInitWindowSize( self.res[0], self.res[1] ) self.window = glutCreateWindow( "Breakin & Poppin" ) #*# setup the event handlers glutDisplayFunc(self.renderFrame) glutIdleFunc(self.on_tick) #glutReshapeFunc(self.changeSize) # keyboard glutKeyboardFunc( self.on_key_press ) glutKeyboardUpFunc( self.on_key_release ) glutIgnoreKeyRepeat( 1 ) # !=0 disables key repeat callbacks glutSpecialFunc( self.on_specialkey_press ) glutSpecialUpFunc( self.on_specialkey_release ) glutMouseFunc( self.on_mouse ) glutPassiveMotionFunc( self.on_mouse_motion ) #glutFullScreen() def _InitGL_(self): """Initialize GL""" # Set up the rendering environment # setup the orthographic projection (firstly) glMatrixMode( GL_MODELVIEW ) glPushMatrix() glLoadIdentity() # Set up the orthographic projection glOrtho(0, self.res[0], 0, self.res[1], -1, 1) # invert the y axis, down is positive glScalef(1, -1, 1) # mover the origin from the bottom left corner # to the upper left corner glTranslatef(0, -self.res[1], 0) # turn off the lighting and depth testing glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_LIGHTING_BIT ) glDisable( GL_LIGHTING ) glDisable( GL_DEPTH_TEST ) glDisable( GL_DITHER ) def on_key_press(self, key, x, y): """On key press""" if self.gState: self.gState = self.gState.on_key_press(key, x, y) def on_key_release(self, key, x, y): """On key release""" if self.gState: self.gState = self.gState.on_key_release(key, x, y) def on_specialkey_press(self, key, x, y): """On special key press""" # game state if self.gState: self.gState = self.gState.on_key_press(key, x, y) def on_specialkey_release(self, key, x, y): """On special key release""" # game state if self.gState: self.gState = self.gState.on_key_release(key, x, y) def on_mouse_motion(self, x, y): """On mouse motion""" # game state if self.gState: self.gState = self.gState.on_mouse_motion(x, y) def on_mouse(self, button, state, x, y): """On mouse press/release""" # game state if self.gState: self.gState = self.gState.on_mouse(button, state, x, y) def on_update(self, elapsed): """ The function that updates every object's animation status (45ms) """ # update the game state if self.gState: self.gState = self.gState.update(elapsed) # gameworld self.gameWorld.update(elapsed) # gamestate glutTimerFunc(50, self.on_update, 50) def on_socket( self, elapsed): """ """ # call the base class version (returns the packet) packet = Client.on_socket(self, elapsed) if packet != None: #print 'client - recv - got a packet' self.readPacket( packet ) # the real meat of this else: # Oh well, no packet for some reason pass glutTimerFunc(20, self.on_socket, 20) ### def readPacket(self, packet): """ This interpets a packet sent by the server """ # This case is usually handled by the GameEngine side # (But this class isn't supposed to know that. :P) if packet['type'] == 'update': #print 'Client : Got an update : ', packet if self.connected: if self.gState: # let the game state handle some bih'ness self.gState= self.gState.on_socket(packet) if self.gameWorld: self.gameWorld.on_socket(packet) # if the level is different or non-existant, load it #if not self.gameWorld.getLevel() \ # or (packet['level'] != self.gameWorld.getLevelName()): # self.gameWorld.setLevelByName( packet['level'] ) if packet['type'] == 'message': #print 'Client : Got a message : ', packet # Connection Reset by Peer if 'CRbP' in packet: print 'Disconnected: The server connection is dead.' self.disconnect() # The server is full if 'ServerFull' in packet: print 'Disconnected: The server is full.' # this is just like getting CRbP for now # but the response to the user should # be different at some point. self.disconnect() if 'CurrentLevel' in packet: #self.engine.gameWorld.setLevel( packet['CurrentLevel'] ) print 'Current level is ', packet['CurrentLevel'] self.gameWorld.setLevelByName(packet['CurrentLevel']) if 'NextLevel' in packet: print 'Next Level is ', packet['NextLevel'] if 'GameStatus' in packet: self.gameWorld.stopGame() if packet['GameStatus'] == 'winner': self.gState = LoserState(self) elif packet['GameStatus'] == 'loser': self.gState = WinnerState(self) def on_tick(self): """Timer event: on tick""" # kill the app if there is no state if not self.gState: self.on_close() # render the scene glutPostRedisplay() def on_close(self): """On close""" # leave the server self.disconnect() glutDestroyWindow(self.window) sys.exit() def renderFrame(self): """The glut display function""" # clear the buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Draw the game world if self.gameWorld: self.screen.drawThis( self.gameWorld ) # Render if we have a state if self.gState: # the state passes any objects the screen to be rendered self.gState.renderFrame() # The screen draws all objects it has been passed self.screen.draw() # Dump the contents to the screen glutSwapBuffers()
class EngineState(): def __init__(self, engine): """ The game determines what is happening on screen based on what state the GameEngine instance has. """ # the game engine that owns this state self.engine = engine # TRYING TO DEPRECATE self.screen = Screen() self.res = self.engine.setsMgr.screenRes res = self.res # get/load the font self.font = FontManager().loadFont( 'JohnDoe' ) self.str_paused = UIText( "Paused", [res[0]*0.5, res[1]*0.5] , self.font, 35 ) self.str_paused.setVisible(False) gameWorld = self.engine.gameWorld #gameWorld.setPlayerType( 'Cop' ) gameWorld.setPlayerType( 'Robber' ) #gameWorld.getPlayer().setName( "Alfonso" ) # This is an optimization... # If using the Cop player type, use the smaller tiles if gameWorld.getPlayer().getType() == "Cop": gameWorld.setLevelByName( 'Level1XS' ) else: gameWorld.setLevelByName( 'Level1L' ) glutTimerFunc(50, self.engine.on_update, 50) def renderFrame(self): """ RenderFrame - Base Class """ if not self.screen: self.screen = Screen() self.screen.drawThis( self.str_paused ) return self def on_key_press(self, key, x, y): """ On key press """ if key == '\x1b': return None # for now, this means to "spawn a server" if key == 'x': if system() == "Linux" or system() == "Macintosh": Popen( [r'/usr/bin/python/python' ,os.path.join( self.engine.setsMgr.home_dir , 'StartServer.py' )] ) elif system() == "Windows": Popen([r'C:\Python25\python.exe' ,os.path.join( self.engine.setsMgr.home_dir , 'StartServer.py' )]) else: print "you are on an unsupported platform for spawning a server" # declare that this game instance is the server owner self.engine.serverOwner = True # for now, its "connect" elif key == 'c': self.engine.connect() elif key == 'v': self.engine.disconnect() elif key == 'g': self.str_paused.toggleVisible() self.engine.gameWorld.pause() return self def on_key_release(self, key, x, y): """ On key release """ return self def on_specialkey_press(self, key, x, y): """ On special key press """ return self def on_specialkey_release(self, key, x, y): """ On special key release """ return self def on_mouse_motion(self, x, y): """ On mouse motion """ self.engine.gameWorld.startGame() return self def on_mouse(self, button, state, x, y): """ On mouse """ return self def on_socket(self, packet): """ On socket """ self.gameTime = packet['time'] return self def update(self, elapsed): """ switches the state based on """ return self
class GameState(EngineState): def __init__(self, engine): """ The game determines what is happening on screen based on what state the GameEngine instance has. """ self.engine = engine self.res = self.engine.setsMgr.screenRes self.screen = None # get/load the font self.font = FontManager().loadFont( 'Basic' ) self.str_paused = UIText( "Paused", [self.res[0]*0.5, self.res[1]*0.5], self.font, 0.05 ) self.str_paused.setVisible(False) engine.gameWorld.setLevelByName( 'Level1L' ) engine.gameWorld.gameTime = 0.0 engine.gameWorld.startGame() #glutTimerFunc(300, self.print_game_world, 300) def print_game_world(self, elapsed): gW = self.engine.gameWorld tileSize = gW.level.getTileSize() peerPos = gW.peers.values()[0].pos print '' print '--- Gameworld ---' print 'Player = {', gW.player.playerName, ":", gW.player.pos, "}" print 'mapPixelPos = ', gW.player.pos[0] + gW.scrScroll[0]\ , gW.player.pos[1] + gW.scrScroll[1] print 'mapTilePos = ', gW.player.pos[0] / tileSize[0],\ gW.player.pos[1] / tileSize[1] print 'renderPos = ', gW.player.pos[0] - gW.scrScroll[0]\ , gW.player.pos[1] - gW.scrScroll[1] print ' ------ ------ ' print 'Peers = {', gW.peers.values()[0].playerName, ":", peerPos, "}" print 'mapTilePos = ', peerPos[0] / tileSize[0],\ peerPos[1] / tileSize[1] print 'renderPos = ', peerPos[0] - gW.scrScroll[0]\ , peerPos[1] - gW.scrScroll[1] print ' ------ ------ ' print 'TileSize = ', tileSize print '' glutTimerFunc(300, self.print_game_world, 300) def renderFrame(self): """ RenderFrame - Base Class """ if not self.screen: self.screen = Screen() scrSize = self.screen.getSize() #self.engine.gameWorld.positionPlayer( [scrSize[0],scrSize[1]] ) self.screen.drawThis( self.str_paused ) return self def on_key_press(self, key, x, y): """ On key press """ if key == chr(27): # Escape return ChoosePlayerState(self.engine) elif key == 'g': self.str_paused.toggleVisible() self.engine.gameWorld.pause() # controller self.engine.gameWorld.on_key_press(key, x, y) return self def on_key_release(self, key, x, y): """On key release""" # controller self.engine.gameWorld.on_key_release(key, x, y) return self def on_specialkey_press(self, key, x, y): """On special key press""" # controller self.engine.gameWorld.on_specialkey_press(key, x, y) return self def on_specialkey_release(self, key, x, y): """On special key release""" # controller self.engine.gameWorld.on_specialkey_release(key, x, y) return self def on_mouse_motion(self, x, y): """On mouse motion""" # controller self.engine.gameWorld.on_mouse_motion(x, y) return self def on_mouse(self, button, state, x, y): """On mouse press/release""" # controller self.engine.gameWorld.on_mouse(button, state, x, y) return self def update(self, elapsed): """ switches the state based on """ if self.engine.gameWorld.gameStatus == "winner": # Send a signal to the server that this player # seems to have won the game ( the server will # have to agree with our word ) # Go to the appropriate engine-state screen #self.engine.gameWorld = GameWorld() print 'switching to winner state' return WinnerState(self.engine) elif self.engine.gameWorld.gameStatus == "loser": # Go to the appropriate engine-state screen #self.engine.gameWorld = GameWorld() return LoserState(self.engine) else: return self
class WinnerState(EngineState): def __init__(self, engine): """ """ self.engine = engine self.res = self.engine.setsMgr.screenRes res = self.res self.screen = None # announce that the game is over #engine.announceGameOver( 'winner' ) self.engine.gameWorld.status = 'winner' self.engine.gameWorld.stopGame() self.font = FontManager().loadFont( 'Basic' ) self.UI = {} self.UI['nice_work'] = UIText("Nice Work!" , pos=[res[0]*0.5, res[1]*0.3], font=self.font, scale=0.047) self.UI['nice_work'].center() self.UI['cop_wins'] = UIText("You Caught The Robber!" , pos=[res[0]*0.5, res[1]*0.5], font=self.font, scale=0.04) self.UI['cop_wins'].center() self.UI['robber_wins'] = UIText("You made it home safe!" , pos=[res[0]*0.5, res[1]*0.5], font=self.font, scale=0.04) self.UI['robber_wins'].center() self.UI['press_esc'] = UIText("Press escape to continue" , pos=[res[0]*0.5, res[1]*0.75], font=self.font, scale=0.04) self.UI['press_esc'].center() self.titleBGImg = UIImage("black_bg.png"\ , pos=[0,0], size=res) def renderFrame(self): """ RenderFrame - Base Class """ if not self.screen: self.screen = Screen() self.screen.drawThis( self.titleBGImg ) self.screen.drawThis( self.UI['nice_work'] ) if self.engine.gameWorld.getPlayerType() == "Robber": self.screen.drawThis( self.UI['robber_wins'] ) elif self.engine.gameWorld.getPlayerType() == "Cop": self.screen.drawThis( self.UI['cop_wins'] ) self.screen.drawThis( self.UI['press_esc'] ) return self def on_key_press(self, key, x, y): """ On key press """ if key == chr(27): # Escape self.engine.disconnect() return TitleScreenState(self.engine) else: return self def on_mouse(self, button, state, x, y): """ On mouse press """ self.engine.disconnect() return TitleScreenState(self.engine)
class TitleScreenState(EngineState): def __init__(self, engine): """ The game determines what is happening on screen based on what state the GameEngine instance has. """ self.engine = engine self.screen = Screen() self.res = self.engine.setsMgr.screenRes res = self.res # saying 'self.res' was making lines too long. :P # get/load the font self.font = FontManager().loadFont( 'Basic' ) # screen objects self.UI = {} self.UI['title'] = UIText("Breakin And Poppin"\ , pos=[res[0]*.01,res[1]*.10], font=self.font, scale=0.05) self.UI['start_server'] = UIText("Start a Server"\ , pos=[res[0]*0.5, res[1]*0.42], font=self.font, scale=0.04) self.UI['start_server'].center() self.UI['join_server'] = UIText("Join a Server"\ , pos=[res[0]*0.5, res[1]*0.5], font=self.font, scale=0.04) self.UI['join_server'].center() self.UI['quit'] = UIText("Quit"\ , pos=[res[0]*0.5, res[1]*0.58], font=self.font, scale=0.04) self.UI['quit'].center() self.titleBGImg = UIImage("TitleScreenBG.png"\ , pos=[0,0], size=res) self.selected = 'start_server' def renderFrame(self): if not self.screen: self.screen = Screen() self.screen.drawThis( self.titleBGImg ) selectionBox = UIImage("box.png", pos=self.UI[self.selected].pos, size=[(self.res[0]*0.05)*10, self.res[1]*0.05]) selectionBox.center() self.screen.drawThis( selectionBox ) for uiObj in self.UI.values(): # draw the background image firstly self.screen.drawThis( uiObj ) return self def on_key_press(self, key, x, y): """ On key press """ if key == '\x1b': return None elif key == chr(13): if self.selected == "start_server": self.statePath = 'start' return CreateServerState(self.engine) elif self.selected == "join_server": self.statePath = 'join' return JoinServerState(self.engine) elif self.selected == "quit": return None elif key == 101: if self.selected == "start_server": self.selected = "quit" elif self.selected == "join_server": self.selected = "start_server" elif self.selected == "quit": self.selected = "join_server" elif key == 103: if self.selected == "start_server": self.selected = "join_server" elif self.selected == "join_server": self.selected = "quit" elif self.selected == "quit": self.selected = "start_server" return self def on_mouse_motion(self, x, y): """ On mouse motion """ # check the mouse pos against all the choices if self.UI['start_server'].CollidePoint( (x,y) ): self.selected = "start_server" elif self.UI['join_server'].CollidePoint( (x,y) ): self.selected = "join_server" elif self.UI['quit'].CollidePoint( (x,y) ): self.selected = "quit" return self def on_mouse(self, button, state, x, y): """ On mouse release """ if button == GLUT_LEFT_BUTTON and state == GLUT_DOWN: # check the mouse pos against all the choices if self.UI['start_server'].CollidePoint( (x,y) ): self.engine.statePath = 'start' return CreateServerState(self.engine) if self.UI['join_server'].CollidePoint( (x,y) ): self.engine.statePath = 'join' return JoinServerState(self.engine) if self.UI['quit'].CollidePoint( (x,y) ): return None return self