I've have this dodging aliens game and it's not working. I can get the front begin screen to open but then when I hit enter to start it crashes and freezes. I've tried running it from python.exe instead of just IDLE but in that case it just pops up then closes right down. A few errors popped up the first few times I tried to run it but now there are no errors indicating what might be wrong. It just stops responding. What am I doing wrong here?
import pygame, random, sys
from pygame.locals import *
def startGame():
if event.type == K_ENTER:
if event.key == K_ESCAPE:
sys.exit()
return
def playerCollision():
for a in aliens:
if playerRect.colliderect(b['rect']):
return True
return False
pygame.init()
screen = pygame.display.set_mode((750,750))
clock = pygame.time.Clock()
pygame.display.set_caption('Dodge the Aliens')
font = pygame.font.SysFont(None, 55)
playerImage = pygame.image.load('')
playerRect = playerImage.get_rect()
alienImage = pygame.image.load('')
drawText('Dodge the Aliens!', font, screen, (750 / 3), (750 / 3))
drawText('Press ENTER to start.', font, screen, (750 / 3) - 45, (750 / 3) + 65)
pygame.display.update()
topScore = 0
while True:
aliens = []
score = 0
playerRect.topleft = (750 /2, 750 - 50)
alienAdd = 0
while True:
score += 1
pressed = pygame.key.get_pressed()
if pressed[pygame.K_LEFT]: x -=3
if pressed[pygame.K_RIGHT]: x += 3
if pressed[pygame.K_ESCAPE]: sys.exit()
alienAdd += 1
if alienAdd == addedaliens:
aliendAdd = 0
alienSize = random.randint(10, 40)
newAlien = {'rect': pygame.Rect(random.randint(0, 750 - alienSize), 0 -alienSize, alienSize, alienSize), 'speed': random.randint(1, 8), 'surface':pygame.transform.scale(alienImage, (alienSize, alienSize)), }
aliens.append(newAlien)
for a in aliens[:]:
if a['rect'].top > 750:
aliens.remove(a)
screen.fill(0,0,0)
drawText('Score %s' % (score), font, screen, 10, 0)
screen.blit(playerImage, playerRect)
for a in aliens:
screen.blit(b['surface'], b['rect'])
pygame.display.update()
if playerCollision(playerRect, aliens):
if score > topScore:
topScore = score
break
clock.tick(60)
drawText('Game Over!', font, screen, (750 / 3), ( 750 / 3))
drawText('Press ENTER To Play Again.', font, screen, ( 750 / 3) - 80, (750 / 3) + 50)
pygame.display.update()
startGame()
Here's my new code after modifying it some
import pygame, random, sys
from pygame.locals import*
alienimg = pygame.image.load('C:\Python27\alien.png')
playerimg = pygame.image.load('C:\Python27\spaceship.png')
def playerCollision(): # a function for when the player hits an alien
for a in aliens:
if playerRect.colliderect(b['rect']):
return True
return False
def screenText(text, font, screen, x, y): #text display function
textobj = font.render(text, 1, (255, 255, 255))
textrect = textobj.get_rect()
textrect.topleft = (x,y)
screen.blit(textobj, textrect)
def main(): #this is the main function that starts the game
pygame.init()
screen = pygame.display.set_mode((750,750))
clock = pygame.time.Clock()
pygame.display.set_caption('Dodge the Aliens')
font = pygame.font.SysFont("monospace", 55)
pressed = pygame.key.get_pressed()
aliens = []
score = 0
alienAdd = 0
addedaliens = 0
while True: #our while loop that actually runs the game
for event in pygame.event.get(): #key controls
if event.type == KEYDOWN and event.key == pygame.K_ESCAPE:
sys.exit()
elif event.type == KEYDOWN and event.key == pygame.K_LEFT:
playerRect.x -= 3
elif event.type == KEYDOWN and event.key == pygame.K_RIGHT:
playerRect.x += 3
playerImage = pygame.image.load('C:\\Python27\\spaceship.png').convert() # the player images
playerRect = playerImage.get_rect()
playerRect.topleft = (750 /2, 750 - 50)
alienImage = pygame.image.load('C:\\Python27\\alien.png').convert() #alien images
alienAdd += 1
pygame.display.update()
if alienAdd == addedaliens: # randomly adding aliens of different sizes and speeds
aliendAdd = 0
alienSize = random.randint(10, 40)
newAlien = {'rect': pygame.Rect(random.randint(0, 750 - alienSize), 0 -alienSize, alienSize, alienSize), 'speed': random.randint(1, 8), 'surface':pygame.transform.scale(alienImage, (alienSize, alienSize)), }
aliens.append(newAlien)
for a in aliens[:]:
if a['rect'].top > 750:
aliens.remove(a) #removes the aliens when they get to the bottom of the screen
screen.blit(screen, (0,0))
screenText('Score %s' % (score), font, screen, 10, 0)
screen.blit(playerImage, playerRect)
for a in aliens:
screen.blit(b['surface'], b['rect'])
pygame.display.flip()
if playerCollision(playerRect, aliens):
if score > topScore:
topScore = score
break
clock.tick(60)
screenText('Game Over!', font, screen, (750 / 6), ( 750 / 6))
screenText('Press ENTER To Play Again.', font, screen, ( 750 / 6) - 80, (750 / 6) + 50)
pygame.display.update()
main()
I still see several issues with your code and I think you're trying to do too much at once for the very beginning. Try to keep it as simple as possible. Try creating a display and draw some image:
import pygame
pygame.init()
display = pygame.display.set_mode((750, 750))
img = pygame.image.load("""C:\\Game Dev\\alien.png""")
display.blit(img, (0, 0))
pygame.display.flip()
You'll have to adjust the img path of course. Running this you should either get an explicit Error (which you should then post in another thread) or see your img on the screen. BUT the program will not respond as there's no event handling and no main loop at all.
To avoid this, you could introduce a main loop like:
import sys
import pygame
pygame.init()
RESOLUTION = (750, 750)
FPS = 60
display = pygame.display.set_mode(RESOLUTION)
clock = pygame.time.Clock()
img = pygame.image.load("""C:\\Game Dev\\alien.png""")
while True: # <--- game loop
# check quit program
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# clear the screen
display.fill((0, 0, 0))
# draw the image
display.blit(img, (0, 0))
# update the screen
pygame.display.flip()
# tick the clock
clock.tick(FPS)
This should result in a program that displays the same img over and over, and it can be quit properly using the mouse. But still it's like a script, and if someone imported this, it would execute immediately, which is not what we want. So let's fix that as well and wrap it all up in a main function like this:
import sys
import pygame
#defining some constants
RESOLUTION = (750, 750)
FPS = 60
def main(): # <--- program starts here
# setting things up
pygame.init()
display = pygame.display.set_mode(RESOLUTION)
clock = pygame.time.Clock()
img = pygame.image.load("""C:\\Game Dev\\alien.png""")
while True: # <--- game loop
# check quit program
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# clear the screen
display.fill((0, 0, 0))
# draw the image
display.blit(img, (0, 0))
# update the screen
pygame.display.flip()
# tick the clock
clock.tick(FPS)
if __name__ == "__main__":
main()
The 'if name == "main":' ensures that the program does not execute when it's imported.
I hope this helps. And remember: Don't try too much all at once. Take small steps, one after another, and try to keep the control over your program. If needed, you can even put a print statement after every single line of code to exactly let you know what your program does and in what order.
Related
When ever I run my pygame script in the web build it shows a black screen, I have tried making a new project and it works fine, pls help
here is my code:
import asyncio
import pygame
import sys
import keyboard
pygame.init()
win = pygame.display.set_mode((500, 500,))
jellee = pygame.font.SysFont("assets/Jellee-Bold.otf", 24)
# init pygame here
def player(posX, posY):
global win
character = pygame.image.load("assets/pole.png")
win.blit(character, (posX, posY))
def pause(sizeX, sizeY):
global win
character_image = pygame.image.load("assets/Menu.png")
character = pygame.transform.scale(character_image, (sizeX, sizeY))
win.blit(character, (0, 0))
def button1(sizeX, sizeY, posX, posY):
global jellee
global win
text_image = jellee.render("Resume", False, pygame.Color(254, 164, 22))
text = pygame.transform.scale(text_image, (sizeX - 20, sizeY - 10))
button_image = pygame.image.load("assets/Button1.png")
button = pygame.transform.scale(button_image, (sizeX, sizeY))
win.blit(button, (posX, posY))
win.blit(text, (posX + 10, posY + 5))
def menu(events):
...
# draw
# check events
# change state
...
def play(events):
...
# draw
# check events
# change state
...
game_state = menu
async def main():
global game_state
openmenu = False
playerX = 250
playerY = 250
# or init pygame here
while True:
win.fill("red")
player(playerX, playerY)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if not openmenu:
if keyboard.is_pressed("ESCAPE"):
openmenu = True
if keyboard.is_pressed("a"):
playerX -= 10
if keyboard.is_pressed("d"):
playerX += 10
if openmenu:
pause(500, 500)
button1(250, 125, 125, 100)
testmouseX, testmouseY = pygame.mouse.get_pos()
if pygame.mouse.get_pressed() == (1, 0, 0) and testmouseX > 126 and testmouseY > 102 and testmouseX < 369 and testmouseY < 217:
print(testmouseX, testmouseY)
openmenu = False
game_state(pygame.event.get())
pygame.display.update()
await asyncio.sleep(0)
# Closing the game. not strictly required, neither on desktop
pygame.quit()
sys.exit()
asyncio.run( main() )
I tried replacing the while loop and pasting code into working project, nothing seems to work
I need a web build for a game jam I am in(not strictly required but nice to have) does anyone know how to fix this? or a alternative to pygbag?
I've been trying to make a Chrome Dino Game, however, I'm struggling with this problem:
On every frame, it should draw a new one at the new position and delete the previous one to make it look as if it's moving. HOWEVER, it remains at its previous position and a new image appears on its next position. I did write the pygame.display.update() code at the end of my maintop.
In the last time I ran into a similar problem, I managed to make it work by drawing a background image, but this time, it doesn't work.
following are my codes:
import pygame
import os
from random import randint
import schedule
pygame.init()
assets = os.path.join(os.path.dirname(__file__), "Assets")
screen_size = (screen_width, screen_height) = (1280, 720)
screen = pygame.display.set_mode(screen_size)
clock = pygame.time.Clock()
fps = 120
bg = pygame.image.load(os.path.join(assets, "IMG_15.png"))
ground = 700
running = True
spacebaridx = 0
gamestart = False
tick_on_start = 0
obs1 = pygame.image.load(os.path.join(assets, "colourmat/light_green.png"))
pygame.transform.scale(obs1, (100, 200))
obs2 = pygame.image.load(os.path.join(assets, "colourmat/light_green.png"))
pygame.transform.scale(obs2, (120, 200))
obs3 = pygame.image.load(os.path.join(assets, "colourmat/light_green.png"))
pygame.transform.scale(obs3, (150, 200))
ls_obs = []
def create_obs():
k = randint(1, 3)
if k == 1:
info = {"type":1, "img":obs1, "x":screen_width, "y":ground - 200, "tox":2}
ls_obs.append(info)
if k == 2:
info = {"type":2, "img":obs2, "x":screen_width, "y":ground - 200, "tox":2}
ls_obs.append(info)
else:
info = {"type":3, "img":obs3, "x":screen_width, "y":ground - 200, "tox":2}
ls_obs.append(info)
schedule.every(3).seconds.do(create_obs)
while running:
dt = clock.tick(fps)
if gamestart == True:
game_ticks = pygame.time.get_ticks() - tick_on_start
schedule.run_pending()
else:
game_ticks = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT: running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if spacebaridx == 0: # Press space to start / to tell whether it's the first press
spacebaridx += 1
gamestart = True
tick_on_start = pygame.time.get_ticks()
else:
pass # Jump
for o in ls_obs:
o["x"] += o["tox"] * -1
screen.blit(bg, (0, 0))
for o in ls_obs:
screen.blit(o["img"], (o["x"], o["y"]))
pygame.display.update()
pygame.quit()
This issue is occurring because you aren't clearing the display within each frame. In pygame, in order to clear the display, we need to use the fill method. So in your code, at the top of your game loop before the event loop, add screen.fill((0, 0, 0)). This will fill your screen in the color black. Don't worry, the black won't be shown if you draw the background on top of it. Now, when you add a new image, the previous images won’t be displayed.
Modified Game Loop
while running:
screen.fill((0, 0, 0))
dt = clock.tick(fps)
if gamestart == True:
game_ticks = pygame.time.get_ticks() - tick_on_start
schedule.run_pending()
else:
game_ticks = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT: running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if spacebaridx == 0: # Press space to start / to tell whether it's the first press
spacebaridx += 1
gamestart = True
tick_on_start = pygame.time.get_ticks()
else:
pass # Jump
for o in ls_obs:
o["x"] += o["tox"] * -1
screen.blit(bg, (0, 0))
for o in ls_obs:
screen.blit(o["img"], (o["x"], o["y"]))
pygame.display.update()
pygame.quit()
i = 1 ## fever_interval = 3
if score > i * 100:
pygame.time.set_timer(pygame.USEREVENT, 5)
mino = randint(1, 1)
next_mino = randint(1, 1)
next_fever = (i + fever_interval) * fever_score # 피버모드 점수 표시
# fever time
if blink:
screen.blit(pygame.transform.scale(ui_variables.fever_image,
(int(SCREEN_WIDTH * 0.5), int(SCREEN_HEIGHT * 0.2))),
(SCREEN_WIDTH * 0.1, SCREEN_HEIGHT * 0.1))
blink = False
else:
blink = True
i += fever_interval
It's my code to change to fever_mode for 5sec if you reach at specific score
so I made some timers EX) pygame.time.get_ticks() and pygame.time.set_timer()
but These stuff doesn't work for me.
How can I do to solve it..
The time argument of pygame.time.set_timer must be specified in milliseconds and not in seconds (5000 milliseconds = 5 seconds):
pygame.time.set_timer(pygame.USEREVENT, 5)
pygame.time.set_timer(pygame.USEREVENT, 5000)
Minimal example: blinking object
import pygame
pygame.init()
window = pygame.display.set_mode((200, 200))
pygame.time.set_timer(pygame.USEREVENT, 500)
blink = True
run = True
clock = pygame.time.Clock()
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.USEREVENT:
blink = not blink
window.fill(0)
if blink:
pygame.draw.circle(window, (255, 0, 0), (100, 100), 80)
pygame.display.flip()
pygame.quit()
exit()
See also Spawning multiple instances of the same object concurrently in python.
I'm currently making a Python clicking game using Pygame. Right now, there is a coin in the center of the screen that you can click. What I want to add now, it a little green "+$10" icon that appears somewhere next to the coin whenever someone clicks it. This is what I want the game to look like whenever someone clicks the coin:
Here is the code of my coin functions:
def button_collide_mouse(element_x, element_y, x_to_remove, y_to_remove):
mouse_x, mouse_y = pygame.mouse.get_pos()
if mouse_x > element_x > mouse_x - x_to_remove and \
mouse_y > element_y > mouse_y - y_to_remove:
return True
def check_events(coin, settings):
for event in pygame.event.get():
# Change button color if mouse is touching it
if button_collide_mouse(coin.image_x, coin.image_y, 125, 125):
coin.image = pygame.image.load('pyfiles/images/click_button.png')
if event.type == pygame.MOUSEBUTTONUP:
settings.money += settings.income
else:
coin.image = pygame.image.load('pyfiles/images/click_button_grey.png')
Using my current code, how can I add that kind of effect?
See How to make image stay on screen in pygame?.
Use pygame.time.get_ticks() to return the number of milliseconds since pygame.init() was called. When the coin is clicked, calculate the point in time after that the text image has to be removed. Add random coordinates and the time to the head of a list:
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
# [...]
if event.type == pygame.MOUSEBUTTONDOWN:
if coin_rect.collidepoint(event.pos):
pos = ... # random position
end_time = current_time + 1000 # 1000 milliseconds == 1 scond
text_pos_and_time.insert(0, (pos, end_time))
Draw the text(s) in the main application loop. Remove the text when the time has expired from the tail of the list:
for i in range(len(text_pos_and_time)):
pos, text_end_time = text_pos_and_time[i]
if text_end_time > current_time:
window.blit(text, text.get_rect(center = pos))
else:
del text_pos_and_time[i:]
break
Minimal example:
import pygame
import random
pygame.init()
window = pygame.display.set_mode((400, 400))
font = pygame.font.SysFont(None, 40)
clock = pygame.time.Clock()
coin = pygame.Surface((160, 160), pygame.SRCALPHA)
pygame.draw.circle(coin, (255, 255, 0), (80, 80), 80, 10)
pygame.draw.circle(coin, (128, 128, 0), (80, 80), 75)
cointext = pygame.font.SysFont(None, 80).render("10", True, (255, 255, 0))
coin.blit(cointext, cointext.get_rect(center = coin.get_rect().center))
coin_rect = coin.get_rect(center = window.get_rect().center)
text = font.render("+10", True, (0, 255, 0))
text_pos_and_time = []
run = True
while run:
clock.tick(60)
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
if coin_rect.collidepoint(event.pos):
pos = pygame.math.Vector2(coin_rect.center) + pygame.math.Vector2(105, 0).rotate(random.randrange(360))
text_pos_and_time.insert(0, ((round(pos.x), round(pos.y)), current_time + 1000))
window.fill(0)
window.blit(coin, coin_rect)
for i in range(len(text_pos_and_time)):
pos, text_end_time = text_pos_and_time[i]
if text_end_time > current_time:
window.blit(text, text.get_rect(center = pos))
else:
del text_pos_and_time[i:]
break
pygame.display.flip()
pygame.quit()
exit()
I have to move the rectangular object straight through the pygame window. I have tried some code with pygame. The code is
import pygame
from itertools import cycle
pygame.init()
screen = pygame.display.set_mode((300, 300))
s_r = screen.get_rect()
player = pygame.Rect((100, 100, 50, 50))
timer = pygame.time.Clock()
movement = "straight"
x = 0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
raise
if movement == 'straight':
x += 50
screen.fill(pygame.color.Color('Black'))
pygame.draw.rect(screen, pygame.color.Color('Grey'), player)
pygame.display.flip()
timer.tick(25)
Here the image didnt moves. What I need is that the image must be moved in a straight way.
x is adding, but that does not affect player, which actually affects the drawing of the rectangle.
import pygame
from itertools import cycle
pygame.init()
screen = pygame.display.set_mode((300, 300))
s_r = screen.get_rect()
timer = pygame.time.Clock()
movement = "straight"
x = 0
player = pygame.Rect((x, 100, 50, 50))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
raise
if movement == 'straight':
x += 10
player = pygame.Rect((x, 100, 50, 50))
if x >= 300:
x = 0
screen.fill(pygame.color.Color('Black'))
pygame.draw.rect(screen, pygame.color.Color('Grey'), player)
pygame.display.flip()
timer.tick(25)
You need to adjust the player rectangle each time you change x. From http://www.pygame.org/docs/ref/rect.html, you can see that the first two arguments are "left" and "top". So, if you want to the rectangle to move from left to right, you'll want something like this:
player = pygame.Rect((100 + x, 100, 50, 50))
pygame.draw.rect(screen, pygame.color.Color('Grey'), player)
import pygame
BLACK = pygame.color.Color('Black')
GREY = pygame.color.Color('Grey')
pygame.init()
screen = pygame.display.set_mode((300, 300))
screen_rect = screen.get_rect()
timer = pygame.time.Clock()
movement = "straight"
player = pygame.Rect(0, 100, 50, 50) # four aguments in place of tuple (,,,)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if movement == 'straight':
player.x += 10
if player.x >= 300: # check only when `player.x` was changed
player.x = 0
screen.fill(BLACK)
pygame.draw.rect(screen, GREY, player)
pygame.display.flip()
timer.tick(25)
BTW:
don't use raise to exit program.
use readable variable - not s_r but screen_rect
you don't need x - you have player.x
you can create rectangle only once
remove repeated empty lines when you add code to question