Collision for array of pathfinding zombies to array of blocks

Relevant Background Information

I'm an eleventh grade high school computer science student in Canada. I'm doing pretty well in the course currently, I have a 96 in the course currently. We're working on our culminating 2D game these final 2 months in our semester. I'm using Object-Oriented Python and Pygame to develop my game.

The game I'm creating is a top down 2D zombie shooter. Very simple, kind of like a 2D versions of the Dead ops arcade game mode in the original Call Of Duty: Black ops.

I currently have a player, he moves around, rotates the mouse and shoot's bullet's in the direction of the mouse (Using a vector class I got online). I also use strings to design my levels, the level loader loads the strings and creates an array of blocks.

I have an array of zombie's that spawn and uses basic (non-vector) (logical) path-finding to get to the player. (Example: If the player is to the right of the zombie, zombie goes right).

Also an array of blocks. Now my collision works for the player. I use basic AABB Collision with the player to all the blocks and act if a collision is detected.

My blocks are in pygame.Rects and my zombie's and player both have collision rectangles that are half the size of their actual rectangles.

What I'm trying to do

I'm trying to keep my zombie's pathfinding it's way to the player, but have the zombies not go right through my blocks. So a basic collision detection algorithm, that goes after my pathfinding. Preventing the zombie's from being away from the blocks.

What I've tried

I tried applying the concept's explained online, I've also tried applying the same collision strategy that I've used with my player. I've tried double for loops ( for each block and each zombie ) that does an AABB check for each zombie wall but it just make's them kind of glitch through the wall.

I'm gonna put some code under. If anyone can give me diagrammed explanations or some code to how I would do this. I'll try and give as much relevant code as I can in the bottom to provide a fundamental understanding of my thinking processes in terms of my code development. Also tips given for the code under would be nice as well.

Relevant code

Player Collision Code (level class, player instance passed in):

""" CHECK PLAYER COLLISION WITH WALLS """
for i in range(1, 5): # run a for loop for all player walls
player.setCollisionBound(i, False) # default all wall collisions to be false
for block in range(len(self.Rects)): # run a for loop for all existing blocks
for wall in range(1, 5): # run a for loop for all walls
if player.getWall(wall).colliderect(self.Rects[block]): # Check if the current wall collided with the current block
player.setCollisionBound(wall, True)


Zombie path-finding code (Zombie class):

        self.setD(0, 0) # Start Displacement at 0
if self.Rect.colliderect(playerRect) != True: # See if the zombie is not overlapping the player
if self.topWallCollided == False and self.bottomWallCollided == False and self.leftWallCollided == False and self.rightWallCollided == False: # check if theres no collisions
if self.x > playerRect.center[0] + 2: # see if zombie is to the right of player, add 2 to end stutter area
self.setDX(-self.getVelocity())
if self.x < playerRect.center[0] - 2: # see if zombie is to the left of player, subtract 2 to end stutter area
self.setDX(self.getVelocity())
if self.y > playerRect.center[1] + 2: # see if player is on top of zombie, add 2 to end stutter area
self.setDY(-self.getVelocity())
if self.y < playerRect.center[1] - 2: # see if player is under zombie , subtract 2 to end stutter area
self.setDY(self.getVelocity())


Zombie Collision Detection Code (level class, zombie manager passed in):

for zombie in range(len(self.zombieManager.getZombies())): # run a for loop for all zombies
if self.zombieManager.getZombies()[zombie].getLifeStatus() == True: # check if the zombie is alive before you do anything with it
for block in range(len(self.Rects)): # run a for loop for all blocks
for wall in range(1, 5): # run a for loop for all walls
if self.zombieManager.getZombies()[zombie].getBlockCollisionWall(wall).colliderect(self.Rects[block]) == True: # check if the current zombie's current wall collided with the current block
self.zombieManager.getZombies()[zombie].setCollisionBound(wall, True) # set the current zombie's current wall's collision to be true


Zombie Collision Action Code (zombie class) :

if self.leftWallCollided == True:
self.setD(self.getVelocity(), 0)
if self.rightWallCollided == True:
self.setD(-self.getVelocity(), 0)
if self.topWallCollided == True:
self.setD(0, self.getVelocity())
if self.bottomWallCollided == True:
self.setD(0, -self.getVelocity())


Zombie - Zombie Collision code (zombie manager class, works, so they don't overlap each other):

for zombie in range(self.zombies_am): # Update for all Zombies
if self.zombies[zombie].getLifeStatus() == True: # Check if the Zombie is currently Alive before you do any relevant Data with it
self.zombies[zombie].update(playerRect) # Update Zombie Data, give relevant data
for i in range(self.zombies_am): # Check rect of all zombies
if self.zombies[i].getLifeStatus() == True: # Check if the Zombie is currently Alive before you do any relevant Data with it
if self.zombies[zombie].getWall(1).colliderect(self.zombies[i].getRect()) == True: # If the left wall of the first-current zombie (zombie) collides with any of the other zombies (i)
self.zombies[zombie].translate(self.zombies[zombie].getVelocity(), 0) # Translate the zombie to the right by it's own velocity
if self.zombies[zombie].getWall(2).colliderect(self.zombies[i].getRect()) == True: # If the right wall of the first-current zombie (zombie) collides with any of the other zombies (i)
self.zombies[zombie].translate(-self.zombies[zombie].getVelocity(), 0) # Translate the zombie to the left by it's own velocity
if self.zombies[zombie].getWall(3).colliderect(self.zombies[i].getRect()) == True: # If the top wall of the first-current zombie (zombie) collides with any of the other zombies (i)
self.zombies[zombie].translate(0, self.zombies[zombie].getVelocity()) # Translate the zombie to the bottom by it's own velocity
if self.zombies[zombie].getWall(4).colliderect(self.zombies[i].getRect()) == True: # If the bottom wall of the first-current zombie (zombie) collies with any of the other zombies (i)
self.zombies[zombie].translate(0, -self.zombies[zombie].getVelocity()) # Translate the zombie to the top by it's own velocity