||/\|M/\
[seikkailupelieditori]
Seikkailupelieditori yksinkertaisten 2D pelien tekemiseen.

- Lataa Seikkailupelieditori (SPE). Ohjelmalla saat määrättyä huoneisiin esteitä, tavaroita, tehtäviä. start_spe.bat käynnistää ohjelman, start_project.bat:illa voit testata projektiasi. Lähdekoodit mukana. MIT lisenssi.
SPE tutoriaali
* Kuinka tehdään pieni peli (jujeman) *
Huom. Kuvat on spe versiosta 0.2.3. Uudemmassa 0.2.4 Listaa polygonit -> Listaa kaikki, Polygonit ikkuna on Objektit. Muuten tämä tutoriaali on päivitetty uusimpaan spe:hen.Esimerkkipelin kuvat, huoneinfot, skriptit
Jos haluat tutkia samalla skriptejä ym kun luet niin lataa peli tästä ja testaa ja tutki. Myös GIMPin omassa XCF-formaatissa olevat kuvat laitoin ladattavaksi, näet miten olen luonut kuvan piirtämällä eri tasoihin.
Pienen pelin tekeminenTämä ei liity spe:hen mutta kun nyt teen tutoriaalin, teen sen alusta loppuun, suunnittelusta alkaen. Eli ensin pelin suunnittelu, sitten on helpompi alkaa piirtämään kuvia.
esimerkkipelin nimi juje-man
suunnittelu:
kuva 1, ranta.
siin makailee pari juoppoo ja ne pyytää et hakisit korin kaljaa
niille niitten mökilt.
kuva 2, mökki.
tyhjii pulloi ja paljon, oven edessä on joku juoppo agressiivisena
eikä päästä sisään. pulloi tutkimalla löytää viinapullon jämät ja
heittää ne juopon kouraan ni se vetäsee ne ja sammuu. sit ovea
klikkaamalla tyyppi hakee korin bisseä.
sit vie korin rannalle ja juopot pyytää liittymään seuraan ja he
alkaa laulamaan juje biisiä!
the end.
muut kuvat:
* oman ukon asennot
* erilaisia pulloja rannalle ja mökille.
* sit kävelevä juoppo rannalle (vois olla samat kävelyliikkeet ku
omal ukol)
* makaava juoppo rannalle
* agressiivinen juoppo mökille
* agressiiivinen sammmuneena
* kaljakori (joka piirretään ukon päälle kun se kantaa sitä)
Ok, riittävän typerää :)
Käytän ilmaista GIMP kuvankäsittelyohjelmaa sekä apuna piirtopöytää. Koska tiedän mitä pitää piirtää ja näen sen päässäni, saan kuvat aikaiseksi vajaassa viikossa. No ei vaiskaa, jokunen hetki niihin menee. Kannattaa käyttää hyväkeen layereita (tasoja), syvyyskartan tekeminen myöhemmin helpottuu huomattavasti.
SyvyyskartaatJos haluaa esineiden ja ukkojen menevän toisten objektien taakse, pitää luoda syvyyskartat jonka perusteella ohjelma tarkistaa piirretäänkö objekti ruudulle vai ei. Objekttien Y on niiden alareunassa (eli ihmisellä Y on jaloissa) ja sitä verrataan syvyyskartassa oleviin väreihin. Ja jos objektin Y on pienempi kuin syvyyskartassa oleva "Z-arvo" väri niin silloin niiltä kohdin pikseleitä ei piirretä.
Jätän ruudulle vain ne kuvat joiden taakse voi mennä ja muutan tason 1 väriseksi (Taso->Värit->Väritä ja kaikki arvot maksimiin) ja sen jälkeen värjään y-arvolla. Eli sama y josta ne kasvaa, sen värin laitan siniseksi. Miksi? R,G ja B määrää värin joten käytän näitä arvoja määräämään mikä z-arvo risulle tulee. B:llä voi pistää 0-255, sitten G:tä lisätään 1:ksi, jolloin z-arvon saa menemään 256-512 jne. Jos täysin valkoinen, risu on aina edessä, eli kiinni kuvaruudussa eikä sen eteen piirretä mitään. Aivan alhaalla olevat risujen eteen ei pääse joten ne jätän valkoiseksi. Ylin risun Y=115 joten väritetään B 115. Siitä alempi risu Y=150 joten sen B on 150:
Suht oikein väritetty syvyyskartta.
Lopuksi tyhjä alue pitää maalata mustaksi (luoda alempi taso joka on musta). Näin ei alpha-arvot häiritse pelissä (bugi?). Alkup kuva oli siis ranta.jpg ja syvyyskartta ranta.png. Huomaa että syvyyskartta pitää tallentaa esim .png muodossa koska kuvadata ei saa muuttua. JPEG muuttaa väriarvoja pakkauksessa joten se ei käy. PCX, GIF käy jos Y 0-255 riittää. PNG käy vallan hyvin kaikille.
SPE säätämistäKopioi luomasi kuvat spe-hakemiston project/pics/ kansioon. Käynnistä SPE. Ensin pitää luoda uusi huone. Anna sille nimi, sillä nimellä myös huone tallennetaan. Aseta taustakuva ja lataa se sieltä mihin se on kopioitu, samoin syvyyskartta jos semmoinen on.
Klikkailemalla kuvaa saat asetettua polygoneja, hiiren oikea nappi sulkee polyn. "Listaa kaikki" ikkunassa näet kaikki polygonit ja asetetut esineet. Näille POLYILLE voit asettaa toimintoja, olkoon se pelkästään este tai linkitetty johonkin objektiin ym. Esineille ei voi asentaa toimintoa, ne pitää tehdä scriptissä jos haluaa. Aseta toiminto ikkunassa näet toiminnot. Mutta ellei ne riitä (ja eihän ne yleensä riitäkkään) voidaan poly käskeä kutsumaan skriptiä jos polylle tehdään jotain. Ok, luodaan esteet joiden läpi ei siis voida ohjata tyyppiä.
Veteen hukkuu (kutsuu scriptiä) ja puskien alle laitoin estepolyt. Niiden läpi ei voi kulkea. Huoneisiin pitää myös asettaa aloituspaikat (Aseta paikka) johon ukko laitetaan kun huoneeseen siirrytään. Luon 2 paikkaa, alku, josta peli alkaa, ja vasen joka on paikka kun toisesta kuvasta siirrytään tähän ruutuun, vasempaan reunaan.Aseta reitti - voi luoda reitin jota pitkin saa jonkun hahmon liikkumaan. Luon hermostuneen juopon kävelevän edestakas rannalla. Reitin nimeksi juoppo.
Miten pääsee toiseen ruutuun? Luodaan polygoni ja asetetaan sille ruudunvaihto toiminto. Luon sen vasempaan reunaan (huom, paikka (tähtikuvio) ei saa olla vaihtopolyn sisällä (eikä tietenkään estepolyn sisälläkään, muuten ei voi liikkua!). Aseta toiminto -ikkunassa Huone tiedoksi toisen huoneen nimi ja paikka johon tyyppi asetetaan. Eli olen tallentanut/tulen tallentamaan toisen huoneen tiedot mokki nimellä joten mokki oikea (koska tyyppi siirtyy oikeaan reunaan ja luon sinne paikan nimeltä oikea, blaablaa).
Aseta toiminto -ikkunan toiminnot:Huone: jos ukko menee polyn päälle, suoritetaan tämä. Jos siinä on esim "mokki oikea", ladataan mökki, aseta ukko "oikea"-paikkaan. Mutta jos siinä on $ merkillä alkava sana, se on kutsu skriptiin, esim pistän järveen kävelyn järvi-polyyn,( $jarvi ). Silloin pitää luoda ranta.sc (huoneen nimi + sc pääte) niminen scriptitiedosto ja sinne func jarvi(). Niistä myöhemmin.
Selitys: jos objektia/polya katsoo, tulee teksti joka tähän kirjoitettu. Asetan järveen selityksen. Myös $skripti_futsu onnistuu.
Ota käytä: jos käyttää "kättä" eli yrittää ottaa tavaraa, käyttää laitetta jne, tulee tämä teksti. Esim risuihin laitan tekstin ettei se halua niitä. Myös $skripti_futsu onnistuu.
Hävitä polygoni: jos ruksattu, niin kun klikkaa polysta, se häviää, esim jos ensin on ovi kiinni, klikkaa sitä niin se häviää jolloin este häviää. Sen takana voi olla ruudunvaihto poly.
Loput on esineiden ottamiseen ja käyttöön olevat säädöt. Ne voi tehdä tässä (näine rajoituksineen) tai hoitaa scripteistä (jos ylläolevaan laitettiin funktiokutsu $tähän_funktionimi). SPE lataa alussa project/items.lst jossa on kaikki projektiin asetetut tavarat.
Aseta esine napilla saat ladattua kuvan, annettua esineelle nimen ja asetettua sen ruudulle (nyt kaikki esineet menee ruudun etuosaan, syvyyskarttaa ei ole käytössä mutta pelissä ne piirtyy niiden objektien taakse kuin pitääkin). Silloin se löytyy alasvetovalikoista ja poly voidaan liittää esineeseen. Jos esineen päälle piirretään poly, Hävitä polygoni, Siirrä tavaroihin ja Hävitä ruudulta ruksattuna, Esineen tietoihin laitettu se esine, niin silloin kun polya klikkaa, tavara häviää ja siirtyy tavaroihin. Lisään tyhjän muutaman pullon rannalle ja nukkuvat juopot.
Tavaroiden käyttäminen taas onnistuu esim Esineen tiedot laitettu lukittu_ovi, Tarvitsee esineen avain1, Onnistuneen käytön palaute "avain avasi oven, ja hajosi!", Poista tavaroista ruksattu, eli kun avainta käyttää, se avaa oven ja häviää tavaroista. Ok, nämä voi hoitaa myös skriptissä using(item, mihin) funktiolla.
Lataa animatio - voit asettaa animaatiota, annat animaatiolle
nimen ja sen jälkeen merkkaat kaikki siihen kuuluvat tiedostot.
Scriptissä saat animaatiot näkyviin ja kulkemaan reittejä pitkin.
Luon animaatiot UP, DOWN, RIGHT ja LEFT joihin asetan
kävelyasennot. Tiedot tallentuu project/anim.cfg tiedostoon joka on
tekstitiedosto muotoa
ANIMAATION_NIMI
montako_kuvaa
kuva_1.png
kuva_2.png
joten voit muokata sitä tekstieditorissa jos jokin menee
vikaan.
Pistin vielä parit pullot maahan ja yhden pullon ympäröimään polyyn laitoin ota/käytä $viini funktiokutsu, Esineen tiedoiksi laitoin pullon nimen eli viini.
Toiselle huoneelle samat, asetetaan tavarat, katsottavat ja hiplailtavat polyt, esteet, scriptikutsut jne. Ja tallennus. Ja sitten päästään mielenkiintoiseen osioon, scriptaamiseen.
2 pakollista scriptiä, config.cfg ja rooms/start.sc jotka ladataan kun peli käynnistyy. 3. scripti joka ladataan (jos löytyy) on everyroom.sc joka suoritetaan joka huoneessa. Tämä ei ole pakollinen. Mutta jos ottaa sen käyttöön, update() funktio on ainut funktio jonka se vaatii.
config.cfg:ssä annat pelin nimen, ikkunan koon ja hakemistot.
Yksinkertaisimmillaan rooms/start.sc se on seuraavanlainen:
# update funktiota kutsutaan joka framella
func update()
endfunc
# render funktiota kutsutaan kun on aika piirtää
func render()
endfunc
update() ja render() funtiot pitää löytyä joka
scriptistä (paitsi everyroom.sc). Ladataan ensin ukkojen animaatiot
ja asetetaan se liikuteltavaksi.
# lataa ohjattavan ukon asennot
loadAnimation("UP");
loadAnimation("DOWN");
loadAnimation("LEFT");
loadAnimation("RIGHT");
# aseta animaatio (EGO on ohjattava ukko)
# parametrit: mihin_objektiin, ylös, alas, vasen, oikea
setAnimation("EGO", "UP", "DOWN", "LEFT", "RIGHT");
Jos ei hiirikursoreita ladata, ruudulla näkyy hiiren tilalla pieni
nuoli joten ladataan 3 eri kuvaa pointtereille.
# vakiokursorit, joiden toiminnallisuus ohjelmoitu
java-ohjelmaan
loadCursor("cur_walk.png", "WALK");
loadCursor("cur_eye.png", "LOOK");
loadCursor("cur_get.png", "TAKE");
Testipelin huoneet on ranta ja mokki, ladataan ranta ennen update()
funktiota.
loadRoom("ranta", "alku"); # aseta ukko alku-paikkaan
Nyt pystyt liikuttamaan ukkoa 2 kuvan välillä, katsomaan tyyppejä
ym. Kaikki muu toimii paitsi funktiokutsut jotka pitää toteuttaa
scripteihin (huoneennimi + .sc). Käyn pääkohdat läpi.
Rannalle tehtiin reitti jota pitkin laitan hermostuneen juopon
kävelemään.
# käytän samoja liikkeitä kuin ohjattavaan ukkoon (ne on ladattu
UP, DOWN jne animaatioihin)
setAnimation("HERMO_JUOPPO", "UP", "DOWN", "LEFT", "RIGHT");
#aseta reitti
setPath("HERMO_JUOPPO", "juoppo", 1);
"juoppo" on reitin nimi. HERMO_JUOPPO on animaatio jolla on UP,
DOWN ym animaatiot liikkeinä. Viimeisen parametrin selvitys:
* jos
* 0, häviää ruudulta kun reitti menty loppuun
* 1, palaa samaa reittiä takas
* 2, paikka muuttuu samantien reitin alkuun.
* 3, jää reitin loppuun
Päivittäminen ja piirtäminen, update() funktioon
updateAnimation("HERMO_JUOPPO");
ja render() funktioon
drawAnimImage("HERMO_JUOPPO", 0);
jossa viimeinen parametri on arvo joka lisätään y:hyn (hienosäätöä
varten jos tuntuu että ukko kävelee missä sattuu). Huom, nyt kun
huoneessa ladataan scripti, ohjattavaa ukkoa ei päivitetä
automaattisesti joten updateen pitää lisätä myös
updateAnimation("EGO");
ja piirretään se render() funktiossa: drawAnimImage("EGO",
5);
toinen parametri on y:n hienosäätämistä.
getItem("viini"); komennolla saat "viini" polyn osoittaman
objektin siirrettyä omiin tavaroihin ja sitten se häviää
ruudulta.
if using("viini", "raivo", 50)=="1"
message(15, -1, -1, "'Viiniä? No kyllä kelpaa, kiitti
saa*ana!'");
endif
eli jos käytetään viiniä raivo (mokki kuvassa oleva jätkä). Eli
voidaan tarkistaa käytetäänkö jotain tavaraa johonkin
objektiin.
# ( itemname, toInventory, toCursor, removePoly,
removeItem)
setItem("viini", 0, 0, 1, 1);
ylläoleva on sama kuin
getItem("viini");
setItem() funktiolla voit poistaa objekteja ruudulta, voit silti
vaikuttaa tuleeko ne tavaroihin ja häviääkö polykin.
Ja vähän kun sääti noitten kanssa niin sain pelin valmiiksi.
Scriptejä tutkimalla ymmärtää paremmin mitä osaan selittää. SPE
itessään on aika simppeli, scripteillä voi sitten luoda jotain
toimintaa enemmänkin. Tässä tämä.
Vielä funktioiden nimet ja parametrit:
(jujeman/test_project koodissa toimivat):
MessageBox( string ); --näyttää tekstin avautuvassa ikkunassa
freeAll() -- poistaa ladatut animaatiot/kuvat/pointterit
muistitsta
delay( ms ); --odottaa ms ajan
waitMousePressed() -- odota hiiren napinpainallusta
endGame(); -- lopettaa ohjelman
loadRoom( roomName, position ) -- lataa huone ja aseta ukko
position-kohtaan
loadImage( fileName, objname ) -- lataa kuva, objname nimisenä
käytetään
loadCursor( fileName, curname ) -- lataa hiirikursori, curname
nimisenä voi vertailla käyttöä esim using funkkarissa
playMidi( fileName ) -- lataa ja soittaa midin
loadAnimation( animName ) -- lataa animName animaation
removeAnimation( objname ) -- poista animaatio
setAnimation( objectName, up,down,left,right ) -- aseta
animaatiolle suunnat
updateAnimation( objectName ) -- päivittää objektin animaation ja
kohdan ruudulla
drawImage( x, y, objname, yp ) -- piirrä name x,y kohtaan
(hienosäätö +yp)
drawAnimImage( objectName, YP ) -- piirrä objekti, YP lisätään
y:hyn, hienosäätö
setPath( objectName, pathName, walkMode ) -- aseta objektille
reitti
* jos walkMode
* 0, häviää ruudulta
* 1, palaa samaa reittiä takas
* 2, niin reitin alkuun.
* 3, jää viimeiseen vertexin kohtaan
message( font_size, x, y, str, waitMousePressed ) -- kirjoita
str-tekstin ruudulle, odottaako hiiren painallusta
* jos x==-1 keskitä x-suunnassa, jos y==-1 keskitä
y-suunnassa
getItem( objname ) -- siirtää objektin tavaroihin, poistaa sen
ruudulta (kuva ja poly)
setItem( itemname, toInventory, toCursor, removePoly, removeItem )
-- mitä itemname-esineelle halutaan tapahtuvan, parametrit 0 tai 1
(false/true)
setPos( x, y, objname ) -- aseta objekti haluttuun kohtaan
setYP( objectname, yp ) -- aseta objektille hienosäätöön
tarkoitettu yp. Tällä korjataan esim jos ukko menee esineiden
taakse vaikkei pitäisi
using( curName, objectName, etäisyys ) -- palauttaa "1" jos hiirenä
on haluttu kursori (curName) ja objecti on max etäisyyden päässä
ukosta.
Taulukot, indexinä objektin nimi esim action["HEREILLA"]=1;
get: (esim if action["PAH"]==1 )
action[]
inventory[]
positionX[]
positionY[]
roomName[]
set: (esim action["PAH"]=2;
action[]
inventory[]
viimeisin päivitys 22.7