pyglet.gl fehlerhaft oder mich ich was falsch

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
Thinilgandir
User
Beiträge: 4
Registriert: Samstag 18. Mai 2019, 12:57

Nach meinen Durchgang des Python tutorials, bin ich etwas schlauer.
Habe mir nach Euren Anraten verschiedene Python videos angesehen, und eines wollte ich probieren.
Leider funktioniert es nicht, obwohl es im Video funktioniert.

Ein paar sachen habe ich probiert, damit ich eventuell ausschliessen kann, dass eine Erweiterung fehlt, oder offensichtlich fehlerhaft ist.
Anbei folgenden Code: Es soll an einen Objekt Texturen wie Grass geladen und angebracht werden.

Code: Alles auswählen

from pyglet.gl import *

class Model:

  def get_tex(self,file):
      tex = pyglet.image.load(file).texture
      return pyglet.graphics.TextureGroup(tex)
    
  
  def __init__(self):

      self.top = self.get_tex('grass_top.JPG')
      self.side = self.get_tex('grass_side.JPG')
      self.bottom = self.get_tex('erde.JPG')

      
      self.batch = pyglet.graphics.Batch()

      tex_coords = ('t2f', (0,0, 1,0, 1,1, 0,1, ))
      
      x,y,z = 0,0,0
      X,Y,Z = x+1, y+1, z+1

      self.batch.add(4, GL_QUADS, self.side, ('v3f', (x,y,z, X,y,z, X,Y,z, x, Y, z, )), tex_coords)

  def draw(self):
      self.batch.draw()


class Window(pyglet.window.Window):

  def Projection(self): glMatrixMode(GL_PROJECTION); glLoadIdentity()
  def Model(self): glMatrixMode(GL_MODELVIEW); glLoadIdentity()
  def set2d(self): self.Projection(); gluOrtho2D(0,self.width,0,self.height); self.Model()
  def set3d(self): self.Projection(); gluPerspective(70,self.width/self.height,0.05,1000); self.Model()
    
  def __init__(self, *args, **kwargs):
      super().__init__(*args, **kwargs)
      self.set_minimum_size(300, 200)

      self.model = Model()

  def on_draw(self):
      self.clear()
      self.model.draw()

if __name__ == '__main__':
    window = Window(width=400, height=300, caption='Minecraft', resizable=True)
    glClearColor(0.5,0.7,1,1)
    pyglet.app.run()
Die Fehlermeldung beim Kopillieren lautet wie folgt:

Code: Alles auswählen

Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.
>>> 
===== RESTART: C:\Users\Christian\Documents\Programmieren\Python\cube.py =====
Traceback (most recent call last):
  File "C:\Users\Christian\Documents\Programmieren\Python\cube.py", line 49, in <module>
    window = Window(width=400, height=300, caption='Minecraft', resizable=True)
  File "C:\Users\Christian\Documents\Programmieren\Python\cube.py", line 42, in __init__
    self.model = Model()
  File "C:\Users\Christian\Documents\Programmieren\Python\cube.py", line 12, in __init__
    self.top = self.get_tex('grass_top.JPG')
  File "C:\Users\Christian\Documents\Programmieren\Python\cube.py", line 6, in get_tex
    tex = pyglet.image.load(file).texture
AttributeError: 'ImageData' object has no attribute 'texture'
Offensichtlich findet er die Texture nicht. Aber was ich nicht verstehe, wieso das Bild kein Attribute hat, wenn es doch geladen wird? Groß und Kleinschreibung habe ich beachtet. ICh weiss nicht weiter.

Die Texturen werden mit der Variable Tex geladen, dann wird jede Texture einer Seite zugeordnet. In meinen Fall Top, side und bottom. Damit er weiss welche Texture wohin gehört habe ich jeder Texture eine bezeichnung gegeben. Aus meiner Sicht, sieht es recht ok aus, ich verstehe nur nicht wieso der keine Attribute hat, wenn das Bild mittels pyglet.image.load geladen wurde.

Ich glaube ich werde nochmals von vorne anfangen.
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Thinilgandir: Wie kommst Du denn darauf, dass es ein `texture`-Attribut gibt? Schau doch mal in der Dokumentation nach was diese Klasse tatsächlich bietet.

Ansonsten würde ich mal auf den Style Guide for Python Code verweisen. Zum Beispiel was die Verwendung von Semikolons angeht — macht man nicht. Und Namen werden klein_mit_unterstrichen geschrieben. Ausnahmen Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). Also die `Model()`-Methode sollte so nicht heissen. Ist auch ein komischer Name, denn Funktions- und Methodennamen beschreiben üblicherweise die Tätigkeit die sie ausführen. Das es zusätzlich noch ein `model`-Attribut gibt, macht das ganze nicht übersichtlicher.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Thinilgandir: Wietere Anmerkungen: Eingerückt wird mit vier Leerzeichen pro Ebene.

Das Hauptprogramm sollte auch in einer Funktion stehen, damit man nicht ausversehen doch irgendwo globale Variablen verwendet.

`get_tex()` ist keine Methode, das wäre einfach nur eine Funktion. Der Name ist auch etwas ungenau. Man sollte keine Abkürzungen verwenden. Der klingt als würde man dort ein Texture bekommen – das `_tex` hier für `TextureGroup` steht, ist IMHO nicht offensichtlich. Und ich würde `load` statt `get` nehmen und `filename` statt `file`. Bei `file` erwartet der Leser das man dort ein Dateiobjekt übergeben muss und keinen Datei*namen*.

Die `__init__()` ist üblicherweise die erste Methode die in einer Klasse definiert wird.

`Projection()` und `Model()` sind eigentlich auch keine Methoden sondern nur Funktionen und so wie sie verwendet werden, könnte man die ganz gut als Kontextmanager schreiben. Vielleicht auch nicht mit einem festen Wert als zweiten Modus, sondern das danach auf den alten zurück gewechselt wird, welcher auch immer das war.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
from contextlib import contextmanager

import pyglet
from pyglet.gl import *


def load_texture_group(filename):
    texture = pyglet.image.load(filename).get_texture()
    return pyglet.graphics.TextureGroup(texture)


class Model:

    def __init__(self):
        self.top = load_texture_group('grass_top.JPG')
        self.side = load_texture_group('grass_side.JPG')
        self.bottom = load_texture_group('erde.JPG')

        self.batch = pyglet.graphics.Batch()

        tex_coords = ('t2f', (0, 0, 1, 0, 1, 1, 0, 1))

        x_a, y_a, z_a = 0, 0, 0
        x_b, y_b, z_b = x + 1, y + 1, z + 1

        self.batch.add(
            4,
            GL_QUADS,
            self.side,
            (
                'v3f',
                (x_a, y_a, z_a, x_b, y_a, z_a, x_b, y_b, z_a, x_a, y_b, z_a)
            ),
            tex_coords
        )

    def draw(self):
        self.batch.draw()


@contextmanager
def matrix_mode(mode):
    old_mode = glGetIntegerv(GL_MATRIX_MODE)
    glMatrixMode(mode)
    glLoadIdentity()
    try:
        yield
    finally:
        glMatrixMode(old_mode)
        glLoadIdentity()


class Window(pyglet.window.Window):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.set_minimum_size(300, 200)
        self.model = Model()

    def set2d(self):
        with matrix_mode(GL_PROJECTION):
            gluOrtho2D(0, self.width, 0, self.height)
    
    def set3d(self):
        with matrix_mode(GL_PROJECTION):
            gluPerspective(70, self.width / self.height, 0.05, 1000)

    def on_draw(self):
        self.clear()
        self.model.draw()


def main():
    _ = Window(width=400, height=300, caption='Minecraft', resizable=True)
    glClearColor(0.5, 0.7, 1, 1)
    pyglet.app.run()


if __name__ == '__main__':
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Code: Alles auswählen

class Window(pyglet.window.Window):
  def Projection(self): glMatrixMode(GL_PROJECTION); glLoadIdentity()
  def Model(self): glMatrixMode(GL_MODELVIEW); glLoadIdentity()
  def set2d(self): self.Projection(); gluOrtho2D(0,self.width,0,self.height); self.Model()
  def set3d(self): self.Projection(); gluPerspective(70,self.width/self.height,0.05,1000); self.Model()
Wenn ich so etwas sehe wird mir schlecht, das ist kein Python, das ist Müll.
Aus einer anderen Sprache von jemandem der in dieser Sprache denkt in Python umgeschrieben.
Das beste Beispiel wie man es nicht machen sollte.
Ich vermute die Source war diese hier: https://www.youtube.com/watch?v=NyBkFkAWnEo mittlerweile 3 Jahre alt.
Der Code zum Download auf einem Werbehoster, hust schluck.
Seriöse Projekte veröffentlicht man auf Github.
Tue dir selbst einen Gefallen und hör auf dir so etwas per copy paste anzueignen um auf Brechen und Biegen auf die Schnelle
Minecraft in Python nach zu programmieren.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Thinilgandir: Das sieht ja ziemlich nach dem Code aus was ThomasL da gefunden hat. Das Ziel in dem Video war aber nicht ein gutes, sauberes Programm zu schreiben, sondern das möglichst in unter 300 Zeilen hinzubekommen.

Man kann mit und bei „code golf“ durchaus etwas über eine Programmiersprache lernen, aber man sollte nicht mit „code golf“ tatsächlich die Programmiersprache oder auch Programmmieren allgemein lernen wollen. Denn beim „code golf“ geht es oft um etwas obskure Eigenarten der Programmiersprache und so gar nicht darum lesbaren, idiomatischen Code zu schreiben. Also das was man normalerweise will.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten