# 1 - Import library
import pygame
from pygame.locals import *
import math
import random
# 2 - Initialize the game
pygame.init()
width, height = 640, 480
screen=pygame.display.set_mode((width, height))
keys = [False, False, False, False]
playerpos=[100,100]
acc=[0,0]
arrows=[]
badtimer=100
badtimer1=0
badguys=[[640,100]]
healthvalue=194
pygame.mixer.init()
# 3 - Load image
player = pygame.image.load("C:\python27\PyGame\resources\images\dude.png")
grass = pygame.image.load("C:\python27\PyGame\resources\images\grass.png")
castle = pygame.image.load("C:\python27\PyGame\resources\images\castle.png")
arrow = pygame.image.load("C:\python27\PyGame\resources\images\bullet.png")
badguyimg1 = pygame.image.load("C:\python27\PyGame\resources\image\badguy.png")
badguyimg=badguyimg1
healthbar = pygame.image.load("C:\python27\PyGame\resources\images\healthbar.png")
health = pygame.image.load("C:\python27\PyGame\resources\images\health.png")
gameover = pygame.image.load("C:\python27\PyGame\resources\images\gameover.png")
youwin = pygame.image.load("C:\python27\PyGame\resources\images\youwin.png")
# 3.1 - Load audio
hit = pygame.mixer.Sound("C:\python27\PyGame\resources\audio\explode.wav")
enemy = pygame.mixer.Sound("C:\python27\PyGame\resources\audio\enemy.wav")
shoot = pygame.mixer.Sound("C:\python27\PyGame\resources\audio\shoot.wav")
hit.set_volume(0.05)
enemy.set_volume(0.05)
shoot.set_volume(0.05)
pygame.mixer.music.load('C:\python27\PyGame\resources\audio\moonlight.wav')
pygame.mixer.music.play(-1, 0.0)
pygame.mixer.music.set_volume(0.25)
# 4 - keep looping through
running = 1
exitcode = 0
while running:
badtimer-=1
# 5 - clear the screen before drawing it again
screen.fill(0)
# 6 - draw the player on the screen at X:100, Y:100
for x in range(width/grass.get_width()+1):
for y in range(height/grass.get_height()+1):
screen.blit(grass,(x*100,y*100))
screen.blit(castle,(0,30))
screen.blit(castle,(0,135))
screen.blit(castle,(0,240))
screen.blit(castle,(0,345 ))
# 6.1 - Set player position and rotation
position = pygame.mouse.get_pos()
angle = math.atan2(position[1]-(playerpos[1]+32),position[0]-(playerpos[0]+26))
playerrot = pygame.transform.rotate(player, 360-angle*57.29)
playerpos1 = (playerpos[0]-playerrot.get_rect().width/2, playerpos[1]-playerrot.get_rect().height/2)
screen.blit(playerrot, playerpos1)
# 6.2 - Draw arrows
for bullet in arrows:
index=0
velx=math.cos(bullet[0])*10
vely=math.sin(bullet[0])*10
bullet[1]+=velx
bullet[2]+=vely
if bullet[1]<-64 or bullet[1]>640 or bullet[2]<-64 or bullet[2]>480:
arrows.pop(index)
index+=1
for projectile in arrows:
arrow1 = pygame.transform.rotate(arrow, 360-projectile[0]*57.29)
screen.blit(arrow1, (projectile[1], projectile[2]))
# 6.3 - Draw badgers
if badtimer==0:
badguys.append([640, random.randint(50,430)])
badtimer=100-(badtimer1*2)
if badtimer1>=35:
badtimer1=35
else:
badtimer1+=5
index=0
for badguy in badguys:
if badguy[0]<-64:
badguys.pop(index)
badguy[0]-=7
# 6.3.1 - Attack castle
badrect=pygame.Rect(badguyimg.get_rect())
badrect.top=badguy[1]
badrect.left=badguy[0]
if badrect.left<64:
hit.play()
healthvalue -= random.randint(5,20)
badguys.pop(index)
#6.3.2 - Check for collisions
index1=0
for bullet in arrows:
bullrect=pygame.Rect(arrow.get_rect())
bullrect.left=bullet[1]
bullrect.top=bullet[2]
if badrect.colliderect(bullrect):
enemy.play()
acc[0]+=1
badguys.pop(index)
arrows.pop(index1)
index1+=1
# 6.3.3 - Next bad guy
index+=1
for badguy in badguys:
screen.blit(badguyimg, badguy)
# 6.4 - Draw clock
font = pygame.font.Font(None, 24)
survivedtext = font.render(str((90000-pygame.time.get_ticks())/60000)+":"+str((90000-pygame.time.get_ticks())/1000%60).zfill(2), True, (0,0,0))
textRect = survivedtext.get_rect()
textRect.topright=[635,5]
screen.blit(survivedtext, textRect)
# 6.5 - Draw health bar
screen.blit(healthbar, (5,5))
for health1 in range(healthvalue):
screen.blit(health, (health1+8,8))
# 7 - update the screen
pygame.display.flip()
# 8 - loop through the events
for event in pygame.event.get():
# check if the event is the X button
if event.type==pygame.QUIT:
# if it is quit the game
pygame.quit()
exit(0)
if event.type == pygame.KEYDOWN:
if event.key==K_w:
keys[0]=True
elif event.key==K_a:
keys[1]=True
elif event.key==K_s:
keys[2]=True
elif event.key==K_d:
keys[3]=True
if event.type == pygame.KEYUP:
if event.key==pygame.K_w:
keys[0]=False
elif event.key==pygame.K_a:
keys[1]=False
elif event.key==pygame.K_s:
keys[2]=False
elif event.key==pygame.K_d:
keys[3]=False
if event.type==pygame.MOUSEBUTTONDOWN:
shoot.play()
position=pygame.mouse.get_pos()
acc[1]+=1
arrows.append([math.atan2(position[1]-(playerpos1[1]+32),position[0]-(playerpos1[0]+26)),playerpos1[0]+32,playerpos1[1]+32])
# 9 - Move player
if keys[0]:
playerpos[1]-=5
elif keys[2]:
playerpos[1]+=5
if keys[1]:
playerpos[0]-=5
elif keys[3]:
playerpos[0]+=5
#10 - Win/Lose check
if pygame.time.get_ticks()>=90000:
running=0
exitcode=1
if healthvalue<=0:
running=0
exitcode=0
if acc[1]!=0:
accuracy=acc[0]*1.0/acc[1]*100
else:
accuracy=0
# 11 - Win/lose display
if exitcode==0:
pygame.font.init()
font = pygame.font.Font(None, 24)
text = font.render("Accuracy: "+str(accuracy)+"%", True, (255,0,0))
textRect = text.get_rect()
textRect.centerx = screen.get_rect().centerx
textRect.centery = screen.get_rect().centery+24
screen.blit(gameover, (0,0))
screen.blit(text, textRect)
else:
pygame.font.init()
font = pygame.font.Font(None, 24)
text = font.render("Accuracy: "+str(accuracy)+"%", True, (0,255,0))
textRect = text.get_rect()
textRect.centerx = screen.get_rect().centerx
textRect.centery = screen.get_rect().centery+24
screen.blit(youwin, (0,0))
screen.blit(text, textRect)
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit(0)
pygame.display.flip()
here is the error message
Traceback (most recent call last):
File "C:\Python27\game2.py", line 22, in
player = pygame.image.load("C:\python27\PyGame\resources\images\dude.png")
error: Couldn't open C:\python27\PyGame\resources\images\dude.png
What should I do?
First, make sure the file exists.
Next, using single backslashes, \, may lead to problems. For example, \r is the carriage return sequence (\n is the more widely known newline sequence). Your file path, happens to contain a \r, which could be causing your issue.
Try one of these instead:
# Use forward slashes
pygame.image.load("C:/python27/PyGame/resources/images/dude.png")
# Use double back-slashes. For file path specification, \\ indicates '\' (depending
# on the platform)
pygame.image.load("C:\\python27\\PyGame\\resources\\images\\dude.png")
# Use the os module
# Note that this assembles a path relative to your .py file.
# Absolute path can still be done here, it's just more verbose.
pygame.image.load(os.path.join("Pygame", "resources", "images", "dude.png"))
The last option is probably the best practice.
Related
I can't seem to figure out why my groups Pygame code keeps flickering when we run it. pygame.display.update is only called once, but our background seems to be potentially causing the issue.
Any an all help would be greatly appreciated! :)
Here's a link to my Replit with the code:
https://replit.com/#LukaLUSV6912/Santa-vs-Evil-Elves-Game?v=1
We are trying to get rid of the flickering from the Pygame animation and implement a winning and loosing screen based off the visibility of the elves(enemies) when the timer runs down to 0
Instructions: move with right + left arrow keys and fire snowballs with spacebar
'''"""
import pygame, random
pygame.init() # initialize pygame managers
# create a window
w = 600
h = 600
win = pygame.display.set_mode((w,h)) # define window variable
# pygame.display.set_caption("Read carefully.") # uncomment & edit to caption the window
#======================== Variables & functions ===================================================
img_size = (50,100)
img_size2 = (30,30)
# class that creates Santa
class Santa:
def __init__(self,color,x,y):
self.color = color
self.x = x
self.y = y
self.img = pygame.image.load("santaimg.png").convert_alpha()
self.img = pygame.transform.scale(self.img, img_size)
self.center=(x,y)
# The methods Right and Left allow Santa to move right and left and have boundries
def Right(self):
if self.x <551:
self.x +=20
self.center=(self.x,self.y)
# self.rect=self.img.get_rect(center=self.center)
def Left(self):
if self.x >0:
self.x -=20
self.center=(self.x,self.y)
# self.rect=self.img.get_rect(center=self.center)
# method that allows the bubbles to be drawn on the screen
def show(self):
# self.img = pygame.image.load("santaimg.png").convert()
# self.rect=self.img.get_rect(center=self.center)
win.blit(self.img, self.center)
#pygame.draw.ellipse(win,self.color,self.img)
#Class that creates the elves
class Elves():
def __init__(self, color, pos_x, pos_y):
self.color = color
self.pos_x= pos_x
self.pos_y = pos_y
self.square = 20
self.velocity = 0 # elves start stationary
self.box = pygame.Rect(self.pos_x,self.pos_y,self.square,self.square)
self.img2 = pygame.image.load("elfimg.png").convert_alpha()
self.img2 = pygame.transform.scale(self.img2,img_size2)
#self.area = pygame.Surface((self.square,self.square))
self.draw = True
# method that displays the elves
def Show(self):
if (self.draw == True):
win.blit(self.img2, (self.pos_x, self.pos_y))
# method that makes elves dissapear if snowball hits them
def dissapear(self, box):
global Dis
if (self.draw):
if self.box.colliderect(box): # box is the rect for elf
Dis += 1 # Each time user hits elf with snowball, value of Dis goes up one
self.draw = False
if (Dis == 20): # New victory image shows once 20 collisions occur
print("Victory! You Saved Christmas!")
global BG
BG = False # Makes it so background image stops refreshing
global SUp
SUp = False #Snowballs stop moving
gameDisplay = pygame.display.set_mode((w,h)) # Background Code - https://stackoverflow.com/questions/65009141/in-pygame-how-do-i-make-an-image-the-background#:~:text=Load%20a%20back%20ground%20image%20%28e.g.%20%27background.jpg%27%29%2C%20scale,pygame.transform.smoothscale%20%28background%2C%20gameDisplay.get_size%20%28%29%29%20gameDisplay.blit%20%28background%2C%20%280%2C%200%29%29
background = pygame.image.load('Victory.png').convert() #Retrieve the image
background = pygame.transform.smoothscale(background, gameDisplay.get_size()) # Sets the image size to the window size
gameDisplay.blit(background, (0, 0)) # Draws the image onto the screen
global running
running = False
# allows the elves to move up and down continuously
def Moving (self):
self.pos_y += self.velocity # Elves move based on velocity value
if self.pos_y >= 0 and self.pos_y < h/2.4: # Elves accelerate downwards when in top half of screen
self.velocity +=.3 # Velocity goes up, pos_y goes down
if self.pos_y > h/2.4: # Elves accelerate upwards when in bottom half of screen
self.velocity -= .3 # Velocity goes down, pos_y goes up
self.box = pygame.Rect(self.pos_x,self.pos_y,self.square,self.square)
#Class that creates snowballs
class Snow:
def __init__(self,color,x,y):
self.x = x
self.y = y
self.color = color
self.height = 15
self.length = 15
self.draw = True
self.snowy = pygame.draw.ellipse(win,self.color,(self.x,self.y,self.height,self.length))
# Show snowballs on screen
def show(self):
if (self.draw == True):
self.snowy = pygame.draw.ellipse(win,self.color,self.snowy)
#Snowballs go up
def upward(self):
global SUp
if SUp == True:
self.snowy.y -= 5
self.snowy = pygame.draw.ellipse(win,self.color,self.snowy)
# class that creates a timer
class Timer:
def __init__(self,limit):
self.limit = limit
self.clock = pygame.time.Clock()
self.start=pygame.time.get_ticks() # get starter tick at Timer instantiation
self.timeLeft = self.countDown()
def countDown(self):
'''Note: Will count down based on time passed, not frame rate, or call frequency.
Retuurns whole value time in seconds (int)'''
currTime=(self.start + pygame.time.get_ticks())/1500 #calculate how many seconds
# if self.timeLeft > 0:
return int(self.limit - currTime) # returns whole second numbers
#================================ Animation loop ===================================================
class Manager:
def __init__(self):
self.colors = ((255,255,255),(0,0,0),(173,216,230),(252,36,2),(0,0,255))
self.ElvesList = []
self.snowballs=[]
global SUp
SUp = True
global BG
BG = True
global Dis
Dis = 0
def main(self):
global running
running = True
clock = pygame.time.Clock()
# code that allows elves to show, everytime you play the game the elves have a different x and y
for i in range(20):
x = random.randint(0,w-20)
y= random.randint(0,h/3)
self.ElvesList.append(Elves(self.colors[2],x,y)) # instantiates the elves class
# calls Santa class in a variable called "SantaC"
SantaC= Santa(self.colors[3],w/2,h-50)
while running:
# clear window (comment out to have trace behind animation)
if (BG == True): # Refresh of image can be turned on/off
gameDisplay = pygame.display.set_mode((w,h)) # Background Code - https://stackoverflow.com/questions/65009141/in-pygame-how-do-i-make-an-image-the-background#:~:text=Load%20a%20back%20ground%20image%20%28e.g.%20%27background.jpg%27%29%2C%20scale,pygame.transform.smoothscale%20%28background%2C%20gameDisplay.get_size%20%28%29%29%20gameDisplay.blit%20%28background%2C%20%280%2C%200%29%29
background = pygame.image.load('SnowBackground.webp').convert() #Retrieve the image
background = pygame.transform.smoothscale(background, gameDisplay.get_size()) # Sets the image size to the window size
gameDisplay.blit(background, (0, 0)) # Draws the image onto the screen
# for every elf created in line 128 they will all show and move, methods of the elves are being called
for evil in self.ElvesList:
evil.Show()
evil.Moving()
# method that allows Santa to be shown
SantaC.show()
#borrowed code in order to display score in left corner (line 141-152)
font = pygame.font.Font("freesansbold.ttf",32)
textx = 10
texty = 10
timer = Timer(27) # 27 is used because there is a 2 second delay to run the code
timeLeft =timer.countDown()
# function that displays timer
def showtimer(x,y):
timing = font.render("Timer :" +str(timeLeft),True,(self.colors[4]))
win.blit(timing,(x,y))
showtimer(textx,texty) # determines where the timer will be displayed
# when the game reaches 0 seconds on the timer, "gameover" is displayed to the terminal
if timeLeft<=0:
gameDisplay = pygame.display.set_mode((w,h)) # Background Code - https://stackoverflow.com/questions/65009141/in-pygame-how-do-i-make-an-image-the-background#:~:text=Load%20a%20back%20ground%20image%20%28e.g.%20%27background.jpg%27%29%2C%20scale,pygame.transform.smoothscale%20%28background%2C%20gameDisplay.get_size%20%28%29%29%20gameDisplay.blit%20%28background%2C%20%280%2C%200%29%29
background = pygame.image.load('Defeat.png').convert() #Retrieve the image
background = pygame.transform.smoothscale(background, gameDisplay.get_size()) # Sets the image size to the window size
gameDisplay.blit(background, (0, 0)) # Draws the image onto the screen
for s in self.snowballs:
s.show()
s.upward()
# Sees if the rect of snowball and rect of elves has collided, if so the elf dissapears
for evil in self.ElvesList:
for s in self.snowballs:
evil.dissapear(s.snowy)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False # stops animation
if event.type == pygame.KEYDOWN:
# handles key press event
if event.key == pygame.K_SPACE:
# When the spacebar is pressed, a snowball will be shot out of Santas location
self.snowballs.append(Snow(self.colors[0],17.5+ SantaC.x,SantaC.y))
if event.key == pygame.K_RIGHT or event.key == pygame.K_d: # santa moves right if right key is clicked. Calls method from Santa's class.
SantaC.Right()
if event.key == pygame.K_LEFT or event.key == pygame.K_a: # santa moves left if left key is clicked. Calls method from Santa's class.
SantaC.Left()
# snowballs will be shown and move upward
#================== Animation control ===================
pygame.display.update()
clock.tick(30) # framerate in fps (30-60 is typical)
Manager().main()
The code is doing a lot of image and font loading repeatedly in the main loop. It's just re-loading the same thing, so this should be moved to before the loop. But I suspect the flickering is caused by the repeated calls to pygame.display.set_mode((w,h)) which is typically only called once, or when handling a window-resize event.
So maybe you want something like this for your main loop:
def showtimer(x,y,font,timeLeft,win):
timing = font.render("Timer :" +str(timeLeft),True,(self.colors[4]))
win.blit(timing,(x,y))
# Set the window size, and setup the timer
gameDisplay = pygame.display.set_mode((w,h))
timer = Timer(27) # 27 because there is a 2 second delay to run the code
timer_x = 10
timer_y = 10
# Load & scale any images, fonts, etc.
font = pygame.font.Font("freesansbold.ttf",32)
snowBackground = pygame.image.load('SnowBackground.webp').convert()
snowBackground = pygame.transform.smoothscale( snowBackground, gameDisplay.get_size())
defBackground = pygame.image.load('Defeat.png').convert()
defBackground = pygame.transform.smoothscale( defBackground, gameDisplay.get_size())
victBackground = pygame.image.load('Victory.png').convert()
victBackground = pygame.transform.smoothscale( victBackground, gameDisplay.get_size())
while running:
timeLeft = timer.countDown()
# clear window (comment out to have trace behind animation)
if (BG == True): # Refresh of image can be turned on/off
# when the game reaches 0 seconds on the timer, "gameover" is displayed to the terminal. Otherwise it's a snowy background
if Dis >= 20:
background = victBackground # player won!
elif timeLeft<=0:
background = defBackground # player defeated
else:
background = snowBackground # still playing
gameDisplay.blit( background, (0, 0) )
# paint & update Evil Elves
for evil in self.ElvesList:
evil.Show()
evil.Moving()
# method that allows Santa to be shown
SantaC.show()
# paint the timer
showtimer( timer_x, timer_y, font, timeLeft, win )
# flush the updates to the window
pygame.display.update()
# handle events & user input
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False # stops animation
# ... etc.
clock.tick( 60 )
I'm not 100% sure how the timer system works, so I just re-arranged it to how I guess it functions. Errors and Omissions should be expected.
The upshot of the changes above is that anything that can be pre-calculated is done outside of the loop. There absolutely no need to re-load and re-scale a background image to the window size every update loop. If you do need to handle window re-size events, do that in an event handler.
I'm new to pygame, and I'm trying to practice skill with 'Plants and Zombies', but here comes a problem when I run the code: the next bullet does not move to the edge of the screen, it ends at a point at which the previous bullet collide with a zombie. I can NOT find out where is the problem, hope someone can help me out. Just run main.py, click on a top menu(weapon), right click on any point of a grass, u'll know the problem.
project directory:
helper.py:
import os
from PIL import Image
import pygame
current_dir = os.getcwd()
def get_path(image_name):
return os.path.join(current_dir, "resource", image_name)
def get_image_size(image_name):
with Image.open(get_path(image_name)) as im:
return im.size
def load_image_source(image_name, with_bullet=False):
if with_bullet:
bullet_name = "bullet_"+image_name.replace("shooter_", "")
return pygame.image.load(get_path(image_name)), pygame.image.load(get_path(bullet_name))
else:
return pygame.image.load(get_path(image_name))
def load_all_shooters():
weapon = {"selected": [], "unselected": []}
shooter_dir = os.path.join(current_dir, "resource")
for shooter in os.listdir(shooter_dir):
if "shooter" in shooter:
if "selected" in shooter:
weapon["selected"].append(shooter)
else:
weapon["unselected"].append(shooter)
weapon["selected"] = sorted(weapon["selected"])
weapon["unselected"] = sorted(weapon["unselected"])
return weapon
def get_nearest_position(source_list, target_number):
return min(source_list, key=lambda x: abs(x - target_number))
config.py:
LINES = 5
ZOMBIE_SPEED_X = 1
ZOMBIE_REFRESH_TIME = 3000
BULLET_REFRESH_TIME = 1000
BULLET_SPEED = 3
SHOOTER_SIZE = (50, 50)
main.py:
import pygame
import sys
import random
from ZombiesVSPlants.common.helper import get_nearest_position, load_image_source, load_all_shooters, get_image_size, get_path, get_path
from ZombiesVSPlants.config.config import BULLET_SPEED, BULLET_REFRESH_TIME, ZOMBIE_REFRESH_TIME, SHOOTER_SIZE, ZOMBIE_SPEED_X, LINES
pygame.init()
# top weapon menu
menu_height = 60
# get background grass and other resource path and size...
background_grass_path = get_path("background_grass.png")
zombie_path = get_path("enemy_zombie.png", )
single_line_height = get_image_size("background_grass.png")[1]
zombie_size = get_image_size("enemy_zombie.png")
# screen size
screen_height = LINES*single_line_height+menu_height
screen_width = 800
# background colour, zombie speed
background_color = 255, 255, 255
ZOMBIE_SPEED = [-ZOMBIE_SPEED_X, 0]
# others
LINES_LIST = [i for i in range(1, LINES+1)]
zombie_start_x = screen_width-zombie_size[0]
zombie_start_y = (single_line_height-zombie_size[1])/2
shooter_centered_position__list_y = [line*single_line_height+zombie_start_y+menu_height for line in range(5)]
# resource boom
boom = load_image_source("boom.png")
# dragging and other global variables
dragging = False
mouse_follow = None
mouse_follow_rect = None
added_shooters = []
shooter_bullets = []
bullets_rect = []
collide_zombies = []
collide_bullets = []
# screen size
screen = pygame.display.set_mode((screen_width, screen_height))
# load top weapon surface
res = load_all_shooters()
menu_start_position = 5, 5
menu_shooters = [load_image_source(unselected_shooter, with_bullet=True) for unselected_shooter in res["unselected"]]
menu_shooters_selected = [load_image_source(selected_shooter) for selected_shooter in res["selected"]]
menu_shooters_rect = [pygame.Rect(menu_start_position[0]+55*i, menu_start_position[1], SHOOTER_SIZE[0], SHOOTER_SIZE[1]) for i in range(len(menu_shooters))]
# background grass surface
grass = load_image_source(background_grass_path)
grass_rect = [pygame.Rect(0, i * single_line_height+menu_height, screen_width, single_line_height) for i in range(LINES)]
# the very first zombie surface
zombie = load_image_source(zombie_path)
zombies_rect = [pygame.Rect(zombie_start_x, zombie_start_y+menu_height, zombie_size[0], zombie_size[1])]
# ZOMBIE_REFRESH_TIME
NEW_ZOMBIE_EVENT = pygame.USEREVENT+1
pygame.time.set_timer(NEW_ZOMBIE_EVENT, ZOMBIE_REFRESH_TIME)
# BULLET_REFRESH_TIME
NEW_BULLET_EVENT = pygame.USEREVENT+2
pygame.time.set_timer(NEW_BULLET_EVENT, BULLET_REFRESH_TIME)
while 1:
screen.fill(background_color)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# left click on a top menu(weapon), dragging is enabled
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
for i in range(len(menu_shooters)):
if menu_shooters_rect[i].collidepoint(event.pos):
dragging = not dragging
mouse_follow = menu_shooters[i]
# right click when dragging, new weapon will be set on a point
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 3:
x = event.pos[0]
if event.pos[1] > menu_height and dragging:
dragging = not dragging
y = get_nearest_position(shooter_centered_position__list_y, event.pos[1])
added_shooters.append([mouse_follow[0], x, y])
shooter_bullets.append([x, y, mouse_follow[1]])
# spawn new bullet
if event.type == NEW_BULLET_EVENT:
for j in range(len(shooter_bullets)):
bullets_rect.append([shooter_bullets[j][2], pygame.Rect(shooter_bullets[j][0], shooter_bullets[j][1], 15, 15)])
# spawn new zombie
if event.type == NEW_ZOMBIE_EVENT:
# random in roads that new zombies will appear
new_zombies_count = random.randint(1, LINES)
new_zombies_lines = random.sample(LINES_LIST, new_zombies_count)
# add to zombies list
for line in new_zombies_lines:
new_zombie_rect = pygame.Rect(zombie_start_x, line * single_line_height + zombie_start_y + menu_height, zombie_size[0], zombie_size[1])
zombies_rect.append(new_zombie_rect)
# blit top weapons menu
for i in range(len(menu_shooters)):
menu_rect = menu_shooters_rect[i]
screen.blit(menu_shooters[i][0], menu_rect)
# blit selected weapon if mouse hover on a weapon menu
for i in range(len(menu_shooters)):
if menu_shooters_rect[i].collidepoint(pygame.mouse.get_pos()):
screen.blit(menu_shooters_selected[i], menu_shooters_rect[i])
# blit background grass
for r in grass_rect:
screen.blit(grass, r)
# blit all the weapons on the grass
for new in added_shooters:
shooter_rect = pygame.Rect(new[1], new[2], 50, 50)
screen.blit(new[0], shooter_rect)
# blit bullets
for j in range(len(bullets_rect)):
bullets_rect[j][1].x += 1
screen.blit(bullets_rect[j][0], bullets_rect[j][1])
# blit zombies
for i in range(len(zombies_rect)):
zombies_rect[i].x -= ZOMBIE_SPEED_X
screen.blit(zombie, zombies_rect[i])
# blit weapon follows mouse move position
if dragging and mouse_follow[0]:
pos_follow_mouse = pygame.mouse.get_pos()
mouse_follow_rect = pygame.Rect(pos_follow_mouse[0], pos_follow_mouse[1], 50, 50)
screen.blit(mouse_follow[0], mouse_follow_rect)
# collide between zombie and bullet
for i in range(len(bullets_rect)):
for j in range(len(zombies_rect)):
if bullets_rect[i][1].colliderect(zombies_rect[j]):
print("collide!")
screen.blit(boom, zombies_rect[j])
collide_bullets.append(bullets_rect[i])
collide_zombies.append(zombies_rect[j])
bullets_rect = [i for i in bullets_rect if i not in collide_bullets]
zombies_rect = [j for j in zombies_rect if j not in collide_zombies]
pygame.display.flip()
I now got a compromise like solution, when need to remove surface in a collide between 2 rects in 2 lists, just draw the 2 lists in 2 separate for loop and remove the collided rect in another for loop, the demo code would be:
# draw bullets
for b in bullets_rect:
b_r = b[1]
b_r.x += BULLET_SPEED
screen.blit(b[0], b_r)
# draw zombies
for z in zombies_rect:
z.x += -ZOMBIE_SPEED_X
screen.blit(zombie, z)
# when collide, use list.remove to remove collided rect
for i, j in itertools.product(bullets_rect, zombies_rect):
b_r = i[1]
z_r = j
if z_r.contains(b_r):
# when collide, remove the collided rect
screen.blit(boom, z_r)
bullets_rect.remove(i)
zombies_rect.remove(j)
FYI.
I have a small animation code that is built using PyGame (and Python 2.7). I am able to build the executable folder with Pyinstaller, however when I try to run the executable it is crashing, although I am able to run the same files (i.e. source code) through my terminal without any problem.
import pygame
import exercise
import random as rd
import copy
import pandas as pd
import numpy as np
def animate():
debug_mode=False
done1 = False
dc_x = 30
dc_y = 30
plant_x = 110
plant_y = 30
supp_x = 190
supp_y = 30
WHITE = (255, 255, 255)
BLACK = (0, 0, 0) #arrows
RED = (255, 0, 0) # Box frames for summary of t, cost and lost sales
GREEN = (0, 255, 0) # Box frames for shipment amounts
DEEPSKYBLUE = (0,191,255) # arc to represent backup WIP inv
DOGERBLUE = (0,191,255) # arc to represent backup FG inv
INDIGO = (75,0,130) # DC/Supp up state
LAVENDER=(238, 130, 238) #DC/Supp down state
OLIVE=(128,128,0) #plant down state
YELLOWGREEN=(173,255,47) #plant up state
DARKYELLOW=(204,204,0)
pygame.init()
screen = pygame.display.set_mode((1000, 600))
clock = pygame.time.Clock()
grand_record={}
############ READ AND PREPARE INITIAL SCREEN for t==0 ################
PLANT_status, SUPP_status, DC_status, disruption, DC_BUp_Plan, Plant_BUp_Plan, Supp_BUp_Plan, Demand, P=exercise.init(debug_mode,False)
grand_record[0]={"DC":DC_status, "Plant":PLANT_status, "Supplier":SUPP_status}
basicFont = pygame.font.SysFont(None, 24)
largeFont = pygame.font.SysFont(None, 35)
pygame.display.set_caption('SCREAM!')
if debug_mode: R=1
else: R= rd.randint(0,25)
scenario_score={"cost":0, "service":0}
while not done1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done1 = True
#if event.type == pygame.KEYDOWN:
# if event.key == pygame.K_DOWN:
# paused()
end_of_one_run=1
total_lost_customer=0
cumulative_inv_holding_cost=0
total_fixed_cost_paid=0
table_output=[]
chart_output=[]
header=["Week","Demand","Upstream shipment", "Shipment from regular DC", "Shipment from backup DC",
"FG Inv at Reg. DC", "FG Inv at B/up. DC", "FG Inv as B/up","LostSales","Start Order for b/up DC", "B/up DC starts","DC Disruption at","Disruption duration", "TotalAvailableWIPSupplyCap",
"Start Order for b/up Supplier", "B/up Supplier starts","Supplier Disruption at","Disruption duration", "Storage Cap Available", "Plant production",
"WIP Inv as B/up","Start Order for b/up Plant", "B/up Plant starts","Plant Disruption at","Disruption duration"]
table_output.append(header)
for t in range(1,P+1): # for the specified number of periods
screen.fill((0, 0, 0))
picture = pygame.image.load('Background.png').convert() #MITwallpaper
screen.blit(picture, [0, 0])
#import pdb; pdb.set_trace()
################################## MAKE CALCULATIONS FOR t>0 ################
grand_record,output=exercise.calculate(t, grand_record[t-1]["Plant"], grand_record[t-1]["Supplier"], grand_record[t-1]["DC"], disruption, DC_BUp_Plan, Plant_BUp_Plan, Supp_BUp_Plan,Demand[R*P+t],grand_record,debug_mode)
chart_output=exercise.prepare_chart_output(chart_output, grand_record)
output_loc=copy.deepcopy(output)
table_output.append(output_loc)
end_of_one_run=end_of_one_run+1
objectives=exercise.calculate_objectives(grand_record, DC_BUp_Plan, Plant_BUp_Plan, Supp_BUp_Plan, t)
lost_cust_text = largeFont.render("Service: "+str(objectives["Service"]), True, WHITE, BLACK)
lost_cust_textRect = lost_cust_text.get_rect()
lost_cust_textRect.centerx = 380
lost_cust_textRect.centery = 420
pygame.draw.rect(screen, RED, (lost_cust_textRect.left - 3, lost_cust_textRect.top - 3, lost_cust_textRect.width + 3, lost_cust_textRect.height + 3))
screen.blit(lost_cust_text, lost_cust_textRect)
inv_hold_text = largeFont.render("Inv.Holding Cost(k$): "+str(round(objectives["InvHoldingCost"]*0.001,1)), True, WHITE, BLACK)
inv_hold_textRect = inv_hold_text.get_rect()
inv_hold_textRect.centerx = 600
inv_hold_textRect.centery = 445
pygame.draw.rect(screen, RED, (inv_hold_textRect.left - 3, inv_hold_textRect.top - 3, inv_hold_textRect.width + 3, inv_hold_textRect.height + 3))
screen.blit(inv_hold_text, inv_hold_textRect)
startup_text = largeFont.render("Startup Cost(k$): "+str(round(objectives["Startup_cost"]*0.001,1)), True, WHITE, BLACK)
startup_textRect = startup_text.get_rect()
startup_textRect.centerx = 840
startup_textRect.centery = 470
pygame.draw.rect(screen, RED, (startup_textRect.left - 3, startup_textRect.top - 3, startup_textRect.width + 3, startup_textRect.height + 3))
screen.blit(startup_text, startup_textRect)
###################################################################################
if t<P:
pygame.display.flip()
clock.tick(8)
else:
#import pdb; pdb.set_trace()
table = pd.DataFrame(table_output)
table.to_excel("Details.xlsx",index=False)
#import pdb; pdb.set_trace()
done1 = True
################################ Want A PARETO Button ###################################
x=500
y=500
w=200
h=50
pygame.draw.rect(screen, DEEPSKYBLUE,(x,y,w,h))
buttontext = basicFont.render("Want A Pareto Solution?", True, BLACK , WHITE )
buttontext_rect=buttontext.get_rect()
buttontext_rect.centerx = (x+(w/2))
buttontext_rect.centery = (y+(h/2))
screen.blit(buttontext, buttontext_rect)
pygame.display.flip()
pygame.time.delay(120)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exercise.plotcharts(chart_output)
################################################################################
animate()
I had the same problem (also Python 2.7), and this did it for me:
pyinstaller usually has trouble with pygame.font.SysFont("some_font", 24)
Instead use pygame.font.Font("your_own_font.ttf", 24).
Download a font and either put it in the same folder as your file, or in a data folder.
I use VeraMono and put it in a data folder, so my code would be
...
basicFont = pygame.font.Font("data/VeraMono", 24)
largeFont = pygame.font.Font("data/VeraMono", 35)
pygame.display.set_caption('SCREAM!')
...
If you don't have a data/ folder added to your project yet, then add the following lines to your spec file (the spec file is created as soon as you run you pyinstaller the first time. It has the same name as your python file.)
# -*- mode: python -*-
block_cipher = None
# This entry is new!
added_files = [
( 'data', 'data'),
]
a = Analysis(['CleanTest.py'],
pathex=['/home/angela/Desktop/Arbeit/VisualTest'],
binaries=[],
datas=added_files, # add the new file to your data tree
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
...
Run pyinstaller <your_file>.spec, and hopefully it'll work.
my guess is that it crashes when trying to load the background image:
picture = pygame.image.load('Background.png').convert() #MITwallpaper
When pyinstaller compiles your code, that is all it compiles (including the imported dependencies). It creates the dist directory where you can run your executable and you are good to go.
But, by default, pyinstaller will not pull in external resources. So when you run the executable, it can't find your image because it is in a different directory. You can test this by manually copying the image to the folder where the exe is located and see if it works.
Also, you can run the exe and push the output into a debug file:
your_file.exe > debug.txt
This way you can capture the output from your program (including error messages).
ok so i dont really understand functions atm and my assignment is to create a separate python module that has all of the functions need to make a program run. the program being supplied by the professor and is already completed and can not be changed by me. im not asking anybody to sit here and do all of the functions them self, although that would be amazing, i just need maybe 1 or two completed and maybe an explanation on how they work. below is completed program given to me.
import pygame
import lab06_bubbles as bubbles
import random
# ### NOTE: In this lab, I *DON'T* want you to change anything in this file. I want you to create
# lab06_bubbles.py so that this works as described in the lab document (and video) ###
# Pygame setup
win_width = 1200
win_height = 800
pygame.display.init()
pygame.font.init()
screen = pygame.display.set_mode((win_width, win_height))
font = pygame.font.SysFont("Courier New", 12)
clock = pygame.time.Clock()
done = False
numBubbles = random.randint(50, 100) # Initial number of bubbles
numWebs = 2 # Initial number of connections between each bubble
paused = False # Are we paused?
minAreaWidth = 50 # The minimum width of the bubble area
maxAreaWidth = win_width # The maximum width of the bubble area
minAreaHeight = 50 # The minimum height of the bubble area
maxAreaHeight = win_height - 50 # The maximum height of the bubble area
# Generate the initial play area and bubble list
currentArea = bubbles.randomArea(minAreaWidth, minAreaHeight, maxAreaWidth, maxAreaHeight)
bubbleList = bubbles.spawnBubbles(numBubbles, currentArea, 5, 20, 100)
# Game Loop
while not done:
# #############
# # UPDATE #
# #############
deltaTime = clock.tick() / 1000.0
if paused:
deltaTime = 0.0
bubbles.updateBubbles(bubbleList, currentArea, deltaTime)
# #############
# # INPUT #
# #############
event = pygame.event.poll()
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
done = True
elif event.key == pygame.K_LEFT:
numBubbles -= 5
if numBubbles < 5:
numBubbles = 5
bubbleList = bubbles.spawnBubbles(numBubbles, currentArea, 5, 20, 100)
elif event.key == pygame.K_RIGHT:
numBubbles += 5
if numBubbles > 100:
numBubbles = 100
bubbleList = bubbles.spawnBubbles(numBubbles, currentArea, 5, 20, 100)
elif event.key == pygame.K_UP:
numWebs += 1
elif event.key == pygame.K_DOWN:
numWebs -= 1
if numWebs < 0:
numWebs = 0
elif event.key == pygame.K_SPACE:
currentArea = bubbles.randomArea(minAreaWidth, minAreaHeight, maxAreaWidth, maxAreaHeight)
bubbleList = bubbles.spawnBubbles(numBubbles, currentArea, 5, 20, 100)
elif event.key == pygame.K_p:
paused = not paused
# #############
# # DRAW #
# #############
screen.fill((0,0,0))
pygame.draw.rect(screen, (255,255,255), currentArea, 1)
bubbles.drawBubbles(bubbleList, screen, numWebs)
screen.blit(font.render("# Bubbles: " + str(len(bubbleList)) + " area: " + str(currentArea) + \
" num_webs: " + str(numWebs), False, (128,128,128)), (0, win_height - 48))
screen.blit(font.render("[Left / Right] : decrease / increase number of bubbles [space]: regenerate bounds [escape]: quit", \
False, (128,128,128)), (0, win_height - 32))
screen.blit(font.render("[Up / Down] : decrease / increase number of connections [p]: pause", False, \
(128,128,128)), (0, win_height - 16))
pygame.display.flip()
# Pygame shutdown
pygame.font.quit()
pygame.display.quit()
this is the function outline module that was given to me and this is where i have no idea what to do.
def randomArea(minW, minH, maxW, maxH):
"""
:param minW: the minimum width of this box
:param minH: the minimum height of this box
:param maxW: the maximum width of this box (normally the width of the "playfield")
:param maxH: the maximum height of this box (normally the height of the "playfield")
:return: a pygame-style rect (x, y, w, h) that fits within the "playfield"
"""
def spawnBubbles(num, area, minSize, maxSize, maxSpeed):
"""
:param num: the number of bubbles to create
:param area: a pygame-style rect (x, y, w, h) that all bubbles should spawn completely inside
:param minSize: the minimum size of a bubble
:param maxSize: the maximum size of a bubble (should fit within the minimum size passed to
randomArea)
:param maxSpeed: the maximum horizontal and vertical speed a bubble should have (in px / s)
:return: A list of lists where each sub-list is of the form [x, y, radius, horiz_speed,
vert_speed]
"""
def getClosest(interest, L, num):
"""
:param interest: the bubble of interest
:param L: the list of all bubbles
:param num: the number of closest bubbles to find
:return: a list of num bubbles (not counting the interest) that are closest to the interest
object
"""
def updateBubbles(L, area, dt):
"""
Makes all bubbles move. If a bubble hits the left / right sides of the area, negate their
horiz_speed and
move them just inside the area; if a bubble hits the top / bottom of the area, negate their
vert_speed and
move them just inside the area.
:param L: The list of all bubbles
:param area: the pygame-style rect bounding the play area.
:param dt: The number of seconds that has passed since the last update
:return: None
"""
def drawBubbles(L, surf, num_webs):
"""
Draws the bubbles and the connections between them. This function calls the getClosest
function internally
:param L: The list of all bubbles
:param surf: The surface to draw to
:param num_webs: The number of connections to draw between bubbles
:return: None
"""
i just need some help with this please. this is what the final product should look like.
First thing I won't do your assignment for you but I can try and help by giving you the following clues:
every time you use the import statement in a python script to import a module (fancy name for another script), Python will go and look for that module in two places:
the current working directory (usually the folder where the script you are working on is)
if it can't find it in the current working directory it will go and look for it in the Python installed libraries.
So the first thing you want, is to make sure that lab06_bubbles is in the same directory as the script you will run.
then, since your professor imports lab06_bubbles as bubbles , everywhere in his program where bubbles.function is mentioned it will go and look for that function in the lab06_bubbles.py file in which you have to build all the functions that the program will need.
Then the professor gives you all the information you need to build the function:
what the arguments are
what the function should return
You, have to do the magic in the middle.
say one of the functions was called getDist with the following description:
def getDist(pointa, pointb):
"""
Takes two points, and return the distance between those points.
:param pointa: a tuple with the x, y coordinates of point a
:param pointb: a tuple with the x, y coordinates of point b
:return: a float representing the distance between the two points
"""
you would need to code the function as follow:
def getDist(pointa, pointb):
xa,ya = pointa
xb,yb = pointb
dist_ab = ((xa-xb)**2+(ya-yb)**2)**0.5
return float(dist_ab)
hope that helps
Just started learning Python/Pygame watching videos and reading to learn . I would like to see a example code to cycle 3 images on a rect button from a mouse press and return to first image. Really I want the pictures to be three options and return different results. So be able to cycle image be able to select option and option when triggered execute choice.
Example
import pygame
pygame.init()
screen = pygame.display.set_mode((300,200))
# three images
images = [
pygame.Surface((100,100)),
pygame.Surface((100,100)),
pygame.Surface((100,100)),
]
images[0].fill((255,0,0))
images[1].fill((0,255,0))
images[2].fill((0,0,255))
# image size and position
images_rect = images[0].get_rect()
# starting index
index = 0
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
# check mouse position and pressed button
if event.button == 1 and images_rect.collidepoint(event.pos):
# cycle index
index = (index+1) % 3
screen.blit(images[index], images_rect)
pygame.display.flip()
pygame.quit()
Example using class - to create many buttons
import pygame
class Button(object):
def __init__(self, position, size):
self._images = [
pygame.Surface(size),
pygame.Surface(size),
pygame.Surface(size),
]
self._images[0].fill((255,0,0))
self._images[1].fill((0,255,0))
self._images[2].fill((0,0,255))
self._rect = pygame.Rect(position, size)
self._index = 0
def draw(self, screen):
screen.blit(self._images[self._index], self._rect)
def event_handler(self, event):
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1 and self._rect.collidepoint(event.pos):
self._index = (self._index+1) % 3
pygame.init()
screen = pygame.display.set_mode((320,110))
button1 = Button((5, 5), (100, 100))
button2 = Button((110, 5), (100, 100))
button3 = Button((215, 5), (100, 100))
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
button1.event_handler(event)
button2.event_handler(event)
button3.event_handler(event)
button1.draw(screen)
button2.draw(screen)
button3.draw(screen)
pygame.display.flip()
pygame.quit()
If I understood the question correctly, you need a single button that changes the look every time you click on it, and changes its relative function accordingly.
You should be able to solve your problem by creating a class that takes two list and a counter
1) list of images
2) list of functions
3) the counter tells you which image/function is selected.
The functions needs to be built in the class, but you can provide the image that you want in the class argument (actually, you could pass them as arguments, but I don't think is worth it).
Here is the code, I commented some lines with their intended meaning (in line comments)
import pygame
import sys
pygame.init()
width = 600
height = 400
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Magic Buttons")
background = pygame.Surface(screen.get_size())
clock = pygame.time.Clock()
class Buttons:
def __init__(self, posX, posY, image1, image2, image3):
self.image_list = [image1, image2, image3] # static list of images
self.function_list = [self.button_function_1,self.button_function_2,self.button_function_3 ]
self.rect_position = (posX, posY) # this is a tuple to identify the upper left corner of the rectangle of the image
self.button_type = 0 # initial value of the button, both for the function and the image
self.image = pygame.image.load(self.image_list[0]) #default image, index number 0 of image_list
self.rect = pygame.Rect(posX, posY, self.image.get_width(), self.image.get_height()) # create a rectangle object same size of the images
def check(self, pos):
if self.rect.collidepoint(pos) ==True:
self.change_button()
else:
pass
def change_button(self):
self.button_type = (self.button_type +1)%3
self.image = pygame.image.load(self.image_list[self.button_type ]) # load the image relative to button_type
self.function_list[self.button_type -1]() # execute the function relative to the new value of button_type
self.draw_button()
def draw_button(self):
screen.blit(self.image, self.rect_position) # blit the new button image
def button_function_1(self):
print ("function 1 in action")
def button_function_2(self):
print ("function 2 in action")
def button_function_3(self):
print ("function 3 in action")
multibutton = Buttons(100,100,"button1.png","button2.png","button3.png") # create an istance of the button in the x=100, y = 100, with the three image button
while True:
background.fill((0,0,0))
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONUP:
pos = pygame.mouse.get_pos() # fetch the position of the mouse
multibutton.check(pos) # check if the mouse is on the button
multibutton.draw_button()
pygame.display.flip()