Reputation: 5605
My goal is to make a module that will make a grid on a pygame canvas and allow you to highlight boxes by their x and y coords.
Here is a simple example usage.
from grid import Grid
g = Grid(100, 100, 10) # width and height in cells, cell width in pixels
g.highlightBox(2, 2, (0, 255, 0)) # cell x and y, rgb color tuple
g.clearGrid()
Here is the code I have so far. The problem is, I need to have an event loop to keep the window open and make the close button functional, but I also need to allow the other functions to draw to the screen.
import pygame
import sys
class Grid:
colors = {"blue":(0, 0, 255), "red":(255, 0, 0), "green":(0, 255, 0), "black":(0, 0, 0), "white":(255, 255, 255)}
def __init__(self, width, height, cellSize, borderWidth=1):
self.cellSize = cellSize
self.borderWidth = borderWidth
self.width = width * (cellSize + borderWidth)
self.height = height * (cellSize + borderWidth)
self.screen = pygame.display.set_mode((self.width, self.height))
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
def clearGrid(self):
pass
def highlightBox(self, x, y, color):
xx = x * (self.cellSize + self.borderWidth)
yy = y * (self.cellSize + self.borderWidth)
pygame.draw.rect(self.screen, color, (xx, yy, self.cellSize, self.cellSize), 0)
When I run the first sample, the code will be stuck in the loop, not allowing me to run the highlightBox
function until the loop is done(the exit button is pressed).
Upvotes: 1
Views: 1736
Reputation: 5605
I got a working version with the multiprocessing library and pipes. It seems kinda unpythonic but it will work for this project.
import pygame
import sys
from multiprocessing import Process, Pipe
class Grid:
colors = {"blue":(0, 0, 255), "red":(255, 0, 0), "green":(0, 255, 0), "black":(0, 0, 0), "white":(255, 255, 255)}
def __init__(self, width, height, cellSize, borderWidth=1):
self.cellSize = cellSize
self.borderWidth = borderWidth
self.width = width * (cellSize + borderWidth)
self.height = height * (cellSize + borderWidth)
#pygame.draw.rect(self.screen, todo[1], (todo[2], todo[3], todo[4], todo[5]), 0)
self.parent_conn, self.child_conn = Pipe()
self.p = Process(target=self.mainLoop, args=(self.child_conn, self.width, self.height,))
self.p.start()
def close():
self.p.join()
def clearGrid(self):
pass
def highlightBox(self, x, y, color):
xx = x * (self.cellSize + self.borderWidth)
yy = y * (self.cellSize + self.borderWidth)
self.parent_conn.send(["box", color, xx, yy, self.cellSize, self.cellSize])
def mainLoop(self, conn, width, height):
#make window
screen = pygame.display.set_mode((self.width, self.height))
running = True
while running:
# is there data to read
if conn.poll():
#read all data
todo = conn.recv()
print("Recived " + str(todo))
#do the drawing
if todo[0] == "box":
print("drawing box")
pygame.draw.rect(screen, todo[1], (todo[2], todo[3], todo[4], todo[5]), 0) #color, x, y, width, height
todo = ["none"]
#draw to screen
pygame.display.flip()
#get events
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
Upvotes: 0
Reputation: 465
I think what you need is to disconnect the Grid class from the display of it. You sould make it generate surfaces, that would be printed to the screen Surface by the main game-loop. Your init , highlight_cell, and clear_grid methods could return Surfaces for example, or make a get_surface method that would be called once every game-loop
This would give much more flexibility
Upvotes: 1
Reputation: 31567
For starters, I wouldn't put the game loop inside the initialization function; find some other place for it. To solve this, simply put the code you want to execute in the game loop, next to the code for handling events:
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
# Print your screen in here
# Also do any other stuff that you consider appropriate
Upvotes: 1