How to place blocks in a grid [duplicate] - python

I'm approaching PyGame but I stepped on a problem: I am trying to draw a grid made out of single rectangle drawings, I want each one of those rectangle to fill or empty when the left mouse button is released on said rectangle. The grid i represented by a matrix of tuples each one representing each rectangle formatted like this (column, row) to be in line with pygame pixel's coordinates, then I create another matrix of tuples to convert from mouse position tuples (colpixel, rowpixel) to rectangle tuples, I also created a dictionary that pairs rectangle tuples as keys with a value that can be 1 or 0, that value represents whether the rectangle is filled or not, that is the value that I change when the mouse button is released. Here is the code:
import pygame
pygame.init()
SCREEN_WIDTH = 40
SCREEN_HEIGHT = 20
DIM = 20
ROWS = int(SCREEN_HEIGHT / DIM)
COLUMNS = int(SCREEN_WIDTH / DIM)
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('Game of Life')
# filling rect_matrix with tuple, each one representing a rectangle of the grid (columns, rows).
# filling rect_map by pairing the tuples from rect_matrix with a value that can be 0 or 1, default 1.
rect_matrix = []
rect_map = {}
for i in range(ROWS):
temp = []
for j in range(COLUMNS):
temp.append(pygame.Rect((j * DIM, i * DIM), (DIM, DIM)))
rect_map[(j, i)] = 1
rect_matrix.append(temp)
# filling mouse_to_rectangle, sort of a decoder to convert from groups of tuples
# (representing mouse coordinates in pixels) to a single tuple (representing single rectangles)
mouse_to_rectangle = []
ii = 0
for i in range(SCREEN_WIDTH):
jj = 0
temp = []
for j in range(SCREEN_HEIGHT):
temp.append((ii, jj))
if ((j + 1) % DIM == 0):
jj += 1
if ((i + 1) % DIM == 0):
ii += 1
mouse_to_rectangle.append(temp)
is_running = True
while is_running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
is_running = False
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONUP:
if rect_map[mouse_to_rectangle[pygame.mouse.get_pos()[0]][pygame.mouse.get_pos()[1]]] == 1:
rect_map[mouse_to_rectangle[pygame.mouse.get_pos()[0]][pygame.mouse.get_pos()[1]]] = 0
else:
rect_map[mouse_to_rectangle[pygame.mouse.get_pos()[0]][pygame.mouse.get_pos()[1]]] = 1
for i, ii in zip(rect_matrix, range(len(rect_matrix))):
for j, jj in zip(i, range(len(i))):
pygame.draw.rect(screen, (100, 100, 100), j, rect_map[(jj, ii)])
pygame.display.update()
I managed to fill (relative value in rect_map goes to 1) a rectangle upon releasing the left button when pointing it but when I try to click again on a rectangle that is now filled it won't empty. I represented the "filled or not" property with ones or zeroes beacuse the rectangle is filled when the width parameter in pygame.draw.rect is set to 0, if a >0 value is used then the rectangle will have a border as thick as the specified value in pixel.

You missed to clear the display before drawing the grid. Thus all the rectangles which hav been draw stayed there for ever:
screen.fill((0, 0, 0))
Anyway you've over complicated the algorithm. The position in the grind can be computed by dividing the components of the mouse position by DIM (// (floor division) operator):
mousepos = pygame.mouse.get_pos()
gridpos = mousepos[0] // DIM, mousepos[1] // DIM
Finally it the grid state can be changed with ease and mouse_to_rectangle is not need at all:
if rect_map[gridpos] == 1:
rect_map[gridpos] = 0
else:
rect_map[gridpos] = 1
See the example:
import pygame
pygame.init()
SCREEN_WIDTH = 200
SCREEN_HEIGHT = 200
DIM = 20
ROWS = int(SCREEN_HEIGHT / DIM)
COLUMNS = int(SCREEN_WIDTH / DIM)
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('Game of Life')
# filling rect_matrix with tuple, each one representing a rectangle of the grid (columns, rows).
# filling rect_map by pairing the tuples from rect_matrix with a value that can be 0 or 1, default 1.
rect_matrix = []
rect_map = {}
for i in range(ROWS):
temp = []
for j in range(COLUMNS):
temp.append(pygame.Rect((j * DIM, i * DIM), (DIM, DIM)))
rect_map[(j, i)] = 1
rect_matrix.append(temp)
is_running = True
while is_running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
is_running = False
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONUP:
mousepos = pygame.mouse.get_pos()
gridpos = mousepos[0] // DIM, mousepos[1] // DIM
if rect_map[gridpos] == 1:
rect_map[gridpos] = 0
else:
rect_map[gridpos] = 1
screen.fill((0, 0, 0))
for i, ii in zip(rect_matrix, range(len(rect_matrix))):
for j, jj in zip(i, range(len(i))):
pygame.draw.rect(screen, (100, 100, 100), j, rect_map[(jj, ii)])
pygame.display.update()

