2

My problem is that I cannot properly blit several squares in the right position.

I have written some code to display a chessboard. The squares are not sprites, but pygame.Surface objects.

My project contains two .py files at the moment:

  • display.py
  • coordinator.py

The coordinator is a function which returns a list containing two lists of tuples, one for even column, and one for odd ones. The tuples are the actual coordinates I am passing to the blit method.

At this stage, I am dealing only with white squares.

The display.py file is the actual display and at the moment contains also the square classes and the chessboard class.

Here is my coordinator.py:

# Returns a list containing two lists of tuples, one for even columns (white squares), and
# one for odd columns (white squares).

# Needs to be implemented to achieve the same for black squares.

def coordinator():
    odd_columns = white_odd_columns()
    even_columns = white_even_columns()
    columns = [odd_columns, even_columns]
    # print(columns)
    return columns
    # print('odd_columns: ' + str(odd_columns))
    # print('even_columns: ' + str(even_columns))

# Returns a list with coordinates
# for white squares in odd columns
def white_odd_columns():
    odd_coordinates = []
    for x in range(0, 800, 200):
        y = 0
        for first_column in range(0, 5):
            odd_coordinates.append((x, y))
            y += 200
    # print('This should be the complete list of odd coordinates' + str(odd_coordinates))
    return odd_coordinates

# Returns a list with coordinates
# for white squares in even columns
def white_even_columns():
    even_coordinates = []
    for x in range(100, 800, 200):
        y = 100
        for first_column in range(0, 4):
            even_coordinates.append((x, y))
            y += 200
    # print('This should be the complete list of even coordinates' + str(even_coordinates))
    return even_coordinates

# white_even_columns()
# white_odd_columns()
coordinator()

And here is my display.py:

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')

# Event loop (outer)
while 1:

    white_columns = coordinator()
    # print(white_columns)
    odd_white_columns = white_columns[0]
    # print(odd_white_columns)
    even_white_columns = white_columns[1]
    # print(even_white_columns)
    l = len(even_white_columns)
    # print(l)
    n = 0
    for n in range(l + 1):
        x = odd_white_columns[n]
        print(x)

    # Event loop (inner)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    class WhiteSquare:
        height = int(window_size[0] / 8)
        width = int(window_size[1] / 8)
        a = height
        b = width
        white_square = pygame.Surface((a, b))
        white_square.fill((255, 255, 255), )

    ws = WhiteSquare()

    class BlackSquare:
        height = int(window_size[0] / 8)
        width = int(window_size[1] / 8)
        a = height
        b = width
        black_square = pygame.Surface((a, b))
        black_square.fill((0, 0, 255), )

    bs = BlackSquare()

    class ChessBoard:
        game_window.blit(ws.white_square, x)  # test
        game_window.blit(bs.black_square, (0, 100))  # test

    cb = ChessBoard()
    pygame.display.update()

Please do not take into account the following:

game_window.blit(bs.black_square, (0, 100))

This is just to make sure that I can actually blit squares when I pass some coordinates.

what bothers me, is the following at line 61:

game_window.blit(ws.white_square, x)

In fact, what I am trying to do is to access every single tuple returned by the coordinator with the following code starting a line 21:

l = len(even_white_columns)
# print(l)
n = 0
for n in range(l + 1):
    x = odd_white_columns[n]
    print(x)

I am printing the tuples just to make sure they are the right ones and that they are all of them. Well, they are all right.

What I don't get is why, when running the code, the only white square displayed looks the one at (200, 600).

I feel like it as something to do with storing the tuples or updating the display, but at the moment it looks out of my league.

Can someone explain to me what I am doing wrong? I might also be doing something wrong by actually iterating that way and trying to pass the coordinates.

Or it might be that I have got to use blits, instead of blit, so that I can pass a sequence of blits. If so, I can't actually figure out how to use this method, as in the examples on Stack Overflow it is shown just as a function.

Thanks for any help.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Techoplite
  • 605
  • 9
  • 23

1 Answers1

3

I recommend to read about the concept of Instance Objects and Method Objects.

Anyway, add a constructor to the classes BlackSquare and WhiteSquare and move it before the main game loop. e.g.:

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.width, self.height))
        self.black_square.fill((0, 0, 255))

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.width, self.height))
        self.white_square.fill((255, 255, 255))

Move the class ChessBoard before the main game loop and add a constructor to with the parameters for the white square, black square and the white columns (later you've to add the black columns, too).
Add a Method (draw), which can draw the white squares (self.ws) a the positions stored in self.white_columns in 2 nested loops. e.g.:

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

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

Create the object befor the game loop and draw the chess board in the loop by calling cb.draw(). e.g.:

pygame.init()
window_size = (800, 800)
game_window = pygame.display.set_mode(window_size)
pygame.display.set_caption('My Game')

white_columns = coordinator()
# print(white_columns)
odd_white_columns = white_columns[0]
# print(odd_white_columns)
even_white_columns = white_columns[1]

ws = WhiteSquare()
bs = BlackSquare()
cb = ChessBoard(ws, bs, white_columns)

# Event loop (outer)
while 1:

    # Event loop (inner)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    game_window.fill(0)
    cb.draw()
    pygame.display.update()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • 1
    Thank you so much Rabbid76, and sorry for the late reply. The answer was so easy but I really couldn't figure that out! The only thing I have done differently is to not pass any argument when crating the chessboard, and not filling the game window, but for the rest, it works perfectly fine. Thanks again. – Techoplite Oct 16 '19 at 05:59