I have been working on making a Pygame for my Social Studies class and I want to add new elements to this existing game. The problem is, when I load the old game, without making any significant changes, I get an error. It seems to have a couple of warnings as well that I have looked up but most of the threads are from years ago. My error is as follows:
Jordans-MacBook-Air:SS-Game Jordanxxi$ python ocean_cleaner.py
2017-05-26 12:23:15.729 Python[61184:1392206] Warning once: This application, or a library it uses, is using NSQuickDrawView, which has been deprecated. Apps should cease use of QuickDraw and move to Quartz.
May 26 12:23:15 Python[61184] <Error>: The function ‘SLSFlushWindow’ is obsolete and will be removed in an upcoming update. Unfortunately, this application, or a library it uses, is using this obsolete function, and is thereby contributing to an overall degradation of system performance. Please use `SLSFlushWindowContentRegion' instead.
Traceback (most recent call last):
File "ocean_cleaner.py", line 30, in <module>
hit = pygame.mixer.Sound("resources/audio/pop.wav")
pygame.error: mixer system not initialized
My code, as of now, is as follows:
#Import statements
import pygame, sys
import pygame.mixer
import time
from pygame.locals import *
#Pygame function to load the game and screen size
pygame.init()
screen = pygame.display.set_mode((700,500))
#Images needed in game
background = pygame.image.load("resources/images/background.png")
slick = pygame.image.load("resources/images/slick.png")
slick_med = pygame.image.load("resources/images/slick_med.png")
slick_sml = pygame.image.load("resources/images/slick_sml.png")
diver = pygame.image.load("resources/images/diver_gun.png")
diver1 = pygame.image.load("resources/images/diver_gun1.png")
spray_right = pygame.image.load("resources/images/spray_right.png")
spray_left = pygame.image.load("resources/images/spray_left.png")
win_screen = pygame.image.load("resources/images/win_screen.png")
lose_screen = pygame.image.load("resources/images/lose_screen.png")
red_bar = pygame.image.load("resources/images/red_bar.png")
green_bar2 = pygame.image.load("resources/images/green_bar2.png")
green_bar4 = pygame.image.load("resources/images/green_bar4.png")
air_bar = pygame.image.load("resources/images/air_bar.png")
spray_bar = pygame.image.load("resources/images/spray_bar.png")
#Sounds
hit = pygame.mixer.Sound("resources/audio/pop.wav")
hit.set_volume(0.5)
wash = pygame.mixer.Sound("resources/audio/spray.wav")
wash.set_volume(0.4)
pygame.mixer.music.load('resources/audio/tune_1.wav')
pygame.mixer.music.play(-1, 0.0)
pygame.mixer.music.set_volume(0.25)
#The Variables
player = diver
spray = spray_right
spray_off_set = 0
pop=False
pop_index=0
player_x = 250
player_y = 100
background_x = 0
background_y = 0
move_x = 0
move_y = 0
keys=[False,False,False,False,False]
slick_large=[[slick,300,250],[slick,1000,650],[slick,1400,1050]]
slick_medium =[]
slick_small = []
clean_up = 12
life = True
sprays = 30
main_loop = 1
while main_loop:
pygame.display.set_caption('Greek Mythology Quiz')
#How the charater moves when certain keys are clicked
#---------------------------------------------------#
#Move Right
if keys[0]==True and move_x <5:
move_x+= 1
player = diver1
spray = spray_left
spray_off_set = -200
#Move Left
if keys[1]==True and move_x >-1310:
move_x-= 1
player = diver
spray = spray_right
spray_off_set = 0
#Move Up
if keys[2]==True and move_y <10:
move_y+= 1
#Move Down
if keys[3]==True and move_y >-1010:
move_y-= 1
#Check for collisions
spray_rect=pygame.Rect(spray.get_rect())
spray_rect.left=(350+spray_off_set)
spray_rect.top=100
player_rect=pygame.Rect(player.get_rect())
player_rect.left= player_x
player_rect.top= player_y
for i in range(len(slick_large)):
slick_rect=pygame.Rect(slick.get_rect())
slick_rect.left=((slick_large[i][1])+move_x)
slick_rect.top=(slick_large[i][2]+move_y)
if spray_rect.colliderect(slick_rect) and keys[4] == True:
pop=True
pop_index=i
if player_rect.colliderect(slick_rect):
life = False
#When pop sound is called, volume depends on object size
if pop==True:
hit.play()
slick_medium.append([slick_med,(slick_large[pop_index][1]+75),(slick_large[pop_index][2]-50)])
slick_medium.append([slick_med,(slick_large[pop_index][1]+150),(slick_large[pop_index][2]+50)])
slick_large.pop(pop_index)
pop=False
#Collision redirect physics
for i in range(len(slick_medium)):
slick_rect=pygame.Rect(slick_med.get_rect())
slick_rect.left=((slick_medium[i][1])+move_x)
slick_rect.top=(slick_medium[i][2]+move_y)
if spray_rect.colliderect(slick_rect) and keys[4] == True:
pop=True
pop_index=i
if player_rect.colliderect(slick_rect):
life = False
if pop==True:
hit.play()
slick_small.append([slick_sml,(slick_medium[pop_index][1]-75),(slick_medium[pop_index][2]-75)])
slick_small.append([slick_sml,(slick_medium[pop_index][1]-150),(slick_medium[pop_index][2]-50)])
slick_medium.pop(pop_index)
pop=False
for i in range(len(slick_small)):
slick_rect=pygame.Rect(slick_sml.get_rect())
slick_rect.left=((slick_small[i][1])+move_x)
slick_rect.top=(slick_small[i][2]+move_y)
if spray_rect.colliderect(slick_rect) and keys[4] == True:
pop=True
pop_index=i
if player_rect.colliderect(slick_rect):
life = False
if pop==True:
hit.play()
slick_small.pop(pop_index)
clean_up -=1
pop=False
#Background scrolling
screen.fill(0)
screen.blit(background,((background_x+move_x),(background_y+move_y)))
screen.blit(player,(player_x,player_y))
if keys[4]==True:
wash.play()
screen.blit(spray,((350+spray_off_set),100))
else:
wash.stop()
for i in range( len(slick_large)):
screen.blit(slick_large[i][0],((slick_large[i][1]+move_x),(slick_large[i][2]+move_y)))
for i in range( len(slick_medium)):
screen.blit(slick_medium[i][0],((slick_medium[i][1]+move_x),(slick_medium[i][2]+move_y)))
for i in range( len(slick_small)):
screen.blit(slick_small[i][0],((slick_small[i][1]+move_x),(slick_small[i][2]+move_y)))
time_remaining = int((60-(pygame.time.get_ticks()/1000)))
screen.blit(air_bar,(8,8))
screen.blit(red_bar,(10,10))
for i in range(time_remaining):
screen.blit(green_bar2,(10+(i*2),10))
screen.blit(spray_bar,(570,8))
screen.blit(red_bar,(572,10))
for i in range(sprays):
screen.blit(green_bar4,(572+(i*4),10))
if clean_up == 0:
screen.blit(win_screen,(0,0))
main_loop = 0
if life == False or sprays == 0 or time_remaining == 0:
screen.blit(lose_screen,(0,0))
main_loop = 0
pygame.display.flip()
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
exit(0)
#Event checkers - Check to see if certain keys are pressed
if event.type == pygame.KEYDOWN:
if event.key==K_LEFT:
keys[0]=True
elif event.key==K_RIGHT:
keys[1]=True
elif event.key==K_UP:
keys[2]=True
elif event.key==K_DOWN:
keys[3]=True
elif event.key==K_SPACE:
keys[4]=True
#Check to see when certain keys are released
if event.type == pygame.KEYUP:
if event.key==K_LEFT:
keys[0]=False
elif event.key==K_RIGHT:
keys[1]=False
elif event.key==K_UP:
keys[2]=False
elif event.key==K_DOWN:
keys[3]=False
elif event.key==K_SPACE:
keys[4]=False
sprays -= 1
end = 1
while end:
#Exit function
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
exit(0)
Any help? Thanks in advance.
Update - I was running the game through terminal instead of Idle. I still get an error but it is a little bit different. Anyone know how to fix this?
Traceback (most recent call last):
File "/Users/Jordanxxi/Desktop/Game/ocean_cleaner.py", line 29, in <module>
hit = pygame.mixer.Sound("resources/audio/pop.wav")
error: mixer system not initialized
I believe you have to do:
pygame.mixer.init()
Check the documentation for mixer (this is always a good idea to do first when you have a problem!): http://www.pygame.org/docs/ref/mixer.html
Related
I need to to build an application that has multiple windows. In one of these windows, I need to be able to play a simple game and another window has to display questions and get response from a user that influences the game.
(1) I was wanting to use pygame in order to make the game. Is there a simple way to have pygame operate with multiple windows?
(2) If there is no easy way to solve (1), is there a simple way to use some other python GUI structure that would allow for me to run pygame and another window simultaneously?
The short answer is no, creating two pygame windows in the same process is not possible (as of April 2015). If you want to run two windows with one process, you should look into pyglet or cocos2d.
An alternative, if you must use pygame, is to use inter-process communication. You can have two processes, each with a window. They will relay messages to each other using sockets. If you want to go this route, check out the socket tutorial here.
Internally set_mode() probably sets a pointer that represents the memory of a unique display. So if we write:
screenA = pygame.display.set_mode((500,480), 0, 32)
screenB = pygame.display.set_mode((500,480), 0, 32)
For instance we can do something like that later:
screenA.blit(background, (0,0))
screenB.blit(player, (100,100))
both blit() calls will blit on the same surface. screenA and screenB are pointing to the same memory address. Working with 2 windows is quite hard to achieve in pygame.
Yes, that is possible. SDL2 is able to open multiple windows. In the example folder you can take a look at "video.py".
https://github.com/pygame/pygame/blob/main/examples/video.py
"This example requires pygame 2 and SDL2. _sdl2 is experimental and will change."
I've been trying to do this for a few days now, and I'm finally making progress. Does this count as simple? Or even as "being in" pygame. In this exampe I never even call pygame.init() That just seems to get in the way. The event pump is running (for mouse and keyboard) but not all the normal events seem to be coming thru (FOCUSGAINED and LOST in particular). In this example each window renders it status (size, position, etc) to it's self. I also have versions where I mix SDL windows with the pygame display. But those involve encapsulating a Window rather than extending it.
In order to draw on these windows you can draw on a vanilla surface as usually and then use the Renderer associated with the window to create a texture that will update the the window. (texture.draw(), renderer.present). You dont't use display.update() or flip() because you you aren't using the pygame display surface.
The X11 package is just my experimental windowing stuff and has nothing to do with X11. I think all my imports are explicit so it should be easy to figure out what the missing pieces are.
from typing import List
from pygame import Rect, Surface, Color
import pygame.event
from pygame.event import Event
from pygame.freetype import Font
from pygame._sdl2.video import Window, Renderer, Texture
from X11.windows import DEFAULT_PAD, default_font, window_info
from X11.text import prt
class MyWindow(Window):
def __init__(self, font: Font=None):
super().__init__()
self._font = font if font else default_font()
self.resizable = True
self._renderer = None
def destroy(self) -> None:
super().destroy()
def update(self):
r = self.renderer
r.draw_color = Color('grey')
r.clear()
#self.render_line(f"TICKS: {pg.time.get_ticks()}", 5, size=16.0)
txt: List[str] = window_info(self)
self.render_text(txt, lineno=0)
r.present()
#property
def renderer(self):
if self._renderer is None:
try:
self._renderer = Renderer.from_window(self)
except:
self._renderer = Renderer(self)
return self._renderer
def render_text(self, txt: List[str], lineno: int=0):
for line in txt:
self.render_line(line, lineno, size=16.0)
lineno += 1
def render_line(self, txt: str, lineno: int = 0, size: float = 0.0):
font = self._font
line_spacing = font.get_sized_height(size) + DEFAULT_PAD
x = DEFAULT_PAD
y = DEFAULT_PAD + lineno * line_spacing
# compute the size of the message
src_rect = font.get_rect(txt, size=size)
# create a new surface (image) of text
l_surf = Surface((src_rect.width, src_rect.height))
src_rect = font.render_to(l_surf, (0, 0), txt, size=size)
# get ready to draw
texture = Texture.from_surface(self.renderer, l_surf)
dst = Rect(x, y, src_rect.width, src_rect.height)
texture.draw(None, dst)
_running: bool = False
def test():
global _running
win1 = MyWindow()
win2 = MyWindow()
my_windows = {win1.id: win1, win2.id: win2}
win = win1
rnd = win1.renderer
print("pygame.get_init():", pygame.get_init())
print("pygame.display.get_init():", pygame.display.get_init())
print("pygame.mouse.get_pos():", pygame.mouse.get_pos())
clock = pygame.time.Clock()
_running = True
while _running:
events = pygame.event.get()
for event in events:
if event.type != pygame.MOUSEMOTION:
print(event)
if event.type == pygame.QUIT:
_running = False
elif event.type == pygame.WINDOWENTER:
win = my_windows[event.window.id]
print(f"Enter Window ({event.window.id}")
elif event.type == pygame.WINDOWLEAVE:
pass
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
_running = False
if event.key == pygame.K_1:
win = my_windows[1]
rnd = win.renderer
if event.key == pygame.K_2:
win = my_windows[2]
rnd = win.renderer
elif event.key == pygame.K_b:
rnd.draw_color = Color('blue')
rnd.clear()
elif event.key == pygame.K_g:
rnd.draw_color = Color('grey')
rnd.clear()
elif event.key == pygame.K_t:
win.render_line("Hello, world")
elif event.key == pygame.K_s:
surface = pygame.display.get_surface()
print("surface: ", surface)
elif event.key == pygame.K_f:
pygame.display.flip()
# pygame.error: Display mode not set
elif event.key == pygame.K_u:
pygame.display.update()
# pygame.error: Display mode not set
for win in my_windows.values():
win.update()
clock.tick(40)
if __name__ == '__main__':
test()
I keep getting this error whenever I try to open the help section:
Traceback (most recent call last):
File "C:/Users/Chris/Desktop/Paul's stuff/Paul/CpmpProject/Window.py", line 142, in <module>
game.help()
File "C:/Users/Chris/Desktop/Paul's stuff/Paul/CpmpProject/Window.py", line 76, in help
if event.type == MOUSEBUTTONDOWN:
UnboundLocalError: local variable 'event' referenced before assignment
I don't know how to fix this issue. I have a lot of code and I feel that it is a lot to go through to find an error. If you can help me to fix this issue, I will be very grateful and I know a few other people working on similar projects that will be grateful as well as they are having the same issue. My code is below. I don't expect anyone to go through it, but I would be grateful to anyone is willing to and find the error I am having. I have included all of it just in case it is something further up than I expected, but I think the issue is in the help function definition.
import pygame, sys
from pygame.locals import *
import random
from random import shuffle
back = True
backbutton = pygame.image.load("Back button.png")
helpsection = pygame.image.load("Hunt Help section.png")
class Game():
def question(self):
questions = ["What species of bird is also a nickname for New Zealand?",
"Which Twins can you play as in Assassin's Creed Syndicate?",
"Which year was 'Killing In The Name' Christmas Number one?"]
answers = [["kiwi", "Kiwi", "Falcon", "Sparrow", "Crow"], ["frye", "Frye", "Bank", "Green", "Bundy"],
["2009", "2009",
"1999", "1993",
"2004"]]
# I had to do it in two separate lists as it's easier to work with later on
# Also I made the correct answers non-case sensitive to make it easier to test.
Game_back = True
while Game_back == True:
r = len(questions)
score = 0
s = random.randrange(0, r, 1)
# This generates a random number within the range of how many questions there are
# and then prints out that question
print(questions[s])
list = answers[s]
output = []
for i in range(1, 5):
output.append(answers[s][i])
shuffle(output)
print(output[0] + " ", output[1] + " ", output[2] + " ", output[3])
# this takes the answers that correspond with the randomly generated question and shuffles the answers
# I did this as otherwise, the answer would always be the first answer to appear and the player could exploit this
player_answer = input()
if player_answer == answers[s][0] or player_answer == answers[s][1]:
score += 1
print(score)
else:
print("Wrong")
panswer = input("Would you like to play another round?: ")
quit = ["Yes", "yes", "Yeah", "yeah"]
if panswer in quit:
Game_back = False
else:
pygame.quit()
sys.exit()
# this is the basics of the algorithm that will determine if a player can move forward or not in the maze and the score
# they will have at the end
## it takes the input from the player and compares it to the first 2 answers in the corresponding answer set which is
## a separate list from the list that is printed out to the player
def help(self):
pygame.init()
self.FPS = 60
self.fps_clock = pygame.time.Clock()
self.surface = pygame.display.set_mode((640, 480))
# This class sets the basic attributes for the window.
# The clock is set to 60 and the name of the window
# is set to The Hunt which is a working title for my project
DISPLAY_SURF.blit(helpsection, (0, 0))
DISPLAY_SURF.blit(backbutton, ((640 - 124), (480 - 87)))
if event.type == MOUSEBUTTONDOWN:
if (640 -124) >= mouse[0] > 640 and (480 - 87) >= mouse[1] > 480:
back = False
while True:
pygame.display.update()
self.fps_clock.tick(self.FPS)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
# This updates the window display to refresh every clock tick
# and to set the background colour as white
# using the RGB colours. I might use these to alter the window's look at a later date
#Initialize pygame and define colours
pygame.init()
white = 255, 255, 255
#Sets the resolution to 640 pixels by 720 pixels and caption for pygame window
DISPLAY_SURF = pygame.display.set_mode((640, 720))
pygame.display.set_caption("The Hunt!")
#Create a clock object
clock = pygame.time.Clock()
FPS = 60
#Define a variable to refer to image
background = pygame.image.load("Startermenu.png")
start = pygame.image.load("PlayGameButton.png")
help = pygame.image.load("HelpButton.png")
credits = pygame.image.load("ShowCreditsButton.png")
Hoveringhelp = pygame.image.load("HoveringHelpButton.png")
#Start main loop
while True:
for event in pygame.event.get():
mouse = pygame.mouse.get_pos()
DISPLAY_SURF.fill(white)
DISPLAY_SURF.blit(background, (0, 0))
DISPLAY_SURF.blit(start, (0, 140))
DISPLAY_SURF.blit(help, (0, 186))
DISPLAY_SURF.blit(credits, (0, 235))
pygame.display.update()
#if 0 <= mouse[0] < 260 and 180 <= mouse[1] < 230:
# DISPLAY_SURF.blit(Hoveringhelp, (0, 186))
# print("hovering over help")
#elif 0 <= mouse[0] < 260 and 235 <= mouse[1] < 270:
# print("hovering over credits")
#elif 0 <= mouse[0] < 260 and 0 <= mouse[1] < 180:
# print("hovering over play button")
if event.type == MOUSEBUTTONDOWN:
if 0 <= mouse[0] < 260 and 140 <= mouse[1] < 180:
game = Game()
game.question()
elif 0 <= mouse[0] < 260 and 180 <= mouse[1] < 230:
game = Game()
game.help()
elif 0 <= mouse[0] < 260 and 240 <= mouse[1] < 285:
game = Game()
game.credits()
elif event.type == QUIT:
pygame.quit()
sys.exit()
In the help() method:
def help(self):
...
if event.type == MOUSEBUTTONDOWN:
...
while True:
...
for event in pygame.event.get():
event is defined in the for loop, but you're referring to it before that.
One way to fix it is to move the if event.type == MOUSEBUTTONDOWN statement inside the for loop.
Or, since .help() is only called from the bottom event loop where the event is already known to be MOUSEBUTTONDOWN, perhaps you could remove the if statement altogether?
(BTW, I thought the error message was pretty clear; did you not understand it?)
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm building a game using PyGame and Python 3.4. I am having an issue with what appears to be the module itself and not the actual code I have because the full error is:
Traceback (most recent call last):
File "C:\Users\----\Desktop\Python\Game.py", line 115, in <module>
playerhit = pygame.sprite.spritecollide(ebullet, psprite, True)
File "C:\Python34\lib\site-packages\pygame\sprite.py", line 1514, in spritecollide
for s in group.sprites():
AttributeError: 'Player' object has no attribute 'sprites'
I dashed out my name but kept the length, though I don't think it matters.
I've looked around the web for different parts of the error and nothing has come up, so I came here. Here's the full code (it's kinda messy and long):
import pygame, time, sys, random, Sprites, os
from pygame.locals import *
BLACK = (0, 0, 0)
MAPX = 10
MAPY = 20
TXY = 32
gameover = False
score = 0
lives = 2
playerXY = [MAPX*TXY//2, MAPY*TXY-TXY-TXY-5]
spritesheet01 = Sprites.Sheet(32, 32, 128, 32, 'spritesheet03.png')
sprites = spritesheet01.clipSheet()
psprite = Sprites.Player(sprites[0])
clock = pygame.time.Clock()
counter = int(clock.get_fps())
ebullet = Sprites.eBullet(sprites[3])
allspriteslist = pygame.sprite.Group()
enemylist = pygame.sprite.Group()
ebulletlist = pygame.sprite.Group()
pbulletlist = pygame.sprite.Group()
allspriteslist.add(psprite)
pygame.init()
enemynum = 5
enemies = []
enemytorf = [False, False, False, False, False, False, False, False, False, False]
def pause():
os.system("pause")
def enemyCreate():
print("enemycreate called")
while len(enemylist) < 5:
randomindex = random.randint(0, MAPX-1)
if enemytorf[randomindex] == False:
enemy = Sprites.Enemy(sprites[1])
enemytorf[randomindex] = True
enemy.rect.x = randomindex
enemy.rect.y = 0
ebullet.rect.x = randomindex
ebullet.rect.y = 0
enemylist.add(enemy)
allspriteslist.add(enemy)
ebulletlist.add(ebullet)
allspriteslist.add(ebullet)
print("enemycreate done")
def eBulletCreate():
print("bulletpassed")
for wi in range(len(ebull)):
ebullappend = ebull[wi]
ebullets.append(ebullappend)
print("Got through function defining")
display = pygame.display.set_mode((MAPX*TXY, MAPY*TXY))
pygame.display.set_caption("Star Smasher")
print("created screen")
pygame.key.set_repeat(10, 10)
endgame = False
create_enemy = pygame.USEREVENT + 1
shootbullet = pygame.USEREVENT + 2
print("created events")
enemyCreate()
pygame.time.set_timer(create_enemy, 7500)
pygame.time.set_timer(shootbullet, 2500)
print("Got to the while")
while endgame == False:
print("got into while")
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_SPACE:
pbullet = Sprites.pBullet(sprites[2])
pbullet.rect.x = playerXY[0]
pbullet.rect.y = playerXY[1]
allspriteslist.add(pbullet)
pbulletlist.add(pbullet)
elif event.key == K_a:
if playerXY[0] > 5:
playerXY[0] -= 5
elif event.key == K_d:
if playerXY[0] < MAPX*TXY-TXY-7:
playerXY[0] += 5
if event.type == create_enemy:
enemyCreate()
if event.type == shootbullet:
eBulletCreate()
print("got through event handling")
for bullet in pbulletlist:
enemyhitlist = pygame.sprite.spritecollide(pbullet, enemylist, True)
for enemy in enemyhitlist:
pbulletlist.remove(bullet)
allspriteslist.remove(bullet)
score += 100
print(score)
if pbullet.rect.y < 0:
pbulletlist.remove(bullet)
allspriteslist.remove(bullet)
for bullet in ebulletlist:
playerhit = pygame.sprite.spritecollide(ebullet, psprite, True)
for player in playerhit:
ebulletlist.remove(bullet)
allspriteslist.remove(bullet)
gameover = True
if ebullet.rect.y > MAPY*TXY:
ebulletlist.remove(bullet)
allspriteslist.remove(bullet)
print("got through bullet handling")
display.fill(BLACK)
allspriteslist.draw(display)
if gameover == True:
font = pygame.font.Font(freesansbold.ttf, 20)
font.render("Game Over, press any button to continue!", True, BLACK, background=None)
display.blit(font, (160, 320, 200, 360))
pause()
pygame.display.update()
clock.tick(60)
print("Got to the display update")
pygame.quit()
Thanks in advance for the help!
It is the wrong way around for a start. playerhit = pygame.sprite.spritecollide(ebullet, psprite, True) - the function definition is spritecollide(sprite, group, dokill, collided = None) so the player should be first, and then the bullet group.
Also please post the Sprite.py code.
I am a novice programming a game in the Python language using Pygame. I'm having a problem with my game loop. I can only run my game once then I can't make my game loop again. I will post my code below here:
This is my mouse based menu (Menu.py)
import pygame, os, sys
from pygame.locals import *
pygame.init()
def play_music(name, volume=0.7, loop=-1):
fullname = os.path.join('data', name)
try:
pygame.mixer.music.load(fullname)
pygame.mixer.music.set_volume(volume)
pygame.mixer.music.play(loop)
except:
raise SystemExit, "Can't load: " + fullname
def load_sound(name, volume=0.05):
fullname = os.path.join('data', name)
try:
sound = pygame.mixer.Sound(fullname)
sound.set_volume(volume)
except:
raise SystemExit, "Can't load: " + fullname
return sound
def run_game():
import Grab
def reset_highscore():
open("data/highscore.sav", "w").write(str(0))
print "Grab High score reset to 0"
class GrabMenu():
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.mouse.set_visible(0) #make the mouse cursor invisible
pygame.display.set_caption("Grab") #name the game
pygame.display.set_icon(pygame.image.load("data/Icon.png")) #set an icon for the game
screen = pygame.display.set_mode((800, 800)) #screen resolution width and height
background = pygame.Surface(screen.get_size()) #make the background
background = pygame.image.load("data/BG.png").convert() #convert background
background = pygame.transform.scale(background,(800, 800)) #scale the background down to the screen resulution
cursor = pygame.image.load("data/Hand1.png") #make a new cursor inside the game
WHITE = (255, 255, 255) # colors
YELLOW = (255, 216, 0)
running = True # value for main loop
clock = pygame.time.Clock()
font = pygame.font.SysFont("times new roman", 28, bold=True) # menu font and text.
fontcolor = WHITE
fontcolor2 = WHITE
fontcolor3 = WHITE
fontcolor4 = WHITE
mousetrigger = False
mouseclick = load_sound("Click.wav", 3.5) # mouse click
Menu1 = True
Menu2 = False #options menu
Menu3 = False #reset score menu
#JOYSTICK
try:
j = pygame.joystick.Joystick(0) # create a joystick instance
j.init() # init instance
print 'Enabled joystick: ' + j.get_name()
except:
pass
#main_loop
while running == True:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
running = False, sys.exit()
if event.type == MOUSEBUTTONDOWN and event.button == 1: # if mouse button is pressed, (left mouse key only)
if Menu1:
if ren_r.collidepoint(pygame.mouse.get_pos()): # play the game
if Menu1 == False:
pass
else:
mouseclick.play()
run_game()
elif ren2_r.collidepoint(pygame.mouse.get_pos()): #options
if Menu1 == False:
pass
else:
mouseclick.play()
Menu1 = False
Menu2 = True
elif ren3_r.collidepoint(pygame.mouse.get_pos()): #how to play
if Menu1 == False:
pass
else:
mouseclick.play()
elif ren4_r.collidepoint(pygame.mouse.get_pos()): #quit the game
if Menu1 == False:
pass
else:
mouseclick.play()
running = False, pygame.quit(), sys.exit()
elif Menu2:
if ren5_r.collidepoint(pygame.mouse.get_pos()): #reset high score
mouseclick.play()
reset_highscore()
elif ren6_r.collidepoint(pygame.mouse.get_pos()): #go back
mouseclick.play()
Menu1 = True
Menu2 = False
screen.blit(background, (0, 0)) #draw the background
screen.blit(cursor, pygame.mouse.get_pos()) #set the cursor image as the new mouse cursor
if Menu1:
ren = font.render("Play", True, (fontcolor))
ren_r = ren.get_rect()
ren_r.x, ren_r.y = 340, 530
ren2 = font.render("Options", True, (fontcolor2))
ren2_r = ren2.get_rect()
ren2_r.x, ren2_r.y = 340, 590
ren3 = font.render("How to Play", True, (fontcolor3))
ren3_r = ren3.get_rect()
ren3_r.x, ren3_r.y = 340, 650
ren4 = font.render("Quit Game", True, (fontcolor4))
ren4_r = ren4.get_rect()
ren4_r.x, ren4_r.y = 340, 710
screen.blit(ren, (340, 530))
screen.blit(ren2, (340, 590))
screen.blit(ren3, (340, 650))
screen.blit(ren4, (340, 710))
if ren_r.collidepoint(pygame.mouse.get_pos()):
mousetrigger = True
fontcolor = YELLOW
else:
fontcolor = WHITE
if ren2_r.collidepoint(pygame.mouse.get_pos()):
mousetrigger = True
fontcolor2 = YELLOW
else:
fontcolor2 = WHITE
if ren3_r.collidepoint(pygame.mouse.get_pos()):
mousetrigger = True
fontcolor3 = YELLOW
else:
fontcolor3 = WHITE
if ren4_r.collidepoint(pygame.mouse.get_pos()):
mousetrigger = True
fontcolor4 = YELLOW
else:
fontcolor4 = WHITE
elif Menu2:
options = font.render("Options", 1, (WHITE))
ren5 = font.render("Reset High Score", True, (fontcolor))
ren5_r = ren5.get_rect()
ren5_r.x, ren5_r.y = 350, 650
ren6 = font.render("Go back", True, (fontcolor2))
ren6_r = ren6.get_rect()
ren6_r.x, ren6_r.y = 350, 700
screen.blit(options, (350, 600))
screen.blit(ren5, (350, 650))
screen.blit(ren6, (350, 700))
if ren5_r.collidepoint(pygame.mouse.get_pos()):
mousetrigger = True
fontcolor = YELLOW
else:
fontcolor = WHITE
if ren6_r.collidepoint(pygame.mouse.get_pos()):
mousetrigger = True
fontcolor2 = YELLOW
else:
fontcolor2 = WHITE
pygame.display.update()
furthermore I use this when I press on "Play" text on my menu:
def run_game():
import Grab
to start my main program "Grab.py":
import pygame, time, math, sys, random, os
from pygame.locals import *
pygame.init() #make pygame ready
pygame.joystick.init
#my game code
done = False
while done == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.key == K_ESCAPE:
if highscore == 0:
pass
if highscore < get_highscore():
pass
else:
save_highscore(highscore)
if score == 0:
pass
else:
save_score(score)
save_level(level)
save_world(world)
done = True
pygame.mixer.music.stop()
Main game loop ends here and sends me back to my menu just like I want. However, when I try to import grab again from my menu then nothing happens. I went and searched for "Python import cycle" from Google and I discovered a few things but i'm still stuck. There must be an easier way to make Grab.py loop from this:
def run_game():
import Grab
Any help is very much appreciated.
Regards HJ.
Generally speaking, use import to load the definition of constants, functions or classes. Do not use it to run a bunch of statements. Call a function to run a bunch of statements.
For efficiency, Python only imports modules once. After it is loaded the first time, the module is cached in sys.modules. Every time Python encounters an import statement it check if the module is in sys.modules and uses the cached module if it exists. Only if the module is not in sys.modules does Python execute the code in the module. Thus the code in the module is never executed more than once. That is why import Grab does not execute the code in Grab.py the second time the import statement is reached.
So, instead, refactor Grab.py to put all the code you wish to run multiple times inside a function:
import pygame, time, math, sys, random, os
from pygame.locals import *
pygame.init() #make pygame ready
pygame.joystick.init() # <-- Note you need parentheses to *call* the init function
def main():
done = False
while done == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.key == K_ESCAPE:
if highscore == 0:
pass
if highscore < get_highscore():
pass
else:
save_highscore(highscore)
if score == 0:
pass
else:
save_score(score)
save_level(level)
save_world(world)
done = True
pygame.mixer.music.stop()
and then change
import Grab
to
import Grab
Grab.main()
You could move import Grab to the top of Menu.py; generally speaking it is recommended to put all the import statements at the top of any Python script or module.
I've been working on a Space Invaders-type game for the past week or so, and it's coming along really well, but for some reason when I run the game on my Windows computer (the one I prefer to code on), most of the sprites don't show up, or only show up when they're moving in a certain direction on the screen. When I run the exact same code on my Mac, everything blits and updates perfectly. Is this a known issue that pygame just doesn't get along with Windows? The fact that everything works on my Mac makes me think that it's not an issue with my code, but just in case, here's my main loop:
dirty = []
score_label = font.render("Score: " + str(score), 1, (255,215,0))
level_label = font.render("Level: " + str(level), 1, (255,215,0))
screen.blit(background,(10,10),(10,10,330,30))
screen.blit(score_label,(10,10))
screen.blit(level_label,(200,10))
dirty.append((10,10,330,30))
# New level
if isEmpty(enemies):
dirty.append((400,300,150,30))
for i in bullets:
dirty.append(i.pos)
screen.blit(background,(i.pos[0],i.pos[1]),i.pos)
bullets.remove(i)
if pauseCounter == 40:
screen.blit(background,(400,300),(400,300,150,30))
pauseCounter = 0
jump = 30
level+=1
for x in range(1,6):
for y in range(11):
enemies[x-1].append(Sprites.Enemy(enemy_values[6-x],(60*y,40*x),6-x))
for x in range(len(enemies)):
for e in enemies[x]:
dirty.append(e.pos)
else:
upLevelLabel = levelFont.render("Next Level!",1,(255,215,0))
screen.blit(upLevelLabel,(400,300))
pauseCounter += 1
# Player input
dirty.append(o.pos)
screen.blit(background,(o.pos[0],o.pos[1]),o.pos)
keys = pygame.key.get_pressed()
if keys[K_a] and o.pos[0]-10 >= 0:
o.speed = -10
o.move()
if keys[K_d] and o.pos[0] <= 907-o.pos[3]-10:
o.speed = 10
o.move()
dirty.append(o.pos)
screen.blit(o.image,o.pos)
# Add bullets
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == K_SPACE:
bullets.append(Sprites.Bullet(bullet,(o.pos[0]+28,o.pos[1])))
# Updates bunkers
for b in bunkers:
screen.blit(b.image,b.pos)
if b.health == 0:
screen.blit(background,(b.pos[0],b.pos[1]),b.pos)
dirty.append(b.pos)
bunkers.remove(b)
# Check if bullets are offscreen/collide, move accordingly
for b in bullets:
dirty.append(b.pos)
if b.pos[1] < 0:
screen.blit(background,(b.pos[0],b.pos[1]),b.pos)
dirty.append(b.pos)
bullets.remove(b)
if isEmpty(enemies) == False:
for x in range(len(enemies)):
if len(enemies[x]) > 0:
temp = enemies[x][0]
if b.pos[1] in range(temp.pos[1],temp.pos[1]+temp.pos[3]):
for e in enemies[x]:
if b.pos.colliderect(e.pos):
score += e.val*10
screen.blit(background,(b.pos[0],b.pos[1]),b.pos)
screen.blit(background,(e.pos[0],e.pos[1]),e.pos)
dirty.append(e.pos)
dirty.append(b.pos)
bullets.remove(b)
enemies[x].remove(e)
for i in bunkers:
if b.pos.colliderect(i.pos):
screen.blit(background,(b.pos[0],b.pos[1]),b.pos)
dirty.append(b.pos)
i.health -= 1
bullets.remove(b)
for b in bullets:
dirty.append(b.pos)
screen.blit(background,(b.pos[0],b.pos[1]),b.pos)
b.move()
screen.blit(b.image,b.pos)
dirty.append(b.pos)
# Moves enemy at appropriate pace, drops bombs
if enemyMoves == jump:
moveCounter += 1
if moveCounter == 20:
jump = jump/2
moveCounter = 0
enemyMoves = 0
for x in range(len(enemies)):
for e in enemies[x]:
dirty.append(e.pos)
screen.blit(background,(e.pos[0],e.pos[1]),e.pos)
e.move()
screen.blit(e.image,e.pos)
dirty.append(e.pos)
else:
for x in range(len(enemies)):
for e in enemies[x]:
screen.blit(e.image,e.pos)
enemyMoves+=1
pygame.display.update(dirty)
clock.tick(30)
print clock.get_fps()
Thanks in advance!
Maybe you should try:
dirty.append(Rect(x,y,width,height))
or
dirty.append(pygame.Rect(x,y,width,height))
Remember, you are passing a rectangle list to pygame.display.update(dirty) and so try and stick to pygame rectangles
instead of:
dirty.append((x,y,width,height))
Thank you to furas, it was the partial update that was causing the error!