1

So I am trying to recreate Minesweeper in pygame. Since I am only drawing a single image over my current screen when a player clicks, I do not have frames. The problem is, when the player first clicks and I draw one image a flip the display. The first time I do that, it clears the background. After that, it doesn't clear the previous images. If I try and call flip first thing, nothing happens. I tried to flip after every image (Just trying things) and nothing changed.

Code:

    import pygame, random, os, sys, math

pygame.init()
font = pygame.font.SysFont('Sans Serif 7', 15)
screenX = 1240
screenY = 720
sprites = pygame.image.load(os.path.dirname(os.path.abspath(__file__)) + "\\Minesweeper\\ImageSheet.png")
spriteList = []

#tiles = 16px, icons = 26px

class Minefield():
    def __init__(self, width, height, mines, surface):
        self.width = width
        self.height = height
        self.mine = sprites.subsurface(80, 49, 16, 16)
        self.rows = []
        self.surface = surface
        for i in range(0, width):
            self.rows.append([])
            for i2 in range(0, height):
                self.rows[i].append(-2)
        for i in range(0, mines):
            print(len(self.rows))
            print(len(self.rows[1]))
            x = random.randint(0, width-1)
            y = random.randint(0, height-1)
            print(x)
            print(y)
            self.rows[x][y]
        self.render()

    def clicked(self, rawPos):
        pos = (math.floor(rawPos[0]/16), math.floor(rawPos[1]/16))
        val = self.rows[pos[0]][pos[1]]
        if val == -2:
            mines = 1
            if not pos[0] == 0 and not pos[1] == 0 and self.rows[pos[0]-1][pos[1]-1] == -1:
                mines += 1
            if not pos[0] == 0 and self.rows[pos[0]-1][pos[1]] == -1:
                mines += 1
            if not pos[0] == 0 and not pos[1] == self.height and self.rows[pos[0]-1][pos[1]+1] == -1:
                mines += 1
            if not pos[1] == 0 and self.rows[pos[0]][pos[1]-1] == -1:
                mines += 1
            if not pos[1] == self.height and self.rows[pos[0]][pos[1]+1] == -1:
                mines += 1
            if not pos[1] == 0 and not pos[0] == self.width and self.rows[pos[0]+1][pos[1]-1] == -1:
                mines += 1
            if not pos[0] == self.width and self.rows[pos[0]+1][pos[1]] == -1:
                mines += 1
            if not pos[1] == self.height and not pos[0] == self.width and self.rows[pos[0]+1][pos[1]+1] == -1:
                mines += 1
            print(mines)
            self.surface.blit(spriteList[mines], (pos[0]*16, pos[1]*16))
            pygame.display.flip()
        elif val == -1:
            playing = False
            return

    def render(self):
        for i in range(0, self.width):
            for i2 in range(0, self.height):
                self.surface.blit(spriteList[0], (i*16, i2*16))
        pygame.display.flip()

class Main():        
    def __init__(self):
        self.screen = pygame.display.set_mode((screenX, screenY), pygame.RESIZABLE)
        spriteList.append(sprites.subsurface(16, 49, 16, 16))
        for i in range(0, 8):
            print(i*16)
            spriteList.append(sprites.subsurface(i*16, 65, 16, 16))
        self.field = Minefield(50, 30, 30, self.screen)

    def gameloop(self):
        while True:
            for event in pygame.event.get():
                if event.type == pygame.VIDEORESIZE:
                    screenX = event.w
                    screenY = event.h
                    self.screen = pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE)
                if event.type == pygame.QUIT:
                    return
                if event.type == pygame.MOUSEBUTTONUP:
                    pos = pygame.mouse.get_pos()
                    self.field.clicked(pos)

    def stop(self):
        pygame.display.quit()
        pygame.quit()
        sys.exit("Window Closed")

main = Main()
main.gameloop()
main.stop()

What I want: On player click the only change is a 1 appears over the cell, but instead the background gets painted over by black.

Big_Bad_E
  • 947
  • 1
  • 12
  • 23
  • Instead of `flip()` you will need to use `update()` to only change a small part of the game window (ie on the cell you clicked). This question seems to answer your question in detail: https://stackoverflow.com/questions/29314987/difference-between-pygame-display-update-and-pygame-display-flip – Hoog Mar 15 '19 at 19:53

1 Answers1

0

pygame.display.set_mode() creates a new window surface. You've to render the background after recreating the window surface in the resize event. When the window was initialized, then immediately 1 resize event is pending.

def gameloop(self):
    while True:
        for event in pygame.event.get():
            if event.type == pygame.VIDEORESIZE:
                screenX = event.w
                screenY = event.h
                self.screen = pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE)
                self.field.render() # <-------------

Note, when the window was resized and the window surface is recreated then the entire scene has to be redrawn.
Probably your game will work only, if the window is not resizable. When you resize the window, then a new event occurs. The surface is recreated and the background is redrawn, but the "clicked" fields are lost. So they would have to be redrawn, too.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174