Esempio n. 1
0
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 )
Esempio n. 2
0
class BaseEntity(Sprite):
    """Base Class Entity to use for games entity.

    Extends pygame.Sprite class
    Use to manage entities, for space collapsing
    and draw animation space.
    
    Instance variable:
    - rect : pygame.Rect class 
    Use for collapse beetween entities
    - direction : direction state 
        UP = 273
        DOWN = 274
        RIGHT = 275
        LEFT = 276
    - speed : list of speed mvt : [abs, ord]
    """

    def __init__(self, name, rect_data, speed, max_frame, max_frame_delay, img):
        """ Init.
        - rect_data : list contains =>
        - x : position x
        - y : position y
        - w : width of rect_collapse
        - h : height of collase
        - direction
        """
        super(BaseEntity, self).__init__()
        self.name = name
        self.rect = None
        self.image = None
        self.childs = Group()
        self.rect_collapse = Rect(rect_data)
        self.speed = speed
        self.direction = UP
        # Create animation for the entity
        self.animation = self.init_animation(max_frame, max_frame_delay, img)

    def add_child(self, child):
        """Add a child entity."""
        self.childs.add(child)

    def remove_child(self, child):
        """Remove a child entity."""
        self.childs.remove(child)

    def direction_get(self):
        return self.direction

    def direction_set(self, direction):
        self.direction = direction

    def get_rect(self, value=0):
        """Return rect 
        
        0 = rect(actual rect to use)
        1 = rect_animation
        2 = rect_collapse
        """
        if value == 1:
            return self.image.get_rect()
        elif value == 2:
            return self.rect_collapse
        else:
            return self.rect

    def init_animation(self, max_frame, max_frame_delay, img):
        """Function for animation initialisation.
        
        Need to be defined.
        """
        pass

    def __str__(self):
        """Custom __str__."""
        string = u"<Entity : %s -- Pos (%s,%s)>\n" % (
            str(self.name),
            str(self.rect_collapse[0]),
            str(self.rect_collapse[1]),
        )
        return string

    def move(self, move_direction):
        """Basic mouvement.

        Basic calcul tomove the entity, defined by direction parameter
        Reimplements if you need to change move's pattern
        """
        x, y = self.rect_collapse.topleft
        direction_num = move_direction - UP
        if direction_num == 0:
            move = (0, -1)
        elif direction_num == 1:
            move = (0, 1)
        elif direction_num == 2:
            move = (1, 0)
        elif direction_num == 3:
            move = (-1, 0)

        x = x + (self.speed[0] * move[0])
        y = y + (self.speed[1] * move[1])
        self.rect_collapse.left = x
        self.rect_collapse.top = y

    def stop(self):
        """Basic stop.
        
        Stop the mouvement of the entity
        Reimplements if you need to change move's pattern
        """
        pass

    def update(self, movement=None):
        """Update function.
        
        Basic update position of the entity (move or stop)
        Redefine it for your own purpose
        Action use by pygame.sprite.Group.update() function.
        """
        if movement is None:
            self.stop()
            self.animation.stop()
        else:
            self.direction = movement
            self.move(movement)
            self.animation.update()

        self.setup_animation(self.direction)
        self.childs.update()

    def setup_collapse(self):
        """Setup variable.
                
        Set up rect attribute for collapse eval"""
        self.rect = self.rect_collapse

    def setup_animation(self, direction):
        """Setup variable.

        Set up rect attribute for animation draw
        Be careful :: is function move anim_sprite to center
        with rect_collapse
        Catch image.get_rect directly will give you the wrong coordinate
        """
        self.image = self.animation.get_sprite(direction).convert_alpha()
        rect_anim_position = self.image.get_rect()
        rect_anim_position.center = self.rect_collapse.center
        self.rect = rect_anim_position
