When I run the code, it does not show any error. The rectangle just doesn't appear. How can that be fixed?
The function responsible is render() with the line pygame.draw.rect(win, (0, 0, 0), (100, 100, 50, 50)).
import pygame
w, h = 1000, 600
caption = "Game"
background = (255, 255, 255)
running = True
clock = pygame.time.Clock()
FPS = 60
win = pygame.display.set_mode((w, h))
pygame.display.set_caption(caption)
def start():
# This function runs only once at the start of the game
pass
def logic():
# This function runs every frame. This function contains the game's logic.
pass
def render():
# This function runs every frame. This function contains code for drawing
# everything to the screen.
pygame.draw.rect(win, (0, 0, 0), (100, 100, 50, 50))
def main():
global running
start()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
logic()
win.fill(background)
render()
pygame.display.update()
if __name__ == "__main__":
main()
pygame.quit()
quit()
Sorry for bothering everyone. I was using Atom to write and run this code but every time I used to run this code in Atom, using script package, it used to show a blank screen. Solution is to use build-python package (its a package that works, unlike script) instead. Sorry, I should’ve been more specific.
Related
I'm new to pygame and now wanted to blit a background image with a text on top of it. Both together should appear on the screen for only half a second, then both should be gone again. The background image is meant to be full-screen.
What I'm stuck on now: every time, a black screen appears shortly before text and image are visible, they disappear quickly again.
pg.init()
info = pg.display.Info()
window = pg.display.set_mode((info.current_w, info.current_h), pg.FULLSCREEN)
font = pg.font.SysFont("Arial", 33, bold=True)
text = font.render(text, True, (0, 0, 0))
background = pg.image.load('temp.png')
window.blit(background, [0, 0])
window.blit(text, text.get_rect(center = window.get_rect().center))
pg.display.flip()
sleep(0.5)
pg.quit()
I feel like this has to be possibly quite easily, still I haven't found out how to do it just yet.
I'm assuming you are using the time.sleep function in your code. This function isn't good for GUIs since it delays the program for a given amount of time without checking for events and updating the display. This is why a black screen appears. So to fix your issue, I wrote a function called wait that waits a given amount of time without freezing the game.
The wait Function:
def wait(ms):
start = pg.time.get_ticks()
running = True
while running:
for event in pygame.event.get():
if event.type == pg.QUIT:
pg.quit()
sys.exit(0)
now = pg.time.get_ticks()
if now - start == ms:
running = False
blit_background()
Explanation
It takes one parameter: ms, which is the amount of time that you want the program to wait in milliseconds (1 second = 1000 milliseconds). In the function, I set a variable called start to pygame.time.get_ticks(), which returns the current time. Then, inside a while loop, I created an event loop which checks for the pygame.QUIT event so that if the user tries to close the game while the function is still running, the game will respond and quit the program. After the event loop, I set a variable called now to pygame.time.get_ticks() to get the current time. Then I checked if now (the current time) subtracted by start (the start time) is equal to ms (the given amount of waiting time in milliseconds). This checks if the given amount of time has passed. If it has, the while loop ends. If not, the while loop keeps running until that condition is True.
I also wrote another function called blit_background, which displays the background and the text on the screen. I am calling this function inside the wait function so that the screen can display the background and the text while also waiting for the given amount of time to pass.
The blit_background Function:
def blit_background():
window.blit(background, [0, 0])
window.blit(text, text.get_rect(center=window.get_rect().center))
pg.display.flip()
Full Modified Code:
import pygame as pg
import pygame.time
import sys
pg.init()
info = pg.display.Info()
WIDTH = info.current_w
HEIGHT = info.current_h
window = pg.display.set_mode((WIDTH, HEIGHT), pg.FULLSCREEN)
font = pg.font.SysFont("Arial", 33, bold=True)
text = font.render("text", True, (0, 0, 0))
background = pg.image.load('temp.png')
background = pg.transform.scale(background, (WIDTH, HEIGHT))
def blit_background():
window.blit(background, [0, 0])
window.blit(text, text.get_rect(center=window.get_rect().center))
pg.display.flip()
def wait(ms):
start = pg.time.get_ticks()
running = True
while running:
for event in pygame.event.get():
if event.type == pg.QUIT:
pg.quit()
sys.exit(0)
now = pg.time.get_ticks()
if now - start == ms:
running = False
blit_background()
wait(500)
pg.quit()
sys.exit(0)
Source Code
import pygame
pygame.init()
space_width = 55
space_height = 40
win = pygame.display.set_mode((600, 400))
pygame.display.set_caption("hi")
playerimg = pygame.image.load('001-spaceship.png')
ply = pygame.transform.rotate(pygame.transform.scale(playerimg, (space_width, space_height)), 90)
print(win)
def draw_window(plyred):
win.fill((255, 0, 0))
win.blit(ply, (plyred.x, plyred.y))
pygame.display.update()
def main():
plyred = pygame.rect(100, 100, (space_width, space_height))
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
plyred += 1
draw_window(plyred)
pygame.quit()
My code won't run and only shows a temporary black screen before crashing.
First of all, there are so many mistake on the code, anyway here, this should at least show you something:
import pygame
pygame.init()
space_width = 55
space_height = 40
win = pygame.display.set_mode((800, 600))
pygame.display.set_caption("hi")
playerimg = pygame.image.load('001-spaceship.jpg')
ply = pygame.transform.rotate(pygame.transform.scale(playerimg, (space_width, space_height)), 90)
def draw_window(plyred):
win.fill((255, 0, 0))
win.blit(ply, (plyred.x, plyred.y))
pygame.display.update()
def main():
plyred = pygame.Rect(100, 100, space_width, space_height)
run = True
while run:
win.blit(playerimg, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
break
draw_window(plyred)
if __name__ == '__main__':
main()
Consideration and area where you should improve
Indentation, indentation, indentation, Python is one of the few Programming languages where it punishes you if you don't indent correctly (hopefully) and so are other Programmers if you don't do so, here ---> Indentation in Python
The Biggest issue was on the variable plyred, for of all is the Class Rect and not rect(which is a function from pygame.draw.rect) -----> Here your best friend Documentation :)
Also, it was givin error because space_width, space_height was inside a tuple, so it should be pygame.Rect(100, 100, space_width, space_height) instead.
You never call the main function, so one way is express it this way:
if name == 'main':
main()
Another is just call it as so at the end of the script:
main()
**DOCUMENTATION What does if name == “main”: do?
Projects
Pygame Tutorial - Creating Space Invaders Tech With Tim Tutorial
Space-Invaders-Pygame
Space-Invaders-Pygame 2
I am creating a game with pygame and I am using pygame.event.set_grab(True) to keep cursor locked in the game window (it keeps all keyboard input in the window also), but when the program crashes (either because of syntax error or some other exception) the set_grab stays turned on and it is impossible to turn off the program afterwards. (fortunately I am using Linux so i can access console that overrides everything so i can turn it off manually)
I am wondering if it is possible to make some error handling which will turn it off (or kills the program) or if there is a better way to keep just mouse inputs in the window. (so it is possible to alt+f4)
import pygame
pygame.init()
size = (600, 700)
monitor=pygame.display.Info()
screen = pygame.display.set_mode(size)#pygame.FULLSCREEN)
pygame.display.set_caption("Meteor Galaxy 3")
done = False
clock = pygame.time.Clock()
pygame.mouse.set_visible(0)
pygame.event.set_grab(True) #this is turned on with the initialization
#(doesnt have to be) of the game
When the game crashes it transforms into the usual black window with the exception you cant do anything.
Thank you.
Edit:
The full code:
#coding: utf-8
import pygame
import random
random.randint(0,2)
#TODO:
#Vymyslieť systém na čakanie framov
#Upraviť zmenu rýchlosti hráčovho náboja
##Pygame init
pygame.init()
size = (600, 700)
possible_sizes=[[600,700],[900,1050],[1200,1400],[1800,2100]] #ASI 1200,1400 obrázky a potom downscale?? (ak vôbec zmena rozlisenia..)
monitor=pygame.display.Info()
screen = pygame.display.set_mode(size)#pygame.FULLSCREEN)
pygame.display.set_caption("Meteor Galaxy 3")
done = False
clock = pygame.time.Clock()
pygame.mouse.set_visible(0)
pygame.event.set_grab(True)
#<VARIABLES>
##<COLORS>
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
##</COLORS>
##<IMAGES> #"../meteo_data/img/"
bg1=[pygame.image.load("../meteo_data/img/bg1.png"),700-5770,True]
#backgrounds.append([pygame.image.load("img/bg2.png"),[600,1924]])
#backgrounds.append([pygame.image.load("img/bg3.png"),[600,1924]])
img_crosshair=pygame.image.load("../meteo_data/img/crosshair.png").convert()
#Ships
img_player=pygame.image.load("../meteo_data/img/ships/player.png").convert()
img_enemy1=pygame.image.load("../meteo_data/img/ships/enemy1.png").convert()
#Bullets
img_b1=pygame.image.load("../meteo_data/img/bullets/bullet.png").convert()
img_player.set_colorkey(BLACK)
img_enemy1.set_colorkey(BLACK)
img_crosshair.set_colorkey(BLACK)
##</IMAGES>
##<SOUNDS>
##</SOUNDS>
menu_game=1 #Nula pre menu , jedna pre hru?? , medzi nula a jedna ostatné??
esc_menu=False
fire=False
level=-1
level_ended=True
## def=0 def=0
##<BULLET TYPES> #[IMAGE,DAMAGE,SPEED,PENETRATION,relX,relY] /relX a relY vziať z relX a relY lode.
B_default=[img_b1,3,4,False,0,0]
##</BULLET TYPES>
##<SHIP TYPES> #[IMAGE,HEALTH,SPEED,RELOAD,X,Y,relX,relY,BULLET_TYPE] /relX a relY je pre bullet
##</SHIP TYPES>
##<LEVELS>
level1=[bg1]
master_level=[level1]
##</LEVELS>
#</VARIABLES>
#<FUNCTIONS>
##<SPRITES>
class bullet(pygame.sprite.Sprite):
def __init__(self,bullet_type):
pygame.sprite.Sprite.__init__(self)
self.image=bullet_type[0]
self.dmg=bullet_type[1]
self.speed=bullet_type[2]
self.penetration=bullet_type[3] ##Prestrelí viac ENIMÁKOV ? True/False
self.rect = self.image.get_rect()
self.rect.x=bullet_type[4] ##Vypočítať pri vystrelení (ship pos -/+ ship.bullet_x(y)) (pre každý typ lode zvlášť)
self.rect.y=bullet_type[5]
self.image.set_colorkey(BLACK)
class ship(pygame.sprite.Sprite):
def __init__(self,ship_type):
pygame.sprite.Sprite.__init__(self)
self.image=ship_type[0]
self.hp=ship_type[1]
self.speed=ship_type[2] ##0 Pre hráča
self.reload=ship_type[3] ##Rýchlosť streľby (koľko framov čakať) 0 = každý frame bullet
self.rect=self.image.get_rect()
self.rect.x=ship_type[4]
self.rect.y=ship_type[5]
self.bullet_x=ship_type[6]
self.bullet_y=ship_type[7]
self.b_type=ship_type[8]
self.image.set_colorkey(BLACK)
class barrier(pygame.sprite.Sprite):
def __init__(self,coord):
pygame.sprite.Sprite.__init__(self)
self.image=pygame.Surface([700,40])
self.image.fill(WHITE)
self.rect=self.image.get_rect()
self.rect.x=coord[0]
self.rect.y=coord[1]
bullets=pygame.sprite.Group()
ships=pygame.sprite.Group()
barriers=pygame.sprite.Group()
player_b_type=B_default
player_b_type[2]=player_b_type[2]*(-1)
player=ship([img_player,100,0,10,279,650,15,3,player_b_type]) ##PLAYER SHIP
wait=player.reload
barrier_top=barrier([-50,-400])
barrier_bottom=barrier([-50,900])
barriers.add(barrier_top)
barriers.add(barrier_bottom)
##</SPRITES>
#</FUNCTIONS>
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button==1:
fire=True
elif event.type == pygame.MOUSEBUTTONUP:
if event.button==1:
fire=False
elif event.type==pygame.KEYDOWN:
if event.key==pygame.K_ESCAPE:
if not esc_menu:
esc_menu=True
pygame.event.set_grab(False)
else:
esc_menu=False
pygame.event.set_grab(True)
coord=pygame.mouse.get_pos()
if menu_game==0:
screen.fill(WHITE) #BG
elif menu_game==1:
#GAME LOGIC
if level_ended:
level=level+1
bg1_y=master_level[level][0][1]
level_ended=False
bg1_y=bg1_y+2
player.rect.x=coord[0]-20
pygame.sprite.groupcollide(barriers,bullets,False,True)
pygame.sprite.groupcollide(barriers,ships,False,True)
if fire:
if wait==0:
bullet_modified=player.b_type
bullet_modified[4]=player.rect.x+player.bullet_x
bullet_modified[5]=player.rect.y+player.bullet_y
b=bullet(bullet_modified)
bullets.add(b)
wait=player.reload
else:
wait=wait-1
#RENDERING
screen.fill(BLACK)
screen.blit(master_level[level][0][0],[0,bg1_y]) #BG
screen.blit(player.image,player.rect)
for naboj in bullets:
screen.blit(naboj.image,naboj.rect)
naboj.rect.y=naboj.rect.y+naboj.speed
screen.blit(img_crosshair,[coord[0]-10,coord[1]-10])
pygame.display.flip() #FRAMY
clock.tick(60)
pygame.quit()
#NOTES:
# Dlzka lvl sa urci vyskou bg (5760 px == 48 sec - 1. lvl)
#189 -
#
So, the problem there is that if some exception happens in the middle of that code, pygame.quit() is never called.
All you have to do is to set a try ... fynaly block around your Pygame code, and put the pygame.quit() call on the finally block.
For that I suggest some reformatting which will also improve the modularity of your code, which is to enclose all that code you put on the module level inside a function.
So:
...
def main():
done = False
while not done:
...
for naboj in bullets:
...
screen.blit(img_crosshair,[coord[0]-10,coord[1]-10])
pygame.display.flip() #FRAMY
clock.tick(60)
try:
main()
finally:
pygame.quit()
In this way, any unhandled exception within the code run in main (or in any other function called from it), as well as well behaved main-loop termination, will immediately run the code within the finally block: Pygame is shut down, along with its event handling, and you get the error traceback on the terminal enabling you to fix the code.
update the finally hint is also essential for anyone making a game with pygame that uses fullscreen, regardless of event_grab.
I am reading data from a file. Basically, those are coordinates where I want my ball to appear after every iteration. The code is working fine except for the fact that the output window 'Trial 1' crashes as soon as I press the exit button. This problem wasn't there before I added for t in range (np.size(T)):; however I require that. Please suggest some possible changes in the code to get rid of the problem.
import numpy as np
import pygame
pygame.init()
T = np.loadtxt('xy_shm1.txt', usecols=range(0,1))
Xcor = np.loadtxt('xy_shm1.txt', usecols=range(1,2))
Ycor = np.loadtxt('xy_shm1.txt', usecols=range(2,3))
clock = pygame.time.Clock()
background_colour = (255,255,255)
(width, height) = (800, 800)
class Particle():
def __init__(self, xy, size):
self.x, self.y = xy
self.size = size
self.colour = (0, 0, 255)
self.thickness = 1
def display(self):
pygame.draw.circle(screen, self.colour, (int(self.x), int(self.y)), self.size, self.thickness)
def move(self):
self.x = Xcor[t] + 400
self.y = Ycor[t] + 400
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Trial 1')
number_of_particles = 1
my_particles = []
for n in range(number_of_particles):
size = 5
x = Xcor[0] + 400
y = Ycor[0] + 400
particle = Particle((x, y), size)
my_particles.append(particle)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
for t in range(np.size(T)):
screen.fill(background_colour)
for particle in my_particles:
particle.move()
particle.display()
pygame.display.flip()
clock.tick(60)
pygame.quit()
The main problem is that you are trying to draw multiple frames within a frame. The frame loop should look like this:
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Draw one frame here
clock.tick(60) # If the game runs faster than 60fps, wait here
Note that in each iteration of the while loop, only one frame is drawn.
In your current code however, you start the loop, check the events once,
and then you draw a frame for each item in your list, without checking the events again.
This most likely causes the QUIT event to be missed, and the operating system intervening because the game seemingly is not responding.
In general, your code is quite messy. I suggest that you read some tutorials on pygame, or you will run into all sorts of similar problems. See for example: http://programarcadegames.com/python_examples/f.php?file=bouncing_rectangle.py
I have come as far as drawing a rectangle in pygame however I need to be able to get text like "Hello" into that rectangle. How can I do this? (If you can explain it as well that would be much appreciated. Thank-you)
Here is my code:
import pygame
import sys
from pygame.locals import *
white = (255,255,255)
black = (0,0,0)
class Pane(object):
def __init__(self):
pygame.init()
pygame.display.set_caption('Box Test')
self.screen = pygame.display.set_mode((600,400), 0, 32)
self.screen.fill((white))
pygame.display.update()
def addRect(self):
self.rect = pygame.draw.rect(self.screen, (black), (175, 75, 200, 100), 2)
pygame.display.update()
def addText(self):
#This is where I want to get the text from
if __name__ == '__main__':
Pan3 = Pane()
Pan3.addRect()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); sys.exit();
Thank you for your time.
You first have to create a Font (or SysFont) object. Calling the render method on this object will return a Surface with the given text, which you can blit on the screen or any other Surface.
import pygame
import sys
from pygame.locals import *
white = (255,255,255)
black = (0,0,0)
class Pane(object):
def __init__(self):
pygame.init()
self.font = pygame.font.SysFont('Arial', 25)
pygame.display.set_caption('Box Test')
self.screen = pygame.display.set_mode((600,400), 0, 32)
self.screen.fill((white))
pygame.display.update()
def addRect(self):
self.rect = pygame.draw.rect(self.screen, (black), (175, 75, 200, 100), 2)
pygame.display.update()
def addText(self):
self.screen.blit(self.font.render('Hello!', True, (255,0,0)), (200, 100))
pygame.display.update()
if __name__ == '__main__':
Pan3 = Pane()
Pan3.addRect()
Pan3.addText()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); sys.exit();
Note that your code seems a little bit strange, since usually you do all the drawing in the main loop, not beforehand. Also, when you make heavy use of text in your program, consider caching the result of Font.render, since it is a very slow operation.
Hi!
To be honestly there is pretty good ways to write text in any place of current rect.
And now i'll show how to do it pretty easy.
First of all we need to create object of rect instance:
rect_obj = pygame.draw.rect(
screen,
color,
<your cords and margin goes here>
)
Now rect_obj is object of pygame.rect instance. So, we are free to manipulate with this methods. But, beforehand lets create our rendered text object like this:
text_surface_object = pygame.font.SysFont(<your font here>, <font size here>).render(
<text>, True, <color>
)
Afterall we are free to manipulate with all methods, as i mensioned before:
text_rect = text_surface_object.get_rect(center=rect_obj.center)
What is this code about?
We've just got center cords of out current rect, so easy!
Now, you need to blit ur screen like this:
self.game_screen.blit(text_surface_object, text_rect)
Happy coding! :)