绘制宽度较小的 pygame 矩形
Draw over a pygame rect with a smaller width
我正在通过 pygame 制作数独求解器,并且我已经能够绘制整个棋盘,但是,在编写处理点击图块的代码部分时,我做到了当前图块会“亮起”绿色,以便用户可以知道当前图块。但是,当用户决定单击不同的图块时,我无法弄清楚如何在绿色突出显示的部分上绘制。我想完全移除那部分,但是,因为它是一个厚度为 4 的矩形,而基础瓷砖的厚度为 1,所以我所做的只是在粗绿线上有一条丑陋的黑线。我尝试重新绘制整个板,但我得到了类似的结果。有帮助吗?
class Tile:
'''Represents each white tile/box on the grid'''
def __init__(self, value, window, x1, x2):
self.value = value #value of the num on this grid
self.window = window
self.active = False
self.rect = pygame.Rect(x1, x2, 60, 60) #dimensions for the rectangle
def draw(self, color, thickness):
'''Draws a tile on the board'''
pygame.draw.rect(self.window, color, self.rect, thickness)
pygame.display.flip()
def main():
board = Board(screen)
tiles = board.draw_board() #store the locations of all the tiles on the grid
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONUP:
mousePos = pygame.mouse.get_pos()
#board.draw_board() or (see next comment)
for i in range(9):
for j in range (9): #look for tile we clicked on
#tiles[i][j].draw((0,0,0),1)
#yield same results
if tiles[i][j].is_clicked(mousePos):
tiles[i][j].draw((50,205,50),4) #redraws that tile but with a highlighted color to show it's been clicked
break
main()
我看到了几个选项。我将从需要最少代码更改的那些开始。
- 仅在图块内绘制您的选择矩形。问题已解决。
- 绘制图块时,也要在其周围绘制边框。
您可能还想将选定的图块存储在一个变量中,这样您以后就可以用它来做一些事情。
您可以简单地将突出显示的图块存储在一个变量中。我也不认为你根本需要 Tile
class,因为数独游戏状态基本上只是一个数字列表。
这是一个简单的例子。注意评论:
import random
import pygame
TILE_SIZE = 64
# function to draw the grid
def draw_board():
board_surface = pygame.Surface((9*TILE_SIZE, 9*TILE_SIZE))
board_surface.fill((255, 255, 255))
for x in range(9):
for y in range(9):
rect = pygame.Rect(x*TILE_SIZE, y*TILE_SIZE, TILE_SIZE, TILE_SIZE)
pygame.draw.rect(board_surface, (0, 0, 0), rect, 1)
pygame.draw.line(board_surface, (0, 0, 0), (0, 3*TILE_SIZE), (9*TILE_SIZE, 3*TILE_SIZE), 5)
pygame.draw.line(board_surface, (0, 0, 0), (0, 6*TILE_SIZE), (9*TILE_SIZE, 6*TILE_SIZE), 5)
pygame.draw.line(board_surface, (0, 0, 0), (3*TILE_SIZE, 0), (3*TILE_SIZE, 9*TILE_SIZE), 5)
pygame.draw.line(board_surface, (0, 0, 0), (6*TILE_SIZE, 0), (6*TILE_SIZE, 9*TILE_SIZE), 5)
return board_surface
def main():
# standard pygame setup
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((9*TILE_SIZE, 9*TILE_SIZE))
font = pygame.font.SysFont(None, 40)
# seperate the game state from the UI
# create a dummy 9x9 sudoku board
state = [[None for _ in range(10)] for _ in range(10)]
for _ in range(15):
x = random.randint(0, 9)
y = random.randint(0, 9)
state[y][x] = random.randint(1, 9)
# a variable to hold the selected tile's position on the board
# (from 0,0 to 8,8)
selected = None
# create the grid surface ONCE and reuse it to clear the screen
board_surface = draw_board()
while True:
for event in pygame.event.get():
pos = pygame.mouse.get_pos()
if event.type == pygame.QUIT:
return
# when the player clicks on a tile
# we translate the screen coordinates to the board coordinates
# e.g. a pos of (140, 12) is the tile at (2, 0)
if event.type == pygame.MOUSEBUTTONDOWN:
w_x, w_y = event.pos
selected = w_x // TILE_SIZE, w_y // TILE_SIZE
# clear everything by blitting the grid surface to the screen
screen.blit(board_surface, (0, 0))
# print all numbers in the state to the screen
# we use a Rect here so we can easily center the numbers
rect = pygame.Rect(0, 0, TILE_SIZE, TILE_SIZE)
for line in state:
for tile in line:
if tile != None:
tmp = font.render(str(tile), True, (0, 0, 0))
screen.blit(tmp, tmp.get_rect(center=rect.center))
rect.move_ip(TILE_SIZE, 0)
rect.x = 0
rect.move_ip(0, TILE_SIZE)
# if a tile is selected, we calculate the world coordinates from the board coordinates
# and draw a simple green rect
if selected:
rect = pygame.Rect(selected[0] * TILE_SIZE, selected[1] * TILE_SIZE, TILE_SIZE, TILE_SIZE)
pygame.draw.rect(screen, (0, 200, 0), rect, 5)
clock.tick(30)
pygame.display.flip()
main()
此外,您不应在主循环之外调用 pygame.display.flip()
。它可能会导致闪烁或图像无法正确显示等效果。
我正在通过 pygame 制作数独求解器,并且我已经能够绘制整个棋盘,但是,在编写处理点击图块的代码部分时,我做到了当前图块会“亮起”绿色,以便用户可以知道当前图块。但是,当用户决定单击不同的图块时,我无法弄清楚如何在绿色突出显示的部分上绘制。我想完全移除那部分,但是,因为它是一个厚度为 4 的矩形,而基础瓷砖的厚度为 1,所以我所做的只是在粗绿线上有一条丑陋的黑线。我尝试重新绘制整个板,但我得到了类似的结果。有帮助吗?
class Tile:
'''Represents each white tile/box on the grid'''
def __init__(self, value, window, x1, x2):
self.value = value #value of the num on this grid
self.window = window
self.active = False
self.rect = pygame.Rect(x1, x2, 60, 60) #dimensions for the rectangle
def draw(self, color, thickness):
'''Draws a tile on the board'''
pygame.draw.rect(self.window, color, self.rect, thickness)
pygame.display.flip()
def main():
board = Board(screen)
tiles = board.draw_board() #store the locations of all the tiles on the grid
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONUP:
mousePos = pygame.mouse.get_pos()
#board.draw_board() or (see next comment)
for i in range(9):
for j in range (9): #look for tile we clicked on
#tiles[i][j].draw((0,0,0),1)
#yield same results
if tiles[i][j].is_clicked(mousePos):
tiles[i][j].draw((50,205,50),4) #redraws that tile but with a highlighted color to show it's been clicked
break
main()
我看到了几个选项。我将从需要最少代码更改的那些开始。
- 仅在图块内绘制您的选择矩形。问题已解决。
- 绘制图块时,也要在其周围绘制边框。
您可能还想将选定的图块存储在一个变量中,这样您以后就可以用它来做一些事情。
您可以简单地将突出显示的图块存储在一个变量中。我也不认为你根本需要 Tile
class,因为数独游戏状态基本上只是一个数字列表。
这是一个简单的例子。注意评论:
import random
import pygame
TILE_SIZE = 64
# function to draw the grid
def draw_board():
board_surface = pygame.Surface((9*TILE_SIZE, 9*TILE_SIZE))
board_surface.fill((255, 255, 255))
for x in range(9):
for y in range(9):
rect = pygame.Rect(x*TILE_SIZE, y*TILE_SIZE, TILE_SIZE, TILE_SIZE)
pygame.draw.rect(board_surface, (0, 0, 0), rect, 1)
pygame.draw.line(board_surface, (0, 0, 0), (0, 3*TILE_SIZE), (9*TILE_SIZE, 3*TILE_SIZE), 5)
pygame.draw.line(board_surface, (0, 0, 0), (0, 6*TILE_SIZE), (9*TILE_SIZE, 6*TILE_SIZE), 5)
pygame.draw.line(board_surface, (0, 0, 0), (3*TILE_SIZE, 0), (3*TILE_SIZE, 9*TILE_SIZE), 5)
pygame.draw.line(board_surface, (0, 0, 0), (6*TILE_SIZE, 0), (6*TILE_SIZE, 9*TILE_SIZE), 5)
return board_surface
def main():
# standard pygame setup
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((9*TILE_SIZE, 9*TILE_SIZE))
font = pygame.font.SysFont(None, 40)
# seperate the game state from the UI
# create a dummy 9x9 sudoku board
state = [[None for _ in range(10)] for _ in range(10)]
for _ in range(15):
x = random.randint(0, 9)
y = random.randint(0, 9)
state[y][x] = random.randint(1, 9)
# a variable to hold the selected tile's position on the board
# (from 0,0 to 8,8)
selected = None
# create the grid surface ONCE and reuse it to clear the screen
board_surface = draw_board()
while True:
for event in pygame.event.get():
pos = pygame.mouse.get_pos()
if event.type == pygame.QUIT:
return
# when the player clicks on a tile
# we translate the screen coordinates to the board coordinates
# e.g. a pos of (140, 12) is the tile at (2, 0)
if event.type == pygame.MOUSEBUTTONDOWN:
w_x, w_y = event.pos
selected = w_x // TILE_SIZE, w_y // TILE_SIZE
# clear everything by blitting the grid surface to the screen
screen.blit(board_surface, (0, 0))
# print all numbers in the state to the screen
# we use a Rect here so we can easily center the numbers
rect = pygame.Rect(0, 0, TILE_SIZE, TILE_SIZE)
for line in state:
for tile in line:
if tile != None:
tmp = font.render(str(tile), True, (0, 0, 0))
screen.blit(tmp, tmp.get_rect(center=rect.center))
rect.move_ip(TILE_SIZE, 0)
rect.x = 0
rect.move_ip(0, TILE_SIZE)
# if a tile is selected, we calculate the world coordinates from the board coordinates
# and draw a simple green rect
if selected:
rect = pygame.Rect(selected[0] * TILE_SIZE, selected[1] * TILE_SIZE, TILE_SIZE, TILE_SIZE)
pygame.draw.rect(screen, (0, 200, 0), rect, 5)
clock.tick(30)
pygame.display.flip()
main()
此外,您不应在主循环之外调用 pygame.display.flip()
。它可能会导致闪烁或图像无法正确显示等效果。