archiv:gf:gf2021_2022:tipps

Dies ist eine alte Version des Dokuments!


Python in Minecraft verwenden

Wir haben gesehen, dass man den Agenten verwenden kann, um Objekte zu bauen. Dies ist jedoch recht kompliziert, da der Agent die Blocks nicht an seiner eigenen Position hinlegt, sondern vor oder hinter oder neben sich stellt. Dies macht die Programmierung nicht sehr einfach.

Will man Blöcke automatisch erstellen lassen, kann man dies auch direkt machen, d.h. ohne den Agenten. Dazu verwendet man hauptsächlich die Befehle: blocks.place und blocks.fill. Damit kann man einen Block an einer bestimmten Position setzen, oder einen ganzen Quader von Blöcken auf einmal erstellen.

Eine Linie von Blocks erstellen, wobei jeder zweite Block aus Gold bzw. aus blauer Wolle besteht: (das %-Zeichen ist die Modulo-Rechnung vgl. Stunde)

for i in range(3,20,1):
    if (i%2)==0:
        blocks.place(GOLD_BLOCK, pos(i, 0, 0))
    else:
        blocks.place(BLUE_WOOL, pos(i,0,0))

Einen Grossen Goldblock erstellen und mit Luft aushöhlen:

blocks.fill(GOLD_BLOCK, pos(1, 1, 1), pos(10, 10, 10))
blocks.fill(AIR, pos(2,2,2),  pos(9, 9, 9))

Eine Variable ist ein Behälter für eine Grösse. Diese wird durch einen Namen repräsentiert und zeigt auf eine bestimmte Adresse im Speicher des Computers. Variablen können beliebig wieder überschrieben werden.

In Variablen kann man ganz unterschiedliche Dinge speichern. Z.B.

  • ganze Zahlen (Integers)
  • Kommazahlen (Float)
  • Zeichenketten (Strings)
  • Wahrheitswerte: True, False (bolean)
  • Listen (Listen sind Datenstrukturen). In Python kann eine Liste komplett unterschiedliche Dinge enthalten, d.h. die Datentypen können beliebig gemischt werden.

In vielen Programmiersprachen muss man sich bei einer bestimmten Variable entscheiden, von welchem Typ sie ist und kann dann nur diesen Typ verwenden. Nicht so in Python. In Python herrscht dynamische Typisierung vor, d.h. ich kann in einer Variablen a zunächst eine Zeichenkette speichern und dann diese durch eine ganze Zahl überschreiben und danach eine Kommazahl daraus machen.

a = 4 # In der Variablen a wird der Wert 4 gespeichert
name = 'Rene Lehmann' # In der Variablen name wird 'Rene Lehmann' gespeichert
strasse = "Lärchenweg" # doppelte Anführungszeichen gehen auch
pi = 3.141592 # Eine Fliesskommazahl
a = "Hallo" #die Variable a wird wieder überschrieben

if agent.get_item_count(2)>=2:
    agent.set_slot(2)
    agent.place(BACK)
    agent.move(FORWARD, 1)
    agent.place(BACK)
elif agent.get_item_count(2)==1:
    agent.set_slot(2)
    agent.place(BACK)
else:
    player.say("Nix mehr in Slot 2")

while agent.get_item_count(1)>0:
    agent.place(BACK)
    agent.move(FORWARD,1)

l1 = [GRASS, STONE, OAK_DOOR] # Liste erstellen
agent.set_slot(1)
for item_type in l1: # Liste durchgehen
    agent.set_item(item_type, 1, 1)
    agent.place(BACK)
    agent.move(FORWARD, 1)

Eine Liste kann man auch sehr elegant mit dem range-Befehl erstellen:

range(10) # => [0,1,2,3,4,5,6,7,8,9]
range(9,18,3) # => [9, 12,15]


# Eine Funktion definieren, welche zwei Parameter (n, type) nimmt
def build_line(n, type):
    agent.set_item(type,1,1)
    agent.set_slot(1)
    for i in range(n):
        agent.place(BACK)
        agent.move(FORWARD,1)

# Nun kann die Funktion aufgerufen werden
build_line(5,GRASS)
build_line(8,STONE)

Der Modulo-Operator % kann praktisch sein, um bei einer Schleife, nur gewisse Schritte anzusteuern, z.B. nur bei jeder zweiten Position einen Block setzen:

for i in range(20):
    if (i % 2) == 0:
        blocks.place(GOLD_BLOCK, world(i, 4, 0))

Was ändert sich, wenn man statt %2, %3, %4 etc. schreibt?

Abwechselnd 3 verschiedene Blöcke platzieren mit Modulo (%)

for i in range(40):
        if (i%3) == 0:
            blocks.place(GOLD_BLOCK,world(i,5,0))
        if (i%3) == 1:
            blocks.place(BLUE_WOOL,world(i,5,0))
        if (i%3) == 2:
            blocks.place(GREEN_WOOL,world(i,5,0))

Elegante Lösung für ein Parkettmuster

for i in range(20):
        for j in range(20):
            if (i+j) % 2 == 0:
                blocks.place(GOLD_BLOCK,pos(i,5,j))
            else:
                blocks.place(BLUE_WOOL,pos(i,5,j))

Damit die Funktion möglichst flexibel eingesetzt werden kann, sollte man sie parametrisieren, d.h. man kann der Funktion als Argumente übergeben, an welcher Position das Haus gebaut wird, bzw. welche Grösse es hat.

def simple_house(xpos,ypos,zpos,breite, hoehe):
    blocks.fill(STONE_BRICKS,world(xpos,ypos,zpos),world(xpos+breite,ypos+hoehe, zpos+breite))
    blocks.fill(AIR, world(xpos+1,ypos,zpos+1),world(xpos+breite-1,ypos+hoehe-1, zpos+breite-1))
    #Tuere
    blocks.fill(AIR,world(xpos+4,ypos,zpos),world(xpos+4,ypos+1,zpos))
    blocks.place(ACACIA_DOOR,world(xpos+4,ypos,zpos))


simple_house(100,4,-18,7,10)
simple_house(140,4,-18,10,5)

Statt z.B. blocks.place(OAK_DOOR,world(0,0,0)) kann man den Block mit zugehörigem Datenwert platzieren:

blocks.place(blocks.block_with_data(OAK_DOOR, 0),world(0,0,0))

Der Daten-Wert gibt an, ob die Türe (oder Treppe) etc. geöffnet ist, nach links aufgeht etc.

def strasse(xpos,ypos,zpos,laenge):
    blocks.fill(LIGHT_GRAY_CONCRETE,world(xpos,ypos,zpos),world(xpos+laenge,ypos,zpos+4))
    for i in range(xpos,xpos+laenge,2):
        blocks.place(CONCRETE,world(i,ypos,zpos+2))

strasse(700,3,700,40)

Zurück zur Übersicht

  • archiv/gf/gf2021_2022/tipps.1661616509.txt.gz
  • Zuletzt geändert: 2022/08/27 18:08
  • von lehmannr