Techoplite
Techoplite

Reputation: 675

Draw circle does not display

I need to draw a circle behind some text.

On a chessboard, I managed to display three letters: a 'P' for a pikeman, a 'K' for a knight, and an 'A' for an archer.

At the moment I am trying to display a circle somewhere on the chessboard, and once I can actually see it, I will pass the right coordinates.

The letters are of a red colour just for testing purposes, but in the future, they will be either black or white. The circle is therefore needed so that I will be able to see black letters on black squares.

I don't care what colour the circle is at the moment, but I am also thinking of not actually filling the circle, but just draw the outline.

Unit is the parent class, and Pikeman, Archer, and Knight are subclasses. I had rather have the circle drawn from the Unit class, as it is a 'variable'(if we want) that the three subclasses have in common.

I tried to create a surface in the Unit class and then draw a circle from there. couldn't make it work.

I tried to create a surface inside the Unit class and draw it from a subclass. couldn't make it work.

So, I decided to create a CircleSurface class, create an instance of this class and pass it to the draw method. Nope, doesn't work!

As I said I had rather have the circle drawn from the Unit class, and not have to create a CircleSurface class.

import pygame
import sys
from coordinator import coordinator

# Sets up the display
pygame.init()
window_size = (800, 800)
game_window = pygame.display.set_mode(size=window_size)
pygame.display.set_caption('My Game')


# Defines classes and related methods
class WhiteSquare:
    def __init__(self):
        self.height = int(window_size[0] / 8)
        self.width = int(window_size[1] / 8)
        self.white_square = pygame.Surface((self.height, self.width))
        self.white_square.fill((255, 255, 255))


class BlackSquare:
    def __init__(self):
        self.height = int(window_size[0] / 8)
        self.width = int(window_size[1] / 8)
        self.black_square = pygame.Surface((self.height, self.width))
        self.black_square.fill((0, 0, 0))


class ChessBoard:
    def __init__(self):
        self.ws = ws
        self.bs = bs
        self.white_columns = white_columns
        self.black_columns = black_columns

    def draw(self):
        for w_columns in self.white_columns:
            game_window.blit(self.ws.white_square, w_columns)

        for b_columns in self.black_columns:
            game_window.blit(self.bs.black_square, b_columns)


# class SquareNames:
#     letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
#     numbers = ['1', '2', '3', '4', '5', '6', '7', '8']
#     square_names = []
#     for letter in letters:
#         for number in numbers:
#             square_name = letter + number
#             square_names.append(square_name)
#     print((square_names))
#     # for coordinate in
#     # coordinates = (square_name : coordinate)

class CircleSurface:
    def __init__(self):
        self.circle_surface = pygame.Surface((100, 100))
        self.circle_surface.fill((0, 0, 255))


class Unit:
    def __init__(self):
        self.surface = pygame.Surface((100, 100))
        self.my_font = pygame.font.SysFont('Time New Roman', 100)
        self.cs = cs

    def draw_circle(self):
        pygame.draw.circle(self.cs.circle_surface, (0, 255, 0), (200, 200), 50)


class Pikeman(Unit):
    unit_type = 'P'
    destination = (125, 125)

    def __init__(self):
        super().__init__()
        self.img = self.my_font.render(self.unit_type, 1, (255, 0, 0))

    def draw(self, surface):
        surface.blit(self.img, self.destination)


class Archer(Unit):
    unit_type = 'A'
    destination = (525, 525)

    def __init__(self):
        super().__init__()
        self.img = self.my_font.render(self.unit_type, 1, (255, 0, 0))

    def draw(self, surface):
        surface.blit(self.img, self.destination)


class Knight(Unit):
    unit_type = 'K'
    destination = (325, 525)

    def __init__(self):
        super().__init__()
        self.img = self.my_font.render(self.unit_type, 1, (255, 0, 0))

    def draw(self, surface):
        surface.blit(self.img, self.destination)


# Sets and gets the coordinates for black and white squares
coordinator = coordinator()
black_columns = coordinator[2] + coordinator[3]
white_columns = coordinator[0] + coordinator[1]

# Creates needed objects
ws = WhiteSquare()
bs = BlackSquare()
cb = ChessBoard()
p = Pikeman()
a = Archer()
k = Knight()
cs = CircleSurface()


# Event loop (outer)
while 1:

    # Event loop (inner)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    # Draws needed objects and updates display
    cb.draw()
    p.draw(game_window)
    p.draw_circle()
    k.draw(game_window)
    a.draw(game_window)
    pygame.display.update()

The error displayed is the following:

Traceback (most recent call last):
  File "C:/Users/oricc/PycharmProjects/designAChessboardChallange/display.py", line 117, in <module>
    p = Pikeman()
  File "C:/Users/oricc/PycharmProjects/designAChessboardChallange/display.py", line 77, in __init__
    super().__init__()
  File "C:/Users/oricc/PycharmProjects/designAChessboardChallange/display.py", line 66, in __init__
    self.cs = cs
NameError: name 'cs' is not defined

Upvotes: 1

Views: 240

Answers (1)

Rabbid76
Rabbid76

Reputation: 211278

The object cs is not define when the instance of Pikeman, Archer and Knight is constructed.

Just create the instance of CircleSurface before, to solve the issue. e.g:

cs = CircleSurface()
p = Pikeman()
a = Archer()
k = Knight()

But I recommend to pass the CircleSurface object as an argument:

class Unit:
    def __init__(self, cs):
        self.surface = pygame.Surface((100, 100))
        self.my_font = pygame.font.SysFont('Time New Roman', 100)
        self.cs = cs

    def draw_circle(self):
        pygame.draw.circle(self.cs.circle_surface, (0, 255, 0), (200, 200), 50)

class Pikeman(Unit):
    unit_type = 'P'
    destination = (125, 125)

    def __init__(self, cs):
        super().__init__(cs)
        self.img = self.my_font.render(self.unit_type, 1, (255, 0, 0))

    def draw(self, surface):
        surface.blit(self.img, self.destination)
cs = CircleSurface()
p = Pikeman(cs)

Do the same for Archer and Knight.


Furthermore you've ensure that the pixel format of the circle surface will include a per-pixel alpha and you've to draw the circle on the circle surface:

class CircleSurface:
    def __init__(self):
        self.circle_surface = pygame.Surface((100, 100), flags=pygame.SRCALPHA)
        self.circle_surface.fill((0, 0, 0, 0))
        pygame.draw.circle(self.circle_surface, (0, 255, 0), (50, 50), 50)

blit the circle surface to the window surface

class Unit:
    # [...]

    def draw_circle(self, surface):
        surface.blit(self.cs.circle_surface, (200, 200))
p.draw_circle(game_window)

Upvotes: 2

Related Questions