Vector2 returning values of zero, making normalising impossible and crashing code

66 Views Asked by At

Here is the specific function, some terms like the .center are appearing white when others appear light blue, so im not too sure if that's a problem, using VSCODE, might be their native colouring or something, the vector2 values for start and end appear as zero when normalise() is removed

    def get_direction(self):
        if self.collision_rects:
            start = pygame.math.Vector2(self.pos)   
            end = pygame.math.Vector2(self.collision_rects[0].center)
            self.direction = (start - end).normalize()
            print(self.direction)
        else:
            self.direction = pygame.math.Vector2(0,0)
            self.path = []

Here is the whole code

import pygame, sys
from pathfinding.core.grid import Grid
from pathfinding.finder.a_star import AStarFinder
from pathfinding.core.diagonal_movement import DiagonalMovement

class Pathfinder:
    
    def __init__(self,matrix):
        #sets up selection icon
        self.matrix = matrix 
        self.grid = Grid(matrix = matrix)
        selectionicon = pygame.image.load('selection.png').convert_alpha()
        self.scaledicon = pygame.transform.scale(selectionicon, (30,30)) 
        self.path = []

        self.Agent = pygame.sprite.GroupSingle(Agent())


    def draw_active_cell(self):
        #gets mouse position
        mouse_pos = pygame.mouse.get_pos()
        row = mouse_pos[1] // 30 
        col = mouse_pos[0] // 30
        current_cell_value = self.matrix[row][col]
        #checks if cell is a viable option
        if current_cell_value == 1:
            rect = pygame.Rect((col * 30 , row * 30),(30,30))
            screen.blit(self.scaledicon,rect)

    def create_path(self):
        
        #start cell
        start_x, start_y = self.Agent.sprite.get_coord()    
        start = self.grid.node(start_x,start_y)

        #end cell
        mouse_pos = pygame.mouse.get_pos()
        end_x = mouse_pos[0] // 30 
        end_y = mouse_pos[1] // 30
        end = self.grid.node(end_x,end_y)

        #pathcreation
        finder = AStarFinder(diagonal_movement = DiagonalMovement.always)
        self.path,_ = finder.find_path(start,end,self.grid)
        self.grid.cleanup()
        self.Agent.sprite.set_path(self.path)

    #draws a path for visualisation
    def draw_path(self):
        if self.path:
            points = []
            for point in self.path:
                x = (point[0] * 30) + 15
                y = (point[1] * 30) + 15
                points.append((x,y))
                pygame.draw.circle(screen,"#11db03",(x,y),2)
            pygame.draw.lines(screen,"#11db03",False,points,5)

    #updates self draw
    def update(self):
        self.draw_active_cell()
        self.draw_path()
        self.Agent.update()
        self.Agent.draw(screen)

class Agent(pygame.sprite.Sprite):
    #creating sprite
    def __init__(self):
        super().__init__()
        image_unscaled = pygame.image.load('agent.png').convert_alpha()
        self.image = pygame.transform.scale(image_unscaled, (30,30))
        self.rect = self.image.get_rect(center = (405,675))

        #movement variables
        self.pos = self.rect.center
        self.speed = 0.5   
        self.direction = pygame.math.Vector2(0,0)

        #path follower
        self.path = []
        self.collision_rects = []
    
    def get_coord(self):
        col = self.rect.centerx // 30
        row = self.rect.centery // 30
        return(col,row)
    
    def set_path(self,path):
        self.path = path
        self.create_collision_rects()
        self.get_direction()

    def create_collision_rects(self):
        if self.path:
            self.collision_rects = []
            for point in self.path:
                x = (point[0] * 30) + 15
                y = (point[1] * 30) + 15
                rect = pygame.Rect((x - 4,y - 4),(8,8))
                self.collision_rects.append(rect)

    def get_direction(self):
        if self.collision_rects:
            start = pygame.math.Vector2(self.pos)   
            end = pygame.math.Vector2(self.collision_rects[0].center)
            self.direction = (start - end).normalize()
            print(self.direction)
        else:
            self.direction = pygame.math.Vector2(0,0)
            self.path = []

    def check_collisions(self):
        if self.collision_rects:
            for rect in self.collision_rects:
                if rect.collidepoint(self.pos):
                    del self.collision_rects[0]
                    self.get_direction()
    
    def update(self):
        self.pos += self.direction * self.speed  
        self.rect.center = self.pos



pygame.init()
screen = pygame.display.set_mode((0,0), pygame.FULLSCREEN)
clock = pygame.time.Clock()
pygame.mouse.set_visible(False)

bg_room1 = pygame.image.load('room1scaled.png').convert()
matrix = [
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
]

pathfinder = Pathfinder(matrix)

#game loop
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit
        if event.type == pygame.MOUSEBUTTONDOWN:
            pathfinder.create_path( )

    #creates background
    screen.blit(bg_room1,(180,0))
    #updates pathfinder function
    pathfinder.update()

    pygame.display.update()
    clock.tick(30)

the function should be giving me the direction to the next node

1

There are 1 best solutions below

2
sloth On

Either check the length of the vector before normalizing it, something like this:

new_direction = (start - end)
if new_direction.length() != 0:
   self.direction = new_direction.normalize()
else:
   self.direction.x = 0
   self.direction.y = 0

or just catch the exception:

try:
    self.direction = (start - end).normalize()
except ValueError:
   self.direction.x = 0
   self.direction.y = 0