Why does my pygame window crash after some time? - python

Here's the code, i'm working on Atom. I've been using pygame for a lot of time, and that rarely happens. I never knew what the problem was, but i never needed to, until now.
import pygame
from random import randint as rnd
from colorama import Cursor
import math
import os
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (600,90)
pygame.init()
xsize, ysize = 700, 700
screen = pygame.display.set_mode((xsize, ysize))
screen.fill((0, 0, 0))
def dis(p1, a1):
return math.sqrt((p1[0] - a1[0])**2 + (p1[1] - a1[1])**2)
inner = 0
tot = 0
pygame.draw.circle(screen, (255, 255, 255), (350, 350), 350, 2)
while True:
pos = (rnd(0, xsize), rnd(0, ysize))
if dis((350, 350), pos) < 350:
color = (50, 255, 50)
inner += 1
else:
color = (50, 50, 250)
tot += 1
pygame.draw.circle(screen, color, pos, 2)
print(" pi = " + str(4 * inner / tot) + "\nnº dots: " + str(tot), Cursor.UP(2))
pygame.display.flip()

The window freeze, because you do not handle the events. You have to handle the events by either pygame.event.pump() or pygame.event.get(), to keep the window responding.
Add an event loop, for instance:
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# [...]

Related

How to store the outcome of a method

I am trying to draw squares in random positions and random rgb values and I want 1000 of them to be created. The problem I'm facing is that everytime the loop for drawing occurs, it randomizes it all again, is there any way to make this not happen
import pygame
import sys
import random
pygame.init()
win = pygame.display.set_mode((800,600))
pygame.display.set_caption("Simulation")
def safeZone():
#Draws a top rectangle
pygame.draw.rect(win, (50,205,50), (0, 0, 800, 100))
def dot():
width = 10
height = 10
spawnX = random.randrange(1, 801)
spawnY = random.randrange(1, 601)
r = random.randrange(1, 256)
g = random.randrange(1, 256)
b = random.randrange(1, 256)
pygame.draw.rect(win, (r, g, b), (spawnX, spawnY, width, height))
def population(size):
for x in range(size):
dot()
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
win.fill((255, 255, 255))
safeZone() # Always draw dots after safe zone
population(1000)
pygame.display.update()
pygame.quit()
Create a dot collection, then just draw that dot collection. Now you can update the dot positions separately, and they will redraw in the new positions. Here, I'm having each dot move a random amount in every loop.
import pygame
import sys
import random
pygame.init()
win = pygame.display.set_mode((800,600))
pygame.display.set_caption("Simulation")
class Dot:
def __init__(self):
self.spawnX = random.randrange(0, 800)
self.spawnY = random.randrange(0, 600)
self.r = random.randrange(0, 256)
self.g = random.randrange(0, 256)
self.b = random.randrange(0, 256)
def safeZone():
#Draws a top rectangle
pygame.draw.rect(win, (50,205,50), (0, 0, 800, 100))
def drawdot(dot):
width = 10
height = 10
pygame.draw.rect(win, (dot.r, dot.g, dot.b), (dot.spawnX, dot.spawnY, width, height))
def population(dots):
for dot in dots:
dot.spawnX += random.randrange(-3,4)
dot.spawnY += random.randrange(-3,4)
drawdot(dot)
alldots = [Dot() for _ in range(1000)]
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
win.fill((255, 255, 255))
safeZone() # Always draw dots after safe zone
population(alldots)
pygame.display.update()
A worthwhile modification is to store the whole rectangle in the object:
...
class Dot:
def __init__(self):
self.location = [
random.randrange(0, 800),
random.randrange(0, 600),
10, 10
]
self.color = (
random.randrange(0, 256),
random.randrange(0, 256),
random.randrange(0, 256)
)
def move(self, dx, dy ):
self.location[0] += dx
self.location[1] += dy
def drawdot(dot):
pygame.draw.rect(win, dot.color, dot.location)
def population(dots):
for dot in dots:
dot.move( random.randrange(-3,4), random.randrange(-3,4) )
drawdot(dot)
...
You call a function dot() in which you have assigned randomization. You should introduce a piece of code that randomizes the values outside of the dot() function, and store them in a separate array, and then call the function.
Your description sounds like you aren't necessarily trying to store the result so much as you want the process to be the same every time, but still sort of random? You could just use a hard-coded seed?
import random
random.seed(10)
print(random.random())
See this link for more detail: Random Seed

Sprite touching something else than a white square [duplicate]

This question already has answers here:
How do I detect collision in pygame?
(5 answers)
Collision between masks in pygame
(1 answer)
Closed 1 year ago.
So, I'm making an app/game in python using pygame module, and my problem is that, I cannot find a way to check if a sprite is entirely touching another sprite or not.
What I mean is
if (sprite is touching anything else that some white rectangle):
do some code
Here is my messy code :
main.py :
import pygame, Classes, Groups, Images, random, time
pygame.init()
pygame.font.init()
# App Variables
run_bool = False
# Fonts
ARAL_20_ITALIC = pygame.font.SysFont('Arial' , 20, italic=True)
# Colors
BG = (30, 30, 30)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
# Window
size = (800, 600)
scr = pygame.display.set_mode(size)
pygame.display.set_caption('Simulation by Cold Fire (0.1)')
# App Loop
while True:
time.sleep(0.01)
# Graphics
scr.fill(BG)
"""TERRAIN"""
terrain_hitbox = pygame.draw.rect(scr, WHITE, (300, 100, size[0] - 350, size[1] - 150))
pygame.draw.rect(scr, BLACK, (300, 100, size[0] - 350, size[1] - 150), width=10)
"""SUBJECTS"""
for subject in Groups.G_Subject:
if run_bool == True:
subject.update__()
scr.blit(subject.img, subject.rect)
"""GUI"""
pygame.draw.line(scr, WHITE, (200, 0), (200, size[1]), width=3)
scr.blit(ARAL_20_ITALIC.render('Subjects' ,False, WHITE), (30, 10))
add_hitbox = scr.blit(Images.add_img.convert_alpha(), (30, 50))
remove_hitbox = scr.blit(Images.remove_img.convert_alpha(), (30, 90))
scr.blit(ARAL_20_ITALIC.render(f'Subjects: {len(Groups.G_Subject)}' , False, WHITE), (30, 130))
if run_bool == False:
run_hitbox = scr.blit(Images.run_img.convert_alpha(), (210, size[1] - 40))
else:
run_hitbox = scr.blit(Images.stop_img.convert_alpha(), (210, size[1] - 40))
# Updating Screen
pygame.display.flip()
# Events
for event in pygame.event.get():
# Quitting App
if event.type == pygame.QUIT:
pygame.quit()
quit()
# Clicking
if event.type == pygame.MOUSEBUTTONDOWN:
mouse = pygame.mouse.get_pos()
if add_hitbox.collidepoint(mouse[0], mouse[1]):
rand_x = random.randint(terrain_hitbox[0], terrain_hitbox[0] + terrain_hitbox[2])
rand_y = random.randint(terrain_hitbox[1], terrain_hitbox[1] + terrain_hitbox[3])
Classes.Subject(rand_x, rand_y, Images.subject0_img.convert_alpha())
if remove_hitbox.collidepoint(mouse[0], mouse[1]) and not 1 > len(Groups.G_Subject):
Groups.G_Subject.remove(random.choice(Groups.G_Subject.sprites()))
if run_hitbox.collidepoint(mouse[0], mouse[1]):
if run_bool == True:
run_bool = False
else:
run_bool = True
Classes.py :
import pygame, Groups, random, math
class Subject(pygame.sprite.Sprite):
def __init__(self, x, y, img=pygame.image.load('assets/img/subject0.png').convert_alpha(pygame.display.set_mode((800, 600))), speed=5):
super().__init__()
self.img = img
self.rect = self.img.get_rect()
self.rect.x = x
self.rect.y = y
self.oldx = self.rect.x
self.oldy = self.rect.y
self.speed = speed
Groups.G_Subject.add(self)
def calculat_new_xy(self, old_xy, speed, angle_in_radians):
new_x = old_xy.x + (speed * math.cos(angle_in_radians))
new_y = old_xy.y + (speed * math.sin(angle_in_radians))
return new_x, new_y
def update__(self):
self.oldx, self.oldy = self.rect.x, self.rect.y
self.rect.x, self.rect.y = self.calculat_new_xy(self.rect, self.speed, random.randint(1, 360))
Images.py :
import pygame
add_img = pygame.transform.scale(pygame.image.load('assets/img/gui/add.png'), (90, 30))
remove_img = pygame.transform.scale(pygame.image.load('assets/img/gui/remove.png'), (90, 30))
subject0_img = pygame.image.load('assets/img/subject0.png')
run_img = pygame.transform.scale(pygame.image.load('assets/img/gui/run.png'), (90, 30))
stop_img = pygame.transform.scale(pygame.image.load('assets/img/gui/stop.png'), (90, 30))
Groups.py :
import pygame
G_Subject = pygame.sprite.Group()
I do know my code is a mess, so if you don't wanna help, it's ok ! Thx in advance :D

How to speed up start time in pygame?

I am starting to write a game but whenever I run my code it takes 2 minutes to boot up and even then some methods are not working. The main ones that's not working are quitting pygame and drawGameScene().
My code is:
import os, random
from pygame import *
init()
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d, %d" %(0, 20)
scalefactor = 2
FPS = 60
screenWidth = round(224 * scalefactor)
screenHeight = round(298 * scalefactor)
size = screenWidth, screenHeight
screen = display.set_mode(size)
button = 0
RED = (255, 0, 0)
BLUE = (0,0,255)
STATEGAME = 1
STATEQUIT = 3
curState = STATEGAME
titleFont = font.SysFont("Times New Roman",45)
def drawText(words, screen,position, color, font):
text = font.render(words, False, color)
textSize = text.get_size()
position[0] = position[0] - textSize[0]//2
position[1] = position[1] - textSize[1]//2
#centers the text
screen.blit(text,position)
def gameRun():
while curState != STATEQUIT:
if curState == STATEGAME:
drawGameScene()
eventCheck()
updater()
def eventCheck():
for evnt in event.get():
if evnt.type == QUIT:
curState == STATEQUIT
def updater():
pass
def drawGameScene():
draw.rect(screen,RED,(0,0,screenWidth,screenHeight))
drawText("High Score", screen, [0,0], BLUE, titleFont)
display.update
gameRun()
display.flip()
no error messages are given
Please Help, It's for a project
For the quitting pygame:
You should use the code as below:
for events in event.get():
if events.type == QUIT:
pygame.quit()
exit() #this is from sys module
This way, your pygame is quitted at the first place. So, you don't need anything about curstate, etc.
Also, you need to use while True statement to repeat the blitting process.
Full code:
import os, random
from pygame import *
from sys import exit
init()
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d, %d" %(0, 20)
scalefactor = 2
FPS = 60
screenWidth = round(224 * scalefactor)
screenHeight = round(298 * scalefactor)
size = screenWidth, screenHeight
screen = display.set_mode(size)
button = 0
RED = (255, 0, 0)
BLUE = (0,0,255)
titleFont = font.SysFont("Times New Roman",45)
def drawText(words,screen,position,color,font):
text = font.render(words, False, color)
textSize = text.get_size()
position[0] = position[0] - textSize[0]//2
position[1] = position[1] - textSize[1]//2
#centers the text
screen.blit(text,position)
def gameRun():
drawGameScene()
eventCheck()
updater()
def eventCheck():
for events in event.get():
if events.type == QUIT:
quit()
exit()
def updater():
pass
def drawGameScene():
draw.rect(screen,RED,(0,0,screenWidth,screenHeight))
drawText("High Score", screen, [0,0], BLUE, titleFont)
#display.update()
while True:
gameRun()
display.flip()

Run pygame codes and it shows 'Module 'pygame' has no 'init' member' and white screen window

I am a beginner for learning Python and I just ran into a problem when I debug a series of codes I copied from a book, and I get a white screen window instead of one with pattern, here is the code:
import pygame, sys, random
import pygame.locals as GAME_GLOBALS
import pygame.event as GAME_EVENTS
pygame.init()
windowWidth = 640
windowHeight = 480
surface = pygame.display.set_mode((windowWidth, windowHeight))
pygame.display.set_caption('Pygame Shapes!')
while True:
surface.fill((200, 0, 0))
pygame.draw.rect(surface, (255, 0, 0), (random.randint(0, windowWidth), random.randint(0, windowHeight), 10, 10))
greenSquareX = windowWidth / 2
greenSquareY = windowHeight / 2
while True:
surface.fill((0, 0, 0))
pygame.draw.rect(surface, (0, 255, 0),
(greenSquareX, greenSquareY, 10, 10))
greenSquareX += 1
# greenSquareY += 1
pygame.draw.rect(surface, (0, 0, 255),
(blueSquareX, blueSquareY, 10, 10))
blueSquareX = 0.0
blueSquareY = 0.0
blueSquareVX = 1
blueSquareVy = 1
while True:
surface.fill((0, 0, 0))
pygame.draw.rect(surface, (0, 0, 255),
(blueSquareX, blueSquareY, 10, 10))
blueSquareX += blueSquareVX
blueSquareY += blueSquareVY
blueSquareVX += 0.1
blueSquareVY += 0.1
for event in GAME_EVENTS.GET():
if event.type == GAME_GLOBALS.QUIT:
pygame.quit()
sys.exit()
pygame.dispaly.update()
And the first error I got was: E1101:Module 'pygame' has no 'init' member'(4 ,1). I have ran other Python code with pygame.init() before, and the result turned out well; but this time I get a white screen window. What is wrong with my code? Thanks for help!!
This took me a great deal of debugging to fix, haha.
First of all, you are not escaping or updating in any of your while loops. Once the code enters your first while loop, nothing (the pygame.display) ever updates after that – resulting in your white-screen syndrome.
In addition, please name your variables consistently and check for typos in your code. You created a blueSquareVy variable only to try to refer to it as blueSquareVY later, and you misspelled pygame.display.update() at the end of the code. Capitalization matters – and that's just a few of the typos!
There are also logical errors within the code. You should not fill your window surface after your graphics have been drawn onto the screen. Looking at your variables, it seems that you would like the little squares to move. You would create the position variables outside of the while loop, as if you create them within the loop, they get recreated at their initial value every iteration of the loop.
The annotated and bugfixed code:
import pygame, sys, random
import pygame.locals as GAME_GLOBALS
import pygame.event as GAME_EVENTS
pygame.init()
windowWidth = 640
windowHeight = 480
surface = pygame.display.set_mode((windowWidth, windowHeight))
pygame.display.set_caption('Pygame Shapes!')
# Renamed variables to be consistent
# Moved variables out of the while loop
greenSquareX = windowWidth / 2
greenSquareY = windowHeight / 2
blueSquareX = 0.0
blueSquareY = 0.0
blueSquareVX = 1
blueSquareVY = 1
# Joined the two while loops into one
while True:
surface.fill((200, 0, 0))
pygame.draw.rect(surface, (255, 0, 0), (random.randint(0, windowWidth), random.randint(0, windowHeight), 10, 10))
surface.fill((0, 0, 0))
pygame.draw.rect(surface, (0, 255, 0),
(greenSquareX, greenSquareY, 10, 10))
greenSquareX += 1
greenSquareY += 1
pygame.draw.rect(surface, (0, 0, 255),
(blueSquareX, blueSquareY, 10, 10))
blueSquareX += blueSquareVX
blueSquareY += blueSquareVY
blueSquareVX += 0.1
blueSquareVY += 0.1
# Do not capitalize the .get() method for pygame.event class
for event in GAME_EVENTS.get():
if event.type == GAME_GLOBALS.QUIT:
pygame.quit()
sys.exit()
# Misspelled pygame.display
pygame.display.update()
Hope this helped!

Python code quits without doing anything

I have a problem. i am trying to program a menu for a game in python I am making now. But I have a problem. Every time I run the code, the code exits without even doing anything. i went through the code, and see nothing that can cause this. Here is the code:
#importing the libraries
import pygame
import sys
WINDOWWIDTH = 640
WINDOWHEIGHT = 480
#colour R G B
WHITE = (255, 255, 255)
BLACK = ( 0, 0, 0)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
DARKGREEN = ( 0, 155, 0)
DARKGREY = ( 40, 40, 40)
BGCOLOR = BLACK
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
def main():
global DISPLAYSURF, BASICFONT
pygame.init()
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
BASICFONT = pygame.font.Font('DrippingCool.ttf, 18')
pygame.display.set_caption('Badger Defense - Aplha(0.0.1)')
showStartScreen()
#Drawing the screen
DISPLAYSURF.fill(BGCOLOR)
pygame.display.update()
#Drawing the message
def drawPressKeyMsg():
pressKeySurf = BASICFONT.render("Press a key to play...", True, DARKGREY)
pressKeyRect = pressKeySurf.get_rect()
pressKeyRect.topleft = (WINDOWWIDTH - 200, WINDOWHEIGHT - 30)
DISPLAYSURF.blit(pressKeySurf, pressKeyRect)
#Reaction to the message
def checkForKeyPress():
if len(pygame.event.get(QUIT)) > 0:
terminate()
keyUpEvents = pygame.event.get(KEYUP)
if len(keyUpEvent) == 0:
return None
if keyUpEvents[0].key == K_SPACE:
terminate()
return keyUpEvents[0].key
#Showing the start screen
def showStartScreen():
titleFont = pygame.font.Font('DrippingCool.ttf', 100)
titleMain = titleFont.render('Badger Defense', True, WHITE, DARKGREEN)
titleSecond = titleFont.render('Badger Defense', True, GREEN)
degrees1 = 0
degrees2 = 0
while True:
DISPLAYSURF.fill(BCOLOR)
rotatedSurf1 = pygame.transform.rotate(titleSurf1, degrees1)
rotatedRect1 = rotatedSurf1.get_rect()
rotatedRect1.center = (WINDOWWIDTH / 2, WINDOWHEIGHT / 2)
DISPLAYSURF.blit(rotatedSurf1, rotatedRect1)
rotatedSurf2 = pygame.transform.rotate(titleSurf2, degrees2)
rotatedRect2 = rotatedSurf2.get_rect()
rotatedRect2.center = (WINDOWWIDTH / 2, WINDOWHEIGHT / 2)
DISPLAYSURF.blit(rotatedSurf2, rotatedRect2)
drawPressKeyMsg()
if checkForKeyPress():
pygame.event.get()
return
pygame.display.update()
degrees1 += 3 #rotate by 3 degrees each frame
degrees2 += 7 #rotate by 7 degrees each frame
def terminate():
pygame.quit()
sys.exit()
I am running Ubuntu 12.04. I wrote the code in Sublime but tried to run it in Geany as well. Both didn't work.
Thanks for the help in advance.
You don't seem to have a if __name__ == '__main__': section at the bottom of your code, or anything else that would actually run your code. You are defining everything, but nothing runs because you have not told it to run.
Try adding something like this to the bottom of your code:
if __name__ == '__main__':
main()
The StackOverflow question What does if __name__ == "__main__": do? talks about why you would put that in your file.

Categories

Resources