Wie kann ich die Größe von Pixelkunst in Pyglet ändern, ohne sie unscharf zu machen?

7

Ich habe ein Kachelset mit 8x8-Pixel-Bildern und möchte die Größe in meinem Spiel so ändern, dass sie doppelt so groß sind (16x16 Pixel, z. B. jedes Pixel in einen 2x2-Block verwandeln). Was ich erreichen möchte, ist ein Minecraft- ähnlicher Effekt, bei dem kleine Pixelbilder auf größere blockierbare Pixel skaliert werden.

In Pyglet scaleverwischt die Eigenschaft des Sprites die Pixel. Gibt es einen anderen Weg?

Arbeitscode:

Hier ist die Lösung, die funktioniert (dank DMans Beharrlichkeit und Jimmys Einsicht):

image = resource.image('tileset.png')                                                                                                                                                               
texture = image.get_texture()   
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)                                                                                                                               
texture.width = 16 # resize from 8x8 to 16x16                                                                                                                                                                  
texture.height = 16                                                                                                                                                                                                                                                                                                                       
texture.blit(100, 30) # draw                                                                                                                                                                        
Theabraham
quelle
3
Ich bin mit Pyglet nicht genug vertraut, um dies zu einer Antwort zu machen, aber ich habe gesehen, dass Sie OpenGL verwenden können, from pyglet.gl import *und rufen Sie dann talisman.org/opengl-1.1/Reference/glTexParameter.html mit an GL_NEAREST.
DMan
Danke, ich werde mir das ansehen, aber ich habe OpenGL noch nie benutzt. Art neu in der Grafikprogrammierung: \
Theabraham
Ich weiß nicht, wie viel Pyglet hinter den Kulissen tut, aber so etwas könnte funktionieren : glEnable(GL_TEXTURE_2D). Dann nehmen wir an, Sie hatten einen Anruf bei a = image.load('blah.jpg'). Weisen Sie tex = a.texturedann glBindTexture(GL_TEXTURE_2D, texture.id)und schließlich einen Anruf zu pyglet.gl.glTexParameteri(pyglet.gl.GL_TEXTURE_2D, pyglet.gl.GL_TEXTURE_MIN_FILTER, pyglet.gl.GL_NEAREST). Ich bin mit dem Namespace für OpenGL in Python nicht allzu vertraut, daher habe ich den vollständigen Aufruf qualifiziert gelassen. Da wir OpenGL importiert haben, glaube ich, dass Sie zumindest den Pyglet vorne entfernen können , und vielleicht auch gl .
DMan
Hey, ich habe es ohne Erfolg versucht. Könnten Sie meinen Code im Update überprüfen? Haben Sie auch gute Ressourcen, um diese GL-Befehle besser zu verstehen? Ich schätze die Hilfe.
Theabraham
Eine Sache, die mir sofort aufgefallen ist, ist, dass Sie die Breite und Höhe der Textur vor Ihrem Anruf einstellen glTexParameteri. OpenGL 1/2/3 ~ , das ich Pyglet vermuten , basiert diese auf haben unmittelbaren Modus Befehle. Das heißt, Sie führen einen Befehl aus, um den Status zu ändern, und danach ändert sich alles. Ich würde damit beginnen, die Anrufe unter die gl-Anrufe zu verschieben.
DMan

Antworten:

8

Auf Wunsch von Kommentatoren ...

Warnung an Pyglet-Profis: Es gibt möglicherweise einen guten Pyglet-Weg, dies zu tun, und das ist es nicht. Es ist ein schöner OpenGL-Weg. Du wurdest gewarnt!

Sie können dies in OpenGL tun, indem Sie zuerst die Textur binden und dann glTexParameterioder ähnliche Variablen aufrufen. Sie können dies in Pyglet tun, indem Sie OpenGL importieren:

from pyglet.gl import *

Sie können dann das GL_TEXTURE_2DFestlegen des Ziels aktivieren . Dies wird nicht immer benötigt, aber ich halte dies für einige andere Bindungen vollständig.

glEnable(GL_TEXTURE_2D)

In Pyglet müssen Sie die Textur anscheinend auch nicht binden. Manchmal müssen Sie Ihr Bild laden, die Textur-ID abrufen und dann verwenden glBindTexture(GL_TEXTURE_2D, texture.id). Meine Annahme, dass dies bereits der für Sie in Pyglet festgelegte Zustand ist.

Der nächste Schritt ist das Anrufen glTexParameteri. Vielen Dank an Jimmy, der mich diesbezüglich korrigiert hat: Der richtige Anruf lautet:

gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)

Ein kurzer Überblick: Der erste besteht darin, das Ziel so festzulegen, dass OpenGL weiß, wovon Sie sprechen. Der zweite Parameter ist der Filtertyp, den Sie festlegen möchten. MAG_FILTERist korrekt, da es die Vergrößerung von Texturen steuert. Der letzte Parameter ist GL_NEAREST, der steuert, wie die Textur skaliert wird. GL_NEARESTist im Grunde eine schnelle Skala, die texturierte Pixel liefert. GL_LINEARist normal und verwischt stattdessen sanft Ihre Textur.

Diese Version von OpenGL, über die ich spreche (über <OpenGL 3.2 offiziell), verwendet den Sofortmodus, der den Status festlegt. Nachdem der Status festgelegt wurde, können Sie Ihre Textur skalieren. Ich kann nichts Besseres sehen, als den Code zu zeigen, den Renold selbst als Arbeitscode gepostet hat.

image = resource.image('tileset.png')                                                                                                                                                               
texture = image.get_texture()   
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)                                                                                                                               
texture.width = 16 # resize from 8x8 to 16x16                                                                                                                                                                  
texture.height = 16                                                                                                                                                                                                                                                                                                                       
texture.blit(100, 30) # draw
DMan
quelle
Renold, wenn Sie sich das ansehen und Verbesserungen vorschlagen könnten, wäre das großartig. Ich bin aber an etwas interessiert. Wenn Sie entfernen texture = image.get_texture(), funktioniert das? Es scheint, als hätten Sie es nie genannt, es sei denn, dies bindet die Textur intern.
DMan
Ja, es stellt sich heraus, dass du es nicht brauchst. Ich habe das Bild schließlich einfach in ein Sprite image = resource.image('tileset.png') \n sprite = sprite.Sprite(image, x_pos, y_pos) \n sprite.scale = 2 \n
eingefügt
4

Für diejenigen wie mich, die einfach ein Spiel im Retro-Stil machen, bei dem ALLES skaliert werden soll, lautet die einfache schnelle Antwort: Beginnen Sie Ihren Code mit:

from pyglet.gl import *
glEnable(GL_TEXTURE_2D)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)

Dann bleibt Ihre gesamte Verwendung von Sprites usw. von da an schön und pixelig.

Nathan
quelle