Created
November 12, 2011 08:46
-
-
Save osa1/1360259 to your computer and use it in GitHub Desktop.
A simple grid class and some helper functions which I wrote to visualize some algorithms
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import threading | |
import pygame | |
class Grid(object): | |
def __init__(self, size_x, size_y=None): | |
if not size_y: | |
self.size_x = size_x[0] | |
self.size_y = size_y[1] | |
else: | |
self.size_x = size_x | |
self.size_y = size_y | |
self.__data = ["" for i in xrange(self.size_x * self.size_y)] | |
self.__connections = {} | |
self.__rects = {} # (x, y) : (r, g, b) | |
self.surface_size = (600, 600) | |
self.surface = None | |
self.__last_highlighted_cell = None | |
pygame.font.init() | |
self.font = pygame.font.Font("visitor2.ttf", 10) | |
def get_at(self, x, y): | |
return self.__data[y * self.size_x + x] | |
def set_at(self, x, y, val): | |
self.__data[y * self.size_x + x] = val | |
def neighbors(self, x, y): | |
return [(x+xi, y+yi) for xi, yi in ((-1, 0), (0, -1), (1, 0), (0, 1)) \ | |
if x+xi >= 0 and x+xi < self.size_x \ | |
and y+yi >= 0 and y+yi < self.size_y] | |
def fill(self, x, y, color): | |
self.__rects[(x, y)] = color | |
def fill_clear(self, x, y): | |
del self.__rects[(x, y)] | |
def connect(self, x1, y1, x2=None, y2=None): | |
if x2 == None: # 0 != None | |
x1, y1 = x1 | |
x2, y2 = y1 | |
l = self.__connections.get((x1, y1), []) | |
if not l: | |
self.__connections[(x1, y1)] = l | |
l.append((x2, y2)) | |
def disconnect(self, x1, y1, x2=None, y2=None): | |
if not x2: | |
x1, y1 = x1 | |
x2, y2 = y1 | |
self.__connections[(x1, y1)].remove((x2, y2)) | |
def draw_hexagon(self): | |
width = self.surface.get_width() / self.size_x | |
height = self.surface.get_height() / self.size_y | |
for x in xrange(self.size_x): | |
for y in xrange(self.size_y): | |
if (y % 2) == 0: | |
centerx = (width*1.7/2+(width/2))*x + width / 2 # 1.7 is sqrt(3) | |
centery = height / 2 + max(height * y / 2, 0) | |
pointlist = [(centerx - width / 2, centery), | |
(centerx - width / 4, centery - height / 2), | |
(centerx + width / 4, centery - height / 2), | |
(centerx + width / 2, centery), | |
(centerx + width / 4, centery + height / 2), | |
(centerx - width / 4, centery + height / 2)] | |
nextx = (width*1.7/2+(width/2))*(x+1) | |
pygame.draw.aalines(self.surface, (100, 255, 0), True, pointlist) | |
pygame.draw.aaline(self.surface, (100, 255, 0), | |
pointlist[3], (nextx, pointlist[3][1])) | |
def highlight_cell(self, pos): | |
width = self.surface.get_width() / self.size_x | |
height = self.surface.get_height() / self.size_y | |
cellx = pos[0] / width | |
celly = pos[1] / height | |
pygame.draw.rect(self.surface, (160, 160, 160), | |
(width * cellx + 1, height * celly + 1, width-1, height-1)) | |
# FIXME: maybe I should just redraw all screen every frame | |
if self.__last_highlighted_cell and self.__last_highlighted_cell != (cellx, celly): | |
pygame.draw.rect(self.surface, (0, 0, 0), | |
(width*self.__last_highlighted_cell[0]+1, | |
height*self.__last_highlighted_cell[1]+1, width-1, height-1)) | |
self.__last_highlighted_cell = (cellx, celly) | |
self.draw() | |
def draw(self, surface=None): | |
# TODO: minimize draw count per frame | |
if not surface: | |
if not self.surface: | |
self.surface = pygame.display.set_mode((600, 600), pygame.RESIZABLE, 32) | |
self.first_draw = False | |
surface = self.surface | |
width = self.surface.get_width() / self.size_x | |
height = self.surface.get_height() / self.size_y | |
# draw vertex lines | |
pygame.draw.rect(surface, (100, 255, 0), | |
(0, 0, width*self.size_x+1, height*self.size_y+1), 1) | |
for x in xrange(self.size_x): | |
for y in xrange(self.size_y): | |
#pygame.draw.aaline(surface, (255, 255, 255), (width*x, height*y), | |
#(width*x, height*(y+1))) | |
#pygame.draw.aaline(surface, (255, 255, 255), (width*x, height*y), | |
#(width*(x+1), height*y)) | |
#pygame.draw.aaline(surface, (255, 255, 255), (width*(x+1), height*y), | |
#(width*(x+1), height*(y+1))) | |
#pygame.draw.aaline(surface, (255, 255, 255), (width*(x+1), height*(y+1)), | |
#(width*x, height*(y+1))) | |
if (x+y) % 2: | |
pygame.draw.rect(surface, (100, 255, 0), (width*x, height*y, | |
width+1, height+1), 1) | |
t = self.get_at(x, y) | |
if t: | |
text = self.font.render(self.get_at(x, y), | |
True, (255, 255, 255)) | |
surface.blit(text, (width*x, height*y)) | |
# fill vertices | |
for vertex, color in self.__rects.iteritems(): | |
pygame.draw.rect(surface, color, | |
(width*vertex[0]+1, height*vertex[1]+1, width-1, height-1)) | |
# draw connection lines | |
for conn_from, conns in self.__connections.iteritems(): | |
self._draw_conn_rect(conn_from[0], conn_from[1], width, height) | |
for conn_to in conns: | |
self._draw_conn_rect(conn_to[0], conn_to[1], width, height) | |
pygame.draw.aaline(surface, (0, 255, 255), | |
(conn_from[0]*width+(width/2), conn_from[1]*height+(height/2)), | |
(conn_to[0]*width+(width/2), conn_to[1]*height+(height/2)), 0) | |
def _draw_conn_rect(self, x, y, width, height): | |
pygame.draw.rect(self.surface, (0, 0, 200), (x*width+(width/2)-5, | |
y*height+(height/2)-5, 10, 10)) | |
def __iter__(self): | |
return iter(self.__data) | |
def run(): | |
pygame.display.init() | |
time = pygame.time.Clock() | |
g.draw() | |
while True: | |
for event in pygame.event.get(): | |
if event.type == pygame.QUIT: | |
g.surface = None | |
pygame.display.quit() | |
return | |
elif event.type == pygame.VIDEORESIZE: | |
g.surface = pygame.display.set_mode(event.size, pygame.RESIZABLE, 32) | |
g.draw() | |
elif event.type == pygame.MOUSEMOTION: | |
g.highlight_cell(pygame.mouse.get_pos()) | |
pygame.display.flip() | |
time.tick(30) | |
def start(): | |
t = threading.Thread(target=run) | |
t.start() | |
return t | |
MOUSE_ENABLED = True | |
g = Grid(20, 20) | |
g.set_at(3, 4, "bok") | |
g.connect(3, 4, 10, 10) | |
g.connect(3, 4, 8, 1) | |
g.fill(5, 5, (255, 255, 255)) | |
g.fill_clear(5, 5) | |
g.fill(6, 6, (255, 0, 0)) | |
if __name__ == "__main__": | |
g.draw() | |
g.draw_hexagon() | |
run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment