archiv:gf:gf2021_2022:2d2:olivierpaulmateo

Drei Minigames

Informatikarbeit von Yeung Paul, Huber Mateo und Gottrau Olivier

Der vollständige Code sowie ein Download-Link zu der Minecraft-Welt finden sich im Anhang.


Idee und Kurzfassung

Unser Spiel besteht aus drei Minigames. Im ersten muss ein Parcours mit unsichtbaren Hindernissen absolviert werden und anschliessend mit Pfeilen vier schwer treffbare Knöpfe treffen. Im zweiten muss ebenfalls ein Parcours abgeschlossen werden, in welchem aber einige Inseln verschwinden, sobald man auf sie steht. Im letzten muss ein Gebäude von 64 Zombie-Pigmen befreit werden, während dem man in Geheimkammern speziell Starke Ausrüstung finden kann.

Der Spieler hat für jedes Level unendlich viele Versuche und muss nicht mit dem ersten Level wieder anfangen, falls er ein Minispiel nicht auf Anhieb erreichen kann.


1. Jump'n'Run mit Zielschiessen: In desem Spiel gilt es, den Parcours mit unsichtbaren Hindernissen abzuschliessen. Diese besetehen aus „Barrier“-Blöcken. Dies soll den Spieler reizen und in der nächsten Aufgabe unkonzentriert machen, damit das Spiel schwerer wird. Danach müssen vier Knöpfe mit Pfeilen abgeschossen werden, welche dem Spieler via Command Block gegeben werden, wenn er auf einen Knopf drückt.

2. Himmelfahrt: Danach absolvieren sie eine tödliche Partie „Himmelfahrt“; dieses Minigame wurde von der Netflixserie „Squid Game“ inspiriert und knüpft an das Jump and Run-Theme des vorherigen Spiels. Der Parcours besteht aus 12 Reihen mit jeweils 2 Inseln. Der Spieler muss über die Inseln springen, dabei werden einige Inseln zerstört, wenn der Spieler darauf steht, fällt er in den Tod. Die Inseln, welche zerstört sind, bleiben nach jedem Respawn zerstört. Wir haben dieses Spiel gewählt, weil es übersetzt so viel wie „Himmelfahrt“ heisst und damit zu der Geschichte passt, mit der kirchlichen Einrichtung. Ebenfalls ist es ein top Spielerlebnis, wenn man auf Inseln springen muss, welche plötzlich verschwinden und man somit einfach runter fällt.

3. Operation Zombie Pigman: Im Letzten Level findet man sich in einer Kirche wieder und muss sie von den Monstern befreien. Sie können auf dem Weg dorthin Waffen und Rüstung bekommen indem sie Kammern finden, welche versteckt sind und nur mit Schlüsseln (Items) geöffnet werden können. Sobald sie den Monsterboss besiegt haben, haben sie das Level geschafft. Es ist ein ziemlich grosses Gebäude mit verschiedensten Einrichtungen, damit der Spieler das perfekte Erlebnis geniessen kann.


Einteilung

Paul Yeung: Bau und Gestaltung der Levels, Programmierung, Idee, Organisation der Gruppe

Mateo Huber: Bau der Levels, Wiki, Programmierung, Organisation der Gruppe

Olivier Gottrau: Idee, Programmierung, Wiki, Bau und Gestaltung der Levels

Danksagung

Laith Ben Yacoub (2BS): Zähl-Funktion im 3. Level, Beratung für Himmelfahrt-Level

Timo Amacker (2D1): Beratung für Himmelfahrt-Level


Bauberichte

1. Jump'n'Run mit Zielschiessen

Code

Die Knöpfe leiten ihr Signal an Command-Blocks weiter, welche den Spieler „ziel1“, „ziel2“ etc. sagen lassen. Der Code erkennt dies mittels player.on_tell_command(). Es wird jeweils eine Variable (insel1, insel2 etc) auf True gesetzt; wenn alle 4 True sind wird das nächste Level gestartet.

Neben dem Schild beim Knopf-Treffe-Spiel befinden sich zwei Commandblocks, welche auf Knopfdruck „give @p“- Befehle ausführen. Sie geben dem Spieler einen Pfeilbogen und 64 Pfeile, was unlimitiert wiederholt werden kann.

Phyischer Bau

Die hohen Mauern rund um den Parcours wurden mit dem folgenden Code erstellt.

fill x y z x y z obsidian

Die restlichen Bauten wurden gänzlich von Hand gebaut.

Schwierigkeiten

Es war zuerst schwer, auf die Idee mit dem Commandblock-Code-Feedback zu kommen.


2. Himmelfahrt

Code

Die Commands in den Command-Blocks am Ende des Spiels:

tp @p[r=2] 18 5 -121
execute @p[r=3] ~ ~ ~ say spiel2
Als Setup werden die Inseln einzeln Block-By-Block gebaut, in dem über player.execute() setblock aufgerufen wird. Dies wird für jeden einzelnen Block wiederholt. Wir können hier die Wiederholungen nicht vermeiden, weil die Befehle zur Verwaltung von Matrizen fehlen. Wir könnten sonst mit for i in range für jedes Element der Matrizen der einzelnen Inseln den setblock-Befehl aufrufen und der Code wäre um einiges kürzer.

Auf dem Dach der Box befinden sich Command Blocks, welche mit dem Befehl testfor die einzelnen Koordinaten der zusammenfallenden Inseln überwachen. Sie sind im „Immer Aktiv“-Modus. Wenn diese Bedingung zutrifft, geben sie über einen Redstone-Comparator ein Signal aus und aktivieren einen anderen Block mit dem Befehl „setblock x y z air“. Dies löscht die Insel Block-By-Block und der Spieler fällt ins Nichts.

Phyischer Bau

Die Box um das Jump'n'Run wurde mit einfachen „fill“-Commands im Chat gebaut.

fill x y z x y z chiseled_polished_blackstone

Wie im vorherigen Level wurden die restlichen Elemente von Hand gebaut. Schwierigkeiten

Es war sehr aufwändig, die Koordinaten der Inseln zu bestimmen. Zudem haben wir keine Methode gefunden, mit dem Code direkt die Inseln zu zerstören; auch Schüler von anderen Klassen konnten keine funktionierenden Lösungen finden. Die Wiederholungen beim Setup lassen sich unseres Erachtens nach nicht vermeiden. Wir haben uns von Laith Ben Yacoub (2BS) und Timo Amacker(2D1) in der Programmierung beraten lassen.


3. Operation Zombie-Pigman

Es war ursprünglich geplant, das Gebäude als Kirche zu bauen, weil wir uns so besonders viel Raum für Feingestaltung erhofften (spez. mit programmierbaren Eastereggs und anderen Elementen). Wir haben uns aber dagegen entschieden, weil wir keine religiösen Ansichten anderer Personen verletzen wollten. Das Gebäude besitzt jedoch noch Kirchen-Elemente, weil wir zum Zeitpunkt dieser Entscheidung bereits viel Arbeit in das Gebäude investiert hatten.

Code

Drei einfache Häuser nebeneinander, ein wenig versetzt gebaut. Die Böden noch für die verschiedenen Etagen eingefügt.


def simple_house(xpos,ypos,zpos,breite, hoehe):
    blocks.fill(BLOCK_OF_QUARTZ, world(xpos,ypos,zpos),world(xpos+breite,ypos+hoehe, zpos+breite),FillOperation.HOLLOW)
    #Tuere
    blocks.fill(AIR,world(xpos+4,ypos,zpos),world(xpos+4,ypos+1,zpos))
    blocks.place(ACACIA_DOOR,world(xpos+4,ypos,zpos))
    
def boden(xpos,ypos,zpos,breite,hoehe):
    blocks.fill(BLOCK_OF_QUARTZ, world(xpos,ypos,zpos), world(xpos+breite, ypos+hoehe, zpos+breite))

boden(10, 34, -105, 20, 1)    

Hier ein Beispiel für die Programmierung einer versteckten Kammer.

found = False

def on_item_interacted():
    global found
    player.say("Schlüssel für verborgene Kammer gefunden")
    found = True
 
player.on_item_interacted(CLOCK, on_item_interacted)
 
def on_travelled_walk():
    x = player.position().get_value(Axis.X)
    y = player.position().get_value(Axis.Y)
    z = player.position().get_value(Axis.Z)
    if (x == 19) and (y== 5) and (z==-99) and found==True:
        blocks.fill(AIR, world(21, 5, -100), world(21, 7, -98))
    
 
player.on_travelled(WALK, on_travelled_walk)

Programmierung der verschiedenen Kammern, welche nur durch einige Items geöffnet werden können und in denen verschiedene Rüstungsgegenstände oder andere Sachen verborgen sind. Die Items haben den Namen der jeweiligen Kammer und sollen Schlüssel darstellen, ebenfalls sind die Kammern mit Schildern gekennzeichnet. Hier der komplette Code für alle Kammern und Räume.

found = False

def on_clock_interacted():
    global found
    player.say("Schlüssel für verborgene Kammer gefunden")
    found = True

def on_compass_interacted():
    global found
    player.say("Schlüssel für Rüstungskammer gefunden")
    found = True

def on_flint_and_steel_interacted():
    global found
    player.say("Schlüssel für Kammer gefunden")
    found = True

def on_shears_interacted():
    global found
    player.say("Schlüssel für Treppenkammer gefunden")
    found = True

def on_book_interacted():
    global found
    player.say("Schlüssel für kleine Kammer gefunden")
    found = True
 
def on_travelled_walk():
    x = player.position().get_value(Axis.X)
    y = player.position().get_value(Axis.Y)
    z = player.position().get_value(Axis.Z)
    if (x == 19) and (y== 5) and (z==-99) and found==True:
        blocks.fill(AIR, world(21, 5, -100), world(21, 7, -98))
    if (x == 18) and (y== 13) and (z==-116) and found==True:
        blocks.fill(AIR, world(17, 13, -118), world(19, 15, -118))
    if (x == 13) and (y== 13) and (z==-119) and found==True:
        blocks.fill(AIR, world(13, 13, -118), world(13, 14, -118))
    if (x == 58) and (y == 59) and (z == -91) and found==True:
        blocks.fill(AIR, world(57, 59, -93), world(59, 61, -93))
    if (x == 46) and (y == 47) and (z == -98) and found==True:
        blocks.fill(AIR, world(44, 47, -98), world(44, 49, -99))
    if (x == 44) and (y == 38) and (z == -94) and found==True:
        blocks.fill(AIR, world(45, 38,-94), world(45, 39, -94))


player.on_item_interacted(CLOCK, on_clock_interacted)
player.on_item_interacted(COMPASS, on_compass_interacted) 
player.on_item_interacted(FLINT_AND_STEEL, on_flint_and_steel_interacted)
player.on_item_interacted(SHEARS, on_shears_interacted)
player.on_item_interacted(BOOK, on_book_interacted)
player.on_travelled(WALK, on_travelled_walk)



Das Zählen der Mobs findet mit der Funktion mobs.mobs_on_mob_killed statt. Jedes Mal, wenn ein Zombie Pigman getötet wird, wird die Funktion addKill aufgerufen, welche 1 von der Variable „alive“ subtrahiert. Wenn diese Variable den Wert 0 erreicht, wird die Schlaufe mit „break“ unterbrochen und der Titel „Spiel Abgeschlossen“ wird mit dem Befehl player.execute(„title @p title Spiel Abgeschlossen“) angezeigt.

Phyischer Bau

Die Inneneinrichtung wurde von Hand, ohne jegliche Programme gebaut. Alle Treppen, Teppiche, Lampen und Brunnen wurden von Hand gebaut. Einige Türen sind mit Redstone verbunden und können durch Hebel geöffnet werden. Die Gegenstände in den Truhen wurden von uns selber so verteilt, ebenfalls die Schlüssel (Items) zu den verschiedenen Kammern wurden von uns auf der Map verteilt. Die Lifte sind ebenfalls von Hand gebaut, damit das Spielerlebnis ein bisschen verändert wird und man nicht nur Treppen laufen muss, sondern auch von selber zu einem anderen Stockwerk gelangen kann. Das Spielerlebnis ist somit besser, da wir uns Mühe für ein gutes Design gegeben haben.

Schwierigkeiten

Wir konnten zuerst keine Möglichtkeit finden, um die Zombie Pigmen zu zählen. Wir haben die Hilfe eines anderen Schülers benötigt. (Laith Ben Yacoub, 2BS).


Fazit

