How I should randomly flip arrow with next arrow? - python

I am creating simple game through pygame. In the code arrow is flipping randomly with each pygame. Draw but I want it to flip (randomly when next arrow in the game.
This is incomplete code
import pygame
import random
import sys
pygame.init()
h=600
w=800
arrow_pos=[w/2,0]
base_size=[w/2,50]
base_pos=[w/4,h-50]
screen=pygame.display.set_mode((w,h))
bg_color=(0,0,0)
base_color=(255,0,0)
arrow_color=(0,150,255)
clock=pygame.time.Clock()
game_over=False
def updating_arrow(arrow_pos):
if arrow_pos[1]>=0 and arrow_pos[1]<h:
arrow_pos[1]+=10
else:
arrow_pos[1]-=h
return arrow_pos[1]
def draw_arrow(screen,arrow_color,arrow_pos,arrow_size):
pygame.draw.polygon(screen, arrow_color, ((arrow_pos[0],
arrow_pos[1]+10), (arrow_pos[0], arrow_pos[1]+20),
(arrow_pos[0]+arrow_size, arrow_pos[1]+20),
(arrow_pos[0]+arrow_size,
arrow_pos[1]+30), (arrow_pos[0]+(arrow_size)*1.5,
arrow_pos[1]+15),
(arrow_pos[0]+arrow_size, arrow_pos[1]),
(arrow_pos[0]+arrow_size,
arrow_pos[1]+10)),0)
while not game_over:
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
screen.fill(bg_color)
arrow_pos[1]=updating_arrow(arrow_pos)
arrow_size=random.choice([50,-50])
draw_arrow(screen,arrow_color,arrow_pos,arrow_size)
pygame.draw.rect(screen,base_color,
(base_pos[0],base_pos[1],base_size[0],base_size[1]))
pygame.display.update()
clock.tick(30)

Randomly initialize the arrow_size before the main loop:
arrow_size = random.choice([50,-50])
while not game_over:
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
Only change the arrow size, when a new arrow appears at the top of the window. You've to use the global statement to change the value of the globale variable arrow_size in the function updating_arrow:
def updating_arrow(arrow_pos):
global arrow_size
if arrow_pos[1] >= 0 and arrow_pos[1] < h:
arrow_pos[1] += 10
else:
arrow_pos[1] -= h
arrow_size = random.choice([50,-50])
return arrow_pos[1]
Or pass arrow_size to the function by a parameter and return the changed, as you do it with arrow_pos:
def updating_arrow(arrow_pos, arrow_size):
if arrow_pos[1]>=0 and arrow_pos[1]<h:
arrow_pos[1]+=10
else:
arrow_pos[1]-=h
arrow_size = random.choice([50,-50])
return arrow_pos, arrow_size
arrow_pos, arrow_size = updating_arrow(arrow_pos, arrow_size)
# arrow_pos[1]=updating_arrow(arrow_pos) <---- delete
# arrow_size=random.choice([50,-50]) <---- delete

Related

How can I end this game

I am trying to make a game wherein when the player icon collides with meowth the game ends and screen shows the text "GAME OVER" persitently. However when i run this program there is a short blink and the game continues. What changes should I make to the given code? Also when i click the quit button of the game window it simply hangs there and the game window/screen does not close. I would relly appreciate any help or inputs or any further suggestons to this game by you guys.
import random
import pygame
import math
from pygame import mixer
pygame.init()
mixer.init()
# create the screen
screen=pygame.display.set_mode((800,600))
#icon and title
pygame.display.set_caption("pokecapture")
icon=pygame.image.load("C:\\users\\khuhan rawat\\Desktop\\pokemon\\pokeball.png")
pygame.display.set_icon(icon)
#background
bg=pygame.image.load("C:\\users\\khuhan rawat\\Desktop\\pokemon\\background.png")
# player
playerImg=pygame.image.load("C:\\users\\khuhan rawat\\Desktop\\pokemon\\pokeball.png")
playerX=374
playerY=536
playerX_change=0
def player(x,y):
screen.blit(playerImg,(x,y))
#sound
mixer.music.load("C:\\users\\khuhan rawat\\Desktop\\pokemon\\bgsound.wav")
mixer.music.play(-1)
#score
score=0
font=pygame.font.SysFont('inkfree.ttf',40)
textX=10
textY=10
def show_score():
score1=font.render('SCORE:'+str(score),True, (0,0,0))
screen.blit(score1,(30,30))
#pokemons
bullbasaur=pygame.image.load("C:\\users\\khuhan rawat\\Desktop\\pokemon\\bullbasaur.png")
charmander=pygame.image.load("C:\\users\\khuhan rawat\\Desktop\\pokemon\\charmander.png")
dratini=pygame.image.load("C:\\users\\khuhan rawat\\Desktop\\pokemon\\dratini.png")
eevee=pygame.image.load("C:\\users\\khuhan rawat\\Desktop\\pokemon\\eevee.png")
jigglypuff=pygame.image.load("C:\\users\\khuhan rawat\\Desktop\\pokemon\\jigglypuff.png")
meowth=pygame.image.load("C:\\users\\khuhan rawat\\Desktop\\pokemon\\meowth (2).png")
pikachu=pygame.image.load("C:\\users\\khuhan rawat\\Desktop\\pokemon\\pikachu.png")
psyduck=pygame.image.load("C:\\users\\khuhan rawat\\Desktop\\pokemon\\psyduck.png")
snorlax=pygame.image.load("C:\\users\\khuhan rawat\\Desktop\\pokemon\\snorlax.png")
squirtle=pygame.image.load("C:\\users\\khuhan rawat\\Desktop\\pokemon\\squirtle.png")
poke=[bullbasaur,charmander,dratini,eevee,jigglypuff,meowth,pikachu,psyduck,snorlax,squirtle]
pokeImg=[meowth,pikachu]
pokeX=[]
pokeY=[]
pokeY_change=[1,1]
for i in range(8):
n=random.randint(0,9)
poke1=poke[n]
pokeImg.append(poke1)
pokeX.append(random.randint(0,768))
pokeY.append(random.randint(-80,400))
pokeY_change.append(1)
for i in range (2):
pokeX.append(random.randint(0,768))
pokeY.append(random.randint(-80,400))
def pokemon(x,y,i,l):
screen.blit(l[i],(x,y))
#collision
def collision(x,y,playerX,playerY):
dist=math.sqrt((math.pow(x-playerX,2))+(math.pow(y-playerY,2)))
if dist<=27:
return True
#game over
over_font=pygame.font.SysFont('inkfree.ttf',60)
def gameover():
overtext=over_font.render("GAME OVER",True,(0,0,0))
screen.blit(overtext,(20,300))
#game loop
running=True
while running:
screen.fill((0,0,0))
screen.blit(bg,(0,0))
for event in pygame.event.get():
if event.type==pygame.QUIT:
running=False
if event.type==pygame.KEYDOWN:
if event.key==pygame.K_LEFT:
playerX_change=-3
if event.key==pygame.K_RIGHT:
playerX_change=3
if event.type==pygame.KEYUP:
playerX_change=0
playerX+=playerX_change
if playerX<=0:
playerX=0
elif playerX>=736:
playerX=736
player(playerX,playerY)
#show score
for i in range(10):
pokeY[i]+=pokeY_change[i]
pokemon(pokeX[i],pokeY[i],i,pokeImg)
col=collision(pokeX[i],pokeY[i],playerX,playerY)
if pokeY[i]>=600:
pokeY[i]=random.randint(-20,40)
pokeX[i]=random.randint(0,768)
if col:
char=pokeImg[i]
if char==pikachu:
np=random.randint(0,9)
pokeX[i]=random.randint(0,736)
pokeY[i]=random.randint(0,40)
pokemon(pokeX[i],pokeY[i],np,poke)
cap=mixer.Sound("C:\\users\\khuhan rawat\\Desktop\\pokemon\\capture.wav")
cap.play()
score+=5
elif char==meowth:
for i in range(10):
pokeY[i]=2000
screen.fill((34,34,34))
gameover()
break
else:
np=random.randint(0,9)
pokeX[i]=random.randint(0,736)
pokeY[i]=random.randint(0,40)
pokemon(pokeX[i],pokeY[i],np,poke)
cap=mixer.Sound("C:\\users\\khuhan rawat\\Desktop\\pokemon\\capture.wav")
cap.play()
score+=5
np=random.randint(0,9)
pokeX[i]=random.randint(0,736)
pokeY[i]=random.randint(0,40)
pokemon(pokeX[i],pokeY[i],np,poke)
cap=mixer.Sound("C:\\users\\khuhan rawat\\Desktop\\pokemon\\capture.wav")
cap.play()
show_score()
pygame.display.update()
The break in the gameover condition only breaks the for loop, not the outer while loop.
elif char==meowth:
for i in range(10):
pokeY[i]=2000
screen.fill((34,34,34))
gameover()
running = False
break
Setting the running flag to False should solve the issue.

How to integrate 'MENU' code for my game with the actual gaming code?

I have created a basic game. Now I want to expand on the basic game and add a video game menu to it. I have two programs:
Basic game code
MENU code
I want to integrate both codes into one so that my game becomes more functional. I am just a beginner and need directions on how to do that. Thanks for helping.
BASIC GAME CODE:
import pygame
import random
import sys
pygame.init()
w=800
h=600
red=(251,63,75)
blue=(104,41,171)
yellow=(255,255,0)
player_size=25
player_pos=[w/2,h-(2*player_size)]
enemy_size=25
enemy_pos=[random.randint(0,w-enemy_size),0]
enemy_list=[ ]
bg_color=(0,0,0)
screen=pygame.display.set_mode((w,h))
game_over=False
speed=10
score=0
clock=pygame.time.Clock()
myFont=pygame.font.SysFont("monospace",35)
def set_level(score,speed):
if score<10:
speed=5
elif score<20:
speed=6
elif score<30:
speed=8
elif score<40:
speed=10
elif score<50:
speed=13
elif score<200:
speed=15
else:
speed=20
return speed
def drop_enemies(enemy_list):
delay=random.random()
if len(enemy_list)<6 and delay<0.1:
x_pos=random.randint(0,w-enemy_size)
y_pos=0
enemy_list.append([x_pos,y_pos])
def draw_enemies(enemy_list):
for enemy_pos in enemy_list:
pygame.draw.rect(screen,blue,
(enemy_pos[0],enemy_pos[1],enemy_size,enemy_size))
def update_enemy_pos(enemy_list,score):
for idx,enemy_pos in enumerate(enemy_list):
if enemy_pos[1]>=0 and enemy_pos[1]<h:
enemy_pos[1]+=speed
else:
enemy_list.pop(idx)
score+=1
return score
def detect_collision(player_pos,enemy_pos):
p_x=player_pos[0]
p_y=player_pos[1]
e_x=enemy_pos[0]
e_y=enemy_pos[1]
if (e_x>=p_x and e_x<(p_x+player_size)) or (p_x>=e_x and p_x<(e_x+enemy_size)):
if (e_y>=p_y and e_y<(p_y+player_size)) or (p_y>=e_y and p_y<(e_y+enemy_size)):
return True
return False
def collision_check(enemy_list,player_pos):
for enemy_pos in enemy_list:
if detect_collision(enemy_pos,player_pos):
return True
return False
while not game_over:
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
if event.type==pygame.KEYDOWN:
x=player_pos[0]
y=player_pos[1]
if event.key==pygame.K_LEFT:
x-=player_size
elif event.key==pygame.K_UP:
y-=player_size
elif event.key==pygame.K_RIGHT:
x+=player_size
elif event.key==pygame.K_DOWN:
y+=player_size
player_pos=[x,y]
screen.fill(bg_color)
drop_enemies(enemy_list)
score=update_enemy_pos(enemy_list,score)
speed=set_level(score,speed)
text='Your Score is:' + str(score)
label=myFont.render(text,1,yellow)
screen.blit(label,(w/2,h-40))
if collision_check(enemy_list,player_pos):
game_over=True
break
draw_enemies(enemy_list)
pygame.draw.rect(screen,red,
(player_pos[0],player_pos[1],player_size,player_size))
clock.tick(30)
pygame.display.update()
pygame.display.flip()
GAME MENU CODE:
import pygame
import random
import sys
pygame.init()
w=800
h=600
bg_color=(34,139,34)
red=(255,0,0)
blue=(0,0,125)
bright_blue=(0,0,255)
font_size=35
b1_pos=[w/2-50,h/2]
b1_size=[105,50]
screen=pygame.display.set_mode((w,h))
myFont=pygame.font.SysFont("freesansbold.tff",font_size)
def button(b1_pos,b1_size):
mouse_pos=pygame.mouse.get_pos()
click=pygame.mouse.get_pressed()
if (b1_pos[0]<mouse_pos[0]<(b1_pos[0]+b1_size[0])) and (b1_pos[1]<mouse_pos[1]<(b1_pos[1]+b1_size[1])):
pygame.draw.rect(screen,bright_blue,(b1_pos[0],b1_pos[1],b1_size[0],b1_size[1]))
if click[0]==1:
print("Left click")
else:
pygame.draw.rect(screen,blue,(b1_pos[0],b1_pos[1],b1_size[0],b1_size[1]))
text='START'
label=myFont.render(text,1,red)
screen.blit(label,(w/2-38,h/2+5))
game_over=False
while not game_over:
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
screen.fill(bg_color)
button(b1_pos,b1_size)
pygame.display.update()
When creating a game you need something called The MainLoop. All the code that needs to be updated in every frame goes inside this loop. This loop runs forever until the game is terminated. Check these video tutorials and this
Let me give you an example:
import pygame
#Import literals such as QUIT
from pygame.locals import *
pygame.init()
w = 800
h = 600
screen = pygame.display.set_mode((w,h))
running = True
def MenuCode():
pass
def GameCode():
pass
#This is the Game Loop.
while running:
#Events are used to check if a key has
#been pressed or a mouse button or a mouse movement.
for event in pygame.event.get():
#If the user pressed the x button.
#terminate the while loop.
if event.type == QUIT:
running = False
break;
#In every frame you must clean the window with a color
#in order to draw anythin else above it.
screen.fill((0,0,0))
#Here draw anything you like
#Also somewhere here call all the code that needs to be
#called every frame (Menu code, Game code, etc)
MenuCode()
GameCode()
#Lastly you must update the display.
#The most important thing that this does
#is called buffer swapping, check it out.
pygame.display.update()
#When the loop terminates, terminate pygame.
pygame.quit()
If you want to learn what the update() method does check about double buffering

drawing the moving objects all at once instead of drawing one then moving onto the next one

this code draws the basics of my orbit simulator but as soon as it has done one orbit with a planet it moves onto the next one in the list, how do i make it so it does all of the different orbits at the same time.
#import the library
import pygame,math
#classes
class planet():
def __init__(self,name,colour,distance,eccentricity,radius,x,y,angle):
self.screen = screen
self.name = name
self.colour = colour
self.distance = distance
self.eccentricity = eccentricity
self.radius = radius
self.x = x
self.y = y
self.angle = angle
def draw(self):
pygame.draw.circle(self.screen,self.colour,(self.x,self.y),self.radius,)
def draw_orbit(screen,colour,x,y,r):
screen.fill(Black)
int(r)
pygame.draw.circle(screen,colour,[x,y],r)
pygame.display.flip
orbit()
also i can make it so there is only one item in the list but it never does more than one rotation so, if i add planet.angle+360 instead of just the 360 it does the first one but never moves of it.
def orbit(planet):
while planet.angle <= 360:
a = planet.distance*(1.496*10**8)
e = planet.eccentricity
angle_radians = math.radians(planet.angle)
r = a*(1-(e*math.cos(angle_radians)))
planet.x = int(math.cos(angle_radians)*r/10**6)
planet.y = int(math.sin(angle_radians)*r/10**6)
planet.angle +=1
## print(planet.angle)
## print(planet.x,planet.y)
planet.x +=800
planet.y +=400
screen.fill(Black)
pygame.draw.circle(screen,Red,center,10)
## pygame.draw.circle(screen,White,center,r,1)
pygame.draw.circle(screen,planet.colour,[planet.x,planet.y],planet.radius)
pygame.display.flip()
#define colours
Black = (0,0,0)
White = (255,255,255)
Green = (0,255,0)
Red = (255,0,0)
Blue = (0,0,255)
#initialise the engine
pygame.init()
#Opening a window
size = (1600,800)
screen = pygame.display.set_mode(size)
center = [800,400]
planets =[]
planet_draw =[]
# screen,name,colour,distance,eccentricity,radius,x,y
planet_list = [
['Mercury',White,0.387,0.2056,5,0,0,120],
['Venus',Green,0.723,0.0068,10,0,0,60],
['Earth',Blue,1,0.0167,10,0,0,0],
['Mars',White,1.524,0.0934,10,0,0,150],
['Jupiter',Green,5.203,0.0484,30,0,0,330],
## [screen,'Saturn',Red,9.537,0.0542,10,0,0],
## [screen,'Uranus',Red,19.191,0.0472,10,0,0],
## [screen,'Neptune',Green,30.069,0.0086,10,0,0]
]
for i in planet_list:
planet_draw.append(planet(i[0],i[1],i[2],i[3],i[4],i[5],i[6],i[7]))
#set window title
pygame.display.set_caption("Orbit Simulator")
#loop unti the user clicks the close button
done = False
#used to manage how fast the screen updates
clock = pygame.time.Clock()
#------ Main program Loop ------
while not done:
#--- Main event loop
for event in pygame.event.get(): #user did something
if event.type == pygame.QUIT: #if user clicked close
done = True #flag that we are done and exit the loop
#------ Game logic should go here ------
for planet in planet_draw:
orbit(planet)
#------ Drawing code should go here -------
#first, clear the screen to white. Don't put other drawing commands above this or they will be erased with this command.
#update the screen
pygame.display.flip()
#------ Limit to 60 frames per second ------
clock.tick(60)
#------ When the loop ends, quit ------
pygame.quit()
The problem is your orbit() function. It's clearing and repainting the entire screen, each time a new planet is drawn.
The function only needs to draw the planet, the clearing of the screen and flipping should be done elsewhere.
Some pseudocode ~
Update Orbits (just the positions)
Clear screen
Draw N planets
Page flip
Wait for timer tick
Giving Code:
def orbit(planet):
while planet.angle <= 360:
a = planet.distance*(1.496*10**8)
e = planet.eccentricity
angle_radians = math.radians(planet.angle)
r = a*(1-(e*math.cos(angle_radians)))
planet.x = int(math.cos(angle_radians)*r/10**6)
planet.y = int(math.sin(angle_radians)*r/10**6)
planet.angle +=1
# Note: Don't paint, Don't offset for screen size
while not done:
#--- Main event loop
for event in pygame.event.get(): #user did something
if event.type == pygame.QUIT: #if user clicked close
done = True #flag that we are done and exit the loop
#------ Game logic should go here ------
# ---- move the planets -----
for planet in planet_draw:
orbit(planet)
# ------ Re-paint the current state of the screen ------
screen.fill(Black)
for planet in planet_draw:
planet.draw()
pygame.display.flip()
#------ Limit to 60 frames per second ------
clock.tick(60)
It might work out easier to modify your planet object such that given the time-tick (or some counter), it re-calculates the orbit co-ordinates at this time. This could give you code like:
while ( True ):
frame_counter = pygame.get_ticks()
screen.fill(Black)
for planet in planet_draw:
planet.calcuateOrbitAt( frame_counter )
planet.draw()
pygame.display.flip()
And it handles jumping orbits at really slow frame rates.

Give time to a bomb before to explode on pygame

I am doing a kind of bomberman, and I am trying to do that the bomb explodes after a while. Sorry if this question already exists. I have been looking for any answer but I didnt find.
This should be like:
1. I put a bomb somewhere
2. The bomb waits 5 seconds
3. The bomb explodes
I dont know how to give the 5 seconds before to explode.
class bomb(object):
def __init__(self, aposX, aposY, bombRange = 5):
self.posX = aposX
self.posY = aposY
self.bombRange = bombRange
self.timeToExplode = 5000
pygame.draw.circle(ventana,(200,0,0),(self.posX,self.posY),20)
def update(self):
pygame.draw.circle(ventana,(200,0,0),(self.posX,self.posY),20)
#Here should wait 5 seconds and then call the explde method
self.explode()
def explode(self):
pygame.draw.line(ventana,(200,0,0),(self.posX,self.posY),(self.posX+20+(40*self.bombRange),self.posY),40)
pygame.draw.line(ventana,(200,0,0),(self.posX,self.posY),(self.posX-20-(40*self.bombRange),self.posY),40)
pygame.draw.line(ventana,(200,0,0),(self.posX,self.posY),(self.posX,self.posY+20+(40*self.bombRange)),40)
pygame.draw.line(ventana,(200,0,0),(self.posX,self.posY),(self.posX,self.posY-20-(40*self.bombRange)),40)
I hope you can help me.I am going to appreciate that.
Here's a little example with the dt variant. I pass the dt to the update method where I use it to decrement the timer attribute. In the main loop I just draw the lines of the explosion if the timer is below 0. To remove the instances I put the exploded bombs into a set which I subtract from the bomb_set that contains all bomb instances.
import pygame
class Bomb(object):
def __init__(self, aposX, aposY, bombRange=5):
self.posX = aposX
self.posY = aposY
self.bombRange = bombRange
self.timeToExplode = 3000
def update(self, dt):
# Subtract the passed time `dt` from the timer each frame.
self.timeToExplode -= dt
def explode(self, screen):
pygame.draw.line(screen,(200,0,0),(self.posX,self.posY),(self.posX+20+(40*self.bombRange),self.posY),40)
pygame.draw.line(screen,(200,0,0),(self.posX,self.posY),(self.posX-20-(40*self.bombRange),self.posY),40)
pygame.draw.line(screen,(200,0,0),(self.posX,self.posY),(self.posX,self.posY+20+(40*self.bombRange)),40)
pygame.draw.line(screen,(200,0,0),(self.posX,self.posY),(self.posX,self.posY-20-(40*self.bombRange)),40)
def draw(self, screen):
pygame.draw.circle(screen,(200,0,0),(self.posX,self.posY),20)
def main():
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
bomb_set = set() # This set holds the bomb instances.
done = False
while not done:
# Get the passed time since last clock.tick call.
dt = clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
bomb_set.add(Bomb(*event.pos))
# Game logic.
to_remove = set()
# Update bombs. Pass the `dt` to the bomb instances.
for bomb in bomb_set:
bomb.update(dt)
# Add old bombs to the to_remove set.
if bomb.timeToExplode <= -3000:
to_remove.add(bomb)
# Remove bombs fromt the bomb_set.
if to_remove:
bomb_set -= to_remove
# Draw everything.
screen.fill((30, 30, 30))
for bomb in bomb_set:
bomb.draw(screen)
# I'm just drawing the explosion lines each
# frame when the time is below 0.
if bomb.timeToExplode <= 0:
bomb.explode(screen)
pygame.display.flip()
if __name__ == '__main__':
pygame.init()
main()
pygame.quit()

text not showing up dynamically, pygame

The code below is supposed to create a green button that makes a score text appear. unfortunately the button does nothing, and the only way I've managed to get it to work is by putting the function call for makeText in the while loop instead of in the clickButton function, but if I do that it's no longer dynamic. Can someone explain why the text isn't showing up when I press the button and fix my code so it does show up?
import pygame
import sys
#game stuff
pygame.init()
screen = pygame.display.set_mode((640, 480),0,32)
clock = pygame.time.Clock()
#functions
def makeText(title,text,posx,posy):
font=pygame.font.Font(None,30)
scoretext=font.render(str(title)+ ": " +str(text), 1,(0,0,0))
screen.blit(scoretext, (posx, posy))
def clickButton(name,x,y,width,height):
if x + width > cur[0] > x and y + height > cur[1] > y:
if click == (1,0,0):
makeText("score",300,100,10)
#objects
button1 = pygame.Rect((0,0), (32,32))
while True:
screen.fill((255,255,255))
screen.fill((55,155,0), button1)
#update display
pygame.display.update()
clock.tick(60)
#event handling
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
elif event.type == pygame.MOUSEBUTTONDOWN:
cur = event.pos
click = pygame.mouse.get_pressed()
clickButton("button1",button1.left,button1.top,button1.width,button1.height)
The problem is that once you created the text, your main loop keeps going and calls screen.fill, overdrawing the text even before pygame.display.update() is called.
You could change it to:
...
def clickButton(name,x,y,width,height):
print x + width > cur[0] > x and y + height > cur[1] > y
if x + width > cur[0] > x and y + height > cur[1] > y:
if click == (1,0,0):
makeText("score",300,100,10)
#objects
button1 = pygame.Rect((0,0), (32,32))
while True:
screen.fill((255,255,255))
screen.fill((55,155,0), button1)
#event handling
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
elif event.type == pygame.MOUSEBUTTONDOWN:
cur = event.pos
click = pygame.mouse.get_pressed()
clickButton("button1",button1.left,button1.top,button1.width,button1.height)
...
so the text is created after filling the screen with the background color and before pygame.display.update() is called, but that does not solve the problem of the screen being filled again the next iteration of the while loop.
So the solution is to keep track of the fact that the button was pressed, a.k.a. keeping track of a state.
Here's an example of a different approach, using classes for the buttons and a dict for the global state (so you don't need global variables, which should you avoid most of the time, because it can get very confusing fast if your game starts becoming more complex).
Click the first button to show or hide the score, and click the second button to change the background color and earn 100 points.
See how easy it becomes to create new buttons; it's just adding a simple function.
import pygame
import sys
import random
pygame.init()
screen = pygame.display.set_mode((640, 480),0,32)
clock = pygame.time.Clock()
# create font only once
font = pygame.font.Font(None,30)
# it's always a good idea to cache all text surfaces, since calling 'Font.render' is
# an expensive function. You'll start to notice once your game becomes more complex
# and uses more text. Also, use python naming conventions
text_cache = {}
def make_text(title, text):
key = "{title}: {text}".format(title=title, text=text)
if not key in text_cache:
text = font.render(key, 1,(0,0,0))
text_cache[key] = text
return text
else:
return text_cache[key]
# we use the 'Sprite' class because that makes drawing easy
class Button(pygame.sprite.Sprite):
def __init__(self, rect, color, on_click):
pygame.sprite.Sprite.__init__(self)
self.rect = rect
self.image = pygame.Surface((rect.w, rect.h))
self.image.fill(color)
self.on_click = on_click
# this happens when the first button is pressed
def toggle_score_handler(state):
state['show_score'] = not state['show_score']
# this happens when the second button is pressed
def toggle_backcolor_handler(state):
state['backcolor'] = random.choice(pygame.color.THECOLORS.values())
state['score'] += 100
# here we create the buttons and keep them in a 'Group'
buttons = pygame.sprite.Group(Button(pygame.Rect(30, 30, 32, 32), (55, 155 ,0), toggle_score_handler),
Button(pygame.Rect(250, 250, 32, 32), (155, 0, 55), toggle_backcolor_handler))
# here's our game state. In a real
# game you probably have a custom class
state = {'show_score': False,
'score': 0,
'backcolor': pygame.color.Color('White')}
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
# you can check for the first mouse button with 'event.button == 1'
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
# to check if the mouse is inside the button, you
# can simple use the 'Rect.collidepoint' function
for button in (b for b in buttons if b.rect.collidepoint(event.pos)):
button.on_click(state)
screen.fill(state['backcolor'])
# draw all buttons by simple calling 'Group.draw'
buttons.draw(screen)
if state['show_score']:
screen.blit(make_text("score", state['score']), (100, 30))
pygame.display.update()
clock.tick(60)
You are checking the value of "click" in the clickButton function, but I don't see click defined anywhere that clickButton would have access to it.
Perhaps you should pass click as an argument in the clickButton function, which would then possibly make the if condition true?

Categories