Tag Archives: scratch

Auf die Plätze, fertig, los !

Mit einem toolgestützten Controller Framework für scratch3-Spiele soll die Entwicklung von Spielen mit scratch vereinfacht werden.

Die Ablaufsteuerung eines Scratch-Spieles mit verschiedenen Spielleveln macht Schülern der siebten Klasse einige Probleme:

  • Das Spiel kann einmal gespielt werden, beim zweiten Durchlauf erscheinen die Figuren an unerwarteten Stellen.
  • Um Fehler zu suchen muß das Spiel jedesmal vom Anfang an gespielt werden; einzelne Spiellevel können nicht separat angesteuert werden.
  • Das Einfügen neuer Level ist sehr aufwendig.
  • Hilfe für die Schüler bei Problemen ist schwierig wenn sich ein Programm zu einem verknäulten Spaghetti entwickelt hat.

Bisher wurde ein Controller Framework vorgestellt und die Implementierung auch angeleitet. Die Implementierung war jedoch teilweise papierbasiert und diese Vorgehensweise insgesamt nicht sehr erfolgreich.

Die Arbeitsschritte waren:

  • Erklärungen der Motivation, Vorgehensweise an der Tafel
  • Checklisten verteilen
  • die Abfolge der Spiellevel und der Ereignisse in einem Diagramm aufzeichnen
  • Anhand einer Beschreibung/ Checkliste dann die Scripte für den Controller aufbauen

Diese manuelle Vorgehensweise war nicht sehr erfolgreich. Der Nutzen für die Entwicklung war nicht sofort ersichtlich und statt endlich mit dem Spiel loszulegen wollte niemand gerne erst mal auf Papier irgendwelche Bilder zeichnen.

  • die auf Papier erstellten Diagramme wurden nicht an die aktuellen Programm angepasst und konnten so zum Verständnis des Spieles nicht herangezogen werden. Oder waren dann nicht mehr greifbar, vergessen, nicht abgeheftet.
  • Die Diagramme wurden im ersten Anlauf ‘zu schön’ gezeichnet mit Karopapier und Lineal. Dieser für erste Versionen überflüssige Aufwand benötigt viel Zeit und schöne Diagramme werden weniger bereitwillig geändert.
  • die Diagramme mussten manuell in Skripte und Ereignisse übertragen werden, hier gab es Tippfehler, Abweichungen bei groß-Kleinschreibung, Auslassungen.
  • Individuelle Abwandlungen der Controller-Skripte führen zu einem hohen Aufwand bei der Unterstützung der Schüler.

Mit einem toolunterstützten ‘Controller-Framework’ sollen diese Probleme vermieden werden. Insbesondere muß der Planungsschritt “Ablaufplanung” schnell und unkompliziert durchgeführt werden können.

Für Schüler wird das Framework altersgemäß als Rezeptsammlung bereitgestellt. Nach einer Einführung soll es im Prinzip möglich sein durch einfache Übernahme der generierten Skripte sehr schnell einen Fortschritt zu erzielen. Was dann – hoffentlich – die Motivation steigert das Framework zu benutzen.

Das Framework soll die folgenden Features aufweisen:

  • Einzelne Level können separat gestartet werden während der Entwicklung und Test.
    Das Durchlaufen komplexer Abläufe bis zu einem bestimmten Fehler wird vermieden.
  • Supportaufwand wird durch Standardisierung verringert.
  • Die Ereignisse wie ‘gewonnen’, ‘verloren’ können simuliert werden und erlauben das einfache Verifizieren der Spielabläufe.
  • Eine Erweiterung des Spieles um zusätzliche Level ist einfach möglich.
  • Der Controller, ein Sprite mit dem Namen ‘Dirigent’, gibt Meldungen aus wenn ein neuer Level gestartet wird. Protokollierung kann ggf. einfach nachgerüstet werden.

