Interaktion#

on_setup und act#

So far, you have simply written commands one below the other, and the commands were then processed from top to bottom.

If you want to write an interactive program, then you have to break this down a bit.

To do this, you can register methods that are called at specific times or respond to specific events.

Wir fangen mit zwei einfachen Methoden an, on_setup und act

  • on_setup is called once when the World has been created.

  • act wird immer und immer wieder aufgerufen, einmal pro Zeiteinheit.

The following program:

from miniworlds import *

world = World()
world.size = (120,210)

@world.register
def on_setup(self):
    print("setup")
  
@world.register
def act(self):
    print("act")

gibt z.B. folgende Ausgabe

setup
act
act
act

Code-Blöcke#

The line def on_setup(self): ends with a colon. Below it, you see a code block:

The contents of the function are all indented, everything that is indented to the same level belongs to a block.

from miniworlds import *

world = World()
world.size = (120,210)

@world.register
def on_setup(self):
    print("Dies ")
    print("ist ")
    print("Teil ")
    print("eines Codeblocks ")
print("Dies aber nicht")

When calling on_setup, the four lines below are called, but not the 5th line.

… note:: In der Regel verwendet man in Python 4 Leerzeichen, wenn man einen Codeblock einrückt. Es ist zwar kein Fehler, wenn du nur 3,2,1 oder 5 Leerzeichen oder ein Tab verwendest, solange du immer gleich weit einrückst - Dies wird von erfahrenen Programmierern aber als schlechter Stil empfunden.

Bildrate - Wie oft wird act() aufgerufen#

You can set how often act() is called by configuring the attributes world.fps and world.speed.

  • world.fps defines the frame rate. Similar to a flipbook, where you turn the pages at a set speed, the frame rate defines how often the image is redrawn per second. world.fps has a default value of 60, meaning 60 frames are displayed per second.

  • Im Attribut world.frame wird der aktuelle Frame gespeichert. Die Frames seit Programmstart werden hochgezählt.

  • world.speed defines how often the program logic (e.g. act) is called per second. A value of 60 means that the act() method is called every 60th frame.

  from miniworlds import *

  world = World()
  world.size = (120,210)

  @world.register
  def on_setup(self):
      world.fps = 1
      world.speed = 3
      
  @world.register
  def act(self):
      print(world.frame)

  world.run()

The program above has the output:

  3
  6
  9
  12
  15

It counts up very slowly because exactly one frame per second is played, and every 3rd frame (i.e., every 3 seconds) the function act() is called.

Warnung

Warning: It can lead to unforeseen side effects if code is indented incorrectly, consider the following program for example:

from miniworlds import *

world = World()
world.size = (120,210)

@world.register
def on_setup(self):
    print(1)

print(2)

@world.register
def act(self):
    print(3)
print(4)

world.run()  

The program has the output:

1
2
4
1
3
3

This is because on_setup() is executed first after the World is created in line 3. Then the two non-indented commands are executed, and as soon as run() starts, the act() function is called. Make sure your instructions are within the code blocks of act and on_setup.

Maus-Interaktionen#

Interaktionen finden in den Miniwelten über Events statt. Events können durch unterschiedlichste Systemereignisse aufgerufen werden, z.B. wenn der Benutzer eine Eingabe mit der Tastatur oder mit der Maus getätigt hat.

First, let’s take a look at mouse interactions:

Mit der Methode get_mouse_position kannst du die Mausposition abfragen:

from miniworlds import *

world = World()

@world.register
def on_setup(self):
   world.size = (200,200)

@world.register
def act(self):
   Ellipse(world.get_mouse_position(), 10, 10) 

world.run()

The circle now follows your mouse position:

Ermittle die Mausposition

To draw lines, you need the current and the last mouse position. This can be done as follows, for example:

from miniworlds import *

world = World()

@world.register
def on_setup(self):
    world.size = (200,200)

@world.register
def act(self):
    Line(world.get_prev_mouse_position(), world.get_mouse_position()) 

world.run()
Ermittle die Mausposition

Listener-Methoden#

It would be nice if we could also react to specific events, such as key presses or mouse clicks. For this, we can register certain listener methods, such as on_mouse_pressed

from miniworlds import *

world = World()

@world.register
def on_setup(self):
    world.size = (200,200)

@world.register
def act(self):
    Ellipse(world.get_mouse_position(), 10, 10) 

@world.register
def on_mouse_left(self, position):
    world.fill_color = (255, 0, 0)
  
@world.register
def on_mouse_right(self, position):
    world.fill_color = (255, 255, 255)
  
world.run()
Holen Sie sich die Mausposition, Farbänderung

Query-Tastatureingaben#

You can also query information from the keyboard:

from miniworlds import *

world = World()

@world.register
def on_setup(self):
    world.size = (200,200)

@world.register
def on_key_down_a(self):
    a = Ellipse.from_center((100, 100), 100, 100) 
    a.fill_color = (255, 0, 0)

@world.register
def on_key_down_b(self):
    a = Ellipse.from_center((100, 100), 100, 100) 
    a.fill_color = (0, 255, 0)

    
world.run()

This program responds to the keys a and b, pressing the a key draws a red ellipse, pressing the b key draws a green ellipse.

Working with chance#

Python provides several possibilities with the random library to create interesting graphical effects:

For example, a circle is created in a random color:

from miniworlds import *
import random
world = World()

@world.register
def on_setup(self):
    world.size = (200,200)

@world.register
def on_key_down_a(self):
    a = Ellipse.from_center((100, 100), 100, 100) 
    a.fill_color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))

    
world.run()

Output:

Farben ändern