9.4. Funkcje w mcpi
O Minecrafcie w wersji na Raspberry Pi myśleć można jak o atrakcyjnej formie wizualizacji tego co można przedstawić w grafice dwu- lub trójwymiarowej. Zobaczmy zatem jakie budowle otrzymamy, wyliczając współrzędne bloków za pomocą funkcji matematycznych. Przy okazji niejako przypomnimy sobie użycie opisywanej już w naszych scenariuszach biblioteki matplotlib, która jest dedykowanym dla Pythona środowiskiem tworzenia wykresów 2D.
9.4.1. Funkcja liniowa
Za pomocą wybranego edytora utwórz pusty plik, umieść w nim podany niżej kod i zapisz
w katalogu mcpi-sim
pod nazwą mcpi-funkcje.py
:
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4import os
5import numpy as np # import biblioteki do obliczeń naukowych
6import matplotlib.pyplot as plt # import biblioteki do tworzenia wykresów
7import mcpi.minecraft as minecraft # import modułu minecraft
8import mcpi.block as block # import modułu block
9
10os.environ["USERNAME"] = "Steve" # wpisz dowolną nazwę użytkownika
11os.environ["COMPUTERNAME"] = "mykomp" # wpisz dowolną nazwę komputera
12
13mc = minecraft.Minecraft.create("192.168.1.10") # połaczenie z mc
14
15
16def plac(x, y, z, roz=10, gracz=False):
17 """
18 Funkcja tworzy podłoże i wypełnia sześcienny obszar od podanej pozycji,
19 opcjonalnie umieszcza gracza w środku.
20 Parametry: x, y, z - współrzędne pozycji początkowej,
21 roz - rozmiar wypełnianej przestrzeni,
22 gracz - czy umieścić gracza w środku
23 Wymaga: globalnych obiektów mc i block.
24 """
25
26 podloga = block.STONE
27 wypelniacz = block.AIR
28
29 # podloga i czyszczenie
30 mc.setBlocks(x, y - 1, z, x + roz, y - 1, z + roz, podloga)
31 mc.setBlocks(x, y, z, x + roz, y + roz, z + roz, wypelniacz)
32 # umieść gracza w środku
33 if gracz:
34 mc.player.setPos(x + roz / 2, y + roz / 2, z + roz / 2)
35
36
37def wykres(x, y, tytul="Wykres funkcji", *extra):
38 """
39 Funkcja wizualizuje wykres funkcji, której argumenty zawiera lista x
40 a wartości lista y i ew. dodatkowe listy w parametrze *extra
41 """
42 if len(extra):
43 plt.plot(x, y, extra[0], extra[1]) # dwa wykresy na raz
44 else:
45 plt.plot(x, y)
46 plt.title(tytul)
47 # plt.xlabel(podpis)
48 plt.grid(True)
49 plt.show()
50
51
52def fun1(blok=block.IRON_BLOCK):
53 """
54 Funkcja f(x) = a*x + b
55 """
56 a = int(raw_input('Podaj współczynnik a: '))
57 b = int(raw_input('Podaj współczynnik b: '))
58 x = range(-10, 11) # lista argumentów x = <-10;10> z krokiem 1
59 y = [a * i + b for i in x] # wyrażenie listowe
60 print x, "\n", y
61 wykres(x, y, "f(x) = a*x + b")
62 for i in range(len(x)):
63 mc.setBlock(x[i], 1, y[i], blok)
64
65
66def main():
67 mc.postToChat("Funkcje w Minecrafcie") # wysłanie komunikatu do mc
68 plac(-80, 0, -80, 160)
69 mc.player.setPos(22, 10, 10)
70 fun1()
71 return 0
72
73
74if __name__ == '__main__':
75 main()
Większość kodu powinna być już zrozumiała, czyli importy bibliotek, nawiązywania połączenia
z serwerem MC Pi, czy funkcja plac()
tworząca przestrzeń do testów.
Podobnie funkcja wykres()
, która pokazuje nam graficzną reprezentację funkcji
za pomocą biblioteki matblotlib. Na uwagę zasługuje w niej tylko parametr *extra
,
który pozwala przekazać argumenty i wartości dodatkowej funkcji.
Funkcja fun1()
pobiera od użytkownika dwa współczynniki i odwzorowuje argumenty
z dziedziny <-10;10> na wartości wg liniowego równania: f(x) = a * x + b
.
Przeciwdziedzinę można byłoby uzyskać „na piechotę” za pomocą kodu:
y = []
for i in x:
y.append(a * i + b)
– ale efektywniejsze jest wyrażenie listowe: y = [a * i + b for i in x]
.
Po zobrazowaniu wykresu za pomocą funkcji funkcji wykres()
i biblioteki matplotlib
„budujemy” ją w MC Pi w pętli odczytującej wyliczone pary argumentów i wartości funkcji,
stanowiących współrzędne kolejnych bloków umieszczanych poziomo.
Uruchom i przetestuj omówiony kod podając współczynniki np. 4 i 6.
9.4.2. Układ współrzędnych
Spróbujmy pokazać w Mc Pi układ współrzędnych oraz ułatwić „budowanie” wykresów
za pomocą osobnej funkcji. Po funkcji wykres()
umieszczamy w pliku mcpi-funkcje.py
nowy kod:
52def uklad(blok=block.OBSIDIAN):
53 """
54 Funkcja rysuje układ współrzędnych
55 """
56 for i in range(-80, 81, 2):
57 mc.setBlock(i, -1, 0, blok)
58 mc.setBlock(0, -1, i, blok)
59 mc.setBlock(0, i, 0, blok)
60
61
62def rysuj(x, y, z, blok=block.IRON_BLOCK):
63 """
64 Funkcja wizualizuje wykres funkcji, umieszczając bloki w pionie/poziomie
65 w punktach wyznaczonych przez pary elementów list x, y lub x, z
66 """
67 czylista = True if len(y) > 1 else False
68 for i in range(len(x)):
69 if czylista:
70 print(x[i], y[i])
71 mc.setBlock(x[i], y[i], z[0], blok)
72 else:
73 print(x[i], z[i])
74 mc.setBlock(x[i], y[0], z[i], blok)
– a pętlę tworzącą wykres w funkcji fun1()
zastępujemy wywołaniem:
rysuj(x, y, [1], blok)
Funkcja rysuj()
potrafi zbudować bloki zarówno w poziomie, jak i w pionie w zależności
od tego, czy lista wartości funkcji przekazana zostanie jako parametr y czy też z.
Do rozpoznania tego wykorzystujemy zmienną sterującą ustawianą w instrukcji: czylista = True if len(y) > 1 else False
.
Zawartość funkcji main()
zmieniamy na:
90def main():
91 mc.postToChat("Funkcje w Minecrafcie") # wysłanie komunikatu do mc
92 plac(-80, -40, -80, 160)
93 mc.player.setPos(-4, 10, 20)
94 uklad()
95 fun1()
96 return 0
Po uruchomieniu zmienionego kodu powinniśmy zobaczyć wykres naszej funkcji w pionie.