Mit der Umstellung des Kurses von scratch1.4 zu scratch3 in 2022 wird eine technische Unterstützung mit einem grafischen Tool eingeführt. Die Schüler müssen zwar im Moment weiterhin die generierten Skripte abtippen, aber durch die genaue Abbildung wird ein besseres Ergebnis erwartet.
Eine automatische Erstellung eines importfähigen Sprite ist noch nicht umgesetzt.

Der Post ist eine Überarbeitung eines früheren Artikels über die Ablaufsteuerung: Auf die Plätze, fertig, los !

Bestandteile des Framework

Das Framework implementiert eine Controller Pattern bestehend aus einer Zustandmaschine für die Abläufe und Interfaces/ Templates für Ereignisse im Spielablauf.

Ein zentrale Controller Komponente implementiert als scratch Sprite ist nur für den übergeordneten Spielablauf zuständig.

Alle Sprite erhalten standardisierte Ereignisse für die Ablaufsteuerung.

UML Diagramm für die Messages zwischen Dirigent und einem Sprite für einen Level ‘Level_1’

Die Ablaufdiagramme sind grafisch vereinfachte UML StateMachineDiagram.

Die Zustände haben links die ‘Entry’-Port, rechts die ‘Exit’-Port so dass die Pfeile an den Events entfallen können.

Entry-Aktionen werden in zwei Phasen ‘fertig’ und ‘los’ aufgeteilt und über Messages, scratch-Ereignisse angesteuert.

Werkzeuge, Toolunterstützung

Das Tool besteht aus einem grafischen Editor für Spielabläufe und der Möglichkeit daraus den Sprite-Skript-Code zu generieren sowie die Templates für die Ereignisse der Sprite-Spielfiguren.

Es wurde wenig Aufwand in eine ‘smarte’ Oberfläche investiert:

Bedienoberfläche des Editor.

Technisch gesehen läuft das Tool im Browser, es wird eine javascript-Bibliothek draw-2d verwendet.
Aus einer einfachen Palette werden die Elemente auf die Arbeitsfläche gezogen. Die Verbindungen werden mit der Maus erstellt.

Undo, Redo werden unterstützt. Alle Veränderungen werden in einer lokalen Datenbank persistiert. Mit “Store” werden Ergebisse gespeichert und die bis dahin angefallen Zwischenstände dann gelöscht.

‘Print’ speichert die Grafik als svg-Datei auf dem Rechner. “skript:dirigent” und “skript:sprite” aktivieren den Generator und die grafische Ausgabe der Skripte. Bisher muß dann manuell abgetippt werden. Für das gezeigte Beispiel sind das im ‘Dirigent’ etwa 50 Blöcke.

Die Server-Komponente ist in python mit ‘tornado’ implementiert, ‘sqlite3’ übernimmt die lokale Speicherung.
Die Generierung der Grafiken erzeugt SVG in Webseiten, hier ein Beispiel für die Ausgabe des “skript:dirigent”:

Anzeige des generierten Dirigent-scratch-Skript

Die Anzeige der Skripte lehnt sich an die aus scratch3 bekannten Formen und Farben an; die schwarze Schrift ist eine Abweichung von der Pastelloptik und besser lesbar.

Das Controller-Framework hat als zentrale Komponente ein scratch-Sprite mit dem Namen ‘Dirigent’. Das ist der ‘Controller’ des Spiels.
Technisch gesehen implementiert der Controller einen Zustandsautomaten, die Level sind die Zustände und die Übergänge werden über Ereignisse gesteuert. GesStartet über die grüne Flagge.

Die einzelnen Sprites in Scratch (Spielfiguren) erhalten eine standardisierte Schnittstelle aus Ereignissen (Messages).

LEVEL_1_fertig: Dirigent zu Sprites. Setze die Startwerte für den Level wie:
– zeige dich / verstecke dich
– Größe
– Position
– Variablen

LEVEL_1_los: Dirigent zu Sprites. Hier geht es los. Die Abläufe werden gestarten, Bewegungen aktiviert etc.

LEVEL_1_stop: Dirigent zu Sprite. Der level ist beendet, beende Aktionen des Sprite. Stoppe Schleifen.

gewonnen, verloren, weiter o.ä.: Sprite zu Dirigent. Damit wird der Übergang zu einem neuen Level gestartet. Hier können die Schüler (fast) beliebige Namen verwenden.

In den Beispielen werden die Level in Großbuchstaben geschrieben. Das erleichtert die Übersicht.

Aus dem Ablaufdiagramm erzeugte Scratch-Snippet für ein Sprite.

Die Schüler füllen – statt den Kommentaren – ihre eigenen Abläufe ein.

Spezialfall ‘wiederverwendbarer Level’

In den von Schülern gezeichneten Ablaufdiagrammen tauchen regelmässig Level auf, die wie ein Unterprogramm an verschiedenen Stellen verwendet wurden. Beispiele sind ein Zwischenlevel ‘der level wurde gewonnen, weiter mit dem nächsten Level oder beenden ?’

Bisher mussten solche Anforderungen durch spezifische (unique) Level gelöst werden oder die Programmierung wurde ad hoc ergänzt.

Das Tooling unterstützt diesen Sonderfall.

Komplexes Beispiel mit Zwischenlevel ‘X’

Die Skripte des ‘Dirigent’ sind sehr ähnlich wie des einfachen Beispiels, lediglich an den Stellen wo die Zwischenlevel eingefügt sind wird eine weitere Variable ‘p_level’ verwendet.

Sprite ‘Dirigent’, Beispiele für das Verarbeiten von Ereignissen mit ‘ZwischenLevel’.

scratch io response times

Scratch 1.4 on raspberry pi allows programs to work with GPIO pins. I was curious to see how fast scratch can react to input values.

To measure these times, I connected an arduino due (84MHz clock) with a raspberry pi 2B. The arduino produces a 0–>1 edge for scratch and scratch responds with a 0–>1-edge on another pin. The red arrow in the chart shows this dependency. The time between these two edges is the response time of scratch. timing

The scratch code is straightforward. Sensor values are 0, 1, so there are logical operations needed.

.scratch_response_times

Response times are aggregated in a chart. X-axes shows the time intervals, y-axis shows how often execution times have been measured in the 0.5 ms intervals.

response_times

The response times range from  3ms to 46ms. The bulk of values is between 5ms and 27ms. The chart is produced from 5659 single measurements. So scratch is sufficient fast to respond in slow environments, but should not be used to control fast systems.

Here the arduino code:

//
// run on an arduino due

int pout = 11;
int pin = 12;

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("response_time_measurement");
  pinMode(pin, INPUT);
  pinMode(pout, OUTPUT);
  digitalWrite(pout, LOW);
}
long randomnumber = 0;
long t0 = 0;
long t1 = 0;

void loop() {
  // wait for input low
  while ( HIGH == digitalRead(pin)) ;

  randomnumber = random(1, 700);
  delay(randomnumber);
  t0 = micros();
  digitalWrite(pout, HIGH);

  while ( LOW == digitalRead(pin)) ;
  t1 = micros();

  Serial.print(randomnumber);
  Serial.print("\t");
  Serial.println(t1 - t0);

  delay(100);
  digitalWrite(pout, LOW);
}

There is a variable delay in the arduino code from 1 to 700ms to prevent a ‘lock in’ to scratch cycle times.

Although time measurements are in microseconds, the accuracy depends on how good the compiler is in producing fast code. As the times to be measured are in millisecond range, this approach is reasonable precise.

Similiar setup with scratchClient yields following results:

response_times_scratchClient

Times are centered around some 67 ms, min is 46 ms which is slower than using gpioserver.

The scratchClient-adapter used is ‘GpioButtonInput’, which already provides edge-detection. The scratch code is

scratch_scratchClient_performance