having problem with drawing lines thickness in pygame

Viewed 110

Here is the board I drew using pygame: https://i.stack.imgur.com/Hne6A.png

I'm facing a bug with the thickness of the last two lines as I marked them on the image. I believe there is something wrong with the if statement in my code but I can't quite figure it out, it just won't take effect.

here is the code that has drawn the board above:

import pygame, sys


pygame.init()

width, height = 750, 750
rows, cols = 9, 9
BLACK = (0,0,0)

screen = pygame.display.set_mode((width, height))
screen.fill((255, 255, 255, 255))

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
            sys.exit()

    surf = pygame.Surface((600, 600))
    surf.fill((255,255,255))

    padding = surf.get_width()/9
    for i in range(rows+1):
        if i % 3 == 0:
            thick = 4
        else:
            thick = 1

        pygame.draw.line(surf, BLACK, (0, i*padding), (width, i*padding), width=thick)
        pygame.draw.line(surf, BLACK, (i*padding, 0), (i*padding, height), width=thick)

    

    surf_center = (
        (width-surf.get_width())/2,
        (height-surf.get_height())/2
    )
    screen.blit(surf, surf_center)
    pygame.display.update()
    pygame.display.flip()

2 Answers

To draw a thick line, half the thickness is applied to both sides of the line. The simplest solution is to make the target surface a little larger and add a small offset to the coordinates of the lines.
For performance reasons, I also recommend creating the surface before the application loop and continuously blit it in the application loop:

import pygame, sys

pygame.init()

width, height = 750, 750
rows, cols = 9, 9
BLACK = (0,0,0)

screen = pygame.display.set_mode((width, height))

surf_size = 600
surf = pygame.Surface((surf_size+4, surf_size+4))
surf.fill((255,255,255))
padding = surf_size/9
for i in range(rows+1):
    thick = 4 if i % 3 == 0 else 1
    offset = i * padding + 1
    pygame.draw.line(surf, BLACK, (0, offset), (width, offset), width=thick)
    pygame.draw.line(surf, BLACK, (offset, 0), (offset, height), width=thick)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
            
    screen.fill((255, 255, 255, 255))
    screen.blit(surf, surf.get_rect(center = screen.get_rect().center))
    pygame.display.update()
    pygame.display.flip()

pygame.quit()
sys.exit()

The code below should do the trick. The thing is that the width in pygame.draw.line is drawn in the middle of the line. So, the border lines are actually cropped in half because the half on one side and another half on the other side are not taken into account. But the catch is that if the thickness is even there is an offset of 1 on the borders as the width is larger on one of the sides.

Even if the thickness (bold_think) is raised or lowered the algorithm below will work flawlessly without any gaps outside the grid.

Thickness of 4 Thickness of 8 Thinkness of 15
Thickness of 4 Thickness of 8 Thickness of 15
import pygame
import sys

pygame.init()

width, height = 750, 750
rows, cols = 9, 9
BLACK = (0, 0, 0)

screen = pygame.display.set_mode((width, height))
screen.fill((255, 255, 255, 255))

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
            sys.exit()

    surf = pygame.Surface((600, 600))
    surf.fill((255, 255, 255))

    bold_thick = 4
    # Calculates the offset of 1 for the even widths
    thick_offset = (bold_thick - 1) % 2
    offset = (bold_thick / 2) - thick_offset

    # The padding should take into account the borders
    padding = (surf.get_width() - bold_thick) / 9
    for i in range(rows+1):
        if i % 3 == 0:
            thick = bold_thick
        else:
            thick = 1

        pygame.draw.line(surf, BLACK, (0, i*padding + offset),
                         (width, i*padding + offset), width=thick)
        pygame.draw.line(surf, BLACK, (i*padding + offset, 0),
                         (i*padding + offset, height), width=thick)

    surf_center = (
        (width-surf.get_width())/2,
        (height-surf.get_height())/2
    )
    screen.blit(surf, surf_center)
    pygame.display.update()
    pygame.display.flip()
Related