I am having a lot of difficulty at the moment with updating the score on the GUI of my basic game in python.
I currently have the code such that it appears in the top left hand corner, with the score appearing as "O". However, the score remains at 0 for the entirety of the program (as it is only getting rendered once. I am unsure how to constantly rerender the score to update it? I have tried many methods and have been unsuccessful. The part of the code with the score render and my attempt at keeping track of the score using the variable conlisionNumber is:
new = bears[:]
for bear in new: #this makes a copy of the array
if player.colliderect(bear):
windowSurface.blit(bearImageTwo, bear)
windowSurface.blit(playerImageTwo, player)
def explosion():
for bear in bears:
if player.colliderect(bear) and (moveLeft == False and moveRight == False and moveUp == False and moveDown == False):
bears.remove(bear)
colisionNumber += 1
if player.colliderect(bear) and (moveLeft == False and moveRight == False and moveUp == False and moveDown == False):
t = Timer(1, explosion)
t.start()
scoreFont = pygame.font.SysFont("impact", 20)
score = scoreFont.render("SCORE:" + str(colisionNumber), True, (192,192,192))
windowSurface.blit(score, (10,10))
Please note: at the start of the program I put:
global colisionNumber
colisionNumber = 0
This was done because if I defined colisionNumber within explosion, then colisionNumber would not be defined in the score variable.
Any help would be greatly appreciated.
colisionNumber = 0
def explosion():
global colisionNumber
colisionNumber += 1
Related
#Bounce bullet when it reaches corners.
def bullet_bounce(rect):
bottom_corner = False
if bottom_corner == False:
rect.y +=5
if rect.bottom == 400:
bottom_corner = True
if bottom_corner == True:
rect.y -=5
if rect.top == 0:
bottom_corner = False
While working with pygame to create Pong I want to make a rectangle bounce every time it reaches the corner of the screen. I came up with this code and it works as intented when I initialize bottom_corner outside the game loop and then run the rest of the code inside the loop. But since it would look much cleaner I want to implement this code inside as a function. The problem is since the function is called inside the loop bottom_corner is initialized as False every time the loop runs which leads to only the first half of the code being iterated. Do you have any recommendations on how to fix this issue?
You should define variable outside function and send to function as parameter and get it back with return
def bullet_bounce(rect, bottom_corner):
if not bottom_corner:
rect.y +=5
if rect.bottom == 400:
bottom_corner = True
else:
rect.y -=5
if rect.top == 0:
bottom_corner = False
return bottom_corner
# --- start program ---
bottom_corner = False
# --- some loop ---
while True:
bottom_corner = bullet_bounce(rect, bottom_corner)
I am not sure if I understood your question. But I recommend you avoid making equality comparisons between boolean values(True, False) and boolean variables. Instead of saying if bottom_corner == True use if bottom_corner: and else:
And to switch boolean variables you can use the not operator
#Bounce bullet when it reaches corners.
def bullet_bounce(rect):
if bottom_corner: rec.y -=5
else rec.y += 5
if (rec.bottom == 400) or (rect.top == 0):
# switch it based on previous value
bottom_corner = not bottom_corner
Recently started trying to learn pygame with the goal of making a simple platformer. So far, I've created a player that can move left and right and is affected by gravity. I haven't yet implemented object collision. Right now I'm trying to make a simple jump script. My current script for vertical movement is the following:
if man.y + man.height < ground:
man.yvel += man.velInc
elif man.y + man.height >= ground:
if man.isJump == True:
man.isJump == False
man.yvel = 0
if keys[pygame.K_SPACE] and man.isJump == False:
man.yvel = -20
man.isJump = True
man.y += man.yvel
This is run in a loop along with other stuff such as horizontal movement. ground is a variable that determines the y-coordinate of the ground, and is currently set to 350. The height of the window is 450. man.velInc is set to 1 and man.height is set to 32 I can provide any other info if necessary.
My problem is that when I run the program, I can only jump once, and then never again. I can still move left and right normally. I put in a script to print out man.x, man.y, and man.isJump. Before the jump, man.isJump is "False", and after, True. It never goes back to False. man.y also reads as 328. The jump itself however seems to work perfectly. I would appreciate any help to fix the issue, and maybe some advice on how to avoid things like this in the future.
You are confusing the == (Boolean equality) with = (set variable)
if man.y + man.height < ground:
man.yvel += man.velInc
elif man.y + man.height >= ground:
if man.isJump == True:
man.isJump = False # replace == with =
man.yvel = 0
if keys[pygame.K_SPACE] and man.isJump == False:
man.yvel = -20
man.isJump = True
man.y += man.yvel
I'm getting the following error:
TypeError: initialisePaddle() missing 1 required positional argument: 'color'
even if i already included a color argument into the code? or should I've added a global color variable?
Also how do I add a score tracker, which gives a point each time player1/2's ball makes contact/collision with a paddle?
from tkinter import *
from random import *
myHeight=400
myWidth=800
mySpeed=10
scoreplayer1=0
scoreplayer2=0
def initialiseBall(dx,dy,radius,color):
b=[myWidth/2,myHeight/2,dx,dy,radius]
b.append(myCanvas.create_oval(myWidth/2-radius,myHeight/2-radius,\
myWidth/2+radius,myHeight/2+radius,\
width=2,fill=color))
return b
def initialisePaddle(x,y,width, height, radius,color):
r=[x,y,0,0,width,height]
r.append(myCanvas.create_rectangle(x-width/2,y-height/2,\
x+width/2,y+height/2,\
width=2,fill=color))
return r
def updateBall():
# new position calculation
global scoreplayer1, scoreplayer2
newX=balle[0]+balle[2]
newY=balle[1]+balle[3]
hit1=paddle1[0]+paddle1[4]
hit2=paddle2[1]+paddle2[5]
if newY<0 or newY>=myHeight:
newY=balle[1]
balle[3]*=-1
# intersection with paddles
bbox1 = myCanvas.bbox(paddle1[6])
bbox2 = myCanvas.bbox(paddle2[6])
if newX <= bbox1[2] and (newY>bbox1[1] and newY<bbox1[3]):
newX=balle[0]
balle[2]*=-1
scoreplayer1+=1
if newX >= bbox2[0] and (newY>bbox2[1] and newY<bbox2[3]):
newX=balle[0]
balle[2]*=-1
scoreplayer2+=1
# update of coordinates
balle[0]=newX
balle[1]=newY
# update of graphic element
myCanvas.coords(balle[5],\
balle[0]-balle[4],balle[1]-balle[4],\
balle[0]+balle[4],balle[1]+balle[4])
def updatePaddle(r):
newY=r[1]+r[3]
if newY-r[5]/2<0 or newY+r[5]/2>=myHeight:
newY=r[1]
r[3]=0
r[1]=newY
myCanvas.coords(r[6],\
r[0]-r[4]/2,r[1]-r[5]/2,\
r[0]+r[4]/2,r[1]+r[5]/2)
def animation():
global score
updateBall()
updatePaddle(paddle1)
updatePaddle(paddle2)
myCanvas.after(mySpeed,animation)
def movePaddles(event):
if event.keysym == 'a':
paddle1[3]=-5
if event.keysym == 'q':
paddle1[3]=5
if event.keysym == 'Up':
paddle2[3]=-5
if event.keysym == 'Down':
paddle2[3]=5
def stopPaddles(event):
if event.keysym == 'q' or event.keysym == 'a':
paddle1[3]=0
if event.keysym == 'Up' or event.keysym == 'Down':
paddle2[3]=0
mainWindow=Tk()
mainWindow.title('Pong')
mainWindow.geometry(str(myWidth)+'x'+str(myHeight))
myCanvas=Canvas(mainWindow,bg='dark grey',height=myHeight,width=myWidth)
myCanvas.pack(side=TOP)
balle=initialiseBall(5,5,20,'red')
paddle1=initialisePaddle(60,myHeight/2,40,100,'green')
paddle2=initialisePaddle(myWidth-60,myHeight/2,40,100,'blue')
mainWindow.bind("<Key>",movePaddles)
mainWindow.bind("<KeyRelease>",stopPaddles)
animation()
mainWindow.mainloop()
Just remove radius from
def initialisePaddle(x,y,width, height, radius,color):
to eliminate the error.
As the previous answer suggested you need to remove the radius parameter.
To display the score you can use the Label widget. Once the ball goes out you need to stop the game so keep a global variable say gameOver=False and assign it True only if the ball goes out.
your updateBall function should look something like this.
def updateBall():
# new position calculation
global scoreplayer1, scoreplayer2, gameOver
newX=balle[0]+balle[2]
newY=balle[1]+balle[3]
hit1=paddle1[0]+paddle1[4]
hit2=paddle2[1]+paddle2[5]
if newY<0 or newY>=myHeight:
newY=balle[1]
balle[3]*=-1
# intersection with paddles
bbox1 = myCanvas.bbox(paddle1[6])
bbox2 = myCanvas.bbox(paddle2[6])
if (newX < bbox1[2] and newX>bbox1[0]) and (newY>=bbox1[1] and newY <= bbox1[3]):
newX=balle[0]
balle[2]*=-1
scoreplayer1+=1
score.config(text=f'Player1: {scoreplayer1}')
if (newX > bbox2[0] and newX<bbox2[2]) and(newY>=bbox2[1] and newY<=bbox2[3]):
newX=balle[0]
balle[2]*=-1
scoreplayer2 +=1
score2.config(text=f'Player2: {scoreplayer2}')
if newX<-20 or newX>myWidth+20:
gameOver = True
# update of coordinates
balle[0]=newX
balle[1]=newY
# update of graphic element
myCanvas.coords(balle[5],\
balle[0]-balle[4],balle[1]-balle[4],\
balle[0]+balle[4],balle[1]+balle[4])
and your animation function:
def animation():
global score, gameOver
if not gameOver:
updateBall()
updatePaddle(paddle1)
updatePaddle(paddle2)
myCanvas.after(mySpeed,animation)
else:
play = messagebox.askquestion('GameOver', f'GameOver!\nplayer1 score: {scoreplayer1}\nplayer2 score: {scoreplayer2}'\
'\n Do you want to continue? ')
if play == 'yes':
gameOver = False
myCanvas.moveto(balle[5], myCanvas.winfo_reqwidth()//2, myCanvas.winfo_reqheight()//2)
balle[0]=myCanvas.winfo_reqwidth()//2
balle[1]=myCanvas.winfo_reqheight()//2
myCanvas.after(100,animation)
the labels
mainWindow.geometry(f'{myWidth+100}x{myHeight+100}')
score = Label(mainWindow, text='Player1: 0')
score.pack()
score2 = Label(mainWindow, text='Player2: 0')
score2.pack()
Also, don't forget to import messagebox
I'm not sure what seems to be the problem with my code, I need some help. When I try running my program, it says invalid syntax next to my first if, I thought I may be an indentation error but nothing is working.
Here is my code:
import random
def montyHall():
car = random.randint(1,3)
guess1 = random.randint(1,3)
for i in range(1,3):
if ((not(i == car) and not(i == guess1)):
return i
newGuess = not(i) and not(guess1)
if (newGuess == car):
stay = True
elif (guess1 == car):
switch = False
return strategyOne
NUM_OF_TRIALS = 1000
stay = 0
switch = 0
for i in range(NUM_OF_TRIALS):
if(montyHall()):
stay += 1
else:
switch += 1
print("Staying wins", stay/NUM_OF_TRIALS, "% of the time")
print("Switching wins", switch/NUM_OF_TRIALS, "% of the time")
To many brackets and you do not need brackets in python.
Try changing:
if ((not(i == car) and not(i == guess1)):
to
if i != car and i != guess1:
Problem with Pygame! Colliderect function doesn't detect when two rects collide! The rects just fall through each other, though no error message is given. Why is this and how can it be fixed? Been struggling on this same problem for days on end! Supposed problem spot is labeled with a comment. Thanks in advance!
#Start it up
import pygame
pygame.init()
fpsClock = pygame.time.Clock()
#surface = pygame.display.set_mode((640,480),pygame.FULLSCREEN)
surface = pygame.display.set_mode((640,480))
pygame.display.set_caption('Game Skeleton')
#Globals and Misc.
x = 10
y = 350
l = 15
w = 35
moveX=0
moveY=0
characterRect= pygame.Rect(x,y,l,w)
ground = pygame.Rect(0,385,700,385)
ledge1= pygame.Rect(310,330,20,20)
jump=0
white = (255,255,255)
black = (0,0,0)
firebrick = (178,34,34)
blockRects = [ground,ledge1]
contact = False
playOn = True
var=0
#standingLeft = pygame.image.load("images/
#standingRight = pygame.image.load("images/
#walkingRight = pygame.image.load("images/
#walkingLeft = pygame.image.load("images/
#straightJumping = pygame.image.load("images/
#rightJumping = pygame.image.load("images/
#leftJumping = pygame.image.load("images/
#inquire = pygame.image.load("images/
#climbing = pygame.image.load("images/
#Game Loop
while playOn:
#Take user input
for event in pygame.event.get():
if(event.type==pygame.KEYDOWN):
if(event.key==pygame.K_RIGHT):
moveX=1
if(event.key==pygame.K_LEFT):
moveX=-1
if(event.key==pygame.K_UP):
moveY=-1
if(event.key==pygame.K_DOWN):
moveY=1
if(event.key==pygame.K_SPACE):
jump=1
if(event.key==pygame.K_ESCAPE):
playOn = False
if(event.type==pygame.KEYUP):
if(event.key==pygame.K_RIGHT):
moveX=0
if(event.key==pygame.K_LEFT):
moveX=0
if(event.key==pygame.K_UP):
moveY=0
if(event.key==pygame.K_DOWN):
moveY=0
#If user input said to move
x = x + moveX
y = y + moveY
#Jump Code
if(jump>0 and contact==False):
y=y-jump - 1
var=var+1
if(var>45):
jump=0
var=0
if(contact==False):
y=y+1
if(contact!=True):
contact==False
#These two "ifs" don't appear to be working D:
if (ground.colliderect(characterRect)):
y=y-1
contact == True
if(ledge1.colliderect(characterRect)):
y=y-1
contact == True
#Renderings
surface.fill(white)
pygame.draw.rect(surface,black,(x,y,l,w))
pygame.draw.rect(surface,firebrick,(0,385,700,385))
pygame.draw.rect(surface,firebrick,(340,350,100,5))
fpsClock.tick(80)
pygame.display.flip()
pygame.quit()
You are initializing:
characterRect= pygame.Rect(x,y,l,w)
Then you update x,y,l,w variables independently and forget about the characterRect, so the characterRect rect is always on the same position.
You can make the updates directly on the characterRect or assign the new y value before checking for colliderect.
#Justin Pearce corrections are also important, otherwise your code will not work correctly.
Also take a look at PEP 8. For a good looking python code, you should remove brackets around the if conditions.
You have this:
if(contact!=True):
contact==False
#These two "ifs" don't appear to be working D:
if (ground.colliderect(characterRect)):
y=y-1
contact == True
if(ledge1.colliderect(characterRect)):
y=y-1
contact == True
Should that not be?:
if(contact!=True):
contact=False
#These two "ifs" don't appear to be working D:
if (ground.colliderect(characterRect)):
y=y-1
contact = True
if(ledge1.colliderect(characterRect)):
y=y-1
contact = True
Double equals is a comparison operator, not an assignment operator.