Question re: objects and square grids

Ian Kelly ian.g.kelly at gmail.com
Wed May 15 14:01:06 EDT 2013


On Wed, May 15, 2013 at 10:56 AM, Andrew Bradley <abradley201 at gmail.com> wrote:
> Hello everyone.
>
> I am having a good time programming with Python 3.3 and Pygame. Pygame seems
> like the perfect platform for the kind of simple games that I want to make.
>
> What I have currently programmed is basically a drawn rectangle filled with
> 200 squares, each side of the squares being 43 pixels. The rectangle is 20
> squares by 10 squares.

It's more work, but I would recommend making the squares scalable in
some manner, instead of arbitrarily hard-coding them at 43 pixels.
What are you going to do when somebody has a 4K monitor and wants to
run the game full screen?

> This grid is what I want to have the entire game on. There will be pieces
> that move certain numbers of squares, perform actions that effect pieces on
> certain squares, etc. The possibilities are endless.
>
> So what I am now trying to do is organize these squares into objects that I
> can easily reference when programming things related to the squares.
>
> So far, I have done this:
>
> A1 = pygame.Rect(10, 12, 43, 43)
> A2
> A3
> A4
> B1
> B2
> etc.

This is a tedious, repetitive, and error-prone way to build all the
squares.  Instead of having a separate variable for each square,
consider putting them in a collection and building them up using
nested loops.  For example, the above could look something like:

squares = []
for row in range(10):
    row_squares = []
    for column in range(20):
        rect = Rect(column * width + x_offset, row * height + y_offset,
                    width, height)
        row_squares.append(rect)
    squares.append(row_squares)

Then the A1 rect is accessible as squares[0][0], A2 as squares[0][1],
B1 as squares[1][0], etc.  Alternatively, you could store the rects in
a dict and use "A1", "B1", etc. as the keys, but I think you will find
that the game logic will be simpler if you use integers internally for
your rows and columns, rather than the square labels.

> where said integers are the precise location of the top left-most square for
> A1, and onward down the line. I would guess that I could continue on in such
> a fashion, with appropriate box names for each square. But I'm running into
> the problem of confirming that the code above actually does something
> useful. For example, I would love to be able to turn A1 a different color,
> but how does this work? How do I actually utilize these object variable
> names? Are there methods that I am not aware of, because most things I try
> tend to do nothing or crash the game. For example, A1.fill(BLUE) does not
> work.

A Rect only stores position and size information and provides methods
for processing the same.  It doesn't know anything about drawing.  Use
the pygame.draw or pygame.gfxdraw functions for that.  For example, to
fill a part of the screen as indicated by the position of a rect:

BLUE = (0, 0, 255)
pygame.draw.rect(screen, BLUE, squares[0][0])

That said, you probably don't just want to color a square blue.  You
probably also want to remember that the square is blue for when you
are redrawing it later.  You need to track not just the position of
each square, but also their state.  This means that each object in
your "squares" container should not just be a rect, but some broader
object that contains square data, *including* a rect.  Something like
this:

class Square:

    def __init__(self, rect):
        self.rect = rect
        self.color = (0, 0, 0)
        self.contents = None
        # ... and whatever else you need to track

Then when you fill the squares container, you would fill it with
instances of your Square class instead of plain Rects, which gives you
a place to keep track of the square's color, among other things.  The
drawing code above then might look something like this:

pygame.draw.rect(screen, some_square.color, some_square.rect)



More information about the Python-list mailing list