image image


image

The Nature of Code reloaded with TigerJython?

Da müßt Ihr jetzt durch! Nachdem ich am Wochenende mit wachsender Begeisterung mit TigerJython gespielt hatte, ist mir der größenwahnsinnige Gedanke gekommen, die Sketche aus Daniel Shiffmans »The Nature of Code« nach TigerJython zu portieren. Meine eigene PVector-Implementierung ist Framework-unabhängig (da sie selber keine Zeichnungen erstellt) und läuft sowohl mit Python 2.7 wie auch mit Python 3. Also habe ich erst einmal getestet, ob sie tatsächlich mit TigerJython zusammen funktioniert. Spoiler: Sie tut es!

Als erste Fingerübung habe ich erst einmal ein paar Bälle auf Reisen geschickt, die – von Vektoren getrieben – zufällig über den Bildschirm gleiten und an den Rändern zurückgestoßen werden. Diese Bouncing Balls habe ich schon in Processing.py (Implementierung), P5.js (Implementierung) und auch in Pygame Zero (Implementierung) programmiert, so daß ich Euch mit den Details nicht langweilen will, sondern einfach nur den Quellcode zum Nachvollziehen und -programmieren hier abdrucke:

from gpanel import *
from pvector import PVector
import random

WIDTH = 640
HEIGHT = 400
dt = 30     # delay time
                
class Mover():
    
    def __init__(self):
        self.d = random.randint(16, 24)
        self.vel = PVector(1, 1)
        self.vel.mult(random.uniform(2.0, 6.0))
        self.direction = PVector(random.uniform(-1.5, 1.5), random.uniform(-1.5, 1.5))
        self.position = PVector(random.randint(2*self.d, WIDTH - 2*self.d), random.randint(2*self.d, HEIGHT - 2*self.d))
        self.red = random.randint(100, 255)
        self.green = random.randint(0, 150)
        self.blue = random.randint(0, 255)
        
    def update(self):
        self.position.x += self.vel.x*self.direction.x
        self.position.y += self.vel.y*self.direction.y
   
    def draw(self):
        pos(int(self.position.x), int(self.position.y))
        setColor(makeColor(self.red, self.green, self.blue))
        fillCircle(self.d)
        setColor("black")
        circle(self.d)
    
    def checkEdges(self):
        if self.position.x <= self.d or self.position.x >= WIDTH - self.d:
            self.vel.x =  -self.vel.x
        if self.position.y <= self.d or self.position.y >= HEIGHT - self.d:
            self.vel.y = -self.vel.y


def drawBackground():
    setColor(makeColor(234, 218, 184))
    fillRectangle(-2, -2, WIDTH + 2, HEIGHT + 4)

def onCloseClicked():
    keepGoing = False
    print("I did it, Babe!")
    dispose()

makeGPanel(Size(WIDTH, HEIGHT), closeClicked = onCloseClicked)
window(0, WIDTH, 0, HEIGHT)
title("Bouncing Ball")
enableRepaint(False)

movers = []
for _ in range(30):
    movers.append(Mover())

keepGoing = True
while keepGoing:
    drawBackground()
    for mover in movers:
        mover.draw()
        mover.checkEdges()
        mover.update()
    repaint()
    delay(dt)

Dann wollte ich wissen, wie man in TigerJython ein Objekt dazu bringt, der Maus zu folgen. Ich habe statt der vielen Bälle also nur einen einzigen Ball der Klasse Mover auf den Schirm gebracht und die eigenständige Bewegung (Methode update()) auskommentiert:

image

In TigerJythons GPanel werden die Mouse-Events per Callback ausgelöst. Die Callback-Funktion wird dabei schon bei der Initialisierung registriert:

makeGPanel(Size(WIDTH, HEIGHT), closeClicked = onCloseClicked, mouseMoved = onMouseMoved)

Ich habe zwei Events als Callback registriert, einmal closeClicked, das ausgelöst wird, wenn der Nutzer den Schließbutton des Fensters anklickt und dann mouseMoved, das auf die Mausbewegungen reagiert. Die Namen der Callback-Funktionen sind in TigerJython fest, sie müssen so und nicht anders benannt werden:

def onCloseClicked():
    keepGoing = False
    print("I did it, Babe!")
    dispose()

def onMouseMoved(x, y):
    mover.position.x = x
    mover.position.y = y

Damit folgt der Kreis (mover) dem Mauszeiger. Und damit sind (fast) alle Voraussetzungen erfüllt, um den Großteil der Sketche aus »The Nature of Code« nach TigerJython zu portieren. Doch zuerst einmal der vollständige Quellcode auch von diesem Skript:

from gpanel import *
from pvector import PVector

WIDTH = 640
HEIGHT = 360
                
class Mover():
    
    def __init__(self):
        self.position = PVector(320, 180)
        self.vel = PVector(2.8, 1.6)
        self.d = 20
        self.color = makeColor(248, 239, 34)
        
    def update(self):
        self.position += self.vel
        if self.position.x <= self.d or self.position.x >= WIDTH - self.d:
            self.vel.x =  -self.vel.x
        if self.position.y <= self.d or self.position.y >= HEIGHT - self.d:
            self.vel.y = -self.vel.y
   
    def draw(self):
        pos(int(self.position.x), int(self.position.y))
        setColor(self.color)
        fillCircle(self.d)
        setColor("black")
        circle(self.d)

def drawBackground():
    setColor(makeColor(146, 82, 161))
    fillRectangle(-2, -2, WIDTH + 2, HEIGHT + 4)

def onCloseClicked():
    keepGoing = False
    print("I did it, Babe!")
    dispose()

def onMouseMoved(x, y):
    mover.position.x = x
    mover.position.y = y

makeGPanel(Size(WIDTH, HEIGHT), closeClicked = onCloseClicked, mouseMoved = onMouseMoved)
window(0, WIDTH, 0, HEIGHT)
title("Steering 1")
enableRepaint(False)

mover = Mover()

keepGoing = True
while keepGoing:
    drawBackground()
    mover.draw()
    # mover.update()
    repaint()
    delay(30)

Mit »fast« alle Voraussetzungen meine ich, daß TigerJythons GPanel im Gegensatz zu Processing(.py) scheinbar kein pushMatrix() und popMatrix() kennt, um Translationen und Rotationen bequem durchzuführen. So, wie es aussieht, muß ich dies wohl von Hand als Bestandteil der Klasse Mover implementieren. Das wird daher mein nächstes Projekt. Still digging!

Den Quellcode inklusive der PVektor-Klasse findet Ihr in meinem GitLab-Repositorium.

Daneben hatte ich am Wochenende noch weiter mit TigerJython gespielt. Die Ergebnisse werde ich Euch in den nächsten Tagen vorstellen. Denn wie ich oben schon schrieb: Da müßt Ihr jetzt durch!

image


(Kommentieren) 

image image



Über …

Der Schockwellenreiter ist seit dem 24. April 2000 das Weblog digitale Kritzelheft von Jörg Kantel (Neuköllner, EDV-Leiter Rentner, Autor, Netzaktivist und Hundesportler — Reihenfolge rein zufällig). Hier steht, was mir gefällt. Wem es nicht gefällt, der braucht ja nicht mitzulesen. Wer aber mitliest, ist herzlich willkommen und eingeladen, mitzudiskutieren!

Alle eigenen Inhalte des Schockwellenreiters stehen unter einer Creative-Commons-Lizenz, jedoch können fremde Inhalte (speziell Videos, Photos und sonstige Bilder) unter einer anderen Lizenz stehen.

Der Besuch dieser Webseite wird aktuell von der Piwik Webanalyse erfaßt. Hier können Sie der Erfassung widersprechen.

Diese Seite verwendet keine Cookies. Warum auch? Was allerdings die iframes von Amazon, YouTube und Co. machen, entzieht sich meiner Kenntnis.


Werbung

Diese Spalte wurde absichtlich leergelassen!


Werbung


image  image  image
image  image  image


image