Kod „budujący” wykresy funkcji możemy urozmaicić wykorzystując poznaną wcześniej
bibliotekę minecraftstuff. Poniżej funkcji rysuj()
dodajemy:
77def rysuj_linie(x, y, z, blok=block.IRON_BLOCK):
78 """
79 Funkcja wizualizuje wykres funkcji, umieszczając bloki w pionie/poziomie
80 w punktach wyznaczonych przez pary elementów list x, y lub x, z
81 przy użyciu metody drawLine()
82 """
83 import local.minecraftstuff as mcstuff
84 mcfig = mcstuff.MinecraftDrawing(mc)
85 czylista = True if len(y) > 1 else False
86 for i in range(len(x) - 1):
87 x1 = int(x[i])
88 x2 = int(x[i + 1])
89 if czylista:
90 y1 = int(y[i])
91 y2 = int(y[i + 1])
92 print (x1, y1, z[0], x2, y2, z[0])
93 mcfig.drawLine(x1, y1, z[0], x2, y2, z[0], blok)
94 else:
95 z1 = int(z[i])
96 z2 = int(z[i + 1])
97 print (x1, y[0], z1, x2, y[0], z2)
98 mcfig.drawLine(x1, y[0], z1, x2, y[0], z2, blok)
– a wywołanie rysuj()
w funkcji fun1()
zmieniamy na rysuj_linie()
.
Sprawdź rezultat.
9.4.3. Kolejne funkcje
W pliku mcpi-funkcje.py
tuż nad funkcją główną main()
umieszczamy kod
wyliczający dziedziny i przeciwdziedziny dwóch kolejnych funkcji:
114def fun2(blok=block.REDSTONE_ORE):
115 """
116 Wykres funkcji f(x), gdzie x = <-1;2> z krokiem 0.15, przy czym
117 f(x) = x/(x+2) dla x >= 1
118 f(x) = x*x/3 dla x < 1 i x > 0
119 f(x) = x/(-3) dla x <= 0
120 """
121 x = np.arange(-1, 2.15, 0.15) # lista argumentów x
122 y = [] # lista wartości f(x)
123
124 for i in x:
125 if i <= 0:
126 y.append(i / -3)
127 elif i < 1:
128 y.append(i ** 2 / 3)
129 else:
130 y.append(i / (i + 2))
131 wykres(x, y, "Funkcja mieszana")
132 x = [round(i * 20, 2) for i in x]
133 y = [round(i * 20, 2) for i in y]
134 print x, "\n", y
135 rysuj(x, y, [1], blok)
136
137
138def fun3(blok=block.LAPIS_LAZULI_BLOCK):
139 """
140 Funkcja f(x) = log2(x)
141 """
142 x = np.arange(0.1, 41, 1) # lista argumentów x
143 y = [np.log2(i) for i in x]
144 y = [round(i, 2) * 2 for i in y]
145 print x, "\n", y
146 wykres(x, y, "Funkcja logarytmiczna")
147 rysuj(x, y, [1], blok)
148
149
150def main():
151 mc.postToChat("Funkcje w Minecrafcie") # wysłanie komunikatu do mc
152 plac(-80, -20, -80, 160)
153 mc.player.setPos(-8, 10, 26)
154 uklad(block.DIAMOND_BLOCK)
155 fun1()
156 fun2()
157 fun3()
158 return 0
W funkcji fun2()
wartości dziedziny uzyskujemy dzięki metodzie arange(start, stop, step)
z biblioteki numpy. Potrafi ona generować listę wartości zmiennopozycyjnych w podanym zakresie <start;stop) z określonym krokiem step.
Przeciwdziedzinę wyliczamy w pętli w zależności od przedziałów, w których znajdują się argumenty,
za pomocą złożonej instrukcji warunkowej. Następnie wartości zarówno dziedziny, jak i przeciwdziedziny
przeskalowujemy w wyrażeniach listowych, mnożąc przez stały współczynnik,
aby wykres w MC Pi był większy i wyraźniejszy. Przy okazji współrzędne zaokrąglamy
do dwóch miejsc po przecinku, np.: x = [round(i * 20, 2) for i in x]
.
W funkcji fun3()
w podobny jak powyżej sposób obliczamy argumenty i wartości funkcji logarytmicznej.
Na koniec zmieniamy też nieco wywołania w funkcji głównej. Przetestuj podany kod.

