class ParkPanel: def __init__(self,bgImage, pos): self.isDone = 0 self.boundRect = bgImage.get_rect() self.deviceGroup = RenderUpdates() self.rideGroup = RenderUpdates() self.carGroup = RenderUpdates() self.lineupGroup = RenderUpdates() self.highlightGroup = RenderUpdates() self.redVisitorGroup = RenderUpdates() self.greenVisitorGroup = RenderUpdates() self.parkGeography = parkGenerationFunction() allobjects.timeOfDay = simulation.startTime self.bgImage = bgImage for r in self.parkGeography.rides: self.rideGroup.add( r ) self.carGroup.add( r.idleCars ) for l in self.parkGeography.lineups: self.lineupGroup.add( l ) totalVisitors = simulation.InitialNumVisitors(0) numGreen = int(totalVisitors*simulation.deviceAcceptanceRate) numRed = totalVisitors - numGreen for i in xrange( numGreen ): device = allobjects.server.NewDevice() if device: self.deviceGroup.add( device ) newGuy = GuidedVisitor( device ) else: newGuy = UnGuidedVisitor() self.AddVisitor( newGuy ) for i in xrange( numRed ): newGuy = UnGuidedVisitor() self.AddVisitor( newGuy ) events.AddListener( self ) events.AddEvent( "SelectVisitor" ) events.AddEvent( "UnSelectVisitor" ) events.AddEvent( "HighlightRide" ) events.AddEvent( "UnHighlightRide" ) events.AddEvent( "HighlightLineup" ) events.AddEvent( "UnHighlightLineup" ) self.paused = False self.showRed = True self.justToggledShowRed = False self.showServer = True self.justToggledShowServer = False self.showGreen = True self.justToggledShowGreen = False self.redCircle = Surface( (17,17),SRCALPHA,32 ) pygame.draw.circle( self.redCircle, (255,0,0), (8,8), 8, 1 ) self.greenCircle = Surface( (17,17),SRCALPHA,32 ) pygame.draw.circle( self.greenCircle, (0,255,0), (8,8), 8, 1 ) self.highlight = Sprite() self.highlight.image = self.greenCircle self.highlight.rect = self.greenCircle.get_rect() self.selection = Sprite() self.selection.image = self.greenCircle self.selection.rect = self.greenCircle.get_rect() self.highlightVisitor = None self.selectedVisitor = None #--------------------------------------------------------------------- def On_Pause(self): log.info( 'parkpanel pause' ) self.paused = not self.paused #--------------------------------------------------------------------- def On_ShowRed(self): self.showRed = not self.showRed self.justToggledShowRed = True #--------------------------------------------------------------------- def On_ShowGreen(self): self.showGreen = not self.showGreen self.justToggledShowGreen = True #--------------------------------------------------------------------- def On_ShowServer(self): self.showServer = not self.showServer self.justToggledShowServer = True #--------------------------------------------------------------------- def On_MouseClick(self,pos): if not self.boundRect.collidepoint( pos ): return if self.selectedVisitor: events.Fire( "UnSelectVisitor", self.selectedVisitor ) self.selectedVisitor = None self.highlightGroup.remove( self.selection ) self.selectedVisitor = self.FindVisitorNear(pos) if not self.selectedVisitor: return self.highlightGroup.add( self.selection ) if hasattr( self.selectedVisitor, 'device' ): self.selection.image = self.greenCircle else: self.selection.image = self.redCircle events.Fire( "SelectVisitor", self.selectedVisitor ) #--------------------------------------------------------------------- def UpdateHighlightGroup(self): if self.selectedVisitor: self.selection.rect.center = self.selectedVisitor.rect.center self.highlightGroup.update() #--------------------------------------------------------------------- def On_MouseMove(self,event): pos = event.pos if not self.boundRect.collidepoint( pos ): return self.highlightVisitor = self.FindVisitorNear(pos) self.HighlightRideNear(pos) self.HighlightLineupNear(pos) if not self.highlightVisitor: self.highlightGroup.remove( self.highlight ) return if hasattr( self.highlightVisitor, 'device' ): self.highlight.image = self.greenCircle else: self.highlight.image = self.redCircle self.highlight.rect.center = self.highlightVisitor.rect.center self.highlightGroup.add( self.highlight ) #--------------------------------------------------------------------- def AddVisitor(self, visitor, pos=None): if hasattr( visitor, "device" ): self.greenVisitorGroup.add( visitor ) else: self.redVisitorGroup.add( visitor ) self.parkGeography.PlaceVisitor( visitor, pos ) allobjects.allVisitors.add( visitor ) #--------------------------------------------------------------------- def DoVisitorEntries( self ): if len( allobjects.allVisitors ) >= simulation.capacity: return totalVisitors = simulation.getEntryRate( allobjects.timeOfDay ) #print "entering ", totalVisitors numGreen = int(totalVisitors*simulation.deviceAcceptanceRate) if not allobjects.thousandCounter%2: numGreen += 1 numRed = totalVisitors - numGreen pos = self.parkGeography.GetEntryPoint() for i in xrange( numGreen ): device = allobjects.server.NewDevice() if device: self.deviceGroup.add( device ) newGuy = GuidedVisitor( device ) else: newGuy = UnGuidedVisitor() self.AddVisitor( newGuy, pos ) for i in xrange( numRed ): newGuy = UnGuidedVisitor() self.AddVisitor( newGuy, pos ) #--------------------------------------------------------------------- def DoVisitorExits( self ): if not allobjects.allVisitors: return totalVisitors = simulation.getExitRate( allobjects.timeOfDay ) for i in xrange( totalVisitors ): allobjects.allVisitors.sprites()[i].LeaveThePark() #--------------------------------------------------------------------- def RemoveVisitor(self, visitor): visitor.kill() #--------------------------------------------------------------------- def FindVisitorNear(self,pos,radius=4): for v in self.greenVisitorGroup.sprites(): if abs( v.rect.centerx - pos[0] ) < radius \ and abs( v.rect.centery - pos[1] ) < radius: return v for v in self.redVisitorGroup.sprites(): if abs( v.rect.centerx - pos[0] ) < radius \ and abs( v.rect.centery - pos[1] ) < radius: return v return None #--------------------------------------------------------------------- def HighlightRideNear(self,pos): events.Fire( "UnHighlightRide" ) for r in self.rideGroup.sprites(): if r.rect.collidepoint( pos ): events.Fire( "HighlightRide", r ) return #--------------------------------------------------------------------- def HighlightLineupNear(self,pos): events.Fire( "UnHighlightLineup" ) for l in self.lineupGroup.sprites(): if l.rect.collidepoint( pos ): events.Fire( "HighlightLineup", l ) return #--------------------------------------------------------------------- def SignalKey( self, event, remainingEvents ): pass #--------------------------------------------------------------------- def Click( self, pos ): pass #--------------------------------------------------------------------- def MouseOver( self, event ): pass #--------------------------------------------------------------------- def DoGraphics( self, screen, display, timeChange ): if self.justToggledShowRed \ or self.justToggledShowGreen \ or self.justToggledShowServer: screen.blit( self.bgImage, self.boundRect ) display.flip() self.justToggledShowRed = False self.justToggledShowGreen = False self.justToggledShowServer = False else: bg = self.bgImage self.rideGroup.clear(screen, self.bgImage) self.lineupGroup.clear(screen, self.bgImage) self.highlightGroup.clear( screen, self.bgImage ) if self.showRed: self.redVisitorGroup.clear( screen, bg ) if self.showGreen: self.greenVisitorGroup.clear( screen, bg ) if self.showServer: self.deviceGroup.clear(screen, self.bgImage ) self.UpdateHighlightGroup() if not allobjects.thousandCounter % 30: self.DoVisitorEntries() self.DoVisitorExits() if not self.paused: allobjects.timeOfDay += simulation.speed self.carGroup.update() self.rideGroup.update() self.lineupGroup.update() self.redVisitorGroup.update() self.greenVisitorGroup.update() if self.showServer: self.deviceGroup.update() changedRects = self.highlightGroup.draw(screen) changedRects += self.rideGroup.draw(screen) changedRects += self.carGroup.draw(screen) changedRects += self.lineupGroup.draw(screen) if self.showRed: changedRects += self.redVisitorGroup.draw(screen) if self.showGreen: changedRects += self.greenVisitorGroup.draw(screen) if self.showServer: changedRects += self.deviceGroup.draw(screen) display.update( changedRects )
def main(): """this function is called when the program starts. it initializes everything it needs, then runs in a loop until the function returns.""" #Initialize Everything global screen screen = None pygame.init() screen = pygame.display.set_mode(RESOLUTION) pygame.display.set_caption('Example Poutine Window') #Create The Backgound bg = pygame.Surface(RESOLUTION) bg.fill(BGCOLOR) #Display The Background screen.blit(bg, (0, 0)) pygame.display.flip() #Prepare Game Objects clock = pygame.time.Clock() label = LabelSprite('foo') label.rect.move_ip(100, 100) #this will be the callback function of the button def buttonWasClicked(): print "button clicked" button = ButtonSprite('bar', None, buttonWasClicked) button.rect.move_ip(100, 300) tEntry = TextEntrySprite('textentry') tEntry.rect.move_ip(100, 400) allWidgets = RenderUpdates() allWidgets.add(label) allWidgets.add(button) allWidgets.add(tEntry) #Main Loop while 1: timeChange = clock.tick(40) #Handle Input Events oldEvents = [] remainingEvents = pygame.event.get() for event in remainingEvents: oldEvents.append(remainingEvents.pop(0)) if event.type == QUIT: return elif event.type == KEYDOWN and event.key == K_ESCAPE: return elif event.type == KEYDOWN: key = event.unicode.encode("ascii") if key and key in string.printable: for s in allWidgets.sprites(): if hasattr(s, "OnKeyPressed"): s.OnKeyPressed(key) else: key = event.key for s in allWidgets.sprites(): if hasattr(s, "OnMetaPressed"): s.OnMetaPressed(key) elif event.type == MOUSEMOTION: for sprite in allWidgets.sprites(): if hasattr(sprite, "OnMouseMove"): sprite.OnMouseMove(event.pos) elif event.type == MOUSEBUTTONDOWN: for sprite in allWidgets.sprites(): if hasattr(sprite, "OnMouseClick"): sprite.OnMouseClick(event.pos) #Draw Everything allWidgets.clear(screen, bg) allWidgets.update() changedRects = allWidgets.draw(screen) pygame.display.update(changedRects) #Game Over pygame.quit()
class GameWorld: """Hold Game World objects Initialize display >>> import pygame as pygame >>> import random >>> from widget import * >>> randomizer = Random() Create a gameworld >>> g = GameWorld(randomizer) >>> s = pygame.surface.Surface((30,30)) >>> w = Widget(s, (0,0,30,30), (0,0)) Add and test bomberman to world >>> g.appendBomber(w) >>> g.bomberGroup <RenderUpdates(1 sprites)> Add and test an immutable to world >>> w1 = Widget(s, (0,0,30,30), (0,0)) >>> g.appendImmutable(w1) >>> g.immutableGroup <RenderUpdates(1 sprites)> Add another bomberman to world >>> p2 = Widget(s, (100,100, 30,30), (0,0)) >>> g.appendBomber(p2) Add a bomb to the game world >>> bomb = Widget(s, (100,100,30,30), (0,0)) >>> g.appendBomb(bomb) Check the number of objects in game world >>> g.universalGroup <RenderUpdates(4 sprites)> Detonate bomb in game world >>> g.detonateBomb(bomb) >>> g.bombGroup <RenderUpdates(0 sprites)> >>> g.universalGroup <RenderUpdates(3 sprites)> Add bomb to populatedBombGroup >>> g.appendPopulatedBomb(bomb) >>> g.populatedBombGroup <RenderUpdates(1 sprites)> Add an explosion to game world >>> explosion = Widget(s, (0,0,30,30),(0,0)) >>> g.appendExplosion(explosion) >>> g.explosionGroup <RenderUpdates(1 sprites)> Add a power up to game world >>> powerup = Widget(s,(0,0,30,30),(0,0)) >>> g.appendPowerUp(powerup) >>> g.powerUpGroup <RenderUpdates(1 sprites)> Remove power up from game world >>> g.removePowerUp(powerup) >>> g.powerUpGroup <RenderUpdates(0 sprites)> Test bomberstrafe algorithm >>> g.bomberStrafe([98, 100]) (98, 100) >>> g.bomberStrafe([90, 100]) (80, 100) >>> g.bomberStrafe([98, 90]) (98, 80) >>> g.bomberStrafe([139, 140]) (144, 144) Test worldWrap >>> g.mapColumns = 19 >>> bomb = Bomb(s, (0,0,30,30),3,3,3,(0,0)) >>> bomb.beingPunched = 1 >>> g.appendBomb(bomb) >>> bomb.setPosition((10,100)) >>> g.worldWrap(bomb) >>> bomb.getPosition() (624, 100) >>> bomb.setPosition((630,100)) >>> g.worldWrap(bomb) >>> bomb.getPosition() (16, 100) >>> g.mapRows = 19 >>> bomb.setPosition((100, 10)) >>> g.worldWrap(bomb) >>> bomb.getPosition() (100, 656) >>> bomb.setPosition((100, 660)) >>> g.worldWrap(bomb) >>> bomb.getPosition() (100, 48) Test for new restart game state >>> g.cleanState() >>> g.populatedBombGroup <RenderUpdates(0 sprites)> >>> g.bombGroup <RenderUpdates(0 sprites)> >>> g.bomberGroup <RenderUpdates(0 sprites)> >>> g.explosionGroup <RenderUpdates(0 sprites)> >>> g.immutableGroup <RenderUpdates(0 sprites)> >>> g.powerUpGroup <RenderUpdates(0 sprites)> >>> g.mutableGroup <RenderUpdates(0 sprites)> >>> g.universalGroup <RenderUpdates(0 sprites)> >>> g.dirtyGroup <RenderUpdates(0 sprites)> >>> g.flyOverGroup <RenderUpdates(0 sprites)> >>> g.update() """ def __init__(self, randomizer): self.randomizer = randomizer # Set title pygame.display.set_caption("Pybomber") # Setup screen self.screen = pygame.display.get_surface() # Create sprite groups self.populatedBombGroup = SpriteGroup() self.bombGroup = SpriteGroup() self.bomberGroup = SpriteGroup() self.explosionGroup = SpriteGroup() self.immutableGroup = SpriteGroup() self.powerUpGroup = SpriteGroup() self.mutableGroup = SpriteGroup() self.universalGroup = SpriteGroup() # For drawing everything. self.dirtyGroup = SpriteGroup() self.flyOverGroup = SpriteGroup() # Load a background self.background = pygame.image.load(BACKGROUND).convert() self.map = None # Draw background on screen self.screen.blit(self.background, ((0, 0), RESOLUTION)) # Number of rows and colums in the current map. self.mapRows = 0 self.mapColumns = 0 def cleanState(self): pygame.display.set_caption("Pybomber") self.screen.blit(self.background, ((0, 0), RESOLUTION)) self.populatedBombGroup = SpriteGroup() self.bombGroup = SpriteGroup() self.bomberGroup = SpriteGroup() self.explosionGroup = SpriteGroup() self.immutableGroup = SpriteGroup() self.powerUpGroup = SpriteGroup() self.mutableGroup = SpriteGroup() self.universalGroup = SpriteGroup() # For drawing everything. self.dirtyGroup = SpriteGroup() self.groundGroup = SpriteGroup() self.flyOverGroup = SpriteGroup() self.mapRows = 0 self.mapColumns = 0 self.curWidgetID = 0 def appendBomb(self, sprite): self.bombGroup.add(sprite) self.universalGroup.add(sprite) self.groundGroup.add(sprite) def flyBomb(self, bombSprite): self.groundGroup.remove(bombSprite) def groundBomb(self, bomb): self.groundGroup.add(bomb) def appendPopulatedBomb(self, sprite): self.populatedBombGroup.add(sprite) def appendExplosion(self, sprite): self.explosionGroup.add(sprite) self.universalGroup.add(sprite) def appendImmutable(self, sprite): self.flyOverGroup.add(sprite) self.immutableGroup.add(sprite) self.universalGroup.add(sprite) self.groundGroup.add(sprite) def appendBomber(self, sprite): self.bomberGroup.add(sprite) self.universalGroup.add(sprite) self.groundGroup.add(sprite) def appendPowerUp(self, sprite): self.powerUpGroup.add(sprite) self.universalGroup.add(sprite) def appendMutable(self, sprite): self.flyOverGroup.add(sprite) self.mutableGroup.add(sprite) self.universalGroup.add(sprite) self.groundGroup.add(sprite) def detonateBomb(self, bomb): """Detonate bomb""" bomb.kill() def removeExplosion(self, explosion): """Remove explosion from all groups.""" self.explosionGroup.remove(explosion) self.universalGroup.remove(explosion) def removeBomber(self, bomber): """Remove explosion from all groups.""" self.bomberGroup.remove(bomber) self.groundGroup.remove(bomber) self.universalGroup.remove(bomber) def removePopulatedBomb(self, sprite): self.populatedBombGroup.remove(sprite) def removePowerUp(self, powerUp): """Remove powerUp from all groups.""" self.powerUpGroup.remove(powerUp) self.universalGroup.remove(powerUp) def bomberStrafe(self, bomberPos): """Take bomberman's position and find the nearest grid square.""" posX = 0 posY = 0 # Get the location between grid. posBetweenGridX = (bomberPos[X] - XOFFSET) % BLOCKSIZE[X] posBetweenGridY = (bomberPos[Y] - YOFFSET) % BLOCKSIZE[Y] # If location is less than 1/3 way, move back, # if over 2/3, move forward. inMiddleX = (BLOCKSIZE[X] / 3, 2 * BLOCKSIZE[X] / 3) inMiddleY = (BLOCKSIZE[Y] / 3, 2 * BLOCKSIZE[Y] / 3) # Fix x if posBetweenGridX <= inMiddleX[0]: posX = bomberPos[X] - posBetweenGridX # Please leave the 0 and 1, they don't mean X and Y. elif(posBetweenGridX > inMiddleX[0] and\ posBetweenGridX < inMiddleX[1]): posX = bomberPos[X] else: # > inMiddle[1] posX = bomberPos[X] + (BLOCKSIZE[X] - posBetweenGridX) # Fix y if posBetweenGridY <= inMiddleY[0]: posY = bomberPos[Y] - posBetweenGridY elif posBetweenGridY > inMiddleY[0] and\ posBetweenGridY < inMiddleY[1]: posY = bomberPos[Y] else: # > inMiddleY[1] posY = bomberPos[Y] + (BLOCKSIZE[Y] - posBetweenGridY) return posX, posY def snapToGrid(self, pos): """Take position and find the nearest grid square.""" posX = posY = 0 # Get the location between grid. posBetweenGridX = (pos[0] - XOFFSET) % BLOCKSIZE[0] posBetweenGridY = (pos[1] - YOFFSET) % BLOCKSIZE[1] # If location is less than 1/2 way, move back, else move forward. if posBetweenGridX <= BLOCKSIZE[X] / 2: posX = pos[X] - posBetweenGridX else: posX = pos[X] + (BLOCKSIZE[X] - posBetweenGridX) if posBetweenGridY <= BLOCKSIZE[Y] / 2: posY = pos[Y] - posBetweenGridY else: posY = pos[Y] + (BLOCKSIZE[Y] - posBetweenGridY) return posX, posY def worldWrap(self, bomb): """Send bomb to other side of world if it was punched out of bounds """ x, y = bomb.getPosition() if bomb.beingPunched: # Check top if y < YOFFSET: bomb.setPosition((x, self.mapRows * BLOCKSIZE[Y] + YOFFSET)) # Check bottom if y > self.mapRows * BLOCKSIZE[Y] + YOFFSET: bomb.setPosition((x, YOFFSET)) # Check left if x < XOFFSET: bomb.setPosition((self.mapColumns * BLOCKSIZE[X] + XOFFSET, y)) # Check right if x > self.mapColumns * BLOCKSIZE[X] + XOFFSET: bomb.setPosition((XOFFSET, y)) def update(self): """Update sprites in enviornment class Attempt to move each sprite, undoing movements that produce collisions. """ explosionsToSort = self.explosionGroup.sprites() explosionsToSort.sort(lambda x, y: cmp(str(x), str(y))) for explosion in explosionsToSort: debug(str(explosion.rect.topleft) + " ") explosion.update() # Update players bombersToSort = self.bomberGroup.sprites() bombersToSort.sort(lambda x, y: cmp(x.id, y.id)) for bomber in bombersToSort: bomber.update() # Update bombs bombsToSort = self.bombGroup.sprites() bombsToSort.sort(lambda x, y: cmp(x.id, y.id)) for bomb in bombsToSort: bomb.update() # Update power-ups powerupSorted = self.powerUpGroup.sprites() powerupSorted.sort(lambda x, y: cmp(x.id, y.id)) for powerup in powerupSorted: powerup.update()
class GameView(View): def __init__( self, screen, display ): self.screen = screen self.screenRect = screen.get_rect() self.display = display self.model = None self.currentTime = 0 self.bgImage = load_png( 'bg_game.png' ) self.hiGroup = RenderUpdates() self.lowGroup = RenderUpdates() self.viewOnlyGroup = RenderUpdates() self.bubbleGroup = RenderUpdates() self.ins_spin = None self.ins_press = None self.quitButton = None self.squeezePrompt = None self.groups = [self.lowGroup, self.bubbleGroup, self.hiGroup, self.viewOnlyGroup] self.locks = [] self.stripeOrder = ['violet','blue','green', 'yellow','orange','red'] self.stripeHeights = { 'violet': 233, 'blue': 189, 'green': 136, 'yellow': 85, 'orange': 44, 'red': 11, } self.heaterRects = { 'green': Rect ( 160, 470, 80, 100 ), 'blue': Rect ( 265, 470, 80, 100 ), 'violet': Rect ( 370, 470, 80, 100 ), 'red': Rect ( 475, 470, 80, 100 ), 'orange': Rect ( 580, 470, 80, 100 ), 'yellow': Rect ( 685, 470, 80, 100 ), } self.purseStatusbars = [] controller = mvcState.GetController() controller.gameEventListeners.append( self ) def ModelStarted( self, model ): self.quitButton = QuitButton() self.quitButton.rect.topleft = (10, 530) self.viewOnlyGroup.add( self.quitButton ) self.ins_spin = InstructionSpin() self.ins_spin.rect.topleft = (380, 440) self.viewOnlyGroup.add( self.ins_spin ) View.ModelStarted( self, model ) heater = self.model.manualHeater heater.rect.topleft = self.heaterRects['red'].topleft self.hiGroup.add( heater ) cloud = self.model.cloud cloud.rect.topleft = (10,40) self.hiGroup.add( cloud ) monWid = self.model.playerMoney monWid.rect.topleft = (10,490) self.hiGroup.add( monWid ) bladder = self.model.bladder bladder.rect.topleft = (410,378) bladder.FixBottom( bladder.rect.midbottom ) self.hiGroup.add( bladder ) self.squeezePrompt = SqueezePrompt( bladder ) self.squeezePrompt.rect.topleft = (190,340) m = self.model stripes = [m.violetstripe, m.bluestripe, m.greenstripe, m.yellowstripe, m.orangestripe, m.redstripe ] for i in range( len(stripes) ): name = stripes[i].name stripes[i].rect.topleft = (146,self.stripeHeights[name]) self.lowGroup.add( stripes[i] ) for i in range( len(m.colorPurses) ): cName = m.colorPurses[i].colorName dimensions = self.heaterRects[cName].move(0,0) dimensions.move_ip(0,100) dimensions.height = 10 sb = StatusBar( m.colorPurses[i], dimensions, outlineImg='sb_outline.png', attrName='amount', fullAmt=m.colorPurses[i].capacity, innerColor=COLORS[cName] ) self.purseStatusbars.append( sb ) self.lowGroup.add( sb ) def OnBubbleLaunch( self, centerx ): #log.debug( 'bubble birth' ) if self.ins_spin: self.ins_spin.kill() self.ins_spin = None bubble = Bubble( 438 ) minX = 140 maxX = 790 xpos = int(rng.normalvariate( 0,50 )) + centerx xpos = min( xpos, maxX ) xpos = max( xpos, minX ) bubble.rect.x = xpos bubble.rect.bottom = 470 self.bubbleGroup.add( bubble ) def Update( self, timeChange ): self.viewOnlyGroup.update( timeChange ) self.bubbleGroup.update( timeChange ) self.currentTime += timeChange #twoSecondsAgo = self.currentTime - 2000 #halfSecondAgo = self.currentTime - 500 heaterRange = [444,530] for sb in self.purseStatusbars: sb.update() def OnBladderShoot( self, power, height ): if self.ins_press: self.ins_press.kill() if height > 3: gey = Geyser( "tall" ) else: gey = Geyser( "short" ) colorName = self.stripeOrder[height] gey.rect.midtop = (450, self.stripeHeights[colorName]) self.viewOnlyGroup.add( gey ) self.viewOnlyGroup.add( self.squeezePrompt ) #print len(self.viewOnlyGroup) def OnBladderShootStop( self ): self.viewOnlyGroup.remove( self.squeezePrompt ) def OnBladderVent( self, power, height ): if height > 3: gey = Geyser( "tall" ) else: gey = Geyser( "short" ) colorName = self.stripeOrder[height] gey.rect.midtop = (450, self.stripeHeights[colorName]) self.viewOnlyGroup.add( gey ) def OnDropBirth( self, drop ): self.lowGroup.add( drop ) def OnStripeHitMaxOpacity(self, stripe): yPos = self.stripeHeights[stripe.name]+4 if yPos in [lock.rect.top for lock in self.locks]: #log.debug( 'already have that lock' ) return lock = Lock() lock.rect.topleft = (111, self.stripeHeights[stripe.name]+4 ) self.hiGroup.add( lock ) self.locks.append( lock ) def OnHeaterBirth( self, heater ): switch= { SolarHeater:'violet', WaterWheelHeater:'blue', WindHeater:'green', FireHeater:'yellow', NuclearHeater:'orange', } klass = heater.__class__ heater.rect.topleft = self.heaterRects[switch[klass]].topleft self.hiGroup.add( heater ) def OnBladderVentingImminent( self ): if self.ins_press == None: self.ins_press = InstructionPress() self.ins_press.rect.topleft = (560, 300) self.viewOnlyGroup.add( self.ins_press ) def Kill( self ): controller = mvcState.GetController() controller.gameEventListeners.remove( self ) for s in self.viewOnlyGroup.sprites(): s.kill() for s in self.bubbleGroup.sprites(): s.kill() def OnUserQuit( self ): self.Kill() def OnWin( self, time, money ): self.Kill()
def main(): """this function is called when the program starts. it initializes everything it needs, then runs in a loop until the function returns.""" #Initialize Everything global screen screen = None pygame.init() screen = pygame.display.set_mode(RESOLUTION) pygame.display.set_caption('Example Poutine Window') #Create The Backgound bg = pygame.Surface( RESOLUTION ) bg.fill( BGCOLOR ) #Display The Background screen.blit(bg, (0, 0)) pygame.display.flip() #Prepare Game Objects clock = pygame.time.Clock() label = LabelSprite( 'foo' ) label.rect.move_ip( 100, 100 ) #this will be the callback function of the button def buttonWasClicked(): print "button clicked" button = ButtonSprite( 'bar', None, buttonWasClicked ) button.rect.move_ip( 100, 300 ) tEntry = TextEntrySprite('textentry') tEntry.rect.move_ip( 100, 400 ) allWidgets = RenderUpdates() allWidgets.add( label ) allWidgets.add( button ) allWidgets.add( tEntry ) #Main Loop while 1: timeChange = clock.tick(40) #Handle Input Events oldEvents = [] remainingEvents = pygame.event.get() for event in remainingEvents: oldEvents.append( remainingEvents.pop(0) ) if event.type == QUIT: return elif event.type == KEYDOWN and event.key == K_ESCAPE: return elif event.type == KEYDOWN: key = event.unicode.encode("ascii") if key and key in string.printable: for s in allWidgets.sprites(): if hasattr( s, "OnKeyPressed" ): s.OnKeyPressed( key ) else: key = event.key for s in allWidgets.sprites(): if hasattr( s, "OnMetaPressed"): s.OnMetaPressed( key ) elif event.type == MOUSEMOTION: for sprite in allWidgets.sprites(): if hasattr( sprite, "OnMouseMove" ): sprite.OnMouseMove( event.pos ) elif event.type == MOUSEBUTTONDOWN: for sprite in allWidgets.sprites(): if hasattr( sprite, "OnMouseClick" ): sprite.OnMouseClick( event.pos ) #Draw Everything allWidgets.clear( screen, bg ) allWidgets.update( ) changedRects = allWidgets.draw(screen) pygame.display.update( changedRects ) #Game Over pygame.quit()
class GameWorld: """Hold Game World objects Initialize display >>> import pygame as pygame >>> import random >>> from widget import * >>> randomizer = Random() Create a gameworld >>> g = GameWorld(randomizer) >>> s = pygame.surface.Surface((30,30)) >>> w = Widget(s, (0,0,30,30), (0,0)) Add and test bomberman to world >>> g.appendBomber(w) >>> g.bomberGroup <RenderUpdates(1 sprites)> Add and test an immutable to world >>> w1 = Widget(s, (0,0,30,30), (0,0)) >>> g.appendImmutable(w1) >>> g.immutableGroup <RenderUpdates(1 sprites)> Add another bomberman to world >>> p2 = Widget(s, (100,100, 30,30), (0,0)) >>> g.appendBomber(p2) Add a bomb to the game world >>> bomb = Widget(s, (100,100,30,30), (0,0)) >>> g.appendBomb(bomb) Check the number of objects in game world >>> g.universalGroup <RenderUpdates(4 sprites)> Detonate bomb in game world >>> g.detonateBomb(bomb) >>> g.bombGroup <RenderUpdates(0 sprites)> >>> g.universalGroup <RenderUpdates(3 sprites)> Add bomb to populatedBombGroup >>> g.appendPopulatedBomb(bomb) >>> g.populatedBombGroup <RenderUpdates(1 sprites)> Add an explosion to game world >>> explosion = Widget(s, (0,0,30,30),(0,0)) >>> g.appendExplosion(explosion) >>> g.explosionGroup <RenderUpdates(1 sprites)> Add a power up to game world >>> powerup = Widget(s,(0,0,30,30),(0,0)) >>> g.appendPowerUp(powerup) >>> g.powerUpGroup <RenderUpdates(1 sprites)> Remove power up from game world >>> g.removePowerUp(powerup) >>> g.powerUpGroup <RenderUpdates(0 sprites)> Test bomberstrafe algorithm >>> g.bomberStrafe([98, 100]) (98, 100) >>> g.bomberStrafe([90, 100]) (80, 100) >>> g.bomberStrafe([98, 90]) (98, 80) >>> g.bomberStrafe([139, 140]) (144, 144) Test worldWrap >>> g.mapColumns = 19 >>> bomb = Bomb(s, (0,0,30,30),3,3,3,(0,0)) >>> bomb.beingPunched = 1 >>> g.appendBomb(bomb) >>> bomb.setPosition((10,100)) >>> g.worldWrap(bomb) >>> bomb.getPosition() (624, 100) >>> bomb.setPosition((630,100)) >>> g.worldWrap(bomb) >>> bomb.getPosition() (16, 100) >>> g.mapRows = 19 >>> bomb.setPosition((100, 10)) >>> g.worldWrap(bomb) >>> bomb.getPosition() (100, 656) >>> bomb.setPosition((100, 660)) >>> g.worldWrap(bomb) >>> bomb.getPosition() (100, 48) Test for new restart game state >>> g.cleanState() >>> g.populatedBombGroup <RenderUpdates(0 sprites)> >>> g.bombGroup <RenderUpdates(0 sprites)> >>> g.bomberGroup <RenderUpdates(0 sprites)> >>> g.explosionGroup <RenderUpdates(0 sprites)> >>> g.immutableGroup <RenderUpdates(0 sprites)> >>> g.powerUpGroup <RenderUpdates(0 sprites)> >>> g.mutableGroup <RenderUpdates(0 sprites)> >>> g.universalGroup <RenderUpdates(0 sprites)> >>> g.dirtyGroup <RenderUpdates(0 sprites)> >>> g.flyOverGroup <RenderUpdates(0 sprites)> >>> g.update() """ def __init__(self, randomizer): self.randomizer = randomizer # Set title pygame.display.set_caption("Pybomber") # Setup screen self.screen = pygame.display.get_surface() # Create sprite groups self.populatedBombGroup = SpriteGroup() self.bombGroup = SpriteGroup() self.bomberGroup = SpriteGroup() self.explosionGroup = SpriteGroup() self.immutableGroup = SpriteGroup() self.powerUpGroup = SpriteGroup() self.mutableGroup = SpriteGroup() self.universalGroup = SpriteGroup() # For drawing everything. self.dirtyGroup = SpriteGroup() self.flyOverGroup = SpriteGroup() # Load a background self.background = pygame.image.load(BACKGROUND).convert() self.map = None # Draw background on screen self.screen.blit(self.background, ((0, 0), RESOLUTION)) # Number of rows and colums in the current map. self.mapRows = 0 self.mapColumns = 0 def cleanState(self): pygame.display.set_caption("Pybomber") self.screen.blit(self.background, ((0, 0), RESOLUTION)) self.populatedBombGroup = SpriteGroup() self.bombGroup = SpriteGroup() self.bomberGroup = SpriteGroup() self.explosionGroup = SpriteGroup() self.immutableGroup = SpriteGroup() self.powerUpGroup = SpriteGroup() self.mutableGroup = SpriteGroup() self.universalGroup = SpriteGroup() # For drawing everything. self.dirtyGroup = SpriteGroup() self.groundGroup = SpriteGroup() self.flyOverGroup = SpriteGroup() self.mapRows = 0 self.mapColumns = 0 self.curWidgetID = 0 def appendBomb(self, sprite): self.bombGroup.add(sprite) self.universalGroup.add(sprite) self.groundGroup.add(sprite) def flyBomb(self, bombSprite): self.groundGroup.remove(bombSprite) def groundBomb(self, bomb): self.groundGroup.add(bomb) def appendPopulatedBomb(self, sprite): self.populatedBombGroup.add(sprite) def appendExplosion(self, sprite): self.explosionGroup.add(sprite) self.universalGroup.add(sprite) def appendImmutable(self, sprite): self.flyOverGroup.add(sprite) self.immutableGroup.add(sprite) self.universalGroup.add(sprite) self.groundGroup.add(sprite) def appendBomber(self, sprite): self.bomberGroup.add(sprite) self.universalGroup.add(sprite) self.groundGroup.add(sprite) def appendPowerUp(self, sprite): self.powerUpGroup.add(sprite) self.universalGroup.add(sprite) def appendMutable(self, sprite): self.flyOverGroup.add(sprite) self.mutableGroup.add(sprite) self.universalGroup.add(sprite) self.groundGroup.add(sprite) def detonateBomb(self, bomb): """Detonate bomb""" bomb.kill() def removeExplosion(self, explosion): """Remove explosion from all groups.""" self.explosionGroup.remove(explosion) self.universalGroup.remove(explosion) def removeBomber(self, bomber): """Remove explosion from all groups.""" self.bomberGroup.remove(bomber) self.groundGroup.remove(bomber) self.universalGroup.remove(bomber) def removePopulatedBomb(self, sprite): self.populatedBombGroup.remove(sprite) def removePowerUp(self, powerUp): """Remove powerUp from all groups.""" self.powerUpGroup.remove(powerUp) self.universalGroup.remove(powerUp) def bomberStrafe(self, bomberPos): """Take bomberman's position and find the nearest grid square.""" posX = 0 posY = 0 # Get the location between grid. posBetweenGridX = (bomberPos[X]-XOFFSET) % BLOCKSIZE[X] posBetweenGridY = (bomberPos[Y]-YOFFSET) % BLOCKSIZE[Y] # If location is less than 1/3 way, move back, # if over 2/3, move forward. inMiddleX = (BLOCKSIZE[X]/3,2 * BLOCKSIZE[X]/3) inMiddleY = (BLOCKSIZE[Y]/3,2 * BLOCKSIZE[Y]/3) # Fix x if posBetweenGridX <= inMiddleX[0]: posX = bomberPos[X] - posBetweenGridX # Please leave the 0 and 1, they don't mean X and Y. elif(posBetweenGridX > inMiddleX[0] and\ posBetweenGridX < inMiddleX[1]): posX = bomberPos[X] else: # > inMiddle[1] posX = bomberPos[X] + (BLOCKSIZE[X] - posBetweenGridX) # Fix y if posBetweenGridY <= inMiddleY[0]: posY = bomberPos[Y] - posBetweenGridY elif posBetweenGridY > inMiddleY[0] and\ posBetweenGridY < inMiddleY[1]: posY = bomberPos[Y] else: # > inMiddleY[1] posY = bomberPos[Y] + (BLOCKSIZE[Y] - posBetweenGridY) return posX, posY def snapToGrid(self, pos): """Take position and find the nearest grid square.""" posX = posY = 0 # Get the location between grid. posBetweenGridX = (pos[0]-XOFFSET) % BLOCKSIZE[0] posBetweenGridY = (pos[1]-YOFFSET) % BLOCKSIZE[1] # If location is less than 1/2 way, move back, else move forward. if posBetweenGridX <= BLOCKSIZE[X]/2: posX = pos[X] - posBetweenGridX else: posX = pos[X] + (BLOCKSIZE[X] - posBetweenGridX) if posBetweenGridY <= BLOCKSIZE[Y]/2: posY = pos[Y] - posBetweenGridY else: posY = pos[Y] + (BLOCKSIZE[Y] - posBetweenGridY) return posX, posY def worldWrap(self, bomb): """Send bomb to other side of world if it was punched out of bounds """ x, y = bomb.getPosition() if bomb.beingPunched: # Check top if y < YOFFSET: bomb.setPosition((x, self.mapRows*BLOCKSIZE[Y] + YOFFSET)) # Check bottom if y > self.mapRows*BLOCKSIZE[Y] + YOFFSET: bomb.setPosition((x, YOFFSET)) # Check left if x < XOFFSET: bomb.setPosition((self.mapColumns*BLOCKSIZE[X] + XOFFSET, y)) # Check right if x > self.mapColumns*BLOCKSIZE[X] + XOFFSET: bomb.setPosition((XOFFSET, y)) def update(self): """Update sprites in enviornment class Attempt to move each sprite, undoing movements that produce collisions. """ explosionsToSort = self.explosionGroup.sprites() explosionsToSort.sort(lambda x, y: cmp(str(x), str(y))) for explosion in explosionsToSort: debug(str(explosion.rect.topleft) + " ") explosion.update() # Update players bombersToSort = self.bomberGroup.sprites() bombersToSort.sort(lambda x, y: cmp(x.id, y.id)) for bomber in bombersToSort: bomber.update() # Update bombs bombsToSort = self.bombGroup.sprites() bombsToSort.sort(lambda x, y: cmp(x.id, y.id)) for bomb in bombsToSort: bomb.update() # Update power-ups powerupSorted = self.powerUpGroup.sprites() powerupSorted.sort(lambda x, y: cmp(x.id, y.id)) for powerup in powerupSorted: powerup.update()
class EntityMaster: bee_ratio = 1 / 5 def __init__(self, initial_hives: int, default_bees_per_hive: int, play_area_dimensions: int(), flower_spawn_strategy: str, hive_spawn_strategy: str, flower_num: int): self.bees = RenderUpdates() self.hives = RenderUpdates() self.plants = RenderUpdates() self.flowers = RenderUpdates() self.ui_elements = RenderUpdates() self.flower_database = {} self.play_area = play_area_dimensions self.sim_paused = False self.grow_flora(play_area_dimensions) self.load_flower_data( get_flower_spawn_strategy(flower_spawn_strategy, play_area_dimensions, flower_num)) self.populate_hives( get_hive_spawn_strategy(hive_spawn_strategy, initial_hives, play_area_dimensions, self.flowers), default_bees_per_hive) self.clean_up_spawn() @property def bee_population(self): """ :return: Total number of bees in the simulation """ return len(self.bees) @property def flower_population(self): """ :return: Total number of flowers in the simulation """ return len(self.flowers) def get_entities(self): """ :return: Entities that need to be rendered next frame """ self.update_game_state() return self.plants.sprites() + self.flowers.sprites() + \ self.hives.sprites() + self.bees.sprites() + self.ui_elements.sprites() def update_game_state(self): """ :return: void """ for hive in self.hives: hive.last_tick = get_ticks() self.handle_hive_highlighting(hive) if hive.current_nectar == hive.max_nectar: self.hive_purchase_bee(hive) for flower in self.flowers: if flower.pollen == 0: flower.crosshair.kill() flower.kill() for hive in self.hives: if flower in hive.flowers: hive.flowers.remove(flower) else: if flower.inspecting_hives.__len__() == 0: self.ui_elements.remove(flower.crosshair) else: self.ui_elements.add(flower.crosshair) flower.inspecting_hives[flower.inspecting_hives.__len__() - 1].recolor_crosshair(flower) if not self.sim_paused: for bee in self.bees: # If the sim is not paused, we update the states of the bees bee.update() self.update_bee_crosshair(bee) bee.handle_collisions(self.flowers) else: for bee in self.bees: # If the sim is paused we only update the crosshairs self.update_bee_crosshair(bee) def update_bee_crosshair(self, bee): """ Updates the state of the bee crosshair, adding it to the list of rendered entities if necessary :param bee: :return: void """ if not bee.highlighted: bee.crosshair.kill() else: self.ui_elements.add(bee.crosshair) bee.crosshair.follow() def handle_hive_highlighting(self, hive): """ Takes care of everything that has to do with hive highlighting, adding the needed ui elements if necessary :param hive: :return: """ if not hive.highlighted: hive.honey_bar.kill() else: self.ui_elements.add(hive.honey_bar) hive.honey_bar.update() def add_bee(self, hive, caste): if caste == 'worker': new_bee = \ WorkerBee((hive.center.x + randint(-10, 10), hive.center.y + randint(-10, 10)), hive) elif caste == 'scout': new_bee = \ ScoutBee((hive.center.x + randint(-50, 50), hive.center.y + randint(-50, 50)), hive) self.ui_elements.add(new_bee.crosshair) hive.add_bee(new_bee, caste) self.bees.add(new_bee) def hive_purchase_bee(self, hive): """ Provided hive purchases a bee using some of its honey :param hive: :return: """ hive.buy_bee() bee_roll = random() self.add_bee(hive, 'scout') if bee_roll >= self.bee_ratio else self.add_bee( hive, 'worker') def populate_hives(self, hives, bees_per_hive): """ Populates the hives with bees :param hives: :param bees_per_hive: :return: """ for hive in hives: self.hives.add(hive) self.spawn_initial_bees(hive, bees_per_hive) def spawn_initial_bees(self, hive, bees_per_hive): """ Fills an individual hive with bees :param hive: :param bees_per_hive: :return: """ scouts = int(bees_per_hive * self.bee_ratio) workers = bees_per_hive - scouts for j in range(workers): self.add_bee(hive, 'worker') for j in range(scouts): self.add_bee(hive, 'scout') def clean_up_spawn(self): """ Removes flowers that are colliding with hives and adds UI elements to the hives :return: """ for hive in self.hives: flowers = self.flowers spritecollide(hive, flowers, True, collide_circle_ratio(1)) def load_flower_data(self, data): """ Loads the list of flowers :param data: :return: """ self.flower_database = data self.flowers = RenderUpdates(data.values()) def grow_flora(self, play_area): """ Grows the decorative plants :param play_area: :return: void """ plant_db = grow_plants(play_area, num=randint(90, 150), plant_type="grass", bias="center") plant_db = merge_plant_sets( plant_db, grow_plants(play_area, num=randint(50, 75), plant_type="grassy_plant", bias="edges")) plant_db = merge_plant_sets( plant_db, grow_plants(play_area, num=randint(1, 2), plant_type="pretty_log", bias="edges")) plant_db = merge_plant_sets( plant_db, grow_plants(play_area, num=randint(0, 3), plant_type="stump", bias="edges")) plant_db = merge_plant_sets( plant_db, grow_plants(play_area, num=randint(25, 55), plant_type="leaves", bias="edges")) plant_db = merge_plant_sets( plant_db, grow_plants(play_area, num=randint(15, 25), plant_type="bushy_grass", bias="edges")) self.plants = RenderUpdates(list(plant_db.values())) def get_hive_at(self, position): """ :param position: :return: Hive at given location, None if there are none such. """ for hive in self.hives: if hive.scaled_rect.collidepoint(position): return hive return None