Having an image appear multiple times Pygame - python

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

Related

How to update blitted text's text?

I'm trying to make a Cookie Clicker type game using PyGame, but when I use this bit of code:
def display(thing: pygame.Surface, where: tuple=(0, 0), center=False):
WIN.blit(thing, where if center == False else thing.get_rect(center = (WIN.get_width() // 2, WIN.get_height() // 2)))
def font(font: pygame.font.Font, text: str, colour: tuple=(255, 255, 255)):
return font.render(text, False, colour)
def main():
cookies = 0
cps = 1
clock = pygame.time.Clock()
tim = time.time()
run = True
while run:
clock.tick(FPS)
if time.time() - tim > 1:
tim = time.time()
cookies += cps
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
t = font(CFONT64, f"{cookies} Cookies")
display(t, t.get_rect(center = (WIN.get_width() // 2, WIN.get_height() * .07)))
pygame.display.update()
quitPy()
(not full code)
It'll do this:
and overlap the text when it next updates.
How do I clear the text/change the text?
Everything that is drawn is drawn on the target Surface. The entire scene has to be redrawn in each frame. Therefore, the display must be cleared at the beginning of each frame in the application loop:
while run:
# [...]
# clear display
WIN.fill((0, 0, 0))
# draw scene
display(t, t.get_rect(center = (WIN.get_width() // 2, WIN.get_height() * .07)))
# update disaply
pygame.display.update()

How to fix pygame blinking gemetric shape

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)

How to show text when true

I want to show a text on the screen when a variable changes to True. The Text "Game Over" is show for a very short period of time with this code but I disappears after less than one second.
import pygame
import random
import time
import math
# Initialize pygame
pygame.init()
# Create window (width, height)
screen1 = pygame.display.set_mode(((800, 600)))
ScreenHeight = screen1.get_height()
ScreenWidth = screen1.get_width()
#Game Over text
go_font = pygame.font.Font('freesansbold.ttf', 128)
go_text = "GAME OVER"
go_textX = 300
go_textY = 300
def show_gameover(go_textX, go_textY):
gameover_text = font.render(go_text, True, (105, 105, 105))
screen1.blit(gameover_text, (go_textY,go_textY))
# Variable to track gameover
gameover = False
while running:
if gameover:
show_gameover(go_textX, go_textY)
# Insert Background
screen1.blit(background, (0, 0))
i = 0
for obs in obstacle_list:
obs.spawn_obstacle()
obs.update_y()
outOfBounds = obs.out_of_bounds(playerX, playerY)
if outOfBounds:
obstacle_list.pop(i)
collision = obs.collision_detection(playerX, playerY)
if collision:
gameover = True
show_gameover(go_textX, go_textY) #Show Gameover-text
i += 1
# Update after each iteration of the while-loop
pygame.display.update()
You have to draw the text after the background. If you draw the text before drawing the background, it will be hidden from the background. Draw it just before updating the display. So it is drawn over all other objects in the scene.
while running:
# Insert Background
screen1.blit(background, (0, 0))
# [...]
if gameover:
show_gameover(go_textX, go_textY)
# Update after each iteration of the while-loop
pygame.display.update()

How do you make the string appear after hitting the return key

I am creating a flashcard game for my kid. Its about Dinos. I am having trouble making "Congrats, You got it right" appear on the screen. I have moved my code all over the place but no luck. Can someone please help me out.
To be clear, What I want to happen is when the user presses the number 1,2,3 on the keypad, and if the key is the correct answer that correlates to the question, the message "Congrats, You got it right!" should appear on the screen.
I know the keydown event right now is the return key, but I did that for testing purposes only. This is also the same for testtext variable. I was using that variable to see if I could print "Hello WOrld" to the screen.
I do have a feeling it has something to do with the loop that is running. My guess would be is that it does show up for a fraction of a second but disappears before anyone can see it.
import pygame, random
pygame.font.init()
pygame.init()
font = pygame.font.Font(None, 48)
#Created the window display
size = width, height = 800,800
screen = pygame.display.set_mode(size)
#Loads the images of the starting game Trex
#t_rex = pygame.image.load('trex1.png')
##Places the image on the screen
#screen.blit(t_rex,(150,50))
count = 0
score = 0
active = False
testtext = font.render("Hello WOrld", True, (250, 250, 250))
#The below code keeps the display window open until user decides to quie app
crashed = False
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
if event.type==pygame.KEYDOWN:
if event.key==pygame.K_RETURN:
screen.blit(testtext, (200,699))
while count < 2:
screen.fill(0)
dinoQuestions = ["Does a t-rex eat meat?\n","Does a trycerotopes have 3 horns?\n"]
dinoAnswer = ["Yes\n", "No\n","Maybe\n"]
wordnum = random.randint(0, len(dinoQuestions)-1)
mainpic = pygame.image.load("trex1.png")
screen.blit(mainpic, (150, 20))
options = [random.randint(0, len(dinoAnswer)-1),random.randint(0, len(dinoAnswer)-1)]
options[random.randint(0,1)] = wordnum
question_display = font.render(dinoQuestions[wordnum].rstrip('\n'),True, (255, 255, 255))
text1 = font.render('1 - ' + dinoAnswer[options[0]].rstrip('\n'),True, (255, 255, 255))
text2 = font.render('2 - ' + dinoAnswer[options[1]].rstrip('\n'),True, (255, 255, 255))
#the below code is for testing purposes only
screen.blit(question_display,(200, 590))
screen.blit(text1, (200, 640))
screen.blit(text2, (200, 690))
count = count + 1
pygame.display.flip()
The blit to your screen surface you perform when handling a Return key down event is overwritten when you later call screen.fill(0).
I've rearranged your code a little and added displaying a result on appropriate key press.
import pygame
import random
pygame.init()
pygame.font.init()
font = pygame.font.Font(None, 48)
size = width, height = 800,800
screen = pygame.display.set_mode(size) #Created the window display
count = 0
score = 0
active = False
white = pygame.color.Color("white")
black = pygame.color.Color("black")
green = pygame.color.Color("green")
# load/create static resources once
mainpic = pygame.image.load("trex1.png")
testtext = font.render("Hello World", True, (250, 250, 250))
correct_text = font.render("Correct! Well Done!", True, green)
clock = pygame.time.Clock() # for limiting FPS
dinoQuestions = ["Does a t-rex eat meat?","Does a triceratops have 3 horns?"]
dinoAnswer = ["Yes", "No","Maybe"]
# initialise state
show_hello = False
show_correct = False
update_questions = True # need to update questions on the first iteration
finished = False
while not finished:
for event in pygame.event.get():
if event.type == pygame.QUIT:
finished = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
show_hello = not show_hello # toggle flag for later display
elif event.key == pygame.K_SPACE:
update_questions = True
elif event.key in [pygame.K_1, pygame.K_2]:
# an answer has been selected
# pygame.K_1 is 0, pygame.K_2 is 1
if dinoAnswer[event.key - pygame.K_1] == "Yes":
show_correct = True
count += 1
else:
show_correct = False
screen.fill(black)
screen.blit(mainpic, (150, 20))
if show_hello:
screen.blit(testtext, (200,199))
if show_correct:
screen.blit(correct_text, (200, 300))
if update_questions:
random.shuffle(dinoQuestions)
random.shuffle(dinoAnswer)
question_display = font.render(dinoQuestions[0],True, white)
text1 = font.render('1 - ' + dinoAnswer[0],True, white)
text2 = font.render('2 - ' + dinoAnswer[1],True, white)
update_questions = False
show_correct = False
# Display the Question
screen.blit(question_display,(200, 590))
screen.blit(text1, (200, 640))
screen.blit(text2, (200, 690))
# count = count + 1
pygame.display.flip()
clock.tick(60)
Hopefully this is enough of a framework for you to extend.
Let me know if you have any questions about any portions of the code.
I am a bit confused about what your exact problem is, so I'm going to try to answer. You say that you want the words "Congrats, , you got it right!", so I can help you with what went wrong. You blit the testtext before you color the screen, so each time the loop loops, it displays the testtext but then almost instantly covers it up with screen.fill(0). To make it better, you should put the blitting of the text after the screen is colored. The best way to do this is to put it right at the start of the loop, or making another event detector after the current position of the screen.fill in the code.
Also, I would get rid of the stacked while loop, and instead replace it with if statement because it is already in the while loop.
Is this what you were looking for?

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