0
\$\begingroup\$

I am currently writing a top down man vs robot shooter. The game works now, but if I have a decent sized level it runs slowly when you are being chased by robots. While just roaming around it can go at full 60 fps, but with the robots on your tail it slows down immensely.

I have traced the source of the problem to the part of the code where the robots decide whether or not their sight of the player is obstructed by a wall. This code works by seeing if the line segment formed by the center of the robot and the center of the player intersects a wall.

I have written this algorithm to see if a line segment goes through a rect:

for wall in wall_rects:

    #is wall between the robot and player:
    if man.rect.centerx < wall.rect.centerx < self.rect.centerx or\
    man.rect.centerx > wall.rect.centerx > self.rect.centerx or\
    man.rect.centery < wall.rect.centery < self.rect.centery or\
    man.rect.centery > wall.rect.centery > self.rect.centery:
        r = [] #are the corners above or below the line between the man and robot
        r.append((self.rect.centerx-man.rect.centerx)*(wall.rect.top-man.rect.centery)\
          - (self.rect.centery-man.rect.centery)*(wall.rect.left-man.rect.centerx))
        r.append((self.rect.centerx-man.rect.centerx)*(wall.rect.top-man.rect.centery)\
          - (self.rect.centery-man.rect.centery)*(wall.rect.right-man.rect.centerx))
        r.append((self.rect.centerx-man.rect.centerx)*(wall.rect.bottom-man.rect.centery)\
          - (self.rect.centery-man.rect.centery)*(wall.rect.left-man.rect.centerx))
        r.append((self.rect.centerx-man.rect.centerx)*(wall.rect.bottom-man.rect.centery)\
          - (self.rect.centery-man.rect.centery)*(wall.rect.right-man.rect.centerx))
        if not(max(r) < 0 or min(r) > 0):
            #if all of the corners are not on the same
            #side then the line does go through the wall
            break
    else: #IT SEES YOU! >:D

however it is not near fast enough to check all 450 some walls there are in my test level. My difficulty is either making it faster or having it find out which walls are worth checking for sight-line blockage. I tried checking the distance between the wall and robot to see if it is closer to the robot than the man, which slowed it down more.

Any suggestions?

EDIT:
I forgot to mention that in this game, while the walls are placed on a grid with 25X25 pixel squares, you are free to move any distance in any direction, and so are the robots, but it looks like the suggestions below will still likely help.

\$\endgroup\$
0

2 Answers 2

1
\$\begingroup\$

You can reduce the number of walls you have to check by using a spatial hash (or spatial partition). It's a data structure that answers the question, “what objects are in this region?” In your case the objects are walls. You'll only have to check the regions that the line goes through instead of all walls. A grid is one form of spatial hash but there are others too.

This article has at the end a section on intersecting a line with a spatial hash. As nihohit mentions, you can use a line drawing algorithm.

However, the next question is, are you doing this for each robot? If you are, you're going through all the walls multiple times. Since the player's location is the same each time you can use a smarter algorithm. Instead of looking at each enemy and asking whether the player is visible, ask once, which enemies are visible from the player.

The roguelike community has collected some resources about the field of view problem.

\$\endgroup\$
2
  • \$\begingroup\$ Spatial partition is what I would definitely use for this case, simple and effective. \$\endgroup\$
    – DogDog
    Apr 19, 2012 at 15:45
  • \$\begingroup\$ Yes I am doing this individually for each robot right now because eventually I want the robots to have different sight regions, but good idea. I already have a grid which the robots use to avoid crashing into walls, and I think I will use to it speed up checking like you mentioned above. Great idea. Very good to know. \$\endgroup\$
    – Sudo Bash
    Apr 19, 2012 at 16:20
0
\$\begingroup\$

it seems you have some kind of 2d grid going there - maybe Bresenham's line algorithm will solve the problem, when run on the grid.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Just a note: Bresenham draws 8-connected lines, thus "skips" valid grid cells; a line of sight would be a 4-connected line. \$\endgroup\$ Apr 19, 2012 at 9:05
  • \$\begingroup\$ What is the difference between 8-connected and 4-connected? \$\endgroup\$
    – Sudo Bash
    Apr 19, 2012 at 16:13
  • \$\begingroup\$ Oh, nevermind. I found a 4-connected line algorithm here link \$\endgroup\$
    – Sudo Bash
    Apr 19, 2012 at 20:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .