Fragen zu Sprites

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

Ich möchte gerne einen Sinus-Scrolltext mit SDL bauen. Für den Zeichensatz nehme ich einen C-64er Zeichensatz. Die Routine, die mir den Zeichensatz vom C64er in Surfaces umrechnet steht so weit und sieht so aus:

Code: Alles auswählen

class char ():
    def __init__ (self, filename):
        # Charset vom C64er laden
        self.charset = []
        data = open (filename, 'rb')
        line = data.read (512)
        for byte in range (0, len (line)):
            self.charset.append ((struct.unpack ('B', line [byte])[0]))

    def makeChar (self, char):
        # Bitmap bauen mit (ord) kann ein ASCII nach INT umgewandelt werden
        charsurface = pygame.Surface ((8, 8), 16)
        charsurface.fill ((0, 0 ,0 ))
        lineindex = 0

        # Zusammensetzen des Buchstaben
        for charindex in range ((ord (char) -96) *8 +2, (ord (char) -96) *8 +8 +2):
            if self.charset [charindex] & 128:
                charsurface.set_at ((1, lineindex), (255))
            if self.charset [charindex] & 64:
                charsurface.set_at ((2, lineindex), 255)
            if self.charset [charindex] & 32:
                charsurface.set_at ((3, lineindex), 255)
            if self.charset [charindex] & 16:
                charsurface.set_at ((4, lineindex), 255)
            if self.charset [charindex] & 8:
                charsurface.set_at ((5, lineindex), 255)
            if self.charset [charindex] & 4:
                charsurface.set_at ((6, lineindex), 255)
            if self.charset [charindex] & 2:
                charsurface.set_at ((7, lineindex), 255)
            if self.charset [charindex] & 1:
                charsurface.set_at ((8, lineindex), 255)
            lineindex = lineindex +1
        return (charsurface)

So weit so gut. Jedes einzelne Zeichen ( Buchstabe ), ist eine Klasseninstanz. Das brauche ich um jeden Buchstaben einzeld, Koordinaten zuzuteilen. Nun bin ich mit der Routine ein wenig unzufrieden. Denn jedes mal wenn ich einen neuen Buchstaben baue, wird im Constructor ja der C64er Zeichensatz geladen.
Ich brauche nur einen kleinen Denkanstoß, wie ich es hinbekomme, nur ein mal den Zeichensatz laden zu müssen? Möchte ungern unnötigen Speicher verballern. Weiß da jemand ne Lösung? Sollte man es überhaupt mit einer Klasse machen?
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo,

1) Deine Leertaste ist kaputt, sie macht immer eine Lücke zwischen Funktionsnamen und öffnender Klammer.
2) Du solltest Dir nochmals ein Tutorial über for-Schleifen durchlesen.
3) Für Deinen Fall wäre eine Zeichensatz-Klasse gut, die mit make_char eben ein Einzelzeichenobjekt zurückliefert.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@The Hit-Man: Ich würde sowas machen (ungetestet):

Code: Alles auswählen

class CharMap(dict):

    def __init__(self, filename):
        with open(filename, 'rb') as data:
            self._bitmaps = [
                struct.unpack('B', byte)[0] for byte in data.read(512)]

    def __missing__(self, char, coors=range(8)):
        surface = pygame.Surface((8, 8), 16)
        surface.fill((0, 0, 0))
        c = (ord(char) - 96) * 8 + 2
        for row in coors:
            bitmap = self._bitmaps[row + c]
            for col in coors:
                if bitmap & (0x100 >> (8 - col)):
                    surface.set_at((col + 1, row), 255)
        self[char] = surface
        return surface

    def __getitem__(self, char):
        return dict.__getitem__(self, char).copy()


cm = CharMap('some_file.xyz')

a1 = cm['a']
a2 = cm['a']
assert a1 is not a2
Hierbei wird die Datei nur einmal gelesen, nicht jedesmal, wenn ein Buchstabe gebraucht wird. Die Methode dict.__missing__(self, key) wird von dict.__getitem__(self, key) automatisch aufgerufen, sofern unter key nichts gefunden wurde, dh. also jedes erste Mal wenn wir ein Surface-Objekt via cm[Buchstabe] holen wollen.

Die Methode __getitem__() habe ich überschrieben, damit man jedesmal ein neues Surface-Objekt bekommt.

Ob die Indizierungs-Formeln alle stimmen solltest du nochmal nachprüfen.
In specifications, Murphy's Law supersedes Ohm's.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

unpack ist ja gerade dazu da, »kompliziertere« Strukturen zu entpacken, da mit einzelnen Bytes daherzukommen, ...
ein einfaches map(ord,bytes) würde hier ja auch schon völlig ausreichen.

Ein Surface Pixel für Pixel aufzubauen ist auch alles andere als effektiv.

Für all die, die was laufen sehen wollen:

Code: Alles auswählen

import pygame
import struct

class CharMap(dict):
    def __init__(self, bytes):
        self._bitmaps = struct.unpack_from('>27Q',bytes,2)

    def __missing__(self, char, mask=[1<<k for k in range(63,-1,-1)]):
        bits = self._bitmaps[ord(char)-96]
        data = struct.pack('<64i', *(-bool(bits&m) for m in mask))
        return pygame.image.fromstring(data, (8,8), 'RGBA')

    def __getitem__(self, char):
        return dict.__getitem__(self, char).copy()


bytes="""
eJwtjSsOAzEMRI0W5QhVzxCYYxUW5HBBg1ZVUVRQrYKMquCAyO04XZMnf+ZZkpxlgEFVJjBVJ/tS
mpqMHRybWCmjNVKczfcPn4M5ZS7HGFPKcg0hXN53wf56jo9KYXkO3arfoR5HJ8217mX+7wN6/67e
c/Tb5vvlTf4H5z8ik3V5gJzyIjIPxbaQbvz3A90ciaI=
""".decode('base64').decode('zip')

cm = CharMap(bytes)
display = pygame.display.set_mode((255, 255))

for k,ch in enumerate('hallo'):
    display.blit(cm[ch], (20+k*8, 20))

pygame.display.flip()
while True:
    event = pygame.event.wait()
    if event.type == pygame.QUIT:
        break
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

Erst mal Danke an alle ... ja, mein Programmierstiel ist alles andere als sauber. Ich weiß :( ich programmiere eher immer so: gut getrickst ist halb gearbeitet.
Allerdings die methode __getitem__ kannte ich bis jetzt noch gar nicht.
Auch die Bytes einzelnd aus der Datei zu holen war eher mal schnell nen GoogleHack. Gesucht und gefunden.
Antworten