Related

Mastermind Game, Pygame, Adding the guess Indicators

I have got my game working, and i am happy with how it looks, I need to add the 4 indicators next to each row in the game, to signal whether the guess by the user is close to the computer guess
A quick explanation of the game
If the user guesses a colour but it is in the wrong position then it should change a indicator to orange
if its in the correct position it shoulde change to red. Then the user uses this to keep guessing
I think i could possibly draw 4 circles next to each row and then change the colour of them depending
On the guess from the user. However I am not sure on how to do this
There also might be a mor efficient way to do this, so of there is any suggestions would be great
The code looks like this
I have added some code, for the computer guess and if you guess correctly
import pygame
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0 , 0, 255)
WIDTH = 20
HEIGHT = 20
WIDTH1 = 30
HEIGHT1 = 30
MARGIN = 5
MARGIN1 = 10
array_width = 4
array_height = 8
grid = []
for row in range(10):
grid.append([])
for column in range(10):
grid[row].append(0)
colors = [(0, 0, 0) for i in range(array_width * array_height)]
blocks = [False for i in range(array_width * array_height)]
pygame.init()
# Set the HEIGHT and WIDTH of the screen
WINDOW_SIZE = [300, 300]
screen = pygame.display.set_mode(WINDOW_SIZE)
# Set title of screen
pygame.display.set_caption("MASTERMIND GAME")
sair = True
done = False
clock = pygame.time.Clock()
# -------- Main Program Loop -----------
grid[row][column] = 1
#TEXT BOX VARIABLES AND DATA
base_font = pygame.font.Font(None, 32)
user_text = ""
input_rect = pygame.Rect (10,250,100,50)
color_active = pygame.Color('lightskyblue3')
color_passive = pygame.Color('gray15')
color=color_passive
active = False
current_color = "white"
grid = [[current_color for column in range(4)] for row in range(8)]
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
print (blocks)
pos = pygame.mouse.get_pos()
column = pos[0] // (WIDTH + MARGIN)
row = pos[1] // (HEIGHT + MARGIN)
print(row)
print(column)
# TEXT BOX CREATION AND USAGE
# check if column and row are valid grid indices
if 0 <= row < array_height and 0 <= column < array_width:
try:
grid[row][column] = current_color
except:
print("invalid color")
if event.type == pygame.MOUSEBUTTONDOWN:
if input_rect.collidepoint(event.pos):
active = True
else:
active = False
if event.type == pygame.KEYDOWN:
if active == True:
if event.key == pygame.K_BACKSPACE:
user_text = user_text[0:-1]
else:
user_text += event.unicode
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
user_text = user_text
print(user_text)
if user_text != "":
current_color = user_text
user_text = ""
print("Click ", pos, "Grid coordinates: ", row, column)
if active:
color = color_active
else:
color=color_passive
screen.fill(0)
pygame.draw.rect(screen,color,input_rect,2)
text_surface= base_font.render(user_text,True,(255,255,255))
screen.blit(text_surface, (input_rect.x +5, input_rect.y + 5))
for row, gridrow in enumerate(grid):
for column, color in enumerate(gridrow):
pygame.draw.rect(screen,
color,
[(MARGIN + WIDTH) * column + MARGIN,
(MARGIN + HEIGHT) * row + MARGIN,
WIDTH,
HEIGHT])
clock.tick(60)
pygame.display.flip()
pygame.quit
Thanks
The question has several sub-questions and I just answered one. So there are plenty of opportunities for additional answers from other contributors.
Create a new grid for the indicators. The initial value for all fields is None:
indicator_grid = [[None for column in range(4)] for row in range(8)]
Draw the indicators in nested loops:
while not done:
# [...]
for row, gridrow in enumerate(indicator_grid):
for column, status in enumerate(gridrow):
x = 100 + (MARGIN + WIDTH) * column + MARGIN
y = (MARGIN + HEIGHT) * row + MARGIN
color = "grey"
if status != None:
color = "red" if status else "orange"
pygame.draw.circle(screen, color, (x+WIDTH//2, y+WIDTH//2), WIDTH//2)
When you want to set the state in indicator_grid to True or False, the color of the corresponding circle changes.

Is it possible to update a pygame drawing attribute when a event occurs?

I'm approaching PyGame but I stepped on a problem: I am trying to draw a grid made out of single rectangle drawings, I want each one of those rectangle to fill or empty when the left mouse button is released on said rectangle. The grid i represented by a matrix of tuples each one representing each rectangle formatted like this (column, row) to be in line with pygame pixel's coordinates, then I create another matrix of tuples to convert from mouse position tuples (colpixel, rowpixel) to rectangle tuples, I also created a dictionary that pairs rectangle tuples as keys with a value that can be 1 or 0, that value represents whether the rectangle is filled or not, that is the value that I change when the mouse button is released. Here is the code:
import pygame
pygame.init()
SCREEN_WIDTH = 40
SCREEN_HEIGHT = 20
DIM = 20
ROWS = int(SCREEN_HEIGHT / DIM)
COLUMNS = int(SCREEN_WIDTH / DIM)
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('Game of Life')
# filling rect_matrix with tuple, each one representing a rectangle of the grid (columns, rows).
# filling rect_map by pairing the tuples from rect_matrix with a value that can be 0 or 1, default 1.
rect_matrix = []
rect_map = {}
for i in range(ROWS):
temp = []
for j in range(COLUMNS):
temp.append(pygame.Rect((j * DIM, i * DIM), (DIM, DIM)))
rect_map[(j, i)] = 1
rect_matrix.append(temp)
# filling mouse_to_rectangle, sort of a decoder to convert from groups of tuples
# (representing mouse coordinates in pixels) to a single tuple (representing single rectangles)
mouse_to_rectangle = []
ii = 0
for i in range(SCREEN_WIDTH):
jj = 0
temp = []
for j in range(SCREEN_HEIGHT):
temp.append((ii, jj))
if ((j + 1) % DIM == 0):
jj += 1
if ((i + 1) % DIM == 0):
ii += 1
mouse_to_rectangle.append(temp)
is_running = True
while is_running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
is_running = False
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONUP:
if rect_map[mouse_to_rectangle[pygame.mouse.get_pos()[0]][pygame.mouse.get_pos()[1]]] == 1:
rect_map[mouse_to_rectangle[pygame.mouse.get_pos()[0]][pygame.mouse.get_pos()[1]]] = 0
else:
rect_map[mouse_to_rectangle[pygame.mouse.get_pos()[0]][pygame.mouse.get_pos()[1]]] = 1
for i, ii in zip(rect_matrix, range(len(rect_matrix))):
for j, jj in zip(i, range(len(i))):
pygame.draw.rect(screen, (100, 100, 100), j, rect_map[(jj, ii)])
pygame.display.update()
I managed to fill (relative value in rect_map goes to 1) a rectangle upon releasing the left button when pointing it but when I try to click again on a rectangle that is now filled it won't empty. I represented the "filled or not" property with ones or zeroes beacuse the rectangle is filled when the width parameter in pygame.draw.rect is set to 0, if a >0 value is used then the rectangle will have a border as thick as the specified value in pixel.
You missed to clear the display before drawing the grid. Thus all the rectangles which hav been draw stayed there for ever:
screen.fill((0, 0, 0))
Anyway you've over complicated the algorithm. The position in the grind can be computed by dividing the components of the mouse position by DIM (// (floor division) operator):
mousepos = pygame.mouse.get_pos()
gridpos = mousepos[0] // DIM, mousepos[1] // DIM
Finally it the grid state can be changed with ease and mouse_to_rectangle is not need at all:
if rect_map[gridpos] == 1:
rect_map[gridpos] = 0
else:
rect_map[gridpos] = 1
See the example:
import pygame
pygame.init()
SCREEN_WIDTH = 200
SCREEN_HEIGHT = 200
DIM = 20
ROWS = int(SCREEN_HEIGHT / DIM)
COLUMNS = int(SCREEN_WIDTH / DIM)
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('Game of Life')
# filling rect_matrix with tuple, each one representing a rectangle of the grid (columns, rows).
# filling rect_map by pairing the tuples from rect_matrix with a value that can be 0 or 1, default 1.
rect_matrix = []
rect_map = {}
for i in range(ROWS):
temp = []
for j in range(COLUMNS):
temp.append(pygame.Rect((j * DIM, i * DIM), (DIM, DIM)))
rect_map[(j, i)] = 1
rect_matrix.append(temp)
is_running = True
while is_running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
is_running = False
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONUP:
mousepos = pygame.mouse.get_pos()
gridpos = mousepos[0] // DIM, mousepos[1] // DIM
if rect_map[gridpos] == 1:
rect_map[gridpos] = 0
else:
rect_map[gridpos] = 1
screen.fill((0, 0, 0))
for i, ii in zip(rect_matrix, range(len(rect_matrix))):
for j, jj in zip(i, range(len(i))):
pygame.draw.rect(screen, (100, 100, 100), j, rect_map[(jj, ii)])
pygame.display.update()

Python program game of life

I am currently trying to make conways game of life in python, I am trying to figure out how to make the program read the black squares as on, however I am having no luck, could anyone help. The onoff print currently just prints everything as off (0's) and I want it to print 1's where there is black squares, in order.
import pygame
import random
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
GREY = (0, 210, 230)
WIDTH = 20
HEIGHT = 20
MARGIN = 1
gridsize = 20
onoff = []
grid = []
for row in range(gridsize):
grid.append([])
for column in range(gridsize): # grid
grid[row].append([])
grid[row][column] = 0 # setting value of pixel to off
for x in range(gridsize*gridsize): #onoff update
onoff.append(grid[row][column])
print(onoff)
pygame.init()
WINDOW_SIZE = [21*gridsize, 21* gridsize]
screen = pygame.display.set_mode(WINDOW_SIZE) # screen size
done = False
clock = pygame.time.Clock()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:# mosue click detection
pos = pygame.mouse.get_pos()
column = pos[0] // (WIDTH + MARGIN)
row = pos[1] // (HEIGHT + MARGIN)
grid[row][column] = 1
print(onoff)
print("Grid coordinates: ", row, column)
for row in range(gridsize):
for column in range(gridsize):
color = WHITE #grid creation
if grid[row][column] == 1:
color = BLACK
pygame.draw.rect(screen,
color,
[(MARGIN + WIDTH) * column + MARGIN, # black rect
(MARGIN + HEIGHT) * row + MARGIN,
WIDTH,
HEIGHT])
clock.tick(60)
pygame.display.flip()
pygame.quit()
onoff = []
grid = []
for row in range(gridsize):
grid.append([])
for column in range(gridsize): # grid
grid[row].append([])
grid[row][column] = 0 # setting value of pixel to off
onoff.append(grid[row][column])
for x in range(len(grid)):
print(grid[x])
its ok i solved it, thanks anyways

Change element in matrix from 0 to 1 when event takes place

I've recently written a program with a list, but now I need to change the list into a matrix. I programmed a grid by drawing rectangles. Now I want to change the color of the rectangle when I click on it. In my program with the list everything worked just fine, but now I have to use a matrix, because I need a matrix for the rest of my program. I've already got a matrix with all zeros, but now I want to change the 0 in to a 1 when I click on a rectangle.
x = 5
y = 5
height = 30
width = 50
size = 20
color = (255,255,255)
new_color = (0,255,0)
screen.fill((0,0,0))
def draw_grid():
for y in range(height):
for x in range(width):
rect = pygame.Rect(x * (size + 1),y * (size + 1),size,size)
pygame.draw.rect(screen,color,rect)
x += 20
y += 20
rects = [[0 for i in range(width)] for j in range(height)]
draw_grid()
while 1:
clock.tick(30)
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
if menu == 'start':
if pygame.mouse.get_pressed()[0]:
mouse_pos = pygame.mouse.get_pos()
for i,(rect,color) in enumerate(rects):
if rect.collidepoint(mouse_pos):
rects[i] = (rect,new_color)
for rect,color in rects:
pygame.draw.rect(screen,color,rect)
pygame.display.flip()
This is the code I used with the list, but I've already replaced the list with a matrix. When I run this code it gives an error:
ValueError: too many values to unpack
What is the best way to solve this problem?
To draw the rects you can iterate over the matrix and depending on the value (0 or 1) draw a white rect or a green rect. (You could also store the colors directly in the matrix, but I don't know if you want to do something else with it.)
To change the color of the clicked cells, you can easily calculate the indexes of the cells by floor dividing the mouse coords by (size+1), e.g. x = mouse_x // (size+1). Then just set matrix[y][x] = 1.
import sys
import pygame
WHITE = pygame.Color('white')
GREEN = pygame.Color('green')
def draw_grid(screen, matrix, size):
"""Draw rectangles onto the screen to create a grid."""
# Iterate over the matrix. First rows then columns.
for y, row in enumerate(matrix):
for x, color in enumerate(row):
rect = pygame.Rect(x*(size+1), y*(size+1), size, size)
# If the color is white ...
if color == 0:
pygame.draw.rect(screen, WHITE, rect)
# If the color is green ...
elif color == 1:
pygame.draw.rect(screen, GREEN, rect)
def main():
screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
height = 30
width = 50
size = 20 # Cell size.
matrix = [[0 for i in range(width)] for j in range(height)]
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if pygame.mouse.get_pressed()[0]:
# To change the color, calculate the indexes
# of the clicked cell like so:
mouse_x, mouse_y = pygame.mouse.get_pos()
x = mouse_x // (size+1)
y = mouse_y // (size+1)
matrix[y][x] = 1
screen.fill((30, 30, 30))
# Now draw the grid. Pass all needed values to the function.
draw_grid(screen, matrix, size)
pygame.display.flip()
clock.tick(30)
if __name__ == '__main__':
pygame.init()
main()
pygame.quit()
sys.exit()

Pygame buttons functionality and correcting grid select mouse function

I've added two rectangles, red and green to the top of the following code, and for some reason my code, which otherwise worked, does not now. The grid cells should go RED when clicked, but the clicking is skewed. Can anyone advise on the problem? I have two issues:
An upvote to the first one to spot and point out the error, unless I get it first!
I also want to add text (user 1 and user 2) to the rectangles and make them clickable. On clicking, the user selects a random grid cell (which turns either red or green)
Code as follows:
import pygame
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
pygame.init()
size = (350, 350)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("My Game")
done = False
clock = pygame.time.Clock()
width=22
height=22
margin=12
grid=[]
#Loop for each row in the list
for row in range(7):
#for each row, create a list that will represent an entire row
grid.append([])
#loop for each column
for column in range(7):
#add the number zero to the current row
grid[row].append(0)
#set row 1, column 5 to one
#grid[1][3]=1
#print(grid[1][3]) #this is the 2nd row and the 4th element along (0...1 row and 0...1...2....3 Column)
# -------- Main Program Loop -----------
while not done:
#ALL EVENT PROCESSING SHOULD GO BELOW THIS LINE
# --- Main event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
#************CODE ADDED HERE**********************
elif event.type == pygame.MOUSEBUTTONDOWN:
#print("user clicked the screen")
pos=pygame.mouse.get_pos()
#x = grid[0]
#y= grid[1]
#print(pos)
#CHANGE THE X and Y screen coordinates as in the comments above to grid coordinates
column=pos[0]//(width+margin+50)
row=pos[1]//(height+margin+60)
#set the location to one (when selected by the mouse)
grid[row][column]=1
#print("User click ", pos, "Grid coordinates:", row+1, column+1)
# --- Game logic should go here
# --- Screen-clearing code goes here
# Here, we clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
# If you want a background image, replace this clear with blit'ing the
# background image.
screen.fill(BLACK)
# --- Drawing code should go here
#Drawing the red and Green rectangles
pygame.draw.rect(screen,RED, [0,0,120,50])
pygame.draw.rect(screen,GREEN, [240,0,120,50])
for row in range(7):
#the column number - this refers to the number of columns it will produce. 2, for example, will produce only 2 columns
for column in range(7):
color = WHITE
if grid[row][column] ==1:
color = RED
#****MOVING THE REST OF THE GRID DOWN*****
#the 60 is the margin from the top
#the 50 is the margin from the left
pygame.draw.rect(screen,color,[(margin + width) * column + margin+50, (margin + height) * row + margin+60,width,height])
#*******PRINTING TEXT TO THE SCREEN**********
# Select the font to use, size, bold, italics
#font = pygame.font.SysFont('Calibri', 25, True, False)
#text = font.render("a", True, BLACK)
# Put the image of the text on the screen at 250x250
#screen.blit(text, [25, 25])
# --- This bit updates the screen with what we've drawn.
pygame.display.flip()
# --- Limit to 60 frames per second
clock.tick(60)
# Close the window and quit.
pygame.quit()
This is by no means an ideal way to achieve your goal, but I tried to keep the code as consistent with yours as possible. Let me know if you have any questions about how this works. I will do my best to answer quickly.
import pygame
from pygame.locals import *
pygame.init()
# first we define some constants
# doing this will reduce the amount of 'magic' numbers throughout the code
WINWIDTH = 350
WINHEIGHT = 350
WINSIZE = (WINWIDTH, WINHEIGHT)
CELLWIDTH = 22
CELLHEIGHT = 22
CELLSIZE = (CELLWIDTH, CELLHEIGHT)
CELLMARGINX = 12 # number of pixels to the left and right of each cell
CELLMARGINY = 12 # number of pixels to the top and bottom of each cell
SCREENPADX = 60 # number of pixels between the GRID and the left and right of the window
SCREENPADY = 70 # number of pixels between the GRID and the top and bottom of the window
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
DONE = False # is our program finished running?
# information about the two buttons (red and green)
REDBUTTON = (0, 0, 120, 50)
GREENBUTTON = (240, 0, 120, 50)
# create the WINDOW and CLOCK
WINDOW = pygame.display.set_mode(WINSIZE)
pygame.display.set_caption('My Game')
CLOCK = pygame.time.Clock()
CURRENTCOLOR = RED # which color is active
# setting up the GRID
# cells can be accessed by GRID[row][col] ie. GRID[3][4] is the 3rd row and 4th column
# each cell contains [x, y, color]
# where x is the x position on the screen
# y is the y position on the screen
# color is the current color of the cell
GRID = []
for y in range(7):
row = []
for x in range(7):
row.append([x * (CELLWIDTH + CELLMARGINX) + SCREENPADX, y * (CELLHEIGHT + CELLMARGINY) + SCREENPADY, WHITE])
GRID.append(row)
# main loop
while not DONE:
# process all events
for event in pygame.event.get():
if event.type == QUIT: # did the user click the 'x' to close the window
DONE = True
if event.type == MOUSEBUTTONDOWN:
# get the position of the mouse
mpos_x, mpos_y = event.pos
# check if REDBUTTON was clicked
button_x_min, button_y_min, button_width, button_height = REDBUTTON
button_x_max, button_y_max = button_x_min + button_width, button_y_min + button_height
if button_x_min <= mpos_x <= button_x_max and button_y_min <= mpos_y <= button_y_max:
CURRENTCOLOR = RED
# check if GREENBUTTON WAS CLICKED
button_x_min, button_y_min, button_width, button_height = GREENBUTTON
button_x_max, button_y_max = button_x_min + button_width, button_y_min + button_height
if button_x_min <= mpos_x <= button_x_max and button_y_min <= mpos_y <= button_y_max:
CURRENTCOLOR = GREEN
# calculations for clicking cells
mpos_x -= SCREENPADX # mouse position relative to the upper left cell
mpos_y -= SCREENPADY # ^ same
col = mpos_x // (CELLWIDTH + CELLMARGINX) # which cell is the mouse clicking
row = mpos_y // (CELLHEIGHT + CELLMARGINY) # ^ same
# make sure the user clicked on the GRID area
if row >= 0 and col >= 0:
try:
# calculate the boundaries of the cell
cell_x_min, cell_y_min = col * (CELLHEIGHT + CELLMARGINY), row * (CELLWIDTH + CELLMARGINX)
cell_x_max = cell_x_min + CELLWIDTH
cell_y_max = cell_y_min + CELLHEIGHT
# now we will see if the user clicked the cell or the margin
if cell_x_min <= mpos_x <= cell_x_max and cell_y_min <= mpos_y <= cell_y_max:
GRID[row][col][2] = CURRENTCOLOR if event.button == 1 else WHITE
else:
# the user has clicked the margin, so we do nothing
pass
except IndexError: # clicked outside of the GRID
pass # we will do nothing
# logic goes here
# drawing
WINDOW.fill(BLACK)
pygame.draw.rect(WINDOW, RED, REDBUTTON)
pygame.draw.rect(WINDOW, GREEN, GREENBUTTON)
for row in GRID:
for x, y, color in row:
pygame.draw.rect(WINDOW, color, (x, y, CELLWIDTH, CELLHEIGHT))
pygame.display.flip()
CLOCK.tick(60)
pygame.quit()

Categories

Resources