I just wrote some code that works in the commandline, so now I'd like to give it some graphics. Now, this is my very first programming project so bear with me as I try to explain the problem:
I'm using PyGame and initialised the window as follows:
import pygame, pygame.midi,pygame.font, random
(width, height) = (600, 400)
background = (220,220,220)
pygame.midi.init()
pygame.font.init()
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Chord trainer")
screen.fill(background)
pygame.display.flip()
Then I attempt to render text (which does not give any errors):
myfont = pygame.font.SysFont("Arial", 80)
letter = myfont.render("SOME WEIRD TEST TO TRY AND GET THINGS WORKING",0,(0,0,0))
screen.blit(letter,(100,100))
And because I'd like to actually see my text before the program closes, I set up an infinite loop:
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
When I run it, I just get the grey screen I wanted, but without any sort of text, which would make me think that there's something wrong with my blit command, but I can't figure out what.
Initially I had the rendering set in a loop, but that just made the program unresponsive so I took is out for debugging. For completeness, here is that loop:
while True:
# Decide on random chord
c1 = random.choice(chords)
# Make sure that no repitition takes place.
if c1==c2:
while c1==c2:
c1=random.choice(chords)
c2 = c1
myfont = pygame.font.SysFont("Arial", 80)
letter = myfont.render(str(c1),0,(0,0,0))
screen.blit(letter,(100,100))
# Listen to Midi device and search for c.
midi_listen(inp,sorted(c1))
score += 1
You need to add
pygame.display.flip()
after
letter = myfont.render("SOME WEIRD TEST TO TRY AND GET THINGS WORKING",0,(0,0,0))
screen.blit(letter,(100,100)
It will update your screen and normally you will be able to see your text.
Related
import pygame
import time
# WINDOW SETUP
window = pygame.display.set_mode((900, 500))
pygame.display.set_caption("Pong")
time.sleep(5)
FPS = 60
# RGB VALUE VARIABLES
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
def background(window):
window.fill(WHITE)
pygame.display.update()
# FRAMERATE AND EVENT LOOP INITIALIZATION
def main():
run = True
clock = pygame.time.Clock()
while run:
clock.tick(FPS)
background(window)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if running == False:
pygame.quit()
Above, is my code. I'm trying to make a pong game with pygame. The text editor I am coding with is Visual Studios Code (VSCODE).
Firstly, you need to call the main. You should also make you're code nice and easy to read when possible. I imported pygame as pg which makes typing pygame functions a bit faster as you have less to type. Also, it's better to use global variables to hold variables that won't change through the program, like screen width, height, colours, etc. Then make sure you initialise the module.
As well as that, the only update you have is in background(). You should put the update at the bottom of the loop and remove it from background(). This way everything above will update each loop.
I apologise for not adding you're FPS counter in here as well but I think this should be enough to help you get you're window running with more readable code and a more efficient loop.
import pygame as pg
# Global Variables
screen_width = 900
screen_height = 500
screen = pg.display
window = screen.set_mode((screen_width, screen_height))
colour = 'red'
def main():
# Initialise module
pg.init()
pg.display.set_caption('PONG')
running = True
while running:
# This is a better way of writing your loop
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
# Call background function
background()
# Updates window
# place this inside the loop near the bottom
# so everything is updated at the end of each loop
screen.flip()
def background():
window.fill(colour)
# Remember to call your main function
# This if statement is good practise but not required
# You can just place main() here
if __name__ == '__main__':
main()
So i wrote this code:
# Pygame development 4
# Focus on making code object oriented
# Introduce classes and objects into our code
# Gain access to the pygame library
import pygame
# Size of the screen
SCREEN_TITLE = 'Crossy RPG'
SCREEN_WIDTH = 500
SCREEN_HEIGHT = 500
# Colors according to RGB codes
WHITE_COLOR = (255, 255, 255)
BLACK_COLOR = (0, 0 , 0)
# Clock used to update game events and frames
clock = pygame.time.Clock()
pygame.font.init()
font = pygame.font.SysFont('comicsans', 75)
class Game:
# Typical rate of 60, equivalent to fps
TICK_RATE = 60
# Initializer for the game class to set up the width, height, and title
def __init__(self, title, width, height):
self.title = title
self.width = width
self.height = height
# Create the window of specified size in white to display the game
self.game_screen = pygame.display.set_mode((width, height))
# Set the game window color to white
self.game_screen.fill(WHITE_COLOR)
pygame.display.set_caption(title)
def run_game_loop(self):
is_game_over = False
# Main game loop, used to update all gameplay suh as movement, check, and graphics
# Runs unit is_game_over = True
while not is_game_over:
# A loop to get a;l of the events occuring at any given time
# Events are most often mouse movement, mouse and button clicks, or eit events
for event in pygame.event.get():
# If we have a quite type event(exit out) then exit out of the game loop
if event.type == pygame.QUIT:
is_game_over = True
print(event)
# Update all game graphics
pygame.display.update()
# Tick the clock to update everything within the game
clock.tick(self.TICK_RATE)
pygame.init()
new_game = Game(SCREEN_TITLE, SCREEN_WIDTH, SCREEN_HEIGHT)
new_game.run_game_loop()
pygame.quit()
quit()
Right now I am learning to code with python so im following a course online and since I couldn't get help from the forums of that website I thought I might ask the question here! So I've looked at the code multiple times to check for spelling mistakes but I couldn't find any and anyway i think that it's' not about something missing but it has something to do with pygame.display.update ! Can somebody pls help me?
Without running your code or having a stack trace of where the problem happens, we need to debug the code for you first. So it would be beneficial to add a full stack trace to your questions. I'm pretty confident however that there's two issues that you should work out.
pygame.display.update() should be correctly indented to be in the while loop of your main game event loop. Secondly, the pygame.init() should be run before any other initialization (or at least so I've been taught over the years and every example points to)
Try this out, I think it solves your problem:
# Pygame development 4
# Focus on making code object oriented
# Introduce classes and objects into our code
# Gain access to the pygame library
import pygame
pygame.init()
# Size of the screen
SCREEN_TITLE = 'Crossy RPG'
SCREEN_WIDTH = 500
SCREEN_HEIGHT = 500
# Colors according to RGB codes
WHITE_COLOR = (255, 255, 255)
BLACK_COLOR = (0, 0 , 0)
# Clock used to update game events and frames
clock = pygame.time.Clock()
pygame.font.init()
font = pygame.font.SysFont('comicsans', 75)
class Game:
# Typical rate of 60, equivalent to fps
TICK_RATE = 60
# Initializer for the game class to set up the width, height, and title
def __init__(self, title, width, height):
self.title = title
self.width = width
self.height = height
# Create the window of specified size in white to display the game
self.game_screen = pygame.display.set_mode((width, height))
# Set the game window color to white
self.game_screen.fill(WHITE_COLOR)
pygame.display.set_caption(title)
def run_game_loop(self):
is_game_over = False
# Main game loop, used to update all gameplay suh as movement, check, and graphics
# Runs unit is_game_over = True
while not is_game_over:
# A loop to get a;l of the events occuring at any given time
# Events are most often mouse movement, mouse and button clicks, or eit events
for event in pygame.event.get():
# If we have a quite type event(exit out) then exit out of the game loop
if event.type == pygame.QUIT:
is_game_over = True
print(event)
# Update all game graphics
pygame.display.update()
# Tick the clock to update everything within the game
clock.tick(self.TICK_RATE)
new_game = Game(SCREEN_TITLE, SCREEN_WIDTH, SCREEN_HEIGHT)
new_game.run_game_loop()
pygame.quit()
This also seams to be a school assignment and not a online course (but I might be wrong here), never the less I'll leave this piece of advice if I'm right. I strongly suggest that if you bump into problems, ask your teacher for guidance. As there's always a reason for teachers giving you a challenge/problem to solve. It teaches you the latest techniques you've learned in class, and if you can't solve the problem with the tools that you've been given - you've most likely haven't learned the fundamentals that has been taught out - and you should really re-do some steps.
Im trying to add graphics for my simple sudoku solver program. I want the program to update the displayed sudoku board in real time as it solves it (I thought I would do this by calling my draw_number function after every correctly solved number, and then delaying the program, so that it would draw the number, pause, then continue solving.)
However, instead the program solves the whole thing while freezing, then displays the whole solution at once, when its done.
Here is a small-scale example of what im trying to do, which illustrates the problem:
import pygame
pygame.init()
window = pygame.display.set_mode((600, 600))
board = [
[1,2,3],
[7,5,6],
[4,9,8],
]
def draw_number(r, c, num):
font = pygame.font.Font('freesansbold.ttf', 26)
text = font.render(str(num), True, (0, 0, 0), (255, 255, 255))
text_rect = text.get_rect()
text_rect.center = ((c+1)*48+11, (r+1)*48+11)
window.blit(text, text_rect)
print("Drawing " + str(num) + " at " + str(r+1) + ", " + str(c+1))
pygame.display.update()
run = True
while run:
for i in board:
for j in range(0, 3):
draw_number(board.index(i), j, board[board.index(i)][j])
pygame.display.update()
pygame.time.delay(20)
run = False
pygame.time.delay(5000)
When we run this, the simple 3x3 grid should draw individually, with pauses, but instead it finishes the for loops, then pauses for 5000ms, then shows the result for a split second, then closes the program.
I know I am doing something wrong here, but I am new to pygame and not sure what the correct way to do this is.
The issue is that when you do pygame.time.delay() it freezes the whole pygame window. In order to prevent this you need to import the time module and then use time.sleep(seconds) instead of the pygame.time.delay()
Here is some code:
import pygame
import time
Then(skipping the irrelevant parts):
run = True
while run:
for i in board:
for j in range(0, 3):
draw_number(board.index(i), j, board[board.index(i)][j])
time.sleep(5)
PyGame uses an event-driven model for programs. The code should never call time.sleep(), or pygame.time.delay() etc. because it pauses the program. If it pauses for long enough, the window manager will consider the program to have stopped responding.
An easy way around this is to time operations with the pygame.time.get_ticks(), which returns an every-increasing number of milliseconds since the pygame program started. Design your program such that it looks at the clock to decide what to do next.
Say you only want to perform an operation every 3 seconds. Look at the start-time, do the operation, but then don't do anything more (except poll for events and update the screen) until 3000 milliseconds have elapsed.
For example:
def doTheThing():
pass # TODO: some super-interesting function
time_we_did_the_thing = 0 # When did we last do the thing
clock = pygame.time.Clock()
running = True
while running:
# check for events
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
running = False
# paint the screen
screen.fill( ( 0, 40, 200 ) ) # bluish
# Do the thing, but only every 3 seconds
time_now = pygame.time.get_ticks()
if ( time_now > time_we_did_the_thing + 3000 ):
doTheThing()
time_we_did_the_thing = time_now
# flush the screen-updates
pygame.display.flip()
clock.tick_busy_loop(60) # max FPS=60
pygame.quit()
I can't get python to work when I am using my Raycast function to display images, how do I fix this?
I tried moving some variables and played around with the function, but I can't seem to get it to work.
import pygame
pygame.init()
Screen = "Title"
DB = 0
Width = 800
Height = 600
Frame = pygame.display.set_mode((Width,Height))
pygame.display.set_caption("GAME")
FPS = pygame.time.Clock()
def Raycast(RayXPos, RayYPos):
RaycastThis = pygame.image.load(TTR)
Frame.blit(RaycastThis, (RayXPos, RayYPos))
Loop = True
while Loop == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
pygame.display.update()
FPS.tick(60)
while Screen == "Title" and DB == 0:
TTR = 'TitleScreenSmall.png'
Raycast(0, 0)
I expected the frame to display the image (the same size as the window) and it instead crashed, and I can't run the program
Your problem is the infinite loop:
while Screen == "Title" and DB == 0:
TTR = 'TitleScreenSmall.png'
Raycast(0, 0)
Since the loop control variables Screen and DB never change, you have no way to exit the loop. You're stuck here, eternally repeating a function that does very little, and includes no changes to observe.
See this lovely debug blog for help.
I am attempting to make a game with two surfaces. However when I try and add an image to the game layer it doesn't show up. I have tried using pygame.display.flip() which, from what I understand, should update everything on the screen.
If I try to use either Game_Layer.update() or Game_Layer.flip() as seen in the code below... (I think Game_Layer.flip() doesn't work because .flip is used to update the entire screen and thus can't be called for specific layers but correct me if I am wrong).
#game play
def Dragon():
DragonIMG=pygame.image.load("Green Dragon.gif")
DragonIMG.convert()
global Game_Layer
x=0
y=0
Game_Layer.blit(DragonIMG,(x,y))
Game_Layer.update()
Dragon()
I get the following error message:
RESTART: C:\Users\Alex\OneDrive\A- Levels\1 COMPUTER SCIENCE\Course work\Coding\CSCW Pre Alfa 1.9.5.py
Traceback (most recent call last):
File "C:\Users\Alex\OneDrive\A- Levels\1 COMPUTER SCIENCE\Course work\Coding\CSCW Pre Alfa 1.9.5.py", line 133, in <module>
Dragon()
File "C:\Users\Alex\OneDrive\A- Levels\1 COMPUTER SCIENCE\Course work\Coding\CSCW Pre Alfa 1.9.5.py", line 131, in Dragon
Game_Layer.update()
AttributeError: 'pygame.Surface' object has no attribute 'update'
>>>
However when I try to display an image on the root layer using the code below it works.
#game play
def Dragon():
DragonIMG=pygame.image.load("Green Dragon.gif")
DragonIMG.convert()
global Base_Layer
x=0
y=0
Base_Layer.blit(DragonIMG,(x,y))
pygame.display.flip()
Dragon()
Below is the code I am using to set up the layers:
#libraries
import time, random, pygame, sqlite3, GIFimage2
pygame.init()
#screen setup
#variables
clock=pygame.time.Clock() #for use in .tick
black=pygame.color.Color("black") #set black
white=pygame.color.Color("white") #set white
#set up the base layer
Base_Layer=pygame.display.set_mode((1000,600)) #desplay setup
pygame.display.set_caption("Dragon King: Legacy") #set caption
black=(0,0,0) #colour set
Base_Layer.fill(black) #colour set
Base_Layer.convert() #converts the base layer, may have no effect in current position
icon=pygame.image.load("LOGO.png") #find logo
pygame.display.set_icon(icon) #set icon to logo
#set up the game layer
Game_Layer=pygame.Surface((600,600)) #set layer peramaters
Game_Layer.fill(white) #set layer to white
Game_Layer.convert() #converts the game layer, may have no effect in current position
Base_Layer.blit(Game_Layer, (10, 0)) #blit layer on to screen
pygame.display.flip() #get the layer to show
If anyone could explain to me why this is not working I would appreciate it. I would also appreciate if someone knows a way to display my images in the way I am currently (within a definition) without using global variables.
Pygame programs are usually structured similarly to the following example. First of all, initialize everything and load the images and other resources (do that only once ahead of the main loop), then, in the main while loop, handle the events, update the game and blit everything. Finally, call pygame.display.flip() or pygame.display.update() to make all changes visible and clock.tick(fps) to limit the frame rate.
import pygame
pygame.init()
screen = pygame.display.set_mode((1000, 600))
# Constants (use uppercase letters to signal that these shouldn't be modified).
BLACK = pygame.color.Color("black")
WHITE = pygame.color.Color("white")
GAME_LAYER = pygame.Surface((600, 600))
GAME_LAYER.fill(WHITE)
# convert() returns a new surface, so you have to assign it to a variable.
DRAGON_IMG = pygame.image.load("Green Dragon.gif").convert()
def main(screen):
clock = pygame.time.Clock()
# Variables
x = 0
y = 0
while True:
# Handle events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
# Game logic.
x += 1
# Clear the screen and blit everything.
screen.fill(BLACK)
screen.blit(GAME_LAYER, (10, 0))
screen.blit(DRAGON_IMG, (x, y))
pygame.display.flip()
clock.tick(60)
if __name__ == '__main__':
main(screen)
pygame.quit()
If you want to blit onto a background surface instead of the screen/display and it's unicolored, you can just fill the background surface each frame with the fill method, then blit the dragon and finally blit the background onto the screen:
game_layer.fill(WHITE)
game_layer.blit(DRAGON_IMG, (x, y))
screen.blit(game_layer, (10, 0))
Or if your background surface is an actual image, you can create a copy each frame and then blit onto this copy:
game_layer_copy = GAME_LAYER.copy()
game_layer_copy.blit(DRAGON_IMG, (x, y))
screen.blit(game_layer_copy, (10, 0))
Game_Layer is a surface, and surfaces have no update method. update is a function of pygame.display. pygame.display.update is like pygame.display.flip except you can specify what parts of the screen should be flipped.
Also, please don't use global if you have any other choice. It's considered better to wrap everything into a class, pass Game_Layer as a argument, or use pygame.display.get_surface()