How to fix pygame blinking gemetric shape - python

Hi I want to make a game with rhombus what I want to fix is that I set the clock to XY and in while true cycles I have function with one built me a cube
I want to create a game with levels on each level a cube will be made again with another random variation of colors. I have not levels method created yet so I want to create a cube with some colors and after a restarting code, It should be another color variation. But I can not fix a blinking.
my code:
import pygame as pg
import random
pg.init()
screen = pg.display.set_mode((500, 800))
clock = pg.time.Clock()
BG_COLOR = pg.Color('black')
WHITE = pg.Color('white')
ORANGE = pg.Color('orange')
BLUE = pg.Color('blue')
RED = pg.Color('red')
PURPLE = pg.Color('purple')
m = 8
def rhumbus(screen,color,plus):
point1=(170, 500-plus)
point2=(350, 500-plus)
point3=(300, 550-plus)
point4=(120, 550-plus)
points=[point1, point2, point3, point4]
return pg.draw.polygon(screen,color, points)
def cube(rando):
plus = -72
old_col = None
for x in range(0,10):
rando = random.choice([RED,ORANGE,RED,BLUE,WHITE])
if rando != old_col:
rhumbus(screen,rando,plus)
plus += 8
old_col = rando
else:
rhumbus(screen,PURPLE,plus)
plus += 8
old_col = rando
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
screen.fill(BG_COLOR)
cube(m)
pg.display.flip()
clock.tick(10)

Instead of choosing a random sequence of colors on each frame, pick them beforehand.
The new make_random_sequence function returns a list chosen randomly from the given sequence, making sure there are no consecutive repeats of the same item (which seemed to be your logic with old_col too?)
You were not actually using the rando parameter given to cube.
Using enumerate to loop over the colors and their indices is shorter than dealing with a plus variable.
import pygame as pg
import random
pg.init()
screen = pg.display.set_mode((500, 800))
clock = pg.time.Clock()
BG_COLOR = pg.Color('black')
WHITE = pg.Color('white')
ORANGE = pg.Color('orange')
BLUE = pg.Color('blue')
RED = pg.Color('red')
PURPLE = pg.Color('purple')
def rhumbus(screen, color, plus):
point1 = (170, 500 - plus)
point2 = (350, 500 - plus)
point3 = (300, 550 - plus)
point4 = (120, 550 - plus)
points = [point1, point2, point3, point4]
return pg.draw.polygon(screen, color, points)
def make_random_sequence(options, n):
seq = []
while len(seq) < n:
choice = random.choice(options)
if seq and choice == seq[-1]: # skip if same as last
continue
seq.append(choice)
return seq
def cube(colors):
for i, color in enumerate(colors):
rhumbus(screen, color, -72 + i * 8)
colors = make_random_sequence([RED, ORANGE, BLUE, WHITE], 8)
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
screen.fill(BG_COLOR)
cube(colors)
pg.display.flip()
clock.tick(10)

Related

How to I make multiple rects in different places? [duplicate]

Right now, my game blits all the images in random positions correctly and also gets the rect of the images correctly, but I can´t figure out how to use colliderect to make sure the images don´t overlap. How could it work for my code?
Also I´m trying to make the first text fade out and I don´t know why it doesn´t work for me.
Here is the code:
class GAME1:
def __init__(self, next_scene):
self.background = pygame.Surface(size)
# Create an array of images with their rect
self.images = []
self.rects = []
self.imagenes1_array = ['autobus.png','coche.png','barco.png','autobus2.png','grua.png','bici.png']
for i in self.imagenes1_array:
# We divide in variables so we can then get the rect of the whole Img (i2)
i2 = pygame.image.load(i)
self.images.append(i2)
s = pygame.Surface(i2.get_size())
r = s.get_rect()
# Trying to use colliderect so it doesnt overlap
if pygame.Rect.colliderect(r,r) == True:
x = random.randint(300,1000)
y = random.randint(200,700)
self.rects.append(r)
def start(self, gamestate):
self.gamestate = gamestate
for rect in self.rects:
# Give random coordinates (we limit the dimensions (x,y))
x = random.randint(300,1000)
y = random.randint(200,700)
rect.x = x
rect.y = y
def draw(self,screen):
self.background = pygame.Surface(size)
font = pygame.font.SysFont("comicsansms",70)
# First half (Show image to remember)
text1 = font.render('¡A recordar!',True, PURPLE)
text1_1 = text1.copy()
# This surface is used to adjust the alpha of the txt_surf.
alpha_surf = pygame.Surface(text1_1.get_size(), pygame.SRCALPHA)
alpha = 255 # The current alpha value of the surface.
if alpha > 0:
alpha = max(alpha-4, 0)
text1_1 = text1.copy()
alpha_surf.fill((255, 255, 255, alpha))
text1_1.blit(alpha_surf, (0,0), special_flags = pygame.BLEND_RGBA_MULT)
screen.blit(text1_1, (600,50))
# Second half (Show all similar images)
text2 = font.render('¿Cuál era el dibujo?',True, PURPLE)
#screen.blit(text2, (500,50))
for i in range(len(self.images)):
#colliding = pygame.Rect.collidelistall(self.rects)
screen.blit(self.images[i], (self.rects[i].x, self.rects[i].y))
def update(self, events, dt):
for event in events:
if event.type == pygame.MOUSEBUTTONDOWN:
for rect in self.rects:
if rect.collidepoint(event.pos):
print('works!')
Use collidelist() to test test if one rectangle in a list intersects:
for i in self.imagenes1_array:
s = pygame.image.load(i)
self.images.append(s)
r = s.get_rect()
position_set = False
while not position_set:
r.x = random.randint(300,1000)
r.y = random.randint(200,700)
margin = 10
rl = [rect.inflate(margin*2, margin*2) for rect in self.rects]
if len(self.rects) == 0 or r.collidelist(rl) < 0:
self.rects.append(r)
position_set = True
See the minimal example, that uses the algorithm to generate random not overlapping rectangles:
import pygame
import random
pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
def new_recs(rects):
rects.clear()
for _ in range(10):
r = pygame.Rect(0, 0, random.randint(30, 40), random.randint(30, 50))
position_set = False
while not position_set:
r.x = random.randint(10, 340)
r.y = random.randint(10, 340)
margin = 10
rl = [rect.inflate(margin*2, margin*2) for rect in rects]
if len(rects) == 0 or r.collidelist(rl) < 0:
rects.append(r)
position_set = True
rects = []
new_recs(rects)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.KEYDOWN:
new_recs(rects)
window.fill(0)
for r in rects:
pygame.draw.rect(window, (255, 0, 0), r)
pygame.display.flip()
pygame.quit()
exit()

Having an image appear multiple times Pygame

I have a single battery image appearing once here and it moves from right to left then goes away. I want batteries constantly coming and going until the player hits one of them.
My question is how do I get the batteries to keep on coming until a player hits it? I want them to appear maybe 100 units apart.
from pygame import *
import os
import random
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d, %d" %(0, 0)
init()
#set screen size
size = width, height = 800, 600
screen = display.set_mode(size)
#set fonts
fontGame=font.SysFont("Times New Roman", 30)
fontBack=font.SysFont("Ariel", 30)
fontTitle=font.SysFont("Ariel", 100)
fontResearch=font.SysFont ("Times New Roman", 18)
#set button and page to 0
button = 0
page=0
#setting colours
BLACK = (0, 0, 0)
RED = (255,0,0)
GREEN = (0, 255, 0)
BLUE = (106,186,232)
#loading image
backgroundPic=image.load("Background.jpg")
backgroundGame=image.load("gameBackground.jpg")
backgroundGame=transform.scale(backgroundGame,(800,600))
battery=image.load("Battery.png")
battery=transform.scale(battery,(100,100))
backgroundx=0
playerPic=image.load("player.png")
playerPic=transform.scale(playerPic,(70,70))
batteryx=[]
#defining what is going to be shown on the screen
def drawScene(screen, button,page,locationx,locationy):
global batteryx
mx, my = mouse.get_pos() #will get where the mouse is
#if the user does nothing
if page==0:
draw.rect(screen, BLACK, (0,0, width, height))
screen.fill(BLACK)
rel_backgroundx= backgroundx % backgroundGame.get_rect().width
screen.blit(backgroundGame, (rel_backgroundx - backgroundGame.get_rect().width,0))
if rel_backgroundx < width:
screen.blit (backgroundGame, (rel_backgroundx,0))
screen.blit(playerPic,(locationx,locationy))
screen.blit(battery,(batteryx,420))
batteryx-=1
display.flip()
return page
#def collision (battery, playerPic):
#if battery.colliderect(playerPic):
#return True
#return False
running = True
myClock = time.Clock()
KEY_LEFT= False
KEY_RIGHT= False
KEY_UP= False
KEY_DOWN= False
locationx=0
jumping=False
accel=20
onGround= height-150
locationy=onGround
batteryx=random.randrange(50,width,10)
# Game Loop
while running:
button=0
print (KEY_LEFT, KEY_RIGHT)
for evnt in event.get(): # checks all events that happen
if evnt.type == QUIT:
running=False
if evnt.type == MOUSEBUTTONDOWN:
mx,my=evnt.pos
button = evnt.button
if evnt.type== KEYDOWN:
if evnt.key==K_LEFT:
KEY_LEFT= True
KEY_RIGHT= False
if evnt.key==K_RIGHT:
KEY_RIGHT= True
KEY_LEFT= False
if evnt.key==K_UP and jumping==False:
jumping=True
accel=20
if evnt.key== K_DOWN:
KEY_DOWN= True
KEY_UP= False
if evnt.type==KEYUP:
if evnt.key==K_LEFT:
KEY_LEFT= False
if evnt.key==K_RIGHT:
KEY_RIGHT= False
if evnt.key==K_DOWN:
KEY_DOWN=False
if KEY_LEFT== True:
locationx-=10
backgroundx+=10
if KEY_RIGHT== True:
locationx+=10
backgroundx-=10
if jumping==True:
locationy-=accel
accel-=1
if locationy>=onGround:
jumping=False
locationy=onGround
#player cannot move off screen
if locationx<0:
locationx=0
if locationx>400:
locationx=400
#if collision(battery, playerPic)==True:
#screen.fill(BLACK)
page=drawScene(screen,button,page,locationx,locationy)
myClock.tick(60) # waits long enough to have 60 fps
if page==6: #if last button is clicked program closes
running=False
quit()
Create a list of rects which serve as the positions of the batteries. Use for loops to update the rects and blit the battery image at the rects. Remove rects that have left the screen and append new rects to create new batteries
import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
BG_COLOR = pg.Color('gray12')
battery_image = pg.Surface((30, 50))
battery_image.fill(pg.Color('sienna1'))
# Append pygame.Rect objects to this list.
batteries = []
batteries.append(battery_image.get_rect(topleft=(700, 100)))
battery_speed = -5
battery_timer = 40
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
# A simple frame based timer.
battery_timer -= 1
if battery_timer <= 0:
battery_timer = 40
# After 40 frames a new rect gets appended to the list.
batteries.append(battery_image.get_rect(topleft=(700, 100)))
temp_list = []
# Iterate over the rects to update them.
for battery_rect in batteries:
battery_rect.x += battery_speed
# Rects with x <= 50 won't be appended to the temp_list.
if battery_rect.x > 50:
temp_list.append(battery_rect)
# Assign the list with the remaining rects to the batteries variable.
batteries = temp_list
# Blit everything.
screen.fill(BG_COLOR)
for battery_rect in batteries:
screen.blit(battery_image, battery_rect)
pg.display.flip()
clock.tick(30)
pg.quit()

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

How do I change the color of a single rectangle in a grid?

I've already programmed a grid, but now I want to change the color of a single rectangle in the grid.
x = 5
y = 5
height = 30
width = 50
size = 20
color = (255,255,255)
new_color = (255,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
rects.append((rect,color))
y += 20
rects = []
colored_rects = []
while 1:
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
draw_grid()
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)
colored_rects.append((rect,new_color))
for rect,color in rects:
pygame.draw.rect(screen,color,rect)
for rect,new_color in colored_rects:
pygame.draw.rect(screen,new_color,rect)
pygame.display.flip()
clock.tick()
Now I only want to change one rectangle when I click on it, but later they must change automatically (for example when there are three rectangles touching in the same color, they all must become white). I've updated a little bit, but there are still some problems. For example: You have to click on the rectangle till it changes color, and it takes to much time te change color.
One solution would be to store the rects together with their color in tuples. If the mouse button is pressed, you iterate over the rectangles list, if a rectangle collides with the mouse, you create a tuple with the rect and the new color and replace the tuple at the current index.
import sys
import pygame as pg
def main():
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
height = 30
width = 50
size = 20
color = (255, 255, 255)
new_color = (255, 255, 0)
rectangles = []
for y in range(height):
for x in range(width):
rect = pg.Rect(x * (size+1), y * (size+1), size, size)
# The grid will be a list of (rect, color) tuples.
rectangles.append((rect, color))
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
if pg.mouse.get_pressed()[0]:
mouse_pos = pg.mouse.get_pos()
# Enumerate creates tuples of a number (the index)
# and the rect-color tuple, so it looks like:
# (0, (<rect(0, 0, 20, 20)>, (255, 255, 255)))
# You can unpack them directly in the head of the loop.
for index, (rect, color) in enumerate(rectangles):
if rect.collidepoint(mouse_pos):
# Create a tuple with the new color and assign it.
rectangles[index] = (rect, new_color)
screen.fill((30, 30, 30))
# Now draw the rects. You can unpack the tuples
# again directly in the head of the for loop.
for rect, color in rectangles:
pg.draw.rect(screen, color, rect)
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
pg.init()
main()
pg.quit()
sys.exit()

Pygame Rectangle and Mouse pos Collidepoint not working

I'm making a basic game where I have a surface and everytime I click on the surface it moves 5 pixels to the right. The program is working just fine without the checkCollide(event) function, but when I put the that condition it doesn't move. What is wrong?
My code until now is this
import pygame, sys
from pygame.locals import *
pygame.init()
DISPLAYSURF = pygame.display.set_mode((300,300))
def checkCollide(event):
k = 0
a,b = event.pos
x = P1[0].get_rect()
if x.collidepoint(a,b):
return True
return False
CP1 = [(150, 150)
,(155, 150)
,(160, 150)
,(165, 150)
,(170, 150)
,(175, 150)
,(180, 150)
,(185, 150)
,(190, 150)]
statp1_1 = 0
WHITE = (255,255,255)
DISPLAYSURF.fill(WHITE)
while True: # the main game loop
P1 = [pygame.image.load('PAzul.png'),CP1[statp1_1],statp1_1]
DISPLAYSURF.blit(P1[0], P1[1])
e = pygame.event.get()
for event in e:
if event.type == MOUSEBUTTONUP:
a = checkCollide(event)
if a:
DISPLAYSURF.fill(WHITE)
statp1_1 +=1
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
Thank you
Check your logic in these lines of your function:
x = P1[0][0].get_rect()
if x.collidepoint(a,b):
return True
return False
Your code hinges on this bit:
a = checkCollide(event)
if a:
DISPLAYSURF.fill(WHITE)
So you're never evaluating this piece to be true.
I just realized what was wrong. When I do x = P1[0].get_rect() it creates a surface with topleft at (0,0).
What I needed to do was change the position of the rectangle using x.topleft = P1[1]
I've got some tips for you. First store the rect in the P1 list (it contains only the image and the rect in the following example, but maybe you could also add the statp1_1 index to it). Now we can just move this rect, if the user clicks on it (in the example I set the topleft attribute to the next point). Read the comments for some more tips. One thing you need to fix is to prevent the game from crashing when the statp1_1 index gets too big.
import sys
import pygame
pygame.init()
DISPLAYSURF = pygame.display.set_mode((300, 300))
WHITE = (255, 255, 255)
# Don't load images in your while loop, otherwise they have to
# be loaded again and again from your hard drive.
# Also, convert loaded images to improve the performance.
P1_IMAGE = pygame.image.load('PAzul.png').convert() # or .convert_alpha()
# Look up `list comprehension` if you don't know what this is.
CP1 = [(150+x, 150) for x in range(0, 41, 5)]
statp1_1 = 0
# Now P1 just contains the image and the rect which stores the position.
P1 = [P1_IMAGE, P1_IMAGE.get_rect(topleft=CP1[statp1_1])]
clock = pygame.time.Clock() # Use this clock to limit the frame rate.
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONUP:
if P1[1].collidepoint(event.pos):
print('clicked')
statp1_1 += 1
# Set the rect.topleft attribute to CP1[statp1_1].
P1[1].topleft = CP1[statp1_1]
DISPLAYSURF.fill(WHITE)
DISPLAYSURF.blit(P1[0], P1[1]) # Blit image at rect.topleft.
pygame.display.update()
clock.tick(30) # Limit frame rate to 30 fps.

Categories

Resources