Esempio n. 3
0
class Game:

    def __init__(self, title='Checkers', log_level=log.INFO, show_fps=False):
        log.basicConfig(level=log_level)
        self.show_fps = show_fps
        self.window_title = title
        self.game = Board(BOARD_DIM)
        # Initialize Game Groups
        self.brown_spaces = RenderUpdates()
        self.pieces = RenderUpdates()
        self.piece_selected = GroupSingle()
        self.space_selected = GroupSingle()
        self.current_piece_position = ORIGIN
        self.screen = None
        self.fps_clock = None
        self.font = None
        self.font_rect = None
        self.background = None
        self.background_rect = None
        self.fps_text = None
        self.fps_rect = None
        self.winner_text = None
        self.winner_rect = None

    def _board_setup(self, **kwargs):
        """ initialize board state """
        brown_spaces = kwargs.get('brown_spaces')
        for col, row in self.game.usable_positions():
            loc = TILE_WIDTH * col + (BORDER_WIDTH / 2), TILE_WIDTH * row + (BORDER_WIDTH / 2)
            brown_spaces.add(SquareSprite(loc, "brown", row, col))

    def _screen_init(self):
        """ Initialise screen """
        pygame.init()
        self.screen = pygame.display.set_mode(SCREEN_RES)
        pygame.display.set_caption(self.window_title)
        return self.screen

    def _get_background(self):
        result = pygame.Surface(self.screen.get_size())
        (bg_img, bg_rect) = ImageLoader.load_img('marble-board.jpg')
        result.blit(bg_img, bg_rect)
        return result.convert(), bg_rect

    def _get_fps_text(self):
        fps_text = self.font.render("%4.1f fps" % self.fps_clock.get_fps(), True, WHITE)
        rect = fps_text.get_rect()
        rect.right, rect.bottom = self.background_rect.right, self.background_rect.bottom
        return fps_text, rect

    def _draw_fps(self):
        if self.show_fps:
            self.fps_text, self.fps_rect = self._get_fps_text()
            self.screen.blit(self.fps_text, self.fps_rect)

    def _clear_fps(self):
        if self.show_fps:
            self.screen.blit(self.background, self.fps_rect, area=self.fps_rect)

    def _clear_items(self):
        self._clear_winner()
        self._clear_fps()
        self.piece_selected.clear(self.screen, self.background)
        self.pieces.clear(self.screen, self.background)

    def _draw_winner(self):
        winner = self.game.winner()
        if winner:
            self.winner_text = self.font.render("%s wins!" % winner.title(), True, WHITE)
            winner_rect = self.winner_text.get_rect()
            winner_rect.centerx = self.background.get_rect().centerx
            winner_rect.top = 100
            self.winner_rect = winner_rect
            self.screen.blit(self.winner_text, winner_rect)

    def _clear_winner(self):
        winner = self.game.winner()
        if winner:
            self.screen.blit(self.background, self.winner_rect, area=self.winner_rect)

    def _quit(self):
        log.debug('quitting')
        sys.exit()

    def _select_piece(self, event):
        # select the piece by seeing if the piece collides with cursor
        self.piece_selected.add(piece for piece in self.pieces if piece.rect.collidepoint(event.pos))
        # Capture piece's original position (at center) to determine move on drop
        if len(self.piece_selected) > 0:
            # Assumed: starting a move
            pygame.event.set_grab(True)
            self.pieces.remove(self.piece_selected)
            self.current_piece_position = (self.piece_selected.sprite.rect.centerx,
                                           self.piece_selected.sprite.rect.centery)
            log.debug('grabbing input, picked up piece at %s', self.current_piece_position)

    def _drag_piece(self):
        #  Until button is let go, move the piece with the mouse position
        self.piece_selected.update(pygame.mouse.get_pos())
        log.debug('updated piece to %s', pygame.mouse.get_pos())

    def _drop_piece(self, event):
        if pygame.event.get_grab():
            pygame.event.set_grab(False)
            log.debug('releasing input')

            # center the piece on the valid space; if it is not touching a space, return it to its original position
            self.space_selected.add(space for space in self.brown_spaces
                                    if space.rect.collidepoint(event.pos))

            if self.piece_selected and self.space_selected:
                log.debug('dropped a piece')
                piece, space = self.piece_selected.sprite, self.space_selected.sprite
                try:
                    captured = self.game.move(piece.location, (space.col, space.row))
                    if captured:
                        self.pieces.remove(captured)
                except InvalidMoveException as ce:
                    log.debug(ce)
                log.debug("%s", str(self.game))

            self.piece_selected.sprite.update_from_board()

            # Add piece back to stationary set
            self.pieces.add(self.piece_selected)

            # clean up for the next selected piece
            self.piece_selected.empty()
            self.space_selected.empty()

    def _draw_items(self):
        self.pieces.draw(self.screen)
        self.piece_selected.draw(self.screen)
        self._draw_winner()
        self._draw_fps()


    def run(self):

        log.debug('starting game')

        log.debug('initializing screen')
        self.screen = self._screen_init()

        log.debug('getting font')
        self.font = pygame.font.Font(None, 36)

        log.debug('loading background')
        self.background, self.background_rect= self._get_background()

        log.debug('building initial game board')
        self._board_setup(brown_spaces=self.brown_spaces)

        log.debug('initializing game pieces')
        for player, x, y in self.game.start_positions():
            new_piece = PieceSprite(player)
            self.game.add_piece(new_piece, (x, y))
            new_piece.update_from_board()
            self.pieces.add(new_piece)

        log.debug('drawing initial content to screen')
        self.screen.blit(self.background, ORIGIN)
        pygame.display.flip()

        self.piece_selected = GroupSingle()
        self.space_selected = GroupSingle()
        self.current_piece_position = ORIGIN

        self.fps_clock = Clock()

        self._draw_fps()

        # Event loop
        while True:

            self._clear_items()

            for event in pygame.event.get():

                if event.type == QUIT:
                    self._quit()

                if event.type == MOUSEBUTTONDOWN:     # select a piece
                    log.debug('mouse pressed')
                    self._select_piece(event)

                if event.type == MOUSEBUTTONUP:     # let go of a piece
                    log.debug('mouse released')
                    self._drop_piece(event)

                if pygame.event.get_grab():          # drag selected piece around
                    log.debug('dragging')
                    self._drag_piece()

            self._draw_items()

            self.fps_clock.tick(60)  # Waits to maintain 60 fps

            # TODO: Use display.update instead
            pygame.display.flip()
Esempio n. 4
0
class Game:
    def __init__(self, title='Checkers', log_level=log.INFO, show_fps=False):
        log.basicConfig(level=log_level)
        self.show_fps = show_fps
        self.window_title = title
        self.game = Board(BOARD_DIM)
        # Initialize Game Groups
        self.brown_spaces = RenderUpdates()
        self.pieces = RenderUpdates()
        self.piece_selected = GroupSingle()
        self.space_selected = GroupSingle()
        self.current_piece_position = ORIGIN
        self.screen = None
        self.fps_clock = None
        self.font = None
        self.font_rect = None
        self.background = None
        self.background_rect = None
        self.fps_text = None
        self.fps_rect = None
        self.winner_text = None
        self.winner_rect = None

    def _board_setup(self, **kwargs):
        """ initialize board state """
        brown_spaces = kwargs.get('brown_spaces')
        for col, row in self.game.usable_positions():
            loc = TILE_WIDTH * col + (BORDER_WIDTH /
                                      2), TILE_WIDTH * row + (BORDER_WIDTH / 2)
            brown_spaces.add(SquareSprite(loc, "brown", row, col))

    def _screen_init(self):
        """ Initialise screen """
        pygame.init()
        self.screen = pygame.display.set_mode(SCREEN_RES)
        pygame.display.set_caption(self.window_title)
        return self.screen

    def _get_background(self):
        result = pygame.Surface(self.screen.get_size())
        (bg_img, bg_rect) = ImageLoader.load_img('marble-board.jpg')
        result.blit(bg_img, bg_rect)
        return result.convert(), bg_rect

    def _get_fps_text(self):
        fps_text = self.font.render("%4.1f fps" % self.fps_clock.get_fps(),
                                    True, WHITE)
        rect = fps_text.get_rect()
        rect.right, rect.bottom = self.background_rect.right, self.background_rect.bottom
        return fps_text, rect

    def _draw_fps(self):
        if self.show_fps:
            self.fps_text, self.fps_rect = self._get_fps_text()
            self.screen.blit(self.fps_text, self.fps_rect)

    def _clear_fps(self):
        if self.show_fps:
            self.screen.blit(self.background,
                             self.fps_rect,
                             area=self.fps_rect)

    def _clear_items(self):
        self._clear_winner()
        self._clear_fps()
        self.piece_selected.clear(self.screen, self.background)
        self.pieces.clear(self.screen, self.background)

    def _draw_winner(self):
        winner = self.game.winner()
        if winner:
            self.winner_text = self.font.render("%s wins!" % winner.title(),
                                                True, WHITE)
            winner_rect = self.winner_text.get_rect()
            winner_rect.centerx = self.background.get_rect().centerx
            winner_rect.top = 100
            self.winner_rect = winner_rect
            self.screen.blit(self.winner_text, winner_rect)

    def _clear_winner(self):
        winner = self.game.winner()
        if winner:
            self.screen.blit(self.background,
                             self.winner_rect,
                             area=self.winner_rect)

    def _quit(self):
        log.debug('quitting')
        sys.exit()

    def _select_piece(self, event):
        # select the piece by seeing if the piece collides with cursor
        self.piece_selected.add(piece for piece in self.pieces
                                if piece.rect.collidepoint(event.pos))
        # Capture piece's original position (at center) to determine move on drop
        if len(self.piece_selected) > 0:
            # Assumed: starting a move
            pygame.event.set_grab(True)
            self.pieces.remove(self.piece_selected)
            self.current_piece_position = (
                self.piece_selected.sprite.rect.centerx,
                self.piece_selected.sprite.rect.centery)
            log.debug('grabbing input, picked up piece at %s',
                      self.current_piece_position)

    def _drag_piece(self):
        #  Until button is let go, move the piece with the mouse position
        self.piece_selected.update(pygame.mouse.get_pos())
        log.debug('updated piece to %s', pygame.mouse.get_pos())

    def _drop_piece(self, event):
        if pygame.event.get_grab():
            pygame.event.set_grab(False)
            log.debug('releasing input')

            # center the piece on the valid space; if it is not touching a space, return it to its original position
            self.space_selected.add(space for space in self.brown_spaces
                                    if space.rect.collidepoint(event.pos))

            if self.piece_selected and self.space_selected:
                log.debug('dropped a piece')
                piece, space = self.piece_selected.sprite, self.space_selected.sprite
                try:
                    captured = self.game.move(piece.location,
                                              (space.col, space.row))
                    if captured:
                        self.pieces.remove(captured)
                except InvalidMoveException as ce:
                    log.debug(ce)
                log.debug("%s", str(self.game))

            self.piece_selected.sprite.update_from_board()

            # Add piece back to stationary set
            self.pieces.add(self.piece_selected)

            # clean up for the next selected piece
            self.piece_selected.empty()
            self.space_selected.empty()

    def _draw_items(self):
        self.pieces.draw(self.screen)
        self.piece_selected.draw(self.screen)
        self._draw_winner()
        self._draw_fps()

    def run(self):

        log.debug('starting game')

        log.debug('initializing screen')
        self.screen = self._screen_init()

        log.debug('getting font')
        self.font = pygame.font.Font(None, 36)

        log.debug('loading background')
        self.background, self.background_rect = self._get_background()

        log.debug('building initial game board')
        self._board_setup(brown_spaces=self.brown_spaces)

        log.debug('initializing game pieces')
        for player, x, y in self.game.start_positions():
            new_piece = PieceSprite(player)
            self.game.add_piece(new_piece, (x, y))
            new_piece.update_from_board()
            self.pieces.add(new_piece)

        log.debug('drawing initial content to screen')
        self.screen.blit(self.background, ORIGIN)
        pygame.display.flip()

        self.piece_selected = GroupSingle()
        self.space_selected = GroupSingle()
        self.current_piece_position = ORIGIN

        self.fps_clock = Clock()

        self._draw_fps()

        # Event loop
        while True:

            self._clear_items()

            for event in pygame.event.get():

                if event.type == QUIT:
                    self._quit()

                if event.type == MOUSEBUTTONDOWN:  # select a piece
                    log.debug('mouse pressed')
                    self._select_piece(event)

                if event.type == MOUSEBUTTONUP:  # let go of a piece
                    log.debug('mouse released')
                    self._drop_piece(event)

                if pygame.event.get_grab():  # drag selected piece around
                    log.debug('dragging')
                    self._drag_piece()

            self._draw_items()

            self.fps_clock.tick(60)  # Waits to maintain 60 fps

            # TODO: Use display.update instead
            pygame.display.flip()
Esempio n. 5
0
File: event.py Progetto: alecain/one
class EventLoop(object):
    def __init__(self):
        self.objs = {}
        self.events = []
        self.render = RenderUpdates()
        self.projectiles = Group()
        self.enemies = Group()
        self.you = None
        self.bg_sprite = BGSprite(pygame.display.get_surface())

        # Since we don't care about MOST EVENTS
        pygame.event.set_allowed(None)
        pygame.event.set_allowed([ MOUSEBUTTONDOWN, KEYDOWN, QUIT, UPDATEEVENT, SPAWNEVENT ])

    def add_object(self, obj, type=""):
        if isinstance(obj, HandlesEvents):
            if obj.events == ALL:
                try:
                    self.objs[ALL].append(obj)
                except KeyError:
                    self.objs[ALL] = [ obj ]
            else:
                for event in obj.events:
                    try:
                        self.objs[event].append(obj)
                    except KeyError:
                        self.objs[event] = [ obj ]
        if isinstance(obj, Sprite):
            self.render.add(obj)
            if type == "enemy":
                self.enemies.add(obj)
            if type == "projectile":
                self.projectiles.add(obj)
            if type == "you":
                self.you = obj

    def rm_object(self, obj):
        for key in self.objs.keys():
            self.render.remove(obj)
            if obj in self.objs[key]:
                self.objs[key].remove(obj)
            if self.projectiles.has(obj):
                self.projectiles.remove(obj)
            if self.enemies.has(obj):
                self.enemies.remove(obj)
            print "Removed {0}".format(obj)

    def enqueue(self, event):
        if isinstance(event, Event):
            return self.events.append(event)
        elif isinstance(event, list):
            return [ self.enqueue(ev) for ev in event ]

    def tick(self):
        try:
            event = self.events.pop()
        except IndexError:
            event = None

        if event is not None:
            if isinstance(event, TargettedEvent):
                event.get_target().handle_event(event)
                for obj in self.objs[ALL]:
                    obj.handle_event(event)
            else:
                for obj in self.objs[type(event)] + self.objs[ALL]:
                    if obj.handles_event(event):
                        obj.handle_event(event)


        if random.randint(0, 10000000) == 26:
            return win()
        if random.randint(0, 10000000) == 26:
            return lose()

        py_events = map(lambda event: PygameEvent(event), pygame.event.get())
        for py_event in py_events:
            for obj in reduce(lambda obj_list, obj: obj_list + obj, map(lambda key: self.objs[key], filter(lambda handler_type: issubclass(handler_type, PygameEvent) if handler_type != ALL else False, self.objs.keys())), []):
                if obj.handles_event(py_event):
                    obj.handle_event(py_event)
Esempio n. 6
0
class Game(StatusHandler):

    def __init__(self, title='Checkers', log_drag=False, show_fps=False, ip='127.0.0.1', port=5000, spectate=False):
        self.game_running = True
        self.player = None
        self.log_drag = log_drag
        self.show_fps = show_fps
        self.window_title = title
        self.game = NetBoard(handler=self, ip=ip, port=port, spectate=spectate)
        # Initialize Game Groups
        self.board_spaces = set()
        self.pieces = RenderUpdates()
        self.piece_selected = GroupSingle()
        self.bg_text = RenderUpdates()
        self.fg_text = RenderUpdates()
        self.current_piece_position = ORIGIN
        self.screen = None
        self.fps_clock = None
        self.font = None
        self.background = None
        self.background_rect = None
        self.fps_text = None
        self.winner_text = None
        self.turn_text = None
        self.player_text = None
        self.game_id_text = None

    def handle_game_id(self, game_id):
        self.game_id_text.text = "Game: %s" % game_id

    def handle_list(self, game_list, list_type):

        if list_type == SPECTATE and game_list:
            game_id = game_list[0]
            self.game.client.spectate(game_id)
            self.player_text.text = 'You are a spectator'
        elif not list_type and game_list:
            game_id = game_list[0]
            self.game.client.join(game_id)
        elif not list_type and not game_list:
            self.game.client.new_game()

    def handle_board(self, board):
        for piece in board:
            new_piece = PieceSprite(piece.player)
            new_piece.king = piece.king
            self.game.add_piece(new_piece, piece.location)
            new_piece.update_from_board()
            self.pieces.add(new_piece)

    def handle_turn(self, player):
        self.game.turn = player

    def handle_you_are(self, player):
        self.player = player

    def handle_moved(self, src, dst):
        moved_pieces = [p for p in self.pieces if p.location == src]
        Board.move(self.game, src, dst)
        if moved_pieces:
            moved_pieces[0].update_from_board()
            Sounds.play('slap.ogg')
            log.debug("board after drop:\n%s", str(self.game))

    def handle_captured(self, loc):
        captured_pieces = [p for p in self.pieces if p.location == loc]
        if captured_pieces:
            self.pieces.remove(captured_pieces[0])

    def _board_space_setup(self):
        """ initialize board state """
        for col, row in self.game.usable_positions():
            self.board_spaces.add(Square(row, col))

    def _screen_init(self):
        """ Initialise screen """
        self.screen = pygame.display.set_mode(SCREEN_RES)
        pygame.display.set_caption(self.window_title)
        return self.screen

    def _get_background(self):
        result = pygame.Surface(self.screen.get_size())
        (bg_img, bg_rect) = Images.load('marble-board.jpg')
        result.blit(bg_img, bg_rect)
        return result.convert(), bg_rect

    def _clear_items(self):
        self.fg_text.clear(self.screen, self.background)
        self.piece_selected.clear(self.screen, self.background)
        self.pieces.clear(self.screen, self.background)
        self.bg_text.clear(self.screen, self.background)

    def _quit(self):
        log.debug('quitting')
        self.game.client.quit()
        self.game_running = False

    def _select_piece(self, event):
        # select the piece by seeing if the piece collides with cursor
        self.piece_selected.add(piece for piece in self.pieces
                                if piece.rect.collidepoint(event.pos)
                                and piece.player == self.player
                                and piece.player == self.game.turn)
        # Capture piece's original position (at center) to determine move on drop
        if len(self.piece_selected) > 0:
            # Assumed: starting a move
            pygame.event.set_grab(True)
            self.pieces.remove(self.piece_selected)
            self.current_piece_position = (self.piece_selected.sprite.rect.centerx,
                                           self.piece_selected.sprite.rect.centery)
            log.debug('grabbing input, picked up piece at %s', self.current_piece_position)
            Sounds.play('slide.ogg')

    def _drag_piece(self):
        #  Until button is let go, move the piece with the mouse position
        if self.log_drag:
            log.debug('dragging')
        rect = self.piece_selected.sprite.rect
        rect.centerx, rect.centery = pygame.mouse.get_pos()
        if self.log_drag:
            log.debug('updated piece to %s', pygame.mouse.get_pos())

    def _reset_selected_piece(self):
        self.piece_selected.sprite.update_from_board()
        Sounds.play('slap.ogg')
        log.debug("board after drop:\n%s", str(self.game))

    def _drop_piece(self, event):
        if pygame.event.get_grab():
            pygame.event.set_grab(False)
            log.debug('releasing input')

            # center the piece on the valid space; if it is not touching a space, return it to its original position
            space_selected = [space for space in self.board_spaces if space.collidepoint(event.pos)]

            if self.piece_selected and space_selected:
                log.debug('dropped a piece')
                piece, space = self.piece_selected.sprite, space_selected[0]
                try:
                    self.game.move(piece.location, (space.col, space.row))
                except InvalidMoveException as ce:
                    log.debug(ce)
                    self._reset_selected_piece()
            else:
                log.debug('dropped on unplayable game space')
                self._reset_selected_piece()

            # Add piece back to stationary set
            self.pieces.add(self.piece_selected)

            # clean up for the next selected piece
            self.piece_selected.empty()

    def _draw_items(self):
        self.bg_text.draw(self.screen)
        self.pieces.draw(self.screen)
        self.piece_selected.draw(self.screen)
        self.fg_text.draw(self.screen)

    def _update(self):
        self.game.update()

        self.fps_text.text = "%4.1f fps" % self.fps_clock.get_fps()

        if self.player:
            self.player_text.text = "Your pieces are %s" % self.player

        if self.game.turn not in players:
            self.turn_text.text = "Waiting for player"
        else:
            if self.player == self.game.turn:
                self.turn_text.text = "Your turn"
            else:
                self.turn_text.text = "%s's turn" % self.game.turn.title()

        if self.game.winner():
            self.turn_text.text = ''
            self.winner_text.text = "%s wins!" % self.game.winner().title()
        else:
            self.winner_text.text = ''

        if not self.piece_selected and self.player == self.game.turn:
            highlight_player = self.game.turn
        else:
            highlight_player = None
        self.pieces.update(highlight_player)
        self.piece_selected.update(self.game.turn)
        self.bg_text.update()
        self.fg_text.update()

    def run(self):

        log.debug('pre-initializing sound')
        mixer.pre_init(buffer=32)

        log.debug('starting game')
        pygame.init()

        log.debug('initializing screen')
        self.screen = self._screen_init()

        log.debug('getting font')
        self.font = pygame.font.Font(None, 36)

        log.debug('loading background')
        self.background, self.background_rect = self._get_background()

        log.debug('setting up drop locations')
        self._board_space_setup()

        log.debug('building text')
        bg_rect = self.background_rect

        class FPSText(Text):
            def update(self, *args):
                Text.update(self, *args)
                self.rect.right, self.rect.bottom = bg_rect.right, bg_rect.bottom

        self.fps_text = FPSText('', self.font, WHITE)
        if self.show_fps:
            self.fg_text.add(self.fps_text)

        class TurnText(Text):
            def update(self, *args):
                Text.update(self, *args)
                self.rect.centerx, self.rect.centery = bg_rect.centerx, bg_rect.centery

        self.turn_text = TurnText('', self.font, WHITE)
        self.bg_text.add(self.turn_text)

        class WinnerText(Text):
            def update(self, *args):
                Text.update(self, *args)
                self.rect.centerx, self.rect.centery = bg_rect.centerx, bg_rect.centery

        self.winner_text = WinnerText('', self.font, WHITE)
        self.fg_text.add(self.winner_text)

        class PlayerText(Text):
            def update(self, *args):
                Text.update(self, *args)
                self.rect.centerx, self.rect.bottom = bg_rect.centerx, bg_rect.bottom

        self.player_text = PlayerText('', pygame.font.Font(None, 24), WHITE)
        self.bg_text.add(self.player_text)

        class GameIdText(Text):
            def update(self, *args):
                Text.update(self, *args)
                self.rect.centerx, self.rect.top = bg_rect.centerx, bg_rect.top + (0.25 * self.font.get_height())

        self.game_id_text = GameIdText('', pygame.font.Font(None, 20), WHITE)
        self.bg_text.add(self.game_id_text)

        log.debug('drawing initial content to screen')
        self.screen.blit(self.background, ORIGIN)
        pygame.display.flip()

        self.piece_selected = GroupSingle()
        self.current_piece_position = ORIGIN

        self.fps_clock = Clock()

        # Event loop
        while self.game_running:

            self._clear_items()

            for event in pygame.event.get():

                if event.type == QUIT:
                    self._quit()

                if event.type == MOUSEBUTTONDOWN:     # select a piece
                    log.debug('mouse pressed')
                    self._select_piece(event)

                if event.type == MOUSEBUTTONUP:     # let go of a piece
                    log.debug('mouse released')
                    self._drop_piece(event)

                if pygame.event.get_grab():          # drag selected piece around
                    self._drag_piece()

            self._update()

            self._draw_items()

            self.fps_clock.tick(60)  # Waits to maintain 60 fps

            # TODO: Use display.update instead
            pygame.display.flip()

        log.debug('finishing game loop')
Esempio n. 7
0
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()
Esempio n. 8
0
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()
Esempio n. 9
0
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()
Esempio n. 10
0
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