Die Umsetzung der Ideen war teilweise unmöglich, weil bestimmte Commands, die in der Java-Edition enthalten sind, nicht in der Education Edition vorhanden sind (z.B. /data). Dies trifft auch auf Python zu (Es fehlen z.B. Funktionen zur Verwaltung von Matrizen, was für das zweite Level notwendig ist). Ansonsten fanden wir es spannend, dieses Projekt zu verwirklichen und wir haben unsere Fähigkeit, methodisch zu denken, stark verbessern können. Wir fanden die Herausforderungen aufgrund der fehlenden Befehle anregend. Zudem fanden wir die Aufgabenstellung gut, weil wir einen grossen Raum an Self-Management und Kreativität einsetzen konnten.


Anhang

Link zur Welt:

https://eduetatfr-my.sharepoint.com/:f:/g/personal/olivier_gottrau_studentfr_ch/EqaaFU7s-jRBiH_t1dh3dAgBA6AumrBKUet_wzAKpTZxCg?e=fr5JYT

Vollständiger Code:

#setup 1: funktionen und variablen definieren

def levelAbgeschlossen():
    player.execute("title @p title Level Abgeschlossen")


# für das erste minispiel
ziel1 = False
ziel2 = False
ziel3 = False
ziel4 = False

def ziel1True():
    global ziel1
    ziel1 = True
    return ziel1

def ziel2True():
    global ziel2
    ziel2 = True
    return ziel2

def ziel3True():
    global ziel3
    ziel3 = True
    return ziel3

def ziel4True():
    global ziel4
    ziel4 = True
    return ziel4

#für das zweite Minispiel
#Wir könenn keine Methode zur "routinisierung" der nachfolgenden Befehle. Es könnte unserem Wissen nach nur so gemacht werden, wenn alle Python-Funktionen zur Bearbeitung von Matrizen verhanden wären

player.execute("setblock 96 3 151 chiseled_polished_blackstone")
player.execute("setblock 97 3 151 chiseled_polished_blackstone")
player.execute("setblock 97 3 150 chiseled_polished_blackstone")
player.execute("setblock 96 3 150 chiseled_polished_blackstone")

player.execute("setblock 93 3 146 chiseled_polished_blackstone")

player.execute("setblock 90 3 143 chiseled_polished_blackstone")
player.execute("setblock 89 3 143 chiseled_polished_blackstone")
player.execute("setblock 89 3 142 chiseled_polished_blackstone")
player.execute("setblock 90 3 142 chiseled_polished_blackstone")

player.execute("setblock 93 3 138 chiseled_polished_blackstone")

player.execute("setblock 90 3 135 chiseled_polished_blackstone")
player.execute("setblock 89 3 135 chiseled_polished_blackstone")
player.execute("setblock 89 3 134 chiseled_polished_blackstone")
player.execute("setblock 90 3 134 chiseled_polished_blackstone")

player.execute("setblock 96 3 135 chiseled_polished_blackstone")
player.execute("setblock 97 3 135 chiseled_polished_blackstone")
player.execute("setblock 97 3 134 chiseled_polished_blackstone")
player.execute("setblock 96 3 134 chiseled_polished_blackstone")

player.execute("setblock 93 3 130 chiseled_polished_blackstone")

player.execute("setblock 89 3 127 chiseled_polished_blackstone")
player.execute("setblock 90 3 127 chiseled_polished_blackstone")
player.execute("setblock 90 3 126 chiseled_polished_blackstone")
player.execute("setblock 89 3 126 chiseled_polished_blackstone")

player.execute("setblock 93 3 122 chiseled_polished_blackstone")

player.execute("setblock 96 3 119 chiseled_polished_blackstone")
player.execute("setblock 97 3 119 chiseled_polished_blackstone")
player.execute("setblock 97 3 118 chiseled_polished_blackstone")
player.execute("setblock 96 3 118 chiseled_polished_blackstone")

player.execute("setblock 89 3 118 chiseled_polished_blackstone")
player.execute("setblock 90 3 118 chiseled_polished_blackstone")
player.execute("setblock 90 3 119 chiseled_polished_blackstone")
player.execute("setblock 89 3 119 chiseled_polished_blackstone")



# Für das letzte Minispiel
def tpLevel2():
    player.execute("spawnpoint @p 18 5 -121")
    player.execute("tp @p 18 5 -121")
    return True    #weil es sonst heisst: "solche funktionen müssen einen return-wert haben" (~)


found = False

def on_clock_interacted():
    global found
    player.say("Schlüssel für verborgene Kammer gefunden")
    found = True
 
def on_compass_interacted():
    global found
    player.say("Schlüssel für Rüstungskammer gefunden")
    found = True
 
def on_flint_and_steel_interacted():
    global found
    player.say("Schlüssel für Kammer gefunden")
    found = True
 
def on_shears_interacted():
    global found
    player.say("Schlüssel für Treppenkammer gefunden")
    found = True
 
def on_book_interacted():
    global found
    player.say("Schlüssel für kleine Kammer gefunden")
    found = True
  
def on_travelled_walk():
    x = player.position().get_value(Axis.X)
    y = player.position().get_value(Axis.Y)
    z = player.position().get_value(Axis.Z)
    if (x == 19) and (y== 5) and (z==-99) and found==True:
        blocks.fill(AIR, world(21, 5, -100), world(21, 7, -98))
    if (x == 18) and (y== 13) and (z==-116) and found==True:
        blocks.fill(AIR, world(17, 13, -118), world(19, 15, -118))
    if (x == 13) and (y== 13) and (z==-119) and found==True:
        blocks.fill(AIR, world(13, 13, -118), world(13, 14, -118))
    if (x == 58) and (y == 59) and (z == -91) and found==True:
        blocks.fill(AIR, world(57, 59, -93), world(59, 61, -93))
    if (x == 46) and (y == 47) and (z == -98) and found==True:
        blocks.fill(AIR, world(44, 47, -98), world(44, 49, -99))
    if (x == 44) and (y == 38) and (z == -94) and found==True:
        blocks.fill(AIR, world(45, 38,-94), world(45, 39, -94))

alive = 64
def addKill():
    global alive
    alive = alive -1 
    return alive




#setup 2: andere einstellungen und zu anfang teleportieren
player.execute("gamemode adventure")
player.execute("tp @p -1 5 20") #zu Anfang teleportieren
player.execute("spawnpoint @p -1 5 20")


#eigentlicher spielcode

#Level 1 ("jump n run")
while True:
    player.on_tell_command("ziel1", ziel1True)
    player.on_tell_command("ziel2", ziel2True)
    player.on_tell_command("ziel3", ziel3True)
    player.on_tell_command("ziel4", ziel4True)

    if ziel1 and ziel2 and ziel3 and ziel4:
        levelAbgeschlossen()
        player.execute("tp @p 92 4 167")
        player.execute("spawnpoint @p 92 4 167")
        break

player.on_tell_command("level2", tpLevel2) # damit der Spieler nicht sofort ins dritte Level teleportiert wird; das zweite Level wurde nur mit Command Blocks programmiert

# Level 3 ("operation zombie pigmen")
player.execute("kill @e[type=zombie_pigman]") # "alte" Pigmen aufräumen (von Testdurchläufen etc.)
player.execute("gamerule mobGriefing false") # Damit die Pigmen keine Blöcke zerstören


#Setup, spawn der Gegner
for i in range(8):
    player.execute("summon zombie_pigman 16 5 -92")
    player.execute("summon zombie_pigman 15 13 -109")
    player.execute("summon zombie_pigman 20 22 107")
    player.execute("summon zombie_pigman 54 14 -98")
    player.execute("summon zombie_pigman 75 28 -92")
    player.execute("summon zombie_pigman 49 47 -89")
    player.execute("summon zombie_pigman 50 59 -88")
    player.execute("summon zombie_pigman 44 69 -87")


while True:
    player.on_item_interacted(CLOCK, on_clock_interacted)  #Die Geheimtüren und ihre Schlüssel
    player.on_item_interacted(COMPASS, on_compass_interacted) 
    player.on_item_interacted(FLINT_AND_STEEL, on_flint_and_steel_interacted)
    player.on_item_interacted(SHEARS, on_shears_interacted)
    player.on_item_interacted(BOOK, on_book_interacted)
    player.on_travelled(WALK, on_travelled_walk)
    
    mobs.on_mob_killed(PIG_ZOMBIE, addKill) # wenn pigmen getötet 1 von "alive" subtrahieren
    if alive == 0: #Wenn alle tot, das spiel beenden.
        player.execute("title @p title Spiel Abgeschlossen")
        break
        

  • archiv/gf/gf2021_2022/2d2/olivierpaulmateo.txt
  • Zuletzt geändert: 2022/08/27 18:08
  • von lehmannr