0
\$\begingroup\$

I'd like to have a map in my pygame game but don't want to waste time moving each individual object in it. To resolve this, I'd like to iterate over a list like this:
[1, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 1, 0, 0, 0]
where 1 means there is a rock and 0 means there is nothing. How would I convert this list into coordinates of where to place each block?

UPDATE:
To clarify if I have a list of lists like so:
[
[1, 1, 1, 1, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]
] And dimensions 500x500,
I'd like the program to put a wall of rocks from x=0 to x=400, with each rock being 100x100.

What I mean is: I'd like to find x-y coordinates to place the rock based on where the 1 is on the map list of lists.

\$\endgroup\$
2
  • \$\begingroup\$ Are you saying that your on-screen graphical map is 500x500, but your list is 5x5? And that each "1" in the list represents a 100x100 rock which you display to the screen? \$\endgroup\$
    – Ian Moote
    Jul 11, 2022 at 17:39
  • \$\begingroup\$ Yes, sorry if this was a bit unclear. \$\endgroup\$ Jul 16, 2022 at 22:30

1 Answer 1

1
\$\begingroup\$

Sorry for the delay in getting back to this question. Based upon your clarification I have completely re-written this answer.

What you're basically doing here is "tiling". You have a 5x5 map (real pixel dimensions are 500x500) and each coordinate on the map can have a rock or not have a rock. You will have a tile for no rock on the map, and another tile which will have the rock. This tile will be a static or animated graphics image like a .png, .jpg, or .gif and you would copy -- or "blit" -- it onto the display in the proper place.

I don't have those graphical files so I have to make do. I will create a "surface" for the tile, and instead of importing an image into it I'll just fill it with a background colour:

tileEmpty = pygame.Surface((100,100))
tileEmpty.fill((0,255,0))

I will base the tile for the rock on the empty tile, then just add the "rock" over top of whatever's there. The "rock" isn't elaborate in any way, just a grey circle, but I first will copy the empty tile:

tileRock = tileEmpty.copy()
tempRect = tileRock.get_rect()
pygame.draw.circle(tileRock, (128,1,28,128), tempRect.center, tempRect.center[0], tempRect.center[0])

What's going on here is that I'm creating a new surface for the rock by copying the surface which contains the "empty" map tile. To do the figuring-outs I'll need to get the rect of that surface. On that surface I will simply draw a grey circle. The .draw.circle() method is well-documented, but I'll need the colour, the centre of the rect, and the width of the line used to draw the circle. The .center property of the rect conveniently gives us the width of the line as well as the centre of the circle.

You wouldn't do it this way, of course; you'd have a tilesheet already drawn up with 100x100 (or whatever) images and you'd just pick off of that.

As per my previous reply, you'd still use y * mapwidth + x to pluck the map contents from the bitmapped map contents. What's different in this reply is that you'd multiply the x and y by the width of the tile to find where to put it.

There are many ways that you could get tiles onto the display, but for simplicity I've chosen to use a simple 'for x / for y' iteration. In practice you'd have a limited view onto your map and you'd have to calculate a rectangle out of a much larger bitmap to display it.

Here is a working program which demonstrates the basics:

import pygame

pygame.init()

#this is the entire 5x5 map as a bitmap
bitMap = [1,1,1,1,0,
          0,0,0,0,0,
          0,0,0,0,0,
          0,0,0,0,0,
          0,0,0,0,0]

#some predefined colour constants
FIELD = pygame.Color(0,255,0)    #colour of the empty field
ROCK = pygame.Color(128,128,128) #colour of the rock

#set up the main 500x500 display
display = pygame.display.set_mode((500, 500))
pygame.display.set_caption("Tile Time")

#make an empty tile
tileEmpty = pygame.Surface((100,100))
tileEmpty.fill(FIELD)

#make a tile with a rock
tileRock = tileEmpty.copy()
tempRect = tileRock.get_rect()
pygame.draw.circle(tileRock, ROCK, tempRect.center, tempRect.center[0], tempRect.center[0])

#draw the map -- very straight-forward!
for x in range(5):      #because bitMap is 5x5
    for y in range(5):  #because bitMap is 5x5
        dest = (x * 100, y * 100)   #calculate where to put the tile
        if bitMap[y*5+x] == 1:      #gets contents of bitmap at (x,y)
            display.blit(tileRock, dest)    #display a rock
        else:
            display.blit(tileEmpty, dest)   #display not a rock

pygame.display.flip()   #update the display

input()

The input() is just to keep the code simple; no need for a game loop for this. Depending how you run the code you may need to Ctl-C out of it, though.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ You may even add a check in the ctor to make sure the number of elements in the list is the right one \$\endgroup\$
    – Vaillancourt
    Jul 10, 2022 at 19:43
  • 2
    \$\begingroup\$ I notice that CodeWizard777 has edited their question. Would you recommend they post the revision as a new question, or would you like to edit your answer to address the update? \$\endgroup\$
    – DMGregory
    Jul 11, 2022 at 22:13
  • \$\begingroup\$ I'm still kind of a n00b myself, so I appreciate any advice you can offer. I have posted a comment asking him about his edit. I'm starting to get the impression that he's actually asking about displaying the map to the display surface, but I'm still not sure if that's what he wants. My intention was to change my answer after he clarifies. Should this situation be addressed more quickly than that, do you think? \$\endgroup\$
    – Ian Moote
    Jul 12, 2022 at 1:58
  • \$\begingroup\$ Based on new information from the OP I've completely re-written my reply. \$\endgroup\$
    – Ian Moote
    Jul 21, 2022 at 21:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .