pygame.error: display Surface quit after filling the surface black - python

After I paint my surface black in pygame. I get the error
pygame.error: display Surface quit.
Full error:
>
D:\Programme\Anaconda3\envs\gameDev\python.exe "C:/Users/xxx/PycharmProjects/Workspace/pygame snake/main.py"
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
File "C:/Users/xxx/PycharmProjects/Workspace/pygame snake/main.py", line 81, in <module>
thegame.execute()
File "C:/Users/xxx/PycharmProjects/Workspace/pygame snake/main.py", line 74, in execute
self.render(self._display_surf)
File "C:/Users/xxx/PycharmProjects/Workspace/pygame snake/main.py", line 41, in render
_display_surf.fill((0,0,0))
pygame.error: display Surface quit
<Surface(Dead Display)>
I tried instead of:
_display_surf.fill((0,0,0))
using:
_display_surf.fill(pygame.color("black"))
But that didnt work either.
Here is my full source code:
import pygame
from pygame.locals import *
class Player(object):
x = 10
y = 10
speed = 1
def moveRight(self):
self.x = self.x + self.speed
def moveLeft(self):
self.x = self.x - self.speed
def moveUp(self):
self.y = self.y - self.speed
def moveDown(self):
self.y = self.y + self.speed
class game:
def __init__(self):
self.resolution = (800, 500)
self._running = True
self._display_surf = None
self.player = Player()
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode(self.resolution)
pygame.display.set_caption("Snake!")
self._running = True
def on_cleanup(self):
pygame.quit()
def render(self, _display_surf):
print(_display_surf)
_display_surf.fill((0,0,0))
pygame.draw.rect(self._display_surf, (0, 128, 255), pygame.Rect(self.player.x, self.player.y, 30, 30))
pygame.display.flip()
def loop(self):
pass
def on_event(self, event):
if event.type == pygame.quit():
print("quiet")
self._running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
self.player.moveRight()
elif event.key == pygame.K_LEFT:
self.player.moveLeft()
elif event.key == pygame.K_UP:
self.player.moveUp()
elif event.key == pygame.K_DOWN:
self.player.moveDown()
def execute(self):
if self.on_init() == False:
self._running = False
while self._running:
for event in pygame.event.get():
self.on_event(event)
self.render(self._display_surf)
self.loop()
self.on_cleanup()
if __name__ == "__main__":
thegame = game()
thegame.execute()
I expect that I have a black surface and nothing happens. But instead, it crashes when I try to paint it black. Hope somebody can help
Solution:
For anybody who is intrested in
instead of
if event.type == pygame.quit():
print("quiet")
self._running = False
i need to to
if event.type == pygame.QUIT:
print("quiet")
self._running = False

The code
if event.type == pygame.quit():
print("quiet")
doesn't do what you expect it to do. pygame.quit() is a function call and uninitializes all pygame modules. The function returns None and so the condition fails. The code runs through and crashes at the next instruction which tries to access a pygame module.
You've to compare event.type to the event enumerator constant pygame.QUIT, which identifies the quit event instead:
if event.type == pygame.QUIT:
print("quiet")
self._running = False
See the documentation of pygame.event.

Related

Pygame Not Responding! despite calling event and updating screen

It works perfectly if I do not add it in a class, but if I do it does not respond, I have tried using pygame.update, as pygame.event.pump/get and even jumbling were event should start from, still the problem persists. What am I doing wrong?Code below
.
.
class start_game:
def __init__(self,path,width = 400,height = 600):
self.width = width
self.height = height
self.head = None
self.running = False
self.path = path
pygame.init()
pygame.mixer.init()
self.background = load_img(self.path + '\AnimatedStreet.png')
self.enemy = pygame.image.load(self.path + '\Enemy.png')
self.backg0_pos = [0,0]
self.screen = pygame.display.set_mode((self.width,self.height))
def _run(self):
self.running = True
while self.running:
#pygame.event.pump()
self.screen.fill([0,0,0])
self.screen.blit(self.background, self.backg0_pos)
pygame.display.flip()
pygame.display.update()
self.backg0_pos[1] += 1
self._init_controls()
return
def _init_controls(self):
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_RIGHT:
self.player_pos[0] += 5
if event.key == K_q:
pygame.quit()
return
a = start_game(path)
a._run()
The error was the return function put inside of the while loop caused it stop.
The solution was putting the return function inside of the run function.

Pygame - event.pos not working in def main()

I've read some similar questions but couldn't understand so just gonna ask here...
import pygame as pg
from pygame import *
import sys, os
pg.init()
current_path = os.path.dirname(__file__)
image_path = os.path.join(current_path, "images")
screen = pg.display.set_mode((1920, 1080))
class token(pg.sprite.Sprite):
def __init__(self, path, x, y):
super().__init__()
self.image = pg.image.load(path)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.click = False
token_group.add(self)
def offset(self):
self.offset_x = event.pos[0] - self.rect.x
self.offset_y = event.pos[1] - self.rect.y
def drag(self):
self.rect.x = event.pos[0] - self.offset_x
self.rect.y = event.pos[1] - self.offset_y
token_group = pg.sprite.Group()
token1 = token("images/token1.png", 1920/2, 1080/2)
def main():
running = True
while running:
for event in pg.event.get():
if event.type == QUIT:
pg.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == MOUSEBUTTONDOWN:
if event.button == 1:
for x in token_group:
if x.rect.collidepoint(event.pos):
x.click = True
x.offset()
elif event.type == MOUSEMOTION:
for x in token_group:
if x.click:
x.drag()
elif event.type == MOUSEBUTTONUP:
for x in token_group:
x.click = False
screen.fill((255, 255, 255))
token_group.draw(screen)
pg.display.update()
main()
If I don't put it in the main(), it works fine but this one has the error below.
File "C:\Users\zsa77\OneDrive\desktop\For_Python\project\ggggg.py", line 63, in <module>
main()
File "C:\Users\zsa77\OneDrive\desktop\For_Python\project\ggggg.py", line 47, in main
x.offset()
File "C:\Users\zsa77\OneDrive\desktop\For_Python\project\ggggg.py", line 21, in offset
self.offset_x = event.pos[0] - self.rect.x
AttributeError: module 'pygame.event' has no attribute 'pos'
I'm doing this to make main() start when clicking the start button in the main menu. But if I make two def(main menu(), main()) and put main() in main menu(), the error occurs. The main menu() which is not written here didn't have a problem of event.pos, but main() did. The error says the problem is event.pos of class token, but I can't find a way to solve this. How should I do about this?
You need to pass the event object to the methods. Add an event parameter to the methods:
class token(pg.sprite.Sprite):
def __init__(self, path, x, y):
# [...]
def offset(self, event):
self.offset_x = event.pos[0] - self.rect.x
self.offset_y = event.pos[1] - self.rect.y
def drag(self, event):
self.rect.x = event.pos[0] - self.offset_x
self.rect.y = event.pos[1] - self.offset_y
Add the event argument when calling the methods:
def main():
running = True
while running:
for event in pg.event.get():
if event.type == QUIT:
# [...]
elif event.type == KEYDOWN:
# [...]
elif event.type == MOUSEBUTTONDOWN:
if event.button == 1:
for x in token_group:
if x.rect.collidepoint(event.pos):
x.click = True
x.offset(event) # <---
elif event.type == MOUSEMOTION:
for x in token_group:
if x.click:
x.drag(event) # <---
elif event.type == MOUSEBUTTONUP:
# [...]

pygame add object with mouse click

Trying to add more boids by using mouse click ingame.
elif event.type == pygame.MOUSEBUTTONUP:
self.boids_group.add(boids.Boids(rect=pygame.Rect(random()*self.width, random()*self.height, 40, 40)))
I get an error msg that there is no object Boids in Boids, however this is the method i am adding boids to the game at start.
self.boids_group = pygame.sprite.Group()
for i in range(cfg.boidNum):
self.boids_group.add(boids.Boids(rect=pygame.Rect(random()*self.width, random()*self.height, 40, 40)))
And the cfg.boidNum is set to 19 at start, and its adding 19 boids, but not adding more when i push the mousebutton.
If anyone can guide me in the right direction....
The error msg i get when i try running is: line 69, there is no object Boids in Boids, line 69 ref to the mouse input line.
#!/usr/bin/env python
from random import random
from pygame.locals import *
import boids, predator, diver, pygame, sys
import config as cfg
bgimage = pygame.image.load("ramfjord.png")
class Ramfjorden:
def __init__(self, width=1024, height=760):
pygame.init()
self.width = width
self.height = height
self.screen = pygame.display.set_mode((self.width, self.height))
pygame.display.set_caption('Ramfjorden')
def loadSprites(self):
self.predator_group = pygame.sprite.Group()
for i in range(cfg.predatorNum):
self.predator_group.add(predator.Predator(rect=pygame.Rect(random()*self.width, random()*self.height, 70, 70)))
self.boids_group = pygame.sprite.Group()
for i in range(cfg.boidNum):
self.boids_group.add(boids.Boids(rect=pygame.Rect(random()*self.width, random()*self.height, 40, 40)))
self.diver_group = pygame.sprite.Group()
self.diver_group.add(diver.Diver(rect=pygame.Rect(300, 300, 150, 231)))
def collision(self, sprite1, sprite2):
if sprite1 == sprite2:
return False
else:
return pygame.sprite.collide_circle(sprite1, sprite2)
def mainLoop(self):
fps = pygame.time.Clock()
self.loadSprites()
while True:
self.screen.blit(bgimage, (0,0))
self.predator_group.draw(self.screen)
self.boids_group.draw(self.screen)
self.diver_group.draw(self.screen)
for predator in self.predator_group.sprites():
predator.update(ramfjord=self)
for boids in self.boids_group.sprites():
boids.update(ramfjord=self)
for predator in self.predator_group.sprites():
predator.swim(ramfjord=self)
for boids in self.boids_group.sprites():
boids.swim(ramfjord=self)
spriteHitList = pygame.sprite.groupcollide(self.predator_group, self.boids_group, False, True, collided=self.collision)
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.event.post(pygame.event.Event(QUIT))
elif event.type == pygame.MOUSEBUTTONUP:
self.boids_group.add(boids.Boids(rect=pygame.Rect(random()*self.width, random()*self.height, 40, 40)))
pygame.display.update()
fps.tick(30)
def main():
ramfjord = Ramfjorden()
ramfjord.mainLoop()
if __name__ == "__main__":
main()

How to make multiple Instances from a class move at the same time in gyame

import pygame, os, sys
from pygame import *
pygame.init()
RED = ( 255, 0, 0)
class WPawn():
def __init__(self, x, y):
self.x = x
self.y = y
self.image = pygame.transform.scale(pygame.image.load('wpawn.png'), (100,100))
self.move_x = 0
self.move_y = 0
def event_handler(self):
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_UP:
self.move_y = -100
if event.key == K_DOWN:
self.move_y = 100
elif event.type == KEYUP:
if event.key in (K_UP, K_DOWN):
self.move_y = 0
def update(self, screen):
self.y = self.y + self.move_y
def draw(self, screen):
screen.blit(self.image, (self.x, self.y))
class Game():
def __init__(self):
screen_width = 900
screen_height = 900
self.screen = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption ("Chess Project")
self.pawn1 = WPawn(50,650)
self.pawn2 = WPawn(150,650)
self.pawn3 = WPawn(250,650)
self.pawn4 = WPawn(350,650)
self.pawn5 = WPawn(450,650)
self.pawn6 = WPawn(550,650)
self.pawn7 = WPawn(650,650)
self.pawn8 = WPawn(750,650)
def play(self):
clock = pygame.time.Clock()
RUNNING = True
while RUNNING:
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
clock.tick(30)
self.pawn1.event_handler()
self.pawn2.event_handler()
self.pawn3.event_handler()
self.pawn4.event_handler()
self.pawn5.event_handler()
self.pawn6.event_handler()
self.pawn7.event_handler()
self.pawn8.event_handler()
self.pawn1.update(self.screen)
self.pawn2.update(self.screen)
self.pawn3.update(self.screen)
self.pawn4.update(self.screen)
self.pawn5.update(self.screen)
self.pawn6.update(self.screen)
self.pawn7.update(self.screen)
self.pawn8.update(self.screen)
self.screen.fill(RED)
self.pawn1.draw(self.screen)
self.pawn2.draw(self.screen)
self.pawn3.draw(self.screen)
self.pawn4.draw(self.screen)
self.pawn5.draw(self.screen)
self.pawn6.draw(self.screen)
self.pawn7.draw(self.screen)
self.pawn8.draw(self.screen)
pygame.display.update()
Game().play()
pygame.quit()
The KEY_UP event (or whatever) is consumed when you process it. So whichever WPawn class gets the event first will move.
Generally an event-driven program has only one event loop.
It may be easier to make this work by handling the event processing outside of the game objects. Have the single event loop handle record the key press, then move each WPawn that you wish to be moved.
Perhaps something like:
event = pygame.event.get()
if event.type == K_DOWN:
foreach pawn in all_pawns:
pawn.moveDown()
elif event.type == K_UP:
foreach pawn in all_pawns:
pawn.moveUp()

"TypeError: 'int' object is not callable" error from this code

The following code gives me this error and I am confused. Sorry If I am asking questions wrong, I'm new here but I think this corresponds to the guidelines. The image will move
across the background as soon as I release the key it gives me this error and crashes.
Traceback (most recent call last):
File "C:\Users\Samga_000\Desktop\game\game.py", line 89, in <module>
rungame()
File "C:\Users\Samga_000\Desktop\game\game.py", line 79, in rungame
p.still()
TypeError: 'int' object is not callable
import pygame, sys
from pygame.locals import *
pygame.init()
WIDTH = 400
HEIGHT = 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
bif = "grass.png"
background = pygame.image.load(bif)
pygame.display.set_caption('RPG')
def drawEntitys():
frispri.update()
frispri.draw(screen)
def drawScreen():
screen.blit(background, (0,0))
class Player(pygame.sprite.Sprite):
image = pygame.image.load("misha.png")
image = image.convert_alpha()
def __init__(self):
pygame.sprite.Sprite.__init__(self, self.groups)
self.pos = (20, 20)
self.image = Player.image
self.rect = self.image.get_rect()
self.movepos = [0,0]
self.area = screen.get_rect()
self.still = True
def update(self):
newpos = self.rect.move(self.movepos)
if self.area.contains(newpos):
self.rect = newpos
pygame.event.pump()
def move(self, x, y):
self.still = 0
if self.still == 0:
self.movepos[0] = self.movepos[0] - x
self.movepos[1] = self.movepos[1] - y
else:
pass
def still(self):
self.still = 1
frispri = pygame.sprite.Group()
Player.groups = frispri
p = Player()
def rungame():
while True:
drawScreen()
drawEntitys()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == KEYDOWN:
if event.key == K_UP:
p.move(0,1)
elif event.key == K_DOWN:
p.move(0,-1)
elif event.key == K_LEFT:
p.move(1,0)
elif event.key == K_RIGHT:
p.move(-1,0)
elif event.type == KEYUP:
if event.key == K_UP:
p.still()
elif event.key == K_DOWN:
p.still()
elif event.key == K_LEFT:
p.still()
elif event.key == K_RIGHT:
p.still()
flipgame()
def flipgame():
pygame.display.flip()
rungame()
Player.still is a boolean, assigned here:
class Player(pygame.sprite.Sprite):
def __init__(self):
# ...
self.still = True
You can't call a boolean, since it isn't a function, as you attempt here:
p = Player()
# ...
p.still()
This is essentially the same problem as discussed in this question
Your problem is that you have an instance variable, still, with the same name as your method. When you do p.still(), Python interprets the p.still as trying to access the variable not the method, and then trying to 'call' that variable.
The solution is to rename the method or the variable. To get your code to work you should only need to change one of the two. But good programming practice might say you should change both.
Since the variable is a flag that indicates if the player is still or not, you might change it's name to be is_still. This is a slightly more descriptive name, that makes it clear what the variable means.
For the method you could rename it to set_still or mark_still to indicate that it is changing the status of the player. Or combined with the above change to the variable name you could make the method name set_is_still, to make it clear exactly what variable you are setting.

Categories

Resources