image image


Random Walk mit der Python Arcade-Bibliothek

Daniel Shiffmans Buch »The Nature of Code« hat auch noch ein Kapitel 0. In diesem einführenden Kapitel geht es unter anderem um Zufallszahlen und Random Walk. Solch einen (zweidimensionalen) Random Walk wollte ich natürlich ebenfalls nach Python portieren, auch mit Vektoren umgesetzt. Zuerst hatte ich das mal mit Pythons Turtle Modul und meiner PVector-Bibliothek versucht, dann erwachte mein Ehrgeiz und ich wollte das auch mit der Python Arcade-Bibliothek umsetzen.

image

Die Hauptschwierigkeit bestand darin, Arcade davon abzuhalten, bei jedem Frame den Hintergrund neu zu zeichnen. Denn sonst sieht man nur einen irrlichtenden Punkt (oder eine irrlichtende kleine Linie) auf dem Monitor. Den Hintergrund bei jedem Frame neu zu zeichnen, ist zwar bei Spielen durchaus sinnvoll (und darum ist es auch bei Arcade der Default), aber bei einigen Simulationen – wie bei meinem Random Walk – unerwünscht.

Nach einigen Versuchen fand ich heraus, daß man in der Hauptklasse die Methode arcade.start_render() nicht in on_draw() aufrufen sollte, sondern im Konstruktur, der daher bei mir so aussieht:

class MyWindow(arcade.Window):
    
    def __init__(self):
        super().__init__(WIDTH, HEIGHT, TITLE)
        self.walker = Walker()
        arcade.set_background_color((43, 62, 80))
        arcade.start_render()

Eine zweite, kleinere Schwierigkeit war noch, herauszufinden, wie man ein Arcade-Script anhalten kann, ohne daß es gleich das Fenster schließt. Die Lösung, die ich gefunden habe, ist zwar nicht unbedingt effektiv, aber sie funktioniert. Ich habe eine Statusvariable walker.paused zu Beginn auf False gesetzt und wenn die gewünschte Anzahl von Iterationen durchlaufen ist, wird diese auf True gesetzt. Das wird in der on_update()-Methode der Hauptklasse dann so behandelt:

    def on_update(self, delta_time):
        if self.walker.paused:
            return
        self.walker.update()

Zwar wird die Methode dann immer noch etwa sechzig Mal in der Sekunde aufgerufen, aber sie macht einfach nichts mehr, läßt aber das Fenster offen.

Hier jetzt erst einmal das vollständige Programm:

import arcade
from pvector import PVector
import random

WIDTH = 600
HEIGHT = 600
TITLE = "Random Walk mit der Arcade-Bibliothek"

class Walker():
    
    def __init__(self):
        # Position and Velocity
        self.location = PVector(WIDTH/2, HEIGHT/2)
        self.prev_location = PVector(WIDTH/2, HEIGHT/2)
        self.velocity = PVector(0, 0)
        # Farbe
        self.color = (255, 255, 178)
        self.count = 0
        self.paused = False
        self.stepsize = 4
    
    def update(self):
        self.prev_location.set(self.location)
        self.count += 1
        if self.count <= 1500:
            self.color = (255, 255, 178)
        elif self.count <= 3000:
            self.color = (254, 204, 92)
        elif self.count <= 4500:
            self.color = (253, 141, 60)
        elif self.count <= 6000:
            self.color = (240, 59, 32)
        elif self.count <= 7500:
            self.color = (189, 0, 38)
        if self.count >= 7500:
            self.paused = True
        roll = random.randint(1, 4)
        if roll == 1:
            self.location.y += self.stepsize
        elif roll == 2:
            self.location.x += self.stepsize
        elif roll == 3:
            self.location.y -= self.stepsize
        elif roll == 4:
            self.location.x -= self.stepsize
            
        
    def draw(self):
        arcade.draw_line(self.prev_location.x, self.prev_location.y,
        self.location.x, self.location.y, self.color, 2)
    

class MyWindow(arcade.Window):
    
    def __init__(self):
        super().__init__(WIDTH, HEIGHT, TITLE)
        self.walker = Walker()
        arcade.set_background_color((43, 62, 80))
        arcade.start_render()
        
    def on_draw(self):
        self.walker.draw()
    
    def on_update(self, delta_time):
        if self.walker.paused:
            return
        self.walker.update()

MyWindow()
arcade.run()

Die Update-Methode der Klasse Walker ist nur deswegen so fett geworden, weil ich nach jeweils 1.500 Schritten die Farbe gewechselt habe, ansonsten wäre auch sie recht kurz geraten. Implementiert habe ich einen klassischen zweidimensionalen Random Walk, bei dem Richtungsänderungen nur in den vier Himmelrichtungen erlaubt sind. Durch den Einsatz der Klasse PVector sind jedoch auch Bewegungen in alle Richtungen möglich. Vielleicht implementiere ich das auch noch mal, Daniel Shiffman hat es schon vorgemacht. Die stepsize habe ich im Konstruktor von Walker initialisiert, zum einen, um damit spielen zu können, zum anderen aber auch, um später einen Random Walk mit Lévy Flight implementieren zu können.

Den Quellcode dieser Version findet Ihr natürlich auch auf GitHub, ebenso wie meine Versuche, einen Random Walk ohne Vektoren und einen Random Walk mit Vektoren mit der Turtle zu programmieren. Das letzte Skript hat auch bewiesen, daß mein PVector-Modul mit Pythons Schildkröte funktioniert. Zwar besitzt diese eine eigene, etwas abgespeckte Implementierung einer Vektor-Klasse (turtle.Vec2D), aber sie beißt sich nicht mit PVector. Bemerkenswert an ihr ist aber, daß sie das innere Produkt zweier Vektoren durch Operator-Überladung implementiert hat. Sollte ich meiner PVecotr-Klasse vielleicht auch noch spendieren. Still digging!


(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