Howto: Buch-Aufgaben ohne Processing lösen
Damit ihr so schnell wie möglich mit dem Programmiertraining loslegen könnt, sind alle Lösungsvorschläge im Buch für die Entwicklungsumgebung Processing optimiert. Processing lässt sich leicht installieren, erlaubt das ballastfreie und sofortige Loslegen, ohne mit Konfigurationswidrigkeiten hadern zu müssen, und beinhaltet Funktionen, mit denen einfache graphische Ausgaben programmiert werden können. Besonders das Zeichnen von Elementen kann in Processing durch die integrierten Funktionen deutlich schneller und leichter umgesetzt werden. Das bedeutet aber auch, dass einige unserer Lösungsvorschläge in der abgedruckten Form nicht in “reinem” Java oder Python funktionieren.
Für fortgeschrittene Programmierer gibt es aber Wege, wie ihr unsere Aufgaben ohne Processing lösen könnt. Diese beschreiben wir in diesem Blogartikel.
Java
Da Processing auf Java basiert, könnt ihr die Java-Library von Processing (Processing Core) in euer Projekt importieren. Die Macher von Processing haben hierfür eine ausführliche Anleitung geschrieben.
Python
Für Python ist das nicht ganz so einfach anpassbar, da der Python-Mode in Processing vor der Ausführung den Python-Code in Java umwandelt (Quelle). Folglich existiert aktuell leider keine Möglichkeit, um die integrierten Processing-Funktionen in Python aufzurufen.
Abseits von Processing existieren für Python jedoch 2D-Zeichenlibraries (z.B. Tkinter, pygame oder graphics.py). Diese kommen zwar unserer Meinung nach nicht an die Einfachheit von Processing heran, bieten jedoch ähnliche Funktionen. Wir zeigen anhand von Pygame, wie sich damit eine Zeichenaufgabe aus dem Buch in Standard Python 3 umsetzen lässt.
Beispiel: pygame
Die Pygame-Programmbibliothek bietet im Gegensatz zu Tkinter auch 2D-Rotationen, weshalb wir sie zur Umsetzung der Windrad-Aufgabe aus dem Kapitel “Kontrollstrukturen” nutzen können. Hierbei werden auch die Grenzen und Möglichkeiten von pygame deutlich.
Installation
Installieren können wir pygame in der Kommandozeile über den Python-Paketmanager pip:
pip install pygame
Alle Klassen und Funktionen von pygame sind in der offiziellen Dokumentation beschrieben. Darüber hinaus sind auf der offiziellen Website einige Tutorials zu finden.
Los geht’s
Die Initialisierung von pygame ist relativ simpel:
# coding=utf-8
import sys, pygame
# Starte Pygame
pygame.init()
Die Fenstergröße (in Processing wäre das der size()
-Befehl) setzen wir mit:
# Definiere Fenstergröße
width = 800
height = 800
# Setze Abmaße für Bildschirmfenster
screen = pygame.display.set_mode((width, height))
Mit dem hier initialisierten screen
-Objekt können wir später den Inhalt des Bildschirmfensters setzen.
Die draw()
-Funktion in Processing können wir in Form einer Endlosschleife abbilden:
while 1:
# Hier folgen dann die weiteren Befehle
Innerhalb dieser Schleife können wir dann die Fensterinhalte zeichnen. Zunächst definieren wir den Hintergrund des Bildschirmfensters:
white = 255, 255, 255
# Setze Hintergrund auf Weiß
screen.fill(white)
Probleme
Da wir in pygame keinen Bogen mit Farbfüllung zeichnen können, verwenden wir im Beispiel stattdessen ein Rechteck.
Pygame besitzt von sich aus leider keine Funktion zum Verschieben des Koordinatensystems (translate()
-Funktion in Processing). Folglich müssen wir hier selbst die Koordinaten der einzelnen Elemente berechnen. Dies hat auch zur Folge, dass wir das Koordinatensystem nicht drehen können (rotate()
-Befehl in Processing).
Daher sind Rotationen in pygame nicht so trivial wie in Processing umzusetzen. Nach Beginn der Schleife wie in der Processing-Lösung
# Erzeuge Einzelteile des Windrades
for i in range(0, 8):
sind folgende Schritte notwendig:
1. Wir müssen zunächst eine Zeichenfläche (leeres Bild) erzeugen
# Erzeuge neue Zeichenfläche für Windrad-Element (radius x radius)
surface = pygame.Surface(((radius, hoehe)))
2. dort entsprechend draufzeichnen
# Setze Hintergrund der Zeichenfläche auf Transparent (blende weiße Farbe aus)
surface.fill(white)
surface.set_colorkey(white)
# Male Rechteck auf die Zeichenfläche
pygame.draw.rect(surface, windrad_farbe, windrad_abmasse)
3. diese Zeichenfläche dann rotieren
# Rotiere den Bogen um entsprechende Gradzahl
winkel = -45*i
# Einfache Rotation durchführen
# Achtung: Ab 90 Grad Rotation verändert pygame die Abmaße unserer
# Zeichenfläche
surface = pygame.transform.rotate(surface, winkel)
4. und diese Zeichenfläche an die entsprechende Position im Fenster zeichnen.
# Rotiere den Bogen um entsprechende Gradzahl
winkel = -45*i
# Einfache Rotation durchführen
# Achtung: Ab 90 Grad Rotation verändert pygame die Abmaße unserer
# Zeichenfläche
surface = pygame.transform.rotate(surface, winkel)
5. Ab einer Rotation um 90 Grad werden von pygame die Bildmaße der Zeichenfläche verändert, sodass wir hier Sonderfälle behandeln müssen.
# Berechne Position der gedrehten Zeichenfläche.
if i<3:
# Zeichne unten rechts
# (obere linke Ecke der Zeichenfläche in der Mitte des Bildes)
position = surface.get_rect(topleft = mitte)
elif i<5:
# Zeichne unten links
# (obere rechte Ecke der Zeichenfläche in der Mitte des Bildes)
position = surface.get_rect(topright = mitte)
elif i<7:
# Zeichne oben links
# (untere rechte Ecke der Zeichenfläche in der Mitte des Bildes)
# Wir müssen dabei die Y-Position um die Hälfte der Höhe verschieben, damit
# wir in der Mitte des Windradflügels sind
position = surface.get_rect(bottomright = (mitte[0], mitte[1]+hoehe/2))
else:
# Zeichne oben rechts
# (untere linke Ecke der Zeichenfläche in der Mitte des Bildes)
# Wir müssen dabei die Y-Position um die Hälfte der Höhe verschieben, damit
# wir in der Mitte des Windradflügels sind
position = surface.get_rect(bottomleft = (mitte[0], mitte[1]+hoehe/2))
6. Schließlich zeichnen wir diese rotierte Zeichenfläche in das Bildschirmfenster:
# Zeichne Fläche in das Bildschirmfenster
screen.blit(surface, position)
Nach Ende dieser Schleife müssen wir dann noch dafür sorgen, dass die gezeichneten Elemente im Fenster dargestellt werden. Dies erfolgt mit:
# Zeige alle gezeichneten Elemente im Fenster an
pygame.display.flip()
Womit wir folgendes Ergebnis erhalten:
Die Lösung haben wir für euch auch auf Github hochgeladen.
Fazit
Die Lösungen lassen sich auch ohne Processing umsetzen. Allerdings wird sich dann besonders in Python der Schwierigkeitsgrad deutlich erhöhen. Aufgaben mit Rotationen sind damit deutlich schwieriger umzusetzen (Tkinter hat keine integrierte Rotationsfunktion!).
Wenn ihr allerdings schon die Workouts aus dem Buch in Processing geschafft habt, könnt ihr es natürlich auch mal in “reinem” Java oder Python probieren. Wenn ihr Lösungen ohne Processing umgesetzt habt, stellen wir sie gerne im Github-Repository zum Buch online.