Piano erraldoia
Galdera-eragilea
Piano erraldoi bat sortzea erraza eta erabat dibertigarria da Minecraften, batik bat taldean lan eginez eta eraikitze-moduan egiten bada. Baina nola lortu teklen gainean jartzean Alexek soinua jotzea?
Aurrekariak
Itxura batean ematen duena baino askoz gehiagorako gai da Python: blokez bloke eraiki beharrean, nola lortu bat-batean magia egin eta pianoa agerraraztea? Programatuz, bistan denez. Beste behin ere, Minecraften barrenak moldatu behar dira jolasa eguneratu eta gauza berriak egin ditzan.
Adierazgarria da, halaber, Minecraft Pi bertsioak ez duela musikarik, ezta soinu-efekturik ere. Gabezia hori ez da ahulgunea, ikasteko aukera baizik: Minecrafteko musika programatu, eta kito!
Sonic Pi izeneko programak soinua programatzeko balio du, eta, horretarako, sasi-lengoaia propioa du. Bi programak elkarlanean aritzeko doitzen dira konexio bat ezartzean: deia Python programazio-kodean eransten da eta entzuten dagoen programak mandatua betetzen du. Hau da, piano erraldoi bat eraikitzeko kodea idaztean, gehitu egiten dira lotura-ezarpenak ere, eta soinuak eragiten ditu Sonic-ek eskaerak jaso ahala. OSC izena duten agindu multzoek osatzen dute komunikazioa, hain zuzen. Dagokion paketea terminaletik instalatu behar da erabiltzeko.
Eskema
Honako pauso hauek jarraitu behar dira:
- Sonicek musika joko du.
- Minecraft erabiliko da pianoa erakusteko eta sarrerako gailu gisara (Alex gainean jartzen den tekla adierazteko, alegia).
- Pythonekin eraikiko da pianoa eta harekin komunikatuko dira bi programak ere.
Informatikako hainbat kontzeptu lantzen dira zeregin honetan: funtzio propioak osatzea, begiztak erabiltzea eta sare-komunikazioak erabiltzen ikastea, besteak beste.
Softwarea instalatzea
Sonic Pi lehenetsita dator Raspbian sisteman, eta ez dago ezer egin beharrik erabiltzeko. Alabaina, programen arteko komunikaziorako behar den softwarea (OSC) falta da. Instalatzeko, sartu honako hau terminalean, eta gogoratu administratzailearen kontuko pasahitza eskatzean, lehentasunez raspberry
dela:
sudo pip3 install python-osc
Mezuak Sonicen jasotzea
Aurrena, komeni da probatzea ea nola bidaltzen diren notak Sonic programara. Pythoneko IDLE bidez egiten da, Open Sound Control (OSC) komunikazioari esker; izan ere, urrutiko agintea ahalbidetzen du, beste programa batetik zein saretik. Musika sintetizatzaileak sarearen bidez elkarrekin komunikatzeko asmatu zen OSC.
Sonicek mezuak jaso ditzan, uneoro zer iritsi entzuten egoteko agindu behar zaio. Proba egiteko, kargatu programa Menua > Programazioa > Sonic Pi aukera eginda. Ondoren, hautatu Buffer 0 oinean idatzirik duen leihoa, ezabatu edukia eta itsatsi kode hau:
set_sched_ahead_time! 0
live_loop :entzuten do
nota = sync "/jo_hau"
play nota
end
Ohitura gisa arriskutsua denez kode bat martxan jartzea zer egiten duen jakin gabe, hona hemen goikoak egiten duenaren xehetasunak:
set_sched_ahead_time! 0
aginduak adierazten dio Sonici jasotzen dituen mezuen artean geldiunerik ez egiteko. Horrela, mezuak jarraian entzuten dira eta ez da noten artean isilunerik sortzen.live_loop :entzuten do
aginduak abiarazten du live loop izeneko begizta berezia. Izenen bidez bereizten dira, aldi berean martxan dabiltzanak ikusteko; adibidez, agindu honek entzuten izena du.nota = sync "/jo_hau"
aginduak aldagai bat sortzen du Sonicentzat,/jo_hau
agindua kanpotik entzuteko zain egoten baita. Kasu honetan mezuan aldagai bakarra bidali denez, aldagai bakarra esleitzea nahikoa da jasotzeko. Gehiago balitu, beste hainbeste jarri beharko lirateke komaz banandurik edo, bestela, bektore bateko hainbat posiziotan jaso.play nota
aginduak eragiten du nota-aldagaiaren barruko balioari dagokion MIDI formatuko doinua.
Scripta, beraz, lasai exekuta daiteke. Izan ere, dagoen-dagoenean ez du ezer askorako balio, oraindik inork ez baitu mezurik bidali.
Sonicera mezuak bidaltzea
Zabaldu Python 3 programatzeko ingurunea Menua > Programazioa > Python 3 (IDLE) sakatuta. Bertan, eman File > New File eta sortu fitxategi berri bat. Dagoeneko python-osc modulua instalatuta dago sisteman, baina goiburuan adierazi beharra dago erabili egingo dela komunikazioa ezartzean. Erantsi, beraz, honako hau hasieran:
from pythonosc import osc_message_builder
from pythonosc import udp_client
Hurrena, mezua gordetzeko objektu edo edukiontzi bat sortu behar da. OSC urrutiko aginteak UDP (User Datagram Protocol) izeneko sareko komunikazio-metodoa erabiltzen du. Metodo hori erabiltzen dute ordenagailuek, besteak beste, elkarrekin Internet bidez hitz egiteko. Adibidez, Raspberry Pi parea elkarrekin hitz egiten jartzeko erabil daiteke, baina kasu honetan makina berean daude komunikatu beharrekoak.
Sonic eta Python Raspberry Pi gailu berean daudenez, beraz, mezua nora bidali adierazteko erabil daiteke localhost
helbide unibertsala; bestela, helburuko sare-helbidea edo IPa adierazi behar da. Horrela bidaltzean, sistemak badaki bere baitako bi programak (lokalean daudenak) elkarrekin komunikatu nahi dutela. localhost aldagaiaren egiazko balioa 127.0.0.1
da, eta, horrenbestez, aukeran dago bata zein bestea erabiltzea.
Halaber, UDP erabilita bidaltzen diren mezuek portu-zenbakia ere zehaztu behar izaten dute. Sistema osoak helbide bakarra partekatu arren, eskariak dagozkien programei bideratzearren egiten da: hots, aldi berean datu-truke handia egon daiteke sarearen eta sistema eragilearen artean, eta portuek adierazten ditute zein diren programa bakoitza entzuteko zain dauden lekuak. Sonic Pi 4.559. portuan egoten da entzuten eta, hortaz, Python programak hori adierazi behar du mezua zuzen helarazteko:
bidaltzailea = udp_client.SimpleUDPClient('127.0.0.1', 4559)
Beste hau ere aurrekoaren baliokidea da:
bidaltzailea = udp_client.SimpleUDPClient(‘localhost’, 4559)
Aurrera jarraitzeko, gorde eta egikaritu idatzitakoa (CTRL + S eta gero F5). Oraindik ezer ez da gertatu, baina komunikazio-bidea egin da. Saiatu honako hau idazten IDLE agindu-leihoan:
>>> bidaltzailea.send_message('/jo_hau', 60)
Entzun al da soinurik bozgorailutik? Ezarritako balioaren arabera, Do eskalako Do nota (lehena) jo behar du. Dena den, erosoago erabiltzeko beste funtzio bat ere programatu daiteke: itzuli Python ingurunera eta sortu funtzio bat sarrera gisa balio bat bakarrik jasoko duena; jotzeko bidaltzeko nota, alegia.
def jo_nota(nota):
'''Z. osoa sartu eta bidali Sonicera nota jo dezan'''
bidaltzailea.send_message(“/jo_hau”, nota)
sleep(0.5)
Berriz ere gorde eta exekutatzean, funtzioa erabilgarri geratzen da agindu-leihoan. Esate baterako, honela agintzen zaio Do-Re-Mi jotzeko:
>>> jo_nota(60)
>>> jo_nota(61)
>>> jo_nota(62)
Pianoaren teklatua osatzea
Piano erraldoi bat sortzeko lanek luze jo dezakete, eta, azkenerako, jarduna astuna gerta daiteke. Betebeharrak eginkizun txikiagoetan banatuta, ordea, asko errazten dira; gainera, hala nahi bada, ardurak ere bana daitezke. Horretan datza erromatarrek erabiltzen zuten teknika militarra ere, latinezko dīvide et īmpera, alegia. Informatikan, prozesu horrek deskonposizioa izena du. Algoritmo bat da, programazio-ideia bat, txantiloi edo eredu gisa baliatzeko.
Piano baten teklatua egiteko, zazpi tekla zurizko multzoak eta bost tekla beltzezko multzoak errepikatu daitezke. Zortziduna deritzo multzoen segida horri. Multzo bakoitza txandaka sortuz, teklatua aise eraiki daiteke.
Hitzetatik ekintzetara pasatzeko abagunea da orain: sartu Minecraften eta sortu mundu berri bat pianoa ezartzeko!
Hasteko eta behin, Minecraft modulua kargatu behar da, idatzitakoak martxan dagoen munduari eragin diezaion. Pianoa ere Alexen aurrean agertu dadin, jokalariaren uneko kokapena jaso behar da. Honela egin daiteke:
from pythonosc import osc_message_builder
from pythonosc import udp_client
from mcpi.minecraft import Minecraft
from time import sleep
bidaltzailea = udp_client.SimpleUDPClient('127.0.0.1', 4559)
mc = Minecraft.create()
Alex_x, Alex_y, Alex_z = mc.player.getTilePos()
Teklatua diseinatzea
Beti komeni izaten da zirriborro bat marraztea zerbait itsu-itsuan eraikitzen hasi ordez. Minecraften ere blokeekin ez nahaspilatzeko, marraztu zortziduna eta adierazi x eta z ardatzetan: nola programatu daitekeen erabakitzen lagundu dezake.
Orri laukidunek asko errazten dute lana, bideo-jokoko blokeak adierazteko balio baitute.
Soilgunea sortzea
Alexen aldamenean pianoa agerraraztea da helburua. Minecraften pianoa ager daiteke mendi baten erdian erdi lurperatuta, eta ez landa lauan. Hori saihestearren, soilgune bat sor daiteke pianoa jarri aurretik eta, hartara, funtzio bat programatu. Airezko blokedun kuboide batekin ordezkatzen da Alexen aurrean dagoen parajea:
def aitzurtu(x, y, z):
mc.setBlocks(x-30, y-3, z-30, x+30, y+20, z+30, 0)
Idatzitakoa probatzeko, gorde fitxategia, exekutatu eta deitu agindu-lerrotik (IDLE):
>>> aitzurtu(Alex_x, Alex_y, Alex_z)
Pi bertsioan, Minecraften leihoaren ezkerreko goialdean agertzen dira jokalariaren uneko kokapenaren balioak. Orduan, arestiko Alex_x
, Alex_y
, Alex_z
aldagaiak ordeztu behar dira bakoitzaren uneko balioekin. Hori egitean, lauguneak agertu behar du Alexen albo batera.
Tekla beltzak eraikitzea
Funtzio bati eman dakioke lehen tekla beltza sortzeko ardura. Funtsean, funtzio bat zeregin bat egiteko agindu multzoa besterik ez da. Izendatu egiten dira, alde batetik, berriz erabili ahal bada erreferentzia edukitzeko, eta, bestetik, zer egiten duten adierazteko. Kode-zatiak funtziotan biltzeak, halaber, aukera ematen du lana aurrezteaz gain, akatsak eta zuzenketak leku berean erraz egiteko.
Gauzak horrela, funtzio honi tekla_beltza
izena eman zaio. Funtzio baten zereginak betetzeko, litekeena da informazio zehatza aurretik behar izatea. Batzuetan, egiten dutena ere balio gisa itzuli eta emaitza eman dezakete; besteetan, ordea, ez dute ezer itzultzeko beharrik izaten, haien lana ekintzaren bat egitea izan bada, behinik behin. Horrelakoa da tekla_beltza,
18 bloke beltz ezartzeko helburua baitu.
Funtzio berriaren definizioa bukatzeko, erabaki egin behar da teklatua non eraiki eta zein parametro izango dituen. Oraingoak, esate baterako, hiru parametro jasoko ditu, Minecraften kokapena zehazteko beharrezko koordenatuenak, hain zuzen (x
, y
eta z
).
def tekla_beltza(x, y, z):
Funtzioa definitu ostean, bloke beltzak jartzen ditu errenkadan setBlocks funtzioak. Zirriborroan diseinatutakoan oinarriturik, tekla beltzek 2 bloke zabal eta 9 bloke luze dituzte. Aurreneko bloke beltza x
eta z
posizioan ezarriz gero, eskuinean jarri beharrekoa x+1
lekuan joan behar da, eta behekoak z+1
lekuraino doaz. Pianoa lurrean agertu dadin, hau da, Alexen oinetan, altuera y-1
dute bloke guztiek. Koloreari dagokionez, obsidianak dirudi egokiena eta id 49
balio du. Honela idazten da honaino azaldutakoa:
def tekla_beltza(x, y, z):
mc.setBlocks(x, y - 1, z, x + 1, y - 1, z + 8, 49)
Jarraian, probatu kodea IDLE agindu-lerrotik abiarazita, bilatu garbigune bat Minecraften teklatua zuzen agertzeko, eta deitu funtzioari:
>>> tekla_beltza(Alex_x, Alex_y, Alex_z)
Beste behin ere, gogoan izan aurreko balioak Minecraft leihoaren goialdean begiratzea eta agindu-lerroan ordezkatuta sartzea, jokalariaren aldamenean tekla beltz bat sortzeko. Alex mugitu eta lurrera begiratzean, tekla ikusten da.
Tekla zuriak eraikitzea
Itzuli berriz ere zirriborrora eta ohartu tekla zuriek 3 bloke zabal eta 15 bloke luze dituztela. setBlocks funtzioari eskatu behar zaio x
-tik x+2
raino eta z
-tik z+14
rainoko blokeak egiteko.
Funtzio berria egitean, bloke mota gisa baldosa zuria erabil daiteke (id 44, 7
). Aintzat izan 44
balioa bloke motari dagokiola eta 7
balioa egoerari (zuria).
def tekla_zuria(x, y, z):
mc.setBlocks(x, y - 1, z, x + 2, y - 1, z + 14, 44, 7)
Idatzitakoa probatzeko, egikaritu kodea eta sartu honako hau agindu-lerroan:
>>> tekla_zuria(Alex_x, Alex_y, Alex_z)
Begizten sasoia
Teklak elkarren atzetik jartzeko aukera dagoen arren, begiztak erabil daitezke alde zabaleko balioen (x) kalkuluak aurrezteko, eta hala, Pythonek berak bakarrik egin dezake. Beharrak eragiten du ikasi beharra: etorri heinean, bilatu informazioa, ikusi erabilerak eta egin probak.
Autonomia lantzearren, bakarkako jarduna izan ohi da nork bere beharrizanak aztertu eta ikas-helburuak ezartzea. Dena den, salbuespen gisa, adibide pare bat erakutsiko ditugu atal hau hobeto ulertzeko. Badakiela erabaki duenak, ostera, azalpena jauztea besterik ez du.
Sortu dokumentu berri bat File > New File eginda IDLE ingurunean. Zenbaki-zerrenda bat inprimatzen duen kodea da honakoa eta balioak komen bidez banatzen dira:
for i in range(19):
print(i, end = ',')
Eta hau da, ostera, ikusi behar litzatekeena:
>>> 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
Teknika hori erabili ezean, banaka egin behar da, baina 19 aldiz idatzi behar da print agindua emaitza bera lortzeko:
print(0, end = ',')
print(1, end = ',')
print(2, end = ',')
(...)
print(18, end = ',')
Alde ederra dago, ez da hala? Batetik, lana aurrezten da, eta, bestetik, akatsak saihesten dira. Gainera, segidak egiteko aukera gehiago ere ematen ditu begizta aginduak. Ikusi bestela hau:
for i in range(0, 19, 3):
print(i, end = ',')
Hau da horren emaitza:
>>> 0,3,6,9,12,15,18,
Hasiera eta bukaera adierazteaz gain, beste aldagai bat ere eman zaio. Arestiko adibidean ikusi bezala, zenbaki batetik bestera banaka batzeko lehenetsita daude, baina aukera dago adierazteko jauziek zenbatekoak izan behar duten. Kasu honetan, beraz, hirunaka joango da. Aukera gehiago ere ematen ditu agindu mota horrek, baina zeregin honetarako nahikoa denez, aurrera egiteko sasoia da. Dena dela, gogoan izan begiztak oso baliabide erabilgarriak direla programatzeko.
Zortziduna eraikitzea
Zortzidunek zazpi nota zuri eta bost nota beltz dituzte. Zirriborroari erreparatuz gero, 19. zutabean bukatzen da, eta ondoren, nahi bada, zortzidun berria hasten da. Adimen konputazionala garatzean, ikusten da x
-tik hasita x+18
raino jarri behar direla bloke-zutabeak. Hortaz, for
begiztak ardatzeko 0
eta 18
balioen artean jarduten du.
Programazio-ideia gisa, logika atera behar zaio egin nahi dena mekanikoki egin dezan; bestela esanda, patroi bat asmatu behar zaio. Tekla beltzak jarri orduko, zutabe osoa jar dakioke zuriz eta, ondoren, haren gainean beltza sortzeko agindu. Zenbaki-segida bat asmatu behar da teklak bata bestearen atzetik egiteko, eta zentzuzkoena da teklak ordena zehatz batean ezartzea.
Aukera ugari dago teklak ordenatzeko: aukeretako bat da tekla zuri bat jartzea hiru bloke-unitateko. Begiztako i
aldagaiak adierazten du maiztasun hori (3 aldiro). Gainera, funtzio batean biltzen bada, berrerabiltzen laguntzen du, eta, bide batez, aukera ematen du zuzenketa guztiak leku berean egiteko:
def zortziduna_egin(x, y, z):
for i in range(0, 19, 3):
tekla_zuria(Alex_x + i, Alex_y, Alex_z)
Gorde eta egikaritu kode idatzi berria. Segidan, idatzi agindu-lerroan zortziduna_egin(Alex_x, Alex_y, Alex_z)
. Erabiltzaile bakoitzaren Minecraft munduan agertu behar lukete lurrean barreiaturiko tekla zuriek.
Tekla beltzak jartzen dira hurrena, eta zurien sistema bera errepikatu daiteke. Zirriborroan ikusten da x = 2
dela lehen tekla beltzaren lekua. zortziduna_egin
funtzioan beste begizta bat erants daiteke, honela:
def zortziduna_egin(x, y, z):
for i in range(0, 19, 3):
tekla_zuria(Alex_x + i, Alex_y, Alex_z)
for i in range(2, 18, 3):
tekla_beltza(Alex_x + i, Alex_y, Alex_z)
Gorde eta martxan jarri beste behin ere kodea. Egin dei zortziduna_egin
funtzioari.
Ia eginda dago zortziduna. Alabaina, akats bat dago, zortzigarren tekla soberan baitago. Arestian asmatutako logika edo patroiak ez du kasu guztietarako balio. Baina egon lasai, informatikan erabat arrunta baita idazten hasi orduko salbuespen guztietan pentsatu behar izatea, salbuespen-kasuak zehaztea. Erraz konpondu ohi dira: begiztan baldintza bat ezar daiteke x = 8
denean ezer egin gabe hurrengora pasa dadin; alegia, i
aldagaiak 8
balioa jasotzen duenean tekla_beltza
funtzioaren deiari salto egin diezaion. Programazio-lengoaiek berezko esamoldeak dituztenez, moldatu egin behar da aginduaren esaldia: if i is not equal to 8 then
egia denean soilik deitzen zaio tekla_beltza
funtzioari. Idatzi honako hau baldintza hori kodean gehitzeko:
def zortziduna_egin(x, y, z):
for i in range(0, 19, 3):
tekla_zuria(Alex_x + i, Alex_y, Alex_z)
for i in range(2, 18, 3):
if i != 8: # hutsunea utzi 5 tekla beltz egoteko
tekla_beltza(Alex_x + i, Alex_y, Alex_z)
Gorde eta exekutatu kodea, zortziduna_egin
eguneratu denetik zuzen deitzeko.
Orain artekoa biltzea
Eraman Alex mapako beste leku batera, eta frogatu egindakoak balio duen programatutako fitxategian honako hau erantsi eta martxan jarrita: hasteko, aitzurtu landa leun gera dadin; gero, sortu pianoa; eta, azkenik, jarri jokalaria erdian. Hiru agindu hauek aski dira fitxategiaren oinean:
aitzurtu(Alex_x, Alex_y, Alex_z)
zortziduna_egin(Alex_x, Alex_y, Alex_z)
mc.player.setPos(Alex_x + 8, Alex_y + 3, Alex_z + 12)
Eta kito, sortu da sasi-pianoa. Aurrerago egongo da astia hobekuntzak sartzeko.
Pianoa jotzea
Pianoa doitu behar da Alexek teklak zapaltzean musika jotzeko.
Hasteko eta behin, amaiera gabeko begizta bat behar da Alexen azkeneko posizioa etenik gabe jasotzeko. Aurrerantzean programatzen den guztiak begizta honen barruan egon behar du:
while True:
x_berria, y_berria, z_berria = mc.player.getTilePos()
Non dagoen jakinda, oinpeko blokea zein den jakin nahi izaten da. Kontuan izan tekla zuriak zapalagoak direla beltzak baino, eta horrek arazoak dakartzala behekoari galdetzean; izan ere, litekeena da tekla zapaletan airea dagoela esatea eta bestean, aldiz, ez. Ezarri baldintza bat, eta akabo buruhausteak:
beheko_blokea = mc.getBlock(x_berria, y_berria-1, z_berria)
if beheko_blokea != 44 and beheko_blokea != 49:
beheko_blokea = mc.getBlock(x_berria, y_berria, z_berria)
Dagoeneko kalkula daiteke Alexen posizio erlatiboa. Nahita eraman da Alex teklatua ezarri bezain laster erdi-erdira, eta kokapen finko horri une bakoitzean Minecraft munduarekiko duen posizioa kentzen bazaio (x_berria
), zein desplazamendu izan duen kalkulatzen da x ardatzean; hots, teklatuan eskuinera (x
positiboa) edo ezkerrera (x
negatiboa). Eta, bidez batez, Alex zortziduneko zein teklatan dagoen ere kalkula daiteke.
posizio_erltiboa = Alex_x-x_berria # piano gaineko posizioa
Horrez gain, jotzeko noten zerrenda ere osa daiteke. Do notatik hasi eta elkarren segidakoak osatzen dira dagozkien MIDI balioak ordenan ezarrita: 60, 62, 64, 65, 67, 68, 71. Tekla beltzek zurien tarteko notak adierazten dituzte. Zerrenda osatzeko, 0 baliodun nota erantsi behar da erdian (isila); izan ere, bost tekla beltz baino ez ditu pianoak.
tekla_zuriak = [60, 62, 64, 65, 67, 69, 71]
tekla_beltzak = [61, 63, 0, 66, 68, 70]
Alexen posizioaren arabera zein tekla zuri jo jakiteko, zatitu posizio_erlatiboa
3rekin; ahaztu hondarra eta geratu hamartar osoarekin soilik. Matematikan, zoru-funtzioa deitzen zaio horri eta automatikoki egiten du Pythonen agindu batek: //
eragiketak, hain zuzen ere.
if beheko_blokea == 44:
nota = posizio_erlatiboa // -3
jo_nota(tekla_zuriak[nota])
Tekla beltza jo behar den jakiteko, bestalde, Alexen posizio erlatiboari balio bat kendu behar zaio 3rekin zatitu orduko, eta ondoren, berriz ere, beste bat kendu:
if beheko_blokea == 49:
nota = ((posizio_erlatiboa-1) // -3) - 1
jo_nota(tekla_beltzak[nota])
Egin proba eta jolastu piano gainean. Horretarako, exekutatu kodea eta ibili oinez teklen gainetik. Sonic martxan eta entzuten dagoen bitartean, pianoak doinuak jo behar lituzke.
Bertsio berriak: hobekuntzak
Dakizunarekin, bertsio hauek sor ditzakezu pianoa hobetzeko:
- Osatu pianoa tarteak estaltzeko beste zortzidun bat erantsita. Begizta bat ere sor daiteke
zortziduna_egin
funtzioari deitzeko. Balio gehiago erantsi behar zaizkienota_beltzak
etanota_zuriak
zerrendei, tekla berriei dagozkien Sonicek jotzeko doinuen balioak, alegia. - Teklak zapaltzean, aldatu kolorea eta nabarmendu. Baldosa mota ere alda daiteke, baita kolorea argitu ere doinuak dirauen bitartean.