__license__ = "Public Domain" SCREEN_SIZE = (800,600) ## Initialize Pygame library and create the screen. import pygame pygame.init() screen = pygame.display.set_mode((SCREEN_SIZE)) from pygame.locals import * ## Convenient constants. ## Create a timer for framerate regulation. clock = pygame.time.Clock() import random ## For demo import time ## For FPS counter. class World: """A demo of a game world with constant "facts". These facts can be changed by the game's *Logic functions.""" def __init__(self,**options): self.world_time = 0 self.alignment = "Good" self.squirrels = True class Game: """The main class of the game. Attempts to follow the MVC Architecture: -Model: class World -View: *Draw functions -Controller (and game logic): *Logic functions """ def __init__(self,**options): self.logic_function = None self.draw_function = None self.states = [] self.framerate = 20 self.world = World() """ State Control """ def GetStateFunctions(self,state_name): try: name = state_name + "Logic" logic_function = getattr(self,name) name = state_name + "Draw" draw_function = getattr(self,name) except: raise "Error: Couldn't find matching logic/draw functions for state \""+state_name+"\"." return logic_function, draw_function def PushState(self,state_name): """Start a new game state, but revert when done.""" logic_function, draw_function = self.GetStateFunctions(state_name) self.logic_function = logic_function self.draw_function = draw_function self.states.append(state_name) def PopState(self): """End the current game state.""" try: self.states.pop() if self.states: self.logic_function, self.draw_function = self.GetStateFunctions(self.states[-1]) else: self.logic_function, self.draw_function = None, None except: raise "Error: There are no game states to pop!" def JumpState(self,state_name): """Pop and push to end this state and switch to another.""" self.PopState() self.PushState(state_name) """ Main Loop """ def MainLoop(self): """Do basic event-handling until the program ends. The game logic and drawing are handled by a pair of functions that can be replaced on the fly to represent switching to different aspects of gameplay, such as a title screen, battle screen etc..""" cycles = 0 starting_time = time.time() while self.states: ## Until there's nothing to do: self.draw_function() unhandled_events = self.logic_function() if unhandled_events: for event in unhandled_events: if event.type == QUIT: return elif event.type == KEYDOWN and event.key == K_ESC: return pygame.display.update() clock.tick(self.framerate) cycles += 1 ## At program's end, display the overall framerate. if cycles: ending_time = time.time() fps = cycles/float(ending_time - starting_time) print "FPS: "+str(fps) """ Game States """ def NevadaLogic(self): """Nonsense demo. Advance the world's time.""" ## Specialized game logic. Increment the game world's timer. self.world.world_time += 1 ## Specialized input handling. for event in pygame.event.get(): if event.type == KEYDOWN: self.PopState() print "World timer: "+str(self.world.world_time) return def NevadaDraw(self): """Nonsense demo. Draw stuff.""" color = random.randint(80,180) x = random.randint(0,700) y = random.randint(0,500) screen.fill((0,0,0)) pygame.draw.rect(screen,(color),(x,y,100,100)) g = Game() ## Create the demo Game object. g.MainLoop() ## Run. Nothing will happen; no states to run. g.PushState("Nevada") ## Give it something to do. g.MainLoop() ## Now go, displaying flashing blue squares till a key is pressed.