9.4.4. Funkcja kwadratowa
Przygotujemy wykres funkcji kwadratowej. Przed funkcją główną umieszczamy następujący kod:
150def fkw(x, a=0.3, b=0.1, c=0):
151 return a * x**2 + b * x + c
152
153
154def fkwadratowa():
155 """
156 Funkcja przygotowuje dziedzinę funkcji kwadratowej
157 oraz dwie przeciwdziedziny, druga z odwróconym znakiem. Następnie
158 buduje ich wykresy w poziomie i w pionie.
159 """
160 while True:
161 lewy = float(raw_input("Podaj lewy kraniec przedziału: "))
162 prawy = float(raw_input("Podaj prawy kraniec przedziału: "))
163 if lewy * prawy < 1 and lewy <= prawy:
164 break
165 print lewy, prawy
166
167 # x = np.arange(lewy, prawy, 0.2)
168 x = np.linspace(lewy, prawy, 60, True)
169 x = [round(i, 2) for i in x]
170 y1 = [fkw(i) for i in x]
171 y1 = [round(i, 2) for i in y1]
172 y2 = [-fkw(i) for i in x]
173 y2 = [round(i, 2) for i in y2]
174 print x, "\n", y1, "\n", y2
175 wykres(x, y1, "Funkcja kwadratowa", x, y2)
176 rysuj_linie(x, [1], y1, block.GRASS)
177 rysuj(x, [1], y2, block.SAND)
178 rysuj(x, y1, [1], block.WOOL)
179 rysuj_linie(x, y2, [1], block.IRON_BLOCK)
180
181
182def main():
183 mc.postToChat("Funkcje w Minecrafcie") # wysłanie komunikatu do mc
184 plac(-80, -20, -80, 160)
185 mc.player.setPos(-15, 10, -15)
186 uklad(block.OBSIDIAN)
187 fkwadratowa()
188 return 0
Na początku w funkcji fkwadratowa()
pobieramy od użytkownika przedział, w którym
budować będziemy funkcję. Wymuszamy przy tym w pętli while
, aby lewa i prawa granica
miały inne znaki. Dalej używamy funkcji linspace(start, stop, num, endpoint)
, która generuje
listę num wartości od punktu początkowego do końcowego, który uwzględniany jest, jeżeli argument
endpoint ma wartość True. Kolejne wyrażenia listowe wyliczają przeciwdziedziny
i zaokrąglają wartości do 2 miejsc po przecinku.
Sama funkcja kwadratowa a*x^2 + b*x + c
zdefiniowana jest w funkcji fkw()
, do której
przekazujemy kolejne argumenty dziedziny i opcjonalnie współczynniki.
Instrukcje rysuj()
i rysuj_linie()
dzięki przekazywaniu przeciwdziedziny jako
2. lub 3. argumentu budują wykresy w poziomie lub w pionie za pomocą pojedynczych
lub połączonych bloków.
Po przygotowaniu w funkcji głównej miejsca, ustawieniu gracza, narysowaniu układu i podaniu przedziału <-20, 20> otrzymamy konstrukcję podobną do poniższej.

Po zmianie funkcji na x**2 / 3 można otrzymać:

Zwróciłeś uwagę na to, że jeden z wykresów opada?
9.4.5. Funkcje trygonometryczne
Na koniec zobrazujemy funkcje trygonometryczne. Przed funkcją główną dopisujemy kod:
182def trygon():
183 x1 = np.arange(-50.0, 50.0, 1)
184 y1 = 5 * np.sin(0.1 * np.pi * x1)
185 y1 = [round(i, 2) for i in y1]
186 print x1, "\n", y1
187
188 x2 = range(0, 361, 10) # lista argumentów x
189 y2 = [None if i == 90 or i == 270 else np.tan(i * np.pi / 180) for i in x2]
190 x2 = [i // 10 for i in x2]
191 y2 = [round(i * 3, 2) if i is not None else None for i in y2]
192 print x2, "\n", y2
193 wykres(x1, y1, "Funkcje sinus i tangens", x2, y2)
194
195 del x2[9] # usuń 10 element listy
196 del y2[9] # usuń 10 element listy
197 del x2[x2.index(27)] # usuń element o wartości 27
198 del y2[y2.index(None)] # usuń element None
199 print x2, "\n", y2
200 rysuj(x1, [1], y1, block.GOLD_BLOCK)
201 rysuj(x2, y2, [1], block.OBSIDIAN)
202
203
204def main():
205 mc.postToChat("Funkcje w Minecrafcie") # wysłanie komunikatu do mc
206 plac(-80, -20, -80, 160)
207 mc.player.setPos(17, 17, 24)
208 uklad(block.DIAMOND_BLOCK)
209 trygon()
210 return 0
W funkcji trygon()
na początku wyliczamy dziedzinę i przeciwdziedzinę funkcji
5 * sin(0.1 * Pi * x), przy czym wartości y zaokrąglamy.
Dalej generujemy argumenty x dla funkcji tangens w przedziale od 0 do 360 co 10 stopni.
Obliczając wartości y za pomocą wyrażenia listowego
y2 = [None if i == 90 or i == 270 else np.tan(i * np.pi / 180) for i in x2]
dla argumentów 90 i 270 wstawiamy None (czyli nic), ponieważ dla tych argumentów
funkcja nie przyjmuje wartości. Dzięki temu uzyskamy poprawny wykres w matplotlib.
Aby wykresy obydwu funkcji nałożyły się na siebie, używając wyrażenia listowego,
skalujemy argumenty i wartości funkcji tangens. Pierwsze dzielimy przez 10, drugie
mnożymy przez 3 (i przy okazji zaokrąglamy). Konstrukcja if i is not None else None
zapobiega wykonywaniu operacji dla wartości None
, co generowałoby błędy.
Przygotowanie danych do zwizualizowania w Minecrafcie wymaga usunięcia 2 argumentów
z listy x2 oraz odpowiadających im wartości None
z listy y2, ponieważ nie tworzą
one poprawnych współrzędnych. Pierwszą parę usuwamy podając wprost odpowiedni indeks
w instrukcjach del x2[9]
i del y2[9]
. Indeksy elementów drugiej pary najpierw
wyszukujemy x2.index(27)
i y2.index(None)
, a później przekazujemy do
instrukcji usuwającej del()
.
Po wywołaniu z ustawieniami w funkcji głównej takimi jak w powyższym kodzie powinniśmy zobaczyć obraz podobny do poniższego.

Ćwiczenia
Warto poeksperymentować z wzorami funkcji, ich współczynnikami, wartościami przedziałów i ilością argumentów, aby zbadać jak te zmiany wpływają na ich reprezentację graficzną.
Można też rysować mieszać metody rysujące wykresy (rysuj()
, rysuj_linie()
),
kolejność przekazywania im parametrów, rodzaje bloków itp.
Spróbuj np. budować wykresy z piasku (block.STONE
) ponad powierzchnią.
Źródła:
Materiały Python 101
udostępniane przez
Centrum Edukacji Obywatelskiej na licencji
Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowa.
- Utworzony:
2025-04-12 o 10:21 w Sphinx 7.3.7
- Autorzy: