I been using pygame to try to color a box I choose in some grid. The box is supposed to be colored when I hover over it with my mouse and press ‘s’ on the keyboard. Only thing is that the wrong box is being colored in the grid. It is always the first box which is being colored and not the one I pick.
The box I choose is supposed to turn green when I hover over it and press ‘s’.
Can someone look at my code to see if I have an obvious mistake? I can’t seem to figure out what’s wrong after trying to debug it for hours.
The class node represents the boxes and the grid class represents the drawn grid that holds the nodes.
This is my main.py that controls the flow of my code:
import sys
from grid import *
# Window details
height = 700
width = 700
window = pygame.display.set_mode((height, width))
window.fill(white)
pygame.display.set_caption("Path Finding Visualizer")
# Get the clicked position of the mouse to find the node
def get_clicked_position(mouse_position, rows):
node_margin = width // rows
x, y = mouse_position
row = x // node_margin
column = y // node_margin
return row, column
# Code is controlled from here
def main(window, width):
# Initialize pygame
pygame.init()
# Create specific sized grid
amount_of_rows = 20
amount_of_columns = 20
grid = Grid(amount_of_rows, amount_of_columns, window, width)
grid_array = grid.draw_grid()
# To keep the window running
run = True
while run == True:
for event in pygame.event.get():
# User closes the window or something, end right away
if event.type == pygame.QUIT:
run = False
# If a button is pressed
if event.type == pygame.KEYDOWN:
# User hovers over square and clicks 's' on the keyboard
if event.key == pygame.K_s:
mouse_position = pygame.mouse.get_pos()
clicked_row, clicked_column = get_clicked_position(mouse_position, amount_of_rows)
node = grid_array[clicked_row][clicked_column]
node.set_start()
grid_array[clicked_row][clicked_column] = node
print(str(node.x) + ', ' + str(node.y))
# Update the grid with any new events
grid.update_grid(grid_array)
print("Set start")
# User hovers over square and clicks 'e' on the keyboard
if event.key == pygame.K_e:
mouse_position = pygame.mouse.get_pos()
clicked_row, clicked_column = get_clicked_position(mouse_position, amount_of_rows)
node = grid_array[clicked_row][clicked_column]
node.set_end()
grid_array[clicked_row][clicked_column] = node
# Update the grid with any new events
grid.update_grid(grid_array)
print("Set end")
#pygame.display.update()
main(window, width)
This is my grid.py:
from node import *
class Grid:
def __init__(self, number_of_rows, number_of_columns, window, window_width):
self.number_of_rows = number_of_rows
self.number_of_columns = number_of_columns
self.window = window
self.window_width = window_width
# Initialize an empty list to represent the grid and then add nodes to it
self.grid_list = []
# Initializes the grid by drawing it onto the screen and returns the grid's array that holds all of the nodes
def draw_grid(self):
self.draw_squares()
self.draw_lines(1)
pygame.display.update()
return self.grid_list
# Draw squares onto the screen
def draw_squares(self):
for row in self.grid_list:
for node in row:
pygame.draw.rect(self.window, node.color, (node.x, node.y, node.node_margin, node.node_margin))
# Draw the lines onto the screen
def draw_lines(self, initial_grid=None):
# Initialize the node's margin by doing integer division between the size of the window and amount of rows
node_margin = self.window_width // self.number_of_rows
# Kind of complicated but pretty much if the grid_array is empty then intialize it with this, else update the grid
if(initial_grid != None):
for x in range(self.number_of_rows):
# For every row, a list will be appended to grid and add all of the columns and its respective nodes
self.grid_list.append([])
# Draw the rows onto the window
pygame.draw.line(self.window, grey, (0, x * node_margin), (self.window_width, x * node_margin))
for y in range(self.number_of_columns):
# Initialize the node and make all nodes white. Then append to the row
node = Node(white, x, y, node_margin, self.window_width)
self.grid_list[x].append(node)
# Draw the columns onto the window
pygame.draw.line(self.window, grey, (y * node_margin, 0), (y * node_margin, self.window_width))
# Just draws the lines to update the grid since the grid is already initialized
else:
for x in range(self.number_of_rows):
# Draw the rows onto the window
pygame.draw.line(self.window, grey, (0, x * node_margin), (self.window_width, x * node_margin))
for y in range(self.number_of_columns):
# Draw the columns onto the window
pygame.draw.line(self.window, grey, (y * node_margin, 0), (y * node_margin, self.window_width))
# Every time an event occurs the grid will update the nodes that have been changed
def update_grid(self, new_grid_list):
self.grid_list = new_grid_list
self.draw_squares()
self.draw_lines()
pygame.display.update()
This is my node.py:
import pygame
# Board and path colors
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
yellow = (255, 255, 0)
white = (255, 255, 255)
black = (0, 0, 0)
purple = (128, 0, 128)
orange = (255, 165, 0)
grey = (128, 128, 128)
turquoise = (64, 224, 208)
# These are the squares that will be marked in the grid
class Node:
def __init__(self, color, row, column, node_margin, board_width):
self.color = color
self.row = row
self.column = column
self.board_width = board_width
self.x = row * board_width
self.y = column * board_width
self.node_margin = node_margin
# Returns position of node
def get_position(self):
return row, column
# Checks if the node is the starting node for the search algorithm
def is_start(self):
if self.color == green:
return True
else:
return False
# Checks if the node is the ending node for the search algorithm
def is_end(self):
if self.color == red:
return True
else:
return False
# Resets the node to white to show nothing has happened to it
def reset_node(self):
self.color = white
# Sets starting node to green
def set_start(self):
self.color = green
# Sets starting node to red
def set_end(self):
self.color = red
Advertisement
Answer
You have to multiply row respectively column by node_margin rather than board_width in the constructor of Node:
class Node:
def __init__(self, color, row, column, node_margin, board_width):
# [...]
self.x = row * node_margin
self.y = column * node_margin