Skip to main content
added 4 characters in body
Source Link
DyingIsFun
  • 1.3k
  • 1
  • 17
  • 41

How to implement enemy that follows wall boundary-following behavior?

        if self.state == "patrolling":

            # sprite travelling right
            if self.vel == vec(1, 0):
                if not tools.point_collides_any_wall(self.game, self.bottomleft) and not tools.point_collides_any_wall(self.game, self.bottomright):
                    # reposition sprite so itsit's touching the wall
                    self.bounding_rect.bottomleft = self.platform.rect.topright
                    # change velocity
                    self.vel = vec(0, 1)

                if tools.point_collides_any_wall(self.game, self.bottomleft) and tools.point_collides_any_wall(self.game, self.bottomright) and tools.point_collides_any_wall(self.game, self.topright):
                    # change velocity
                    self.vel = vec(0, -1)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midright_raycast)][0]

            # sprite travelling left
            elif self.vel == vec(-1, 0):
                if not tools.point_collides_any_wall(self.game, self.topleft) and not tools.point_collides_any_wall(self.game, self.topright):
                    # reposition sprite so itsit's touching the wall
                    self.bounding_rect.topright = self.platform.rect.bottomleft
                    # change velocity
                    self.vel = vec(0, -1)

                if tools.point_collides_any_wall(self.game, self.topleft) and tools.point_collides_any_wall(self.game, self.topright) and tools.point_collides_any_wall(self.game, self.bottomleft):
                    # change velocity
                    self.vel = vec(0, 1)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midleft_raycast)][0]


            # sprite travelling up
            elif self.vel == vec(0, -1):
                if not tools.point_collides_any_wall(self.game, self.topright) and not tools.point_collides_any_wall(self.game, self.bottomright):
                    # reposition sprite so itsit's touching the wall
                    self.bounding_rect.bottomright = self.platform.rect.topleft
                    # change velocity
                    self.vel = vec(1, 0)

                if tools.point_collides_any_wall(self.game, self.topleft) and tools.point_collides_any_wall(self.game, self.topright) and tools.point_collides_any_wall(self.game, self.bottomright):
                    # change velocity
                    self.vel = vec(-1, 0)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midtop_raycast)][0]


            # sprite travelling down
            elif self.vel == vec(0, 1):
                if not tools.point_collides_any_wall(self.game, self.topleft) and not tools.point_collides_any_wall(self.game, self.bottomleft):
                    # reposition sprite so itsit's touching the wall
                    self.bounding_rect.topleft = self.platform.rect.bottomright
                    # change velocity
                    self.vel = vec(-1, 0)

                if tools.point_collides_any_wall(self.game, self.topleft) and tools.point_collides_any_wall(self.game, self.bottomleft) and tools.point_collides_any_wall(self.game, self.bottomright):
                    # change velocity
                    self.vel = vec(1, 0)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midbottom_raycast)][0]

            self.pos = self.bounding_rect.center

How to implement enemy that follows wall boundary

        if self.state == "patrolling":

            # sprite travelling right
            if self.vel == vec(1, 0):
                if not tools.point_collides_any_wall(self.game, self.bottomleft) and not tools.point_collides_any_wall(self.game, self.bottomright):
                    # reposition sprite so its touching the wall
                    self.bounding_rect.bottomleft = self.platform.rect.topright
                    # change velocity
                    self.vel = vec(0, 1)

                if tools.point_collides_any_wall(self.game, self.bottomleft) and tools.point_collides_any_wall(self.game, self.bottomright) and tools.point_collides_any_wall(self.game, self.topright):
                    # change velocity
                    self.vel = vec(0, -1)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midright_raycast)][0]

            # sprite travelling left
            elif self.vel == vec(-1, 0):
                if not tools.point_collides_any_wall(self.game, self.topleft) and not tools.point_collides_any_wall(self.game, self.topright):
                    # reposition sprite so its touching the wall
                    self.bounding_rect.topright = self.platform.rect.bottomleft
                    # change velocity
                    self.vel = vec(0, -1)

                if tools.point_collides_any_wall(self.game, self.topleft) and tools.point_collides_any_wall(self.game, self.topright) and tools.point_collides_any_wall(self.game, self.bottomleft):
                    # change velocity
                    self.vel = vec(0, 1)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midleft_raycast)][0]


            # sprite travelling up
            elif self.vel == vec(0, -1):
                if not tools.point_collides_any_wall(self.game, self.topright) and not tools.point_collides_any_wall(self.game, self.bottomright):
                    # reposition sprite so its touching the wall
                    self.bounding_rect.bottomright = self.platform.rect.topleft
                    # change velocity
                    self.vel = vec(1, 0)

                if tools.point_collides_any_wall(self.game, self.topleft) and tools.point_collides_any_wall(self.game, self.topright) and tools.point_collides_any_wall(self.game, self.bottomright):
                    # change velocity
                    self.vel = vec(-1, 0)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midtop_raycast)][0]


            # sprite travelling down
            elif self.vel == vec(0, 1):
                if not tools.point_collides_any_wall(self.game, self.topleft) and not tools.point_collides_any_wall(self.game, self.bottomleft):
                    # reposition sprite so its touching the wall
                    self.bounding_rect.topleft = self.platform.rect.bottomright
                    # change velocity
                    self.vel = vec(-1, 0)

                if tools.point_collides_any_wall(self.game, self.topleft) and tools.point_collides_any_wall(self.game, self.bottomleft) and tools.point_collides_any_wall(self.game, self.bottomright):
                    # change velocity
                    self.vel = vec(1, 0)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midbottom_raycast)][0]

            self.pos = self.bounding_rect.center

How to implement wall-following behavior?

        if self.state == "patrolling":

            # sprite travelling right
            if self.vel == vec(1, 0):
                if not tools.point_collides_any_wall(self.game, self.bottomleft) and not tools.point_collides_any_wall(self.game, self.bottomright):
                    # reposition sprite so it's touching the wall
                    self.bounding_rect.bottomleft = self.platform.rect.topright
                    # change velocity
                    self.vel = vec(0, 1)

                if tools.point_collides_any_wall(self.game, self.bottomleft) and tools.point_collides_any_wall(self.game, self.bottomright) and tools.point_collides_any_wall(self.game, self.topright):
                    # change velocity
                    self.vel = vec(0, -1)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midright_raycast)][0]

            # sprite travelling left
            elif self.vel == vec(-1, 0):
                if not tools.point_collides_any_wall(self.game, self.topleft) and not tools.point_collides_any_wall(self.game, self.topright):
                    # reposition sprite so it's touching the wall
                    self.bounding_rect.topright = self.platform.rect.bottomleft
                    # change velocity
                    self.vel = vec(0, -1)

                if tools.point_collides_any_wall(self.game, self.topleft) and tools.point_collides_any_wall(self.game, self.topright) and tools.point_collides_any_wall(self.game, self.bottomleft):
                    # change velocity
                    self.vel = vec(0, 1)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midleft_raycast)][0]


            # sprite travelling up
            elif self.vel == vec(0, -1):
                if not tools.point_collides_any_wall(self.game, self.topright) and not tools.point_collides_any_wall(self.game, self.bottomright):
                    # reposition sprite so it's touching the wall
                    self.bounding_rect.bottomright = self.platform.rect.topleft
                    # change velocity
                    self.vel = vec(1, 0)

                if tools.point_collides_any_wall(self.game, self.topleft) and tools.point_collides_any_wall(self.game, self.topright) and tools.point_collides_any_wall(self.game, self.bottomright):
                    # change velocity
                    self.vel = vec(-1, 0)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midtop_raycast)][0]


            # sprite travelling down
            elif self.vel == vec(0, 1):
                if not tools.point_collides_any_wall(self.game, self.topleft) and not tools.point_collides_any_wall(self.game, self.bottomleft):
                    # reposition sprite so it's touching the wall
                    self.bounding_rect.topleft = self.platform.rect.bottomright
                    # change velocity
                    self.vel = vec(-1, 0)

                if tools.point_collides_any_wall(self.game, self.topleft) and tools.point_collides_any_wall(self.game, self.bottomleft) and tools.point_collides_any_wall(self.game, self.bottomright):
                    # change velocity
                    self.vel = vec(1, 0)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midbottom_raycast)][0]

            self.pos = self.bounding_rect.center
Source Link
DyingIsFun
  • 1.3k
  • 1
  • 17
  • 41

How to implement enemy that follows wall boundary

I am working on an action platformer and am trying to implement an enemy with simple wall-following behavior. I want the enemy to follow the boundary of whatever connected constellation of walls it is standing on, whether it's a freestanding platform or a connected room.

The enemy has a position, a velocity, a bounding rectangle, various points on the bounding rectangle (topleft, bottomright, etc.), and various points raycasted a few pixels outside the bounding rectangle (midleft_raycast, bottom_raycast, etc.). The walls are rectangular and have the usual attributes of a rectangle.

Currently I am implementing the wall-following behavior in the following way. If the enemy has a positive horizontal velocity, I check whether various corners intersect or don't intersect a wall. For example, if the bottomleft and bottomright no longer intersect a wall, I know the enemy has moved over a gap and his velocity needs to be adjusted for him to move downward. I realign his bottomleft corner to the wall's topright corner and change his velocity to a positive vertical velocity. I do something similar for the other cases.

Here is an illustration:

![enter image description here

And here is my code:

        if self.state == "patrolling":

            # sprite travelling right
            if self.vel == vec(1, 0):
                if not tools.point_collides_any_wall(self.game, self.bottomleft) and not tools.point_collides_any_wall(self.game, self.bottomright):
                    # reposition sprite so its touching the wall
                    self.bounding_rect.bottomleft = self.platform.rect.topright
                    # change velocity
                    self.vel = vec(0, 1)

                if tools.point_collides_any_wall(self.game, self.bottomleft) and tools.point_collides_any_wall(self.game, self.bottomright) and tools.point_collides_any_wall(self.game, self.topright):
                    # change velocity
                    self.vel = vec(0, -1)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midright_raycast)][0]

            # sprite travelling left
            elif self.vel == vec(-1, 0):
                if not tools.point_collides_any_wall(self.game, self.topleft) and not tools.point_collides_any_wall(self.game, self.topright):
                    # reposition sprite so its touching the wall
                    self.bounding_rect.topright = self.platform.rect.bottomleft
                    # change velocity
                    self.vel = vec(0, -1)

                if tools.point_collides_any_wall(self.game, self.topleft) and tools.point_collides_any_wall(self.game, self.topright) and tools.point_collides_any_wall(self.game, self.bottomleft):
                    # change velocity
                    self.vel = vec(0, 1)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midleft_raycast)][0]


            # sprite travelling up
            elif self.vel == vec(0, -1):
                if not tools.point_collides_any_wall(self.game, self.topright) and not tools.point_collides_any_wall(self.game, self.bottomright):
                    # reposition sprite so its touching the wall
                    self.bounding_rect.bottomright = self.platform.rect.topleft
                    # change velocity
                    self.vel = vec(1, 0)

                if tools.point_collides_any_wall(self.game, self.topleft) and tools.point_collides_any_wall(self.game, self.topright) and tools.point_collides_any_wall(self.game, self.bottomright):
                    # change velocity
                    self.vel = vec(-1, 0)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midtop_raycast)][0]


            # sprite travelling down
            elif self.vel == vec(0, 1):
                if not tools.point_collides_any_wall(self.game, self.topleft) and not tools.point_collides_any_wall(self.game, self.bottomleft):
                    # reposition sprite so its touching the wall
                    self.bounding_rect.topleft = self.platform.rect.bottomright
                    # change velocity
                    self.vel = vec(-1, 0)

                if tools.point_collides_any_wall(self.game, self.topleft) and tools.point_collides_any_wall(self.game, self.bottomleft) and tools.point_collides_any_wall(self.game, self.bottomright):
                    # change velocity
                    self.vel = vec(1, 0)
                    # set platform
                    self.platform = [wall for wall in self.game.walls if wall.rect.collidepoint(self.midbottom_raycast)][0]

            self.pos = self.bounding_rect.center

This method works, but I can't help but think that there is a more elegant way. For example, what if I wanted the enemy to move in the opposite direction. I would need to write another chunk of (symmetric) code for this.

So my question is: Are there other, simpler, or more general ways to implement wall-following behavior?