2

So I'm developing a game using Pygame and trying to abstract away a lot of the code. In the process though, I'm getting some weird errors. Namely, when I run main.py, I get this trace:

>>> 
initializing pygame...
initalizing screen...
initializing background...
<Surface(Dead Display)> #Here I print out the background instance
Traceback (most recent call last):
  File "C:\Users\Ceasar\Desktop\pytanks\main.py", line 19, in <module>
    background = Background(screen, BG_COLOR)
  File "C:\Users\Ceasar\Desktop\pytanks\background.py", line 8, in __init__
    self.fill(color)
error: display Surface quit

I imagine it has something to do with me using a context in my main to manage the screen.

#main.py
import math
import sys

import pygame
from pygame.locals import *

...

from screen import controlled_screen
from background import Background

BATTLEFIELD_SIZE = (800, 600)
BG_COLOR = 100, 0, 0
FRAMES_PER_SECOND = 20

with controlled_screen(BATTLEFIELD_SIZE) as screen:
    background = Background(screen, BG_COLOR)

    ...

#screen.py
import pygame.display
import os

#The next line centers the screen
os.environ['SDL_VIDEO_CENTERED'] = '1'

class controlled_screen:
    def __init__(self, size):
        self.size = size

    def __enter__(self):
        print "initializing pygame..."
        pygame.init()
        print "initalizing screen..."
        return pygame.display.set_mode(self.size)

    def __exit__(self, type, value, traceback):
        pygame.quit()

#background.py
import pygame

class Background(pygame.Surface):
def __init__(self, screen, color):
    print "initializing background..."
    print screen
    super(pygame.Surface, self).__init__(screen.get_width(),
                                         screen.get_height())
    print self
    self.fill(color)
    self = self.convert() 
    screen.blit(self, (0, 0))

Any thoughts on what is causing the error here?

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
Ceasar
  • 22,185
  • 15
  • 64
  • 83
  • Looking at it, I'm guessing you intended to have your `controlled_screen` class subclass the `screen` from pygame. It doesn't look like the subclass is written correctly. What is the return value of `pygame.display.set_mode`? If it's not a screen object then that'll be the cause of your error. – g.d.d.c Aug 08 '11 at 22:50
  • It seems to work right. The printed value is "". – Ceasar Aug 08 '11 at 22:52
  • Ok ... I think perhaps you want to assign the return value from `pygame.display.set_mode` to a member variable of your controlled_screen, then return the member variable. Because you're returning it immediately and it's not a member variable it goes immediately out of scope and is cleaned up. That's speculative though - I haven't worked much with pygame. – g.d.d.c Aug 08 '11 at 22:55
  • No luck. The screen appears to be fine. Printing it throughout the stack, it looks like it's always in good shape. By the way, when I wrote " #Here I print out the screen instance" I meant " #Here I print out the background instance" if perhaps that makes any difference in how you're visualizing this. – Ceasar Aug 08 '11 at 22:59
  • So I suspect the problem is more closely related to inheriting from Surface than anything else.. I can create a surface via test = pygame.Surface((100, 100)) but super(pygame.Surface, self).__init__((100, 100)) seems to fail. – Ceasar Aug 08 '11 at 23:16

2 Answers2

0

i was also trying to subclass pygame.Surface because i wanted to be able to add attributes to it. the following accomplishes that. i hope it helps future people.

pygame.display.set_mode() must be called because it inits all the pygame.video stuff. it appears that pygame.display is the surface that ultimately gets drawn to the screen. therefore we need to blit whatever surface we create to the return value of pygame.display.set_mode() (which is just another pygame.Surface object).

import pygame
from pygame.locals import *

pygame.init()
SCREEN_SIZE = (800, 600)

font = pygame.font.SysFont('exocet', 16)

class Screen(pygame.Surface):

    def __init__(self):

        pygame.Surface.__init__(self, SCREEN_SIZE)
        self.screen = pygame.display.set_mode((SCREEN_SIZE))
        self.text = "ella_rox"

My_Screen = Screen()        

text_surface = font.render(My_Screen.text, 1, (155, 0, 0))

while True:
    My_Screen.fill((255, 255, 255))
    My_Screen.blit(text_surface, (50, 50))
    My_Screen.screen.blit(My_Screen, (0, 0))
    pygame.display.update()
Ella Rose
  • 526
  • 7
  • 15
0

Not technically my answer here, but the problem is that Surface cannot be extended with Python's super. Rather, it should be referred to as a Python old style class like so:

class ExtendedSurface(pygame.Surface):
   def __init__(self, string):
       pygame.Surface.__init__(self, (100, 100))
       self.fill((220,22,22))
       # ...

SOURCE: http://archives.seul.org/pygame/users/Jul-2009/msg00211.html

Ceasar
  • 22,185
  • 15
  • 64
  • 83