Related
I struggle a lot with While Loops and For loops.
I also struggle with Augmented Assigned Operators. I.e, "+=, -=, *=, /="
will you guys help me "dumb it down" all of the things I struggle with?
also, how do you make the text move up and down like a grainy horror movie?
lastly, I keep getting an "error not found in the directory" when it comes to putting an image in the game caption window.
import pygame
pygame.init()
#window
size =(700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("1999")
clock = pygame.time.Clock()
#colors
red = ((153,0,0))
black = ((0,0,0))
white = ((255,255,255))
blue = ((0,100,255))
green = ((0,155,0))
#font of the text
font = pygame.font.Font("C:/Windows/Fonts/CHILLER.TTF", 100)
font = pygame.font.Font("C:/Windows/Fonts/CHILLER.TTF", 55)
font = pygame.font.Font("C:/Windows/Fonts/CHILLER.TTF", 55)
#text
text = font.render("1999", True, red)
text_2 = font.render("The Cursed Game: ", True, red)
text_3 = font.render("Enter if you Dare! ",True, red)
screen.blit(text,[300,100])
screen.blit(text_2,[220,150])
screen.blit(text_3, [230, 200])
exit_window = False
while not exit_window:
rect_x = 50
rect_y = 50
rect_x += 1
rect_y += 1
pygame.draw.rect(screen, green, [rect_x,rect_y,50,50])
pygame.display.update()
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit_window = True
pygame.quit()
Is the problem really that you should be updating rect_x and rect_y (which I assume are x and y coordinates) after you've done the drawing? You'll also need to move setting their initial values outside of the loop of course. Otherwise, they are just reinitialised to 50 on each iteration of the loop.
This question already has answers here:
How can I create a text input box with Pygame?
(5 answers)
Why is my pygame display not responding while waiting for input?
(1 answer)
Closed 1 year ago.
I am new to python programming and am trying to create a game for class. Every time I run the program, before the user gets to put input in the surface screen goes non responsive. What am I doing wrong?
#import modules needed
import pygame, sys, time, random
from pygame.locals import *
def main():
#Assigns Colors
ORANGE = (255, 127, 80) #Background
BLACK = (0, 0, 0 ) #Mountains
WHITE = (255,255,255) #Snow & Trees
BROWN = (61, 16, 16) #moose & Mountains
GREEN = (0, 153, 0) #Trees
L_BROWN=(181, 101, 29) #Tree Trunks
YELLOW =(255, 255, 204) #Sky
BLUE = (67, 111, 181) #Lake
LIME = (57, 255, 20)
#initiate modules
pygame.init()
done=False
#assign screen values and display captions
screen = pygame.display.set_mode((1000,600))
pygame.display.set_caption("Welcome To Michelle Era's Final Project - Moose Scene")
#start clock
clock=pygame.time.Clock()
fps = (60)
#Assign Variables
drink = " "
name = " "
welcome = " "
water= " "
quit = " "
i = 0
Moose_img = pygame.image.load('moose.png')
Beer_img = pygame.image.load('beer.png')
mikey_img=pygame.image.load('Mikey.jpg')
Water_img = pygame.image.load('water.png')
font = pygame.font.SysFont('Calibri',25,False,False)
text=font.render("My text", True, YELLOW)
player_num = 0
moose_num = random.randrange(1,26)
while not done:
pygame.event.pump()
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill(ORANGE) #fills background orange
#Draw Scene
def draw_mountains(screen, x,y):
pygame.draw.rect(screen, BLACK,(1,200,1000,100)) # Base of mountain
x_offset=0
while x_offset<1000:
pygame.draw.polygon(screen, WHITE, [[100+x_offset,100], [0+x_offset ,225], [200+x_offset, 225]], 0) # snow caps on mountain
pygame.draw.polygon(screen, BROWN, [[100+x_offset,120], [0+x_offset ,225], [200+x_offset, 230]], 0)
x_offset=x_offset+120#tells how many pixels to move over until you reached 1000
def draw_trees(screen, x,y):
x_offset=0
while x_offset<1000:
pygame.draw.ellipse(screen, GREEN, [27+x_offset,158,40,50], 0) #draws leaves starting at x27 to x 1000 every 50 pixels
x_offset=x_offset +50 #tells how many pixels to move over until you reached 1000
pygame.draw.line(screen,L_BROWN,[x_offset,200],[x_offset +10,250],8) #draws trunk starting at x0 to x 1000 every 50 pixels
pygame.draw.line(screen,WHITE,[x_offset,207],[x_offset +10,250],1) #draws snow starting at x0 to x 1000 every 50 pixels
x_offset=x_offset +50
def draw_lake(screen, x,y):
pygame.draw.rect(screen,BLUE, [0,300,1000,200],0)# draws the lake
pygame.draw.rect(screen,L_BROWN,[0,500,1000,100],0) #draws grass
def gameover():
screen.fill(BLACK) #fills play surface
pygame.display.flip() #updates the display
gameOverFont=pygame.font.Font('freesansbold.ttf',17)
gameOversurf = gameOverFont.render("A Big thank you to my brother Michael Era who originally painted the mural that was the inspiration for this project",True, YELLOW)
gameOverRect = gameOversurf.get_rect()
gameOverRect.midtop = (500,40)
screen.blit(gameOversurf, gameOverRect)
screen.blit(mikey_img, (200,100))
pygame.display.flip()
time.sleep(30)
draw_mountains(screen, 0,0)
draw_trees(screen,0,0)
draw_lake(screen,300,400)
screen.blit(Moose_img, (600,400))
welcome = font.render("WELCOME TO MOOSEVILLE", True, YELLOW)
screen.blit(welcome, [300,50])
pygame.display.update()
#
#GET user input
name=(input('What is your Moose named ? '))
name=font.render("I like The Name " + str(name), True, YELLOW)
draw_mountains(screen, 0,0)
draw_trees(screen,0,0)
draw_lake(screen,300,400)
screen.blit(Moose_img, (600,400))
screen.blit(name, (550, 355))
pygame.display.update()
num_game=font.render("I am thinking of a number between 1 and 25, can you guess it? ", True, LIME)
screen.blit(num_game,(25,325))
player_num=(input(" What is your guess 1 to 10: "))
player_num = font.render('You Choose The Number: ' +str(player_num), True, LIME)
screen.blit(player_num,(25,350))
pygame.display.update()
moose_num = random.randrange(1,11)
moose_num=font.render('My number choice was : ' + str(moose_num), True, LIME)
screen.blit(moose_num,(25,376))
pygame.display.update()
if player_num == moose_num:
won=font.render('You Won!!!', True, YELLOW)
screen.blit(won,(25,400))
pygame.display.update()
else:
lose=font.render('You Lose!' , True, YELLOW)
screen.blit(lose,(25,400))
pygame.display.update()
quit = input('Do you want to try again? y or n ')
if quit == "n":
gameover()
else:
done=False
pygame.quit()
main()
Firstly, you don't need both event.pump() and event.get(), just use event.get in the loop as now. Also, you don't usually define functions inside a while loop. They would be outside the loop and called from inside it. You are also calling both event.pump and event.get and getting input via "input."
You also call pygame.quit() inside the while loop. Break this up into a bunch of functions.
main() - this calls all the others
get_input()
draw_screen()
etc
Also the numbers game says:
num_game=font.render("I am thinking of a number between 1 and 25, can you guess it? "
and then asks for:
player_num=(input(" What is your guess 1 to 10: "))
You cannot use input in the application loop. input waits for an input. While the system is waiting for input, the application loop will halt and the game will not respond. Use the KEYDOWN event instead of input:
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
# [...]
Either implement a textbox (see How to create a text input box with pygame?)
or get the input in a separate thread (see Why is my display not responding while waiting for input?).
I am developing a small game for learning purposes. I have created a simple animation for the title screen. Since there is also a function for full screen in the code, I wanted to create a title screen that:
Displayed the animation
Turned into full screen when the key was activated
Continued the animation at the point it was before activating full screen
In order to do this, I resorted to threading. However, this is the first time I tried to do any multi-threading, and I donĀ“t know what did I do wrong. The result is an undetermined error.
The code for the title screen is this:
try:
GameAnimation = threading.Thread(target=GameTitleAnimation, (Window, WindowDimensions, FontDictionary, CurrentVersion))
GameAnimation.start()
except:
print "There was an error while loading the screen. Press one key to exit the program."
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
Quit()
if event.type == pygame.KEYDOWN:
if event.key == K_ESCAPE:
Quit()
elif event.key == K_f:
Fullscreen(Window, WindowDimensions)
else:
return
The code for the animation is:
TitleWhite = [255, 255, 255, 0]
Black = BASE_BLACK
TitleLetters = ("R", "O", "G", "U", "E", " ", "H", "U", "N", "T", "E", "R")
Title = FontDictionary["TitleFont"][1].render("ROGUE HUNTER", False, TitleWhite)
TextWidth = Title.get_width()
TextHeight = Title.get_height()
TitleXPosition = (WindowDimensions[0] - TextWidth) / 2
TitleYPosition = (WindowDimensions[1] / 2) - (TextHeight / 2)
for letter in TitleLetters:
if letter == " ":
TitleXPosition += CurrentLetterWidth
else:
while TitleWhite[3] < 100:
TitleWhite[3] += 1
CurrentLetter = FontDictionary["TitleFont"][1].render(letter, False, TitleWhite)
CurrentLetter.set_alpha(TitleWhite[3])
Window.blit(CurrentLetter, (TitleXPosition, TitleYPosition))
time.sleep(0.008)
try:
pygame.display.update()
except Exception:
traceback.print_exception
TitleWhite[3] = 0
CurrentLetterWidth = CurrentLetter.get_width()
TitleXPosition += CurrentLetterWidth
FadeInSurface = pygame.Surface((WindowDimensions[0], WindowDimensions[1]))
FadeInSurface.fill(TitleWhite)
OpacityRounds = 1
while TitleWhite[3] < 100.0:
TitleWhite[3] = 1.1 ** OpacityRounds
FadeInSurface.set_alpha(TitleWhite[3])
Window.blit(FadeInSurface, (0, 0))
OpacityRounds += 1
pygame.display.update()
time.sleep (0.015)
time.sleep(0.7)
TitleXPosition = (WindowDimensions[0] - TextWidth) / 2
Version = FontDictionary["BodyFont"][1].render(CURRENT_VERSION, False, TitleWhite)
VersionHeight = Version.get_height()
VersionWidth = Version.get_width()
VersionXPosition = (WindowDimensions[0] - VersionWidth) / 2
VersionYPosition = TitleYPosition + TextHeight
while True:
pygame.draw.rect(Window, Black, (0, 0, WindowDimensions[0], WindowDimensions[1]), 0)
Window.blit(Title, (TitleXPosition, TitleYPosition))
Window.blit(Version, (VersionXPosition, VersionYPosition))
pygame.display.update()
I'd be very grateful if anyone could help me with this. I am going crazy.
There's no reason to use threading in your code. It will only make your code harder to read, harder to debug and error prone.
Usually you want to have some kind of state in your game that you use to determinate what should happen in a frame. You can find a class based example here.
Another way to handle this, which is a bit similar to your code, is to use coroutines.
Look at your animation code and instead of calling pygame.display.update(), give the control back to the main loop. The main loop will handle events, frame limiting and drawing, then give control back to the coroutine (which keeps track of it's own state).
Here's a simple hacky example:
import pygame
import pygame.freetype
pygame.init()
size = (640, 480)
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
def game_state(surf):
rect = pygame.Rect(200, 200, 32, 32)
while True:
events = yield
pressed = pygame.key.get_pressed()
x = 1 if pressed[pygame.K_RIGHT] else -1 if pressed[pygame.K_LEFT] else 0
rect.move_ip(x*5, 0)
pygame.draw.rect(surf, pygame.Color('dodgerblue'), rect)
yield
def title_state(surf):
text = 'Awesome Game'
colors = [[255, 255, 255, 20] for letter in text]
font = pygame.freetype.SysFont(None, 22)
font.origin = True
while True:
for color in colors:
color[3] += 33
if color[3] > 255: color[3] = 0
x = 200
for (letter, c) in zip(text, colors):
bounds = font.get_rect(letter)
font.render_to(surf, (x, 100), letter, c)
x += bounds.width + 1
font.render_to(surf, (180, 150), 'press [space] to start', pygame.Color('grey'))
events = yield
yield
def main():
title = title_state(screen)
game = game_state(screen)
state = title
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_ESCAPE:
return
if e.key == pygame.K_SPACE:
state = game if state == title else title
if e.key == pygame.K_f:
if screen.get_flags() & pygame.FULLSCREEN:
pygame.display.set_mode(size)
else:
pygame.display.set_mode(size, pygame.FULLSCREEN)
screen.fill(pygame.Color('grey12'))
next(state)
state.send(events)
pygame.display.update()
clock.tick(60)
if __name__ == '__main__':
main()
See how the main loop is clean and simple, and all of the game state is handled in the coroutines. The title screen part of the code does not care about fullscreen or not or how to switch to fullscreen, and the main loop does not care of what the title screen coroutine does. And we don't need threading.
In practice it's not that different from the class based example I linked above, but using coroutines makes it easy to implement the title screen animation.
Basically you have an endless loop, you mutate some state (like the color of a letter), and then say "now draw this!" by just calling yield.
This is a large chunk of code to debug.
I'm not familiar with pygame or python threading, but it seems to me that you need to include some debug lines to determine exactly where the error occurs during your game animation thread (if it's even occuring there at all).
Something like this pattern should help determine the source of the problem:
import logging
logging.info("start animation initialization")
...
logging.info("begin animation loop")
...
logging.info("end animation loop")
https://docs.python.org/2/howto/logging.html
I am creating a flashcard game for my kid. Its about Dinos. I am having trouble making "Congrats, You got it right" appear on the screen. I have moved my code all over the place but no luck. Can someone please help me out.
To be clear, What I want to happen is when the user presses the number 1,2,3 on the keypad, and if the key is the correct answer that correlates to the question, the message "Congrats, You got it right!" should appear on the screen.
I know the keydown event right now is the return key, but I did that for testing purposes only. This is also the same for testtext variable. I was using that variable to see if I could print "Hello WOrld" to the screen.
I do have a feeling it has something to do with the loop that is running. My guess would be is that it does show up for a fraction of a second but disappears before anyone can see it.
import pygame, random
pygame.font.init()
pygame.init()
font = pygame.font.Font(None, 48)
#Created the window display
size = width, height = 800,800
screen = pygame.display.set_mode(size)
#Loads the images of the starting game Trex
#t_rex = pygame.image.load('trex1.png')
##Places the image on the screen
#screen.blit(t_rex,(150,50))
count = 0
score = 0
active = False
testtext = font.render("Hello WOrld", True, (250, 250, 250))
#The below code keeps the display window open until user decides to quie app
crashed = False
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
if event.type==pygame.KEYDOWN:
if event.key==pygame.K_RETURN:
screen.blit(testtext, (200,699))
while count < 2:
screen.fill(0)
dinoQuestions = ["Does a t-rex eat meat?\n","Does a trycerotopes have 3 horns?\n"]
dinoAnswer = ["Yes\n", "No\n","Maybe\n"]
wordnum = random.randint(0, len(dinoQuestions)-1)
mainpic = pygame.image.load("trex1.png")
screen.blit(mainpic, (150, 20))
options = [random.randint(0, len(dinoAnswer)-1),random.randint(0, len(dinoAnswer)-1)]
options[random.randint(0,1)] = wordnum
question_display = font.render(dinoQuestions[wordnum].rstrip('\n'),True, (255, 255, 255))
text1 = font.render('1 - ' + dinoAnswer[options[0]].rstrip('\n'),True, (255, 255, 255))
text2 = font.render('2 - ' + dinoAnswer[options[1]].rstrip('\n'),True, (255, 255, 255))
#the below code is for testing purposes only
screen.blit(question_display,(200, 590))
screen.blit(text1, (200, 640))
screen.blit(text2, (200, 690))
count = count + 1
pygame.display.flip()
The blit to your screen surface you perform when handling a Return key down event is overwritten when you later call screen.fill(0).
I've rearranged your code a little and added displaying a result on appropriate key press.
import pygame
import random
pygame.init()
pygame.font.init()
font = pygame.font.Font(None, 48)
size = width, height = 800,800
screen = pygame.display.set_mode(size) #Created the window display
count = 0
score = 0
active = False
white = pygame.color.Color("white")
black = pygame.color.Color("black")
green = pygame.color.Color("green")
# load/create static resources once
mainpic = pygame.image.load("trex1.png")
testtext = font.render("Hello World", True, (250, 250, 250))
correct_text = font.render("Correct! Well Done!", True, green)
clock = pygame.time.Clock() # for limiting FPS
dinoQuestions = ["Does a t-rex eat meat?","Does a triceratops have 3 horns?"]
dinoAnswer = ["Yes", "No","Maybe"]
# initialise state
show_hello = False
show_correct = False
update_questions = True # need to update questions on the first iteration
finished = False
while not finished:
for event in pygame.event.get():
if event.type == pygame.QUIT:
finished = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
show_hello = not show_hello # toggle flag for later display
elif event.key == pygame.K_SPACE:
update_questions = True
elif event.key in [pygame.K_1, pygame.K_2]:
# an answer has been selected
# pygame.K_1 is 0, pygame.K_2 is 1
if dinoAnswer[event.key - pygame.K_1] == "Yes":
show_correct = True
count += 1
else:
show_correct = False
screen.fill(black)
screen.blit(mainpic, (150, 20))
if show_hello:
screen.blit(testtext, (200,199))
if show_correct:
screen.blit(correct_text, (200, 300))
if update_questions:
random.shuffle(dinoQuestions)
random.shuffle(dinoAnswer)
question_display = font.render(dinoQuestions[0],True, white)
text1 = font.render('1 - ' + dinoAnswer[0],True, white)
text2 = font.render('2 - ' + dinoAnswer[1],True, white)
update_questions = False
show_correct = False
# Display the Question
screen.blit(question_display,(200, 590))
screen.blit(text1, (200, 640))
screen.blit(text2, (200, 690))
# count = count + 1
pygame.display.flip()
clock.tick(60)
Hopefully this is enough of a framework for you to extend.
Let me know if you have any questions about any portions of the code.
I am a bit confused about what your exact problem is, so I'm going to try to answer. You say that you want the words "Congrats, , you got it right!", so I can help you with what went wrong. You blit the testtext before you color the screen, so each time the loop loops, it displays the testtext but then almost instantly covers it up with screen.fill(0). To make it better, you should put the blitting of the text after the screen is colored. The best way to do this is to put it right at the start of the loop, or making another event detector after the current position of the screen.fill in the code.
Also, I would get rid of the stacked while loop, and instead replace it with if statement because it is already in the while loop.
Is this what you were looking for?
I'm trying to create "end credits" like the ones at the end of a movie, using pygame. I've googled for other ways to achieve this using python, but I haven't found any yet.
I've almost achieved this with the following code: http://pastebin.com/nyjxeDYQ
#!/usr/bin/python
import time
import threading
import pygame
from pygame.locals import *
# Initialise pygame + other settings
pygame.init()
pygame.fastevent.init()
event_get = pygame.fastevent.get
pygame.display.set_caption('End credits')
screen = pygame.display.set_mode((1920, 1080))
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((255, 255, 255))
fontsize = 40
font = pygame.font.SysFont("Arial", fontsize)
x = 0
def main():
global x
credit_list = ["CREDITS - The Departed"," ","Leonardo DiCaprio - Billy","Matt Damon - Colin Sullivan", "Jack Nicholson - Frank Costello", "Mark Wahlberg - Dignam", "Martin Sheen - Queenan"]
going = True
while going:
events = event_get()
for e in events:
if e.type in [QUIT]:
going = False
if e.type in [KEYDOWN] and e.key == pygame.K_ESCAPE:
going = False
# Loop that creates the end credits
ypos = screen.get_height()
while ypos > (0 - len(credit_list)*50) and x == 0: # Loop through pixel by pixel, screenheight + height of all the textlines combined
drawText(credit_list,ypos)
ypos = ypos - 1
x = 1
pygame.quit()
def drawText(text,y):
for line in text:
text = font.render(line, 1, (10, 10, 10))
textpos = text.get_rect()
textpos.centerx = background.get_rect().centerx
background.blit(text, (textpos.x,y))
y = y + 45
# Blit all the text
screen.blit(background, (0, 0))
pygame.display.flip()
time.sleep(0.0001) # Sleep function to adjust speed of the end credits
# Blit white background (else all the text will stay visible)
background.fill((255, 255, 255))
screen.blit(background, (0, 0))
pygame.display.flip()
if __name__ == '__main__': main()
The problem is that the scrolling text is flickering. This is because I use a time.sleep()-function to control the speed of the scrolling. When I use a value like 0.04 sec, it works pretty well, but the text moves too slow and there is still a bit of flickering. When I use a much lower value, like: 0.001 sec, the text is moving at a speed that I like, but there is a lot more flickering going on.
There is another value I can use to adjust the speed of the scrolling: the number of pixels to move. But when I set this to anything higher than 1, the scrolling isn't smooth anymore.
Does anyone know a solution to this problem? I don't necessarily have to use pygame, I do have to use python though.
Many thanks in advance!
Albrecht
Here are some simpe rule you should follow that will help you with your problem:
Don't call pygame.display.flip() more than once per frame
Don't use time.sleep() to control the speed of something in your application
Use a Clock to control the framerate
Here's a cleaned up, minimal working example:
#!/usr/bin/python
import pygame
from pygame.locals import *
pygame.init()
pygame.display.set_caption('End credits')
screen = pygame.display.set_mode((800, 600))
screen_r = screen.get_rect()
font = pygame.font.SysFont("Arial", 40)
clock = pygame.time.Clock()
def main():
credit_list = ["CREDITS - The Departed"," ","Leonardo DiCaprio - Billy","Matt Damon - Colin Sullivan", "Jack Nicholson - Frank Costello", "Mark Wahlberg - Dignam", "Martin Sheen - Queenan"]
texts = []
# we render the text once, since it's easier to work with surfaces
# also, font rendering is a performance killer
for i, line in enumerate(credit_list):
s = font.render(line, 1, (10, 10, 10))
# we also create a Rect for each Surface.
# whenever you use rects with surfaces, it may be a good idea to use sprites instead
# we give each rect the correct starting position
r = s.get_rect(centerx=screen_r.centerx, y=screen_r.bottom + i * 45)
texts.append((r, s))
while True:
for e in pygame.event.get():
if e.type == QUIT or e.type == KEYDOWN and e.key == pygame.K_ESCAPE:
return
screen.fill((255, 255, 255))
for r, s in texts:
# now we just move each rect by one pixel each frame
r.move_ip(0, -1)
# and drawing is as simple as this
screen.blit(s, r)
# if all rects have left the screen, we exit
if not screen_r.collidelistall([r for (r, _) in texts]):
return
# only call this once so the screen does not flicker
pygame.display.flip()
# cap framerate at 60 FPS
clock.tick(60)
if __name__ == '__main__':
main()