Ejemplo n.º 1
0
 def hasNoFreeMovementTo(self, target, source=None):
     """Check if the character has NOT free straight movement to a destination point.
     If this is True, the character can't move directly on the vector that link his current
     position to the target due to a collision that will be raised.
     @target: a point coordinate, goal of the movement
     @source: optional parameter to test the free movement from a coordinate different fron the current one.
     @return False if no collision is detected, or the collisions points tuples
     """
     position = self.position
     collide_rect = self.collide_rect
     if not source:
         source = position
     else:
         # I need a collide_rect traslated to the new source
         rx, ry = position[0]-int(source[0]), position[1]-int(source[1])
         collide_rect.move_ip(rx, ry)
     v = Vector2.from_points(source, target)
     magnitude = v.get_magnitude()
     heading = v.normalize()
     distance = min(collide_rect.w, collide_rect.h)
     total_distance = 0
     while True:
         total_distance+=distance
         movement = heading * total_distance
         x = movement.get_x()
         y = movement.get_y()
         collision = self.checkCollision(x, y, silent=True)
         if collision:
             return (x,y)
         if total_distance>=magnitude:
             return False
Ejemplo n.º 2
0
 def normalizeDrawPositionBasedOn(self, reference, time_passed):
     """Slowly move drawn portion of the total level, for centering it on the given reference object.
     reference can be a GameSprite or a position tuple info.
     """
     if type(reference)==tuple:
         referencePointOnScreen = reference
     else:
         referencePointOnScreen = reference.position
     if self.isPointAtScreenCenter(referencePointOnScreen, (160,160) ):
         return
     heading = Vector2.from_points(self.center, referencePointOnScreen)
     # More near to screen border, faster will be the screen centering procedure
     speed = self._centeringSpeed
     magnitude = heading.get_magnitude()
     if magnitude<120:
         pass
     elif magnitude<150:
         speed = speed*3
     elif magnitude<200:
         speed = speed*5
     elif magnitude>=250:
         speed = speed*6                        
     
     heading.normalize()
     distance = time_passed * speed
     movement = heading * distance
     x = movement.get_x()
     y = movement.get_y()
     self.topleft = (self.topleft[0]+x,self.topleft[1]+y)
Ejemplo n.º 3
0
 def hasFreeSightOn(self, sprite):
     """Check if the target sprite is in sight of the current character
     @sprite: the sprite to be tested.
     @return: True if the target sprite is in sight; False otherwise.
     """
     # BBB: check if this can be enanched someway; the use of 5 pixel is ugly and imperfect
     to_target = Vector2.from_points(self.position, sprite.position)
     magnitude = to_target.get_magnitude()
     # 1 - False if sprite position is outside the character sight
     if self.sightRange<magnitude:
         return False
     # 2 - Now I need to get the line sight on the target
     to_target.normalize()
     magnitude_portion = 5
     visual_obstacles = self.currentLevel['visual_obstacles']
     screen_position = self.toScreenCoordinate()
     while magnitude>0:
         for obstacle in visual_obstacles:
             temp_v = (to_target*magnitude).as_tuple()
             temp_pos = screen_position[0]+temp_v[0], screen_position[1]+temp_v[1]
             if obstacle.collide_rect.collidepoint(temp_pos):
                 logging.debug("%s can't see %s due to the presence of %s" % (self, sprite, obstacle))
                 return False
         magnitude-=magnitude_portion
     return True
Ejemplo n.º 4
0
 def getHeadingTo(self, target):
     """Return the heading to a given object or position.
     Object must have a "position" attribute or be a position tuple itself.
     """
     if hasattr(target, 'position'):
         position = target.position
     else:
         position = target
     heading = Vector2.from_points(self.position, position)
     return heading.normalize()
Ejemplo n.º 5
0
    def update(self, time_passed):
        """Update method of pygame Sprite class.
        Overrided the one in Character main class because we need to handle user controls here.
        """
        GameSprite.update(self, time_passed)
        if cblocals.global_lastMouseLeftClickPosition or cblocals.global_lastMouseRightClickPosition:
            self.stopThinking()
        
        if self._brain.active_state and self._brain.active_state.name!="controlled":
            return Character.update(self, time_passed)
        
        pressed_keys = pygame.key.get_pressed()
        # update stealth level
        if pressed_keys[K_LSHIFT] and self.canStealthAgain() and not self.stealth:
            self.stealth = True
        elif not pressed_keys[K_LSHIFT] and self.stealth:
            self.stealth = False
        
        # Check for mouse actions setted
        if cblocals.global_lastMouseLeftClickPosition:
            self.navPoint.set(self.currentLevel.transformToLevelCoordinate(cblocals.global_lastMouseLeftClickPosition))
            cblocals.global_lastMouseLeftClickPosition = ()
        if cblocals.global_lastMouseRightClickPosition and not self.isAttacking():
            attackHeading = Vector2.from_points(self.position, self.currentLevel.transformToLevelCoordinate(cblocals.global_lastMouseRightClickPosition))
            attackHeading.normalize()
            cblocals.global_lastMouseRightClickPosition = ()
            # Right click on a distant enemy will move the hero towards him...
            if self.seeking:
                # enable the hero brain
                enemy = self.seeking
                print "Seeking %s" % enemy.name
                self.enemyTarget = enemy
                self._brain.setState("hunting")
            # ...or attack (even if moving)...
            else:
                self.setAttackState(attackHeading)

        if pygame.key.get_pressed()[K_z] and not self.stealth:
            self._brain.setState("retreat")

        if self.navPoint:
            self.moveBasedOnNavPoint(time_passed)
        
        if self._attackDirection:
            self.updateAttackState(time_passed)
Ejemplo n.º 6
0
    def moveBasedOnNavPoint(self, time_passed, destination=None, relative=False):
        """Main method for move character using navPoint infos.
        If a destination is not specified, then the current character navPoint is used.
        @destination: can be None (navPoint will be taken), a point or a Vector2 instance
        @relative: destination is a relative offset from the character position
        """
        # TODO: the current collision checking is broken: a too fast character can pass over an obstacle
        if not destination:
            destination = self.navPoint.get()
            if not destination:
                return
        else:
            if type(destination)==tuple and relative:
                ox, oy = destination
                cx, cy = self.position
                destination = (cx+ox, cy+oy)
            self.navPoint.set(destination)
            destination = self.navPoint.get()
        self.heading = Vector2.from_points(self.position, destination)
        magnitude = self.heading.get_magnitude()
        self.heading.normalize()

        distance = time_passed * self.speed
        # I don't wanna move over the destination!
        if distance>magnitude:
            distance = magnitude
        else:
            # I don't check for a new direction if I'm only fixing the last step distance
            direction = self._generateDirectionFromHeading(self.heading)
            self._checkDirectionChange(direction)

        movement = self.heading * distance
        self._updateStepTime(time_passed)
        x = movement.get_x()
        y = movement.get_y()
        collision = self.checkCollision(x, y)
        if not collision:
            self.move(x, y)
            if self.isNearTo(self.navPoint.as_tuple()):
                self.navPoint.next()
        else:
            #self.navPoint.reroute()
            self.navPoint.reset()
Ejemplo n.º 7
0
    def adjustStealthIndexFromPosition(cls, rogueStealthIndex, rogue, prey):
        """Modify a passed stealthIndex of a rogue character checking also:
        1) the distance between rogue and prey
        2) the facing direction of the prey.
        
        The idea is that the rogue has good bonus if he's arriving from behind the prey.
        He gets no bonus if is arriving from beside the prey.
        Finally he get some malus if is arriving in front of the prey.
        
        Is also impossible that the prey didn't identify the hidden rogue if he's
        very near and directly in front of him!
        """
        distance = rogue.v.get_distance_to(prey.v)
        preySight = int(prey.sightRange * prey.getPreySightRangeReductionFactor())
        modifier = 1.

        if distance<preySight/5:
            modifier+=.2                    # malus 20%
        elif distance<preySight/3:
            modifier+=.15                   # malus 15%
        elif distance<preySight/3*2:
            modifier+=.10                   # malus 10%
        
        # The rogue has malus if the prey is watching it: +25% (angle >=-30° and <=+30°)
        # The rogue has bonus if the prey is watching in the other direction: -20% (angle <=-150° and >=+150°)
        prey_to_rogue = Vector2.from_points(prey.position, rogue.position).normalize()
        angle_between = prey.heading.angle_between(prey_to_rogue)
        logging.debug("Prey heading: %s - Prey to rogue: %s - Angle: %s" % (prey.heading, prey_to_rogue, angle_between))
        
        if angle_between>=-30 and angle_between<=30:
            modifier+=.25
        elif angle_between<=-150 or angle_between>=150:
            modifier-=.2
        
        rogueStealthIndex = rogueStealthIndex*modifier
        
        if rogueStealthIndex>.95:
            rogueStealthIndex=.95
        elif rogueStealthIndex<.2:
            rogueStealthIndex=.2
        return rogueStealthIndex
Ejemplo n.º 8
0
 def moveBasedOnRetreatAction(self, time_passed):
     """See moveBasedOnRetreatAction of Character class.
     The playing character movement is based on the mouse position on the screen, but you can't retreat moving
     in front.
     """
     cpos = self.toScreenCoordinate()
     mpos = pygame.mouse.get_pos()
     toMouse = Vector2.from_points(cpos,mpos)
     toMouse.normalize()
     rheading = -toMouse
     
     heading = self.heading
     angle_between = heading.angle_between(rheading)
     if angle_between>=-30 and angle_between<=30:
         return
     
     distance = time_passed * self.speed
     movement = rheading * distance
     x = movement.get_x()
     y = movement.get_y()
     if not self.checkCollision(x, y) and self.checkValidCoord(x, y):
         self.move(x, y)
Ejemplo n.º 9
0
 def distanceFrom(self, sprite):
     """Return the distance between this sprite and another one"""
     return Vector2.from_points(self.position,sprite.position).get_magnitude()