Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PySDL2 issue with SDL_Surface / LP_SDL_Surface

Im running win7 with python 3.3 and PySDL2 0.5. When creating surfaces (no matter what method) i get an LP_SDL_Surface instead of a SDL_Surface. The LP_SDL_Surface lacks any of the methods and attribute you would expect it to have. Here is the issue using example code from the documentation:

import os
os.environ["PYSDL2_DLL_PATH"] = os.path.dirname(os.path.abspath(__file__))

import sys
import ctypes
from sdl2 import *

def main():
    SDL_Init(SDL_INIT_VIDEO)
    window = SDL_CreateWindow(b"Hello World",
                              SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                              592, 460, SDL_WINDOW_SHOWN)
    windowsurface = SDL_GetWindowSurface(window)

    image = SDL_LoadBMP(b"exampleimage.bmp")
    SDL_BlitSurface(image, None, windowsurface, None)
    print(image.h)

    SDL_UpdateWindowSurface(window)
    SDL_FreeSurface(image)

    running = True
    event = SDL_Event()
    while running:
        while SDL_PollEvent(ctypes.byref(event)) != 0:
            if event.type == SDL_QUIT:
                running = False
                break

    SDL_DestroyWindow(window)
    SDL_Quit()
    return 0

if __name__ == "__main__":
    sys.exit(main())

and the traceback is:

Traceback (most recent call last):
File "C:/.../test.py", line 35, in <module>
sys.exit(main())
File "C:/.../test.py", line 17, in main
print(image.h)
AttributeError: 'LP_SDL_Surface' object has no attribute 'h'

A google search for "LP_SDL_Surface" brings 0 (!) results.

like image 879
user2697966 Avatar asked Oct 22 '22 02:10

user2697966


1 Answers

If you work with the lower level SDL methods (e.g. sdl2.SDL_LoadBMP) you will have to deal with ctypes conversions, referencing(byref) and dereferencing of pointers (.contents, .value).

So for the specific question, as you've already commented, using print(image.contents.h) would be enough.

There are some higher level classes and methods provided by pysdl2 (sdl2.ext), however, that could do most of those conversions for you, if desired. The code below achieves the same goal without having to touch ctypes:

import os
os.environ["PYSDL2_DLL_PATH"] = os.path.dirname(os.path.abspath(__file__))

import sys
import sdl2
import sdl2.ext

def main():
    sdl2.ext.init()
    window = sdl2.ext.Window(
        title="Hello World!", size=(592, 460), flags=sdl2.SDL_WINDOW_SHOWN,
        position=(sdl2.SDL_WINDOWPOS_CENTERED, sdl2.SDL_WINDOWPOS_CENTERED))

    window.show()

    renderer = sdl2.ext.Renderer(window)
    factory = sdl2.ext.SpriteFactory(sdl2.ext.TEXTURE, renderer=renderer)
    spriterenderer = factory.create_sprite_render_system(window)

    image = factory.from_image("exampleimage.bmp")
    print(image.size[1])  # image.size = (w, h)

    running = True
    while running:
        for event in sdl2.ext.get_events():
            if event.type == sdl2.SDL_QUIT:
                running = False
                break
        spriterenderer.render(image)

    sdl2.ext.quit()
    return 0

if __name__ == '__main__':
    sys.exit(main())

It also makes use of texture rendering, using hardware acceleration, instead of surface blitting (software based).

Finally, using the higher level sdl2.ext you could also instantiate classes (instead of having to write a whole new sprite class yourself) like sdl2.ext.sprite.TextureSprite, and implement a h property:

class TextureSprite(sdl2.ext.TextureSprite):

    @property
    def h(self):
        """The height of the TextureSprite."""
        return self.size[1]

    @property
    def w(self):
        """The width of the TextureSprite."""
        return self.size[0]
like image 150
Lucas Siqueira Avatar answered Nov 03 '22 05:11

Lucas Siqueira