- GKO, luennot 6.-8.5.2004
- Bittikartat ja framet
- Delphi-moniste: multimediaa Delphillä -> Jätettiin pääteohjauksiin ja demoihin
- Esimerkkiohjelma: liikkuvat autot ja TAuto-komponentti
- Ks. Delphin Helpistä TPaintBox, TCanvas ja esimerkki
- Canvas kapseloi WinAPIn standardit piirtofunktiot
- TPaintBox suunniteltu erityisesti piirtämistä varten
- Monilla muillakin komponenteilla on Canvas (esim Form)
- HIDAS. Ei vakavaan pelikäyttöön.
- Yksittäisten pikselien käsittelyä nopeampi tapa on käyttää TBitmapin ScanLine -propertyä, joka on matalan tason taulukkoesityksen yksittäisistä riveistä, ks. delpin help
- Järeämpää grafiikan käsittelyä varten kannattaa käyttää DirectX:aa tai OpenGL:aa (menevät kurssin ulkopuolelle...)
- monisäikeisissä sovelluksissa Canvas on syytä lukita piirron ajaksi (lock ja unlock -metodit)
- TImageList: Bittikartojen keskitetty hallinta listarakenteessa
- Sisältää Draw-metodin, joka piirtää määrätyn bittikartan Canvas-olioon
- ImageListia voi käyttää mm. menujen ikonien varastointiin
- Kokeile doublebuffered-propertyä ja autojen dynaamista lisäystä
- doublebuffered: oliot piirretään ensin muistiin ja vasta sitten ruudulle kerralla
- hidasta, mutta vähentää välkkymistä verrattuna siihen, että jokainen olio piirrettäisiin esikseen
- Framet
- Framet == komponenttimalleja, jotka voivat sisältää useita komponentteja
- Framekin on komponentti (ja samalla olio), jolle voi merkitä omia propertyjä ja toimintoja
- Valitettavasti Framen omat propertyt eivät näy object inspectorissa...
- Frameja voidaan periä toisistaan kuten muitakin komponentteja ja lomakkeita
- Uuden framen periminen: File->New->Other->Projektin nimi. Valitse dialogin alaosasta inherit-optio ja frame, josta haluat periä
- Frames-esimerkki
- Framen luonti: File->new frame
- Sijoitellaan frameen komponentit ja tehdään mahdollisia tapahtumakäsittelijöitä
- Framen saa komponettipalettiin painamalla lomakkeen ponnahdusvalikosta Add to Palette
- Framea voi käyttää suunnitteluaikana tai dynaamisesti ajonaikana (kuten muutkin komponentit)
- Autolaskuri Frameilla
- Framet soveltuvat myös esim. tietokantasovelluksen käyttöliittymän toistuviin osiin
- Esim. editoitavat kentät:
- Oletus: jokaisella kentällä on Label-komponentti, jossa on kentän nimi. Lisäksi label osoittaa editoitavaan kenttään (focuscontrol)
- Tehdään yliluokkaframe, joka sisältää pelkän labelin ja hoitaa focuscontrolin asettamisen, kunhan kohdekomponentti asetataan
- Peritään framesta edit-versio, memoversio ja labelversio (readonly-kenttiä varten)
- Frameja voi laajentaa esim. määrittelemällä kentille validointisääntöjä ja ottamalla mukaan tietokannan käsittelyä tai käyttäjän näkemän esityksen muokkausta
- Erittäin käytännöllisiä, vähentävät koodia huomattavasti
- Ongelmia saattaa tulla, jos muokataan (erityisesti perittyä) framea, joka on jo sijoitettu suunnitteluaikana sovellukseen
- Varaudu muokkaamaan DFM-tiedostoa
- Suurissa muutoksissa pidä varmuuskopiot edellisestä tilanteesta
- ...tai hyödynnä versionhallintajärjestelmää (esim. CVS), jos sellainen on käytettävissä
- Frameja voi sijoittaa komponenttien tapaan paketteihin, mutta niiden käyttö suunnitteluaikana sovelluksessa edellyttää myös niiden lisäämistä sovellukseen
- Dynaamisessa käytössä pelkkä pakettiin (tai yleensä DLL-tiedostoon) sijoittaminen riittää
- Seuraus: jos monessa sovelluksessa käytetään samoja frameja, koodin hallinta sovellusten välillä on mietittävä.
- Tällöin frame-koodit kannattaa pitää yhdessä paikassa ja ottaa ne manuaalisesti mukaan tarvittaviin sovelluksiin.
- Korttikomponentit
- so. "miten tehdä windowsin pasianssi" ja muut vastaavat oliopohjaisesti :-)
- Ks. UML-luokkakaavio
- Alkuperäinen koodi vuodelta 1997 (Tanja Partanen ja Niina Riikonen + V. Lappalaisen muutoksia)
- Ei metodien kuormitusta käytössä...
- Korttien kuvat tallennettu resurssitiedostoon, joka on muodostettu RC-tiedoston avulla
- Wanha (jo win16), mutta edelleen toimiva tekniikka staattisen datan liittämiseen sovelluskiin
- RC-tiedoston voi kääntää RES-tiedostoksi Resource Compilerilla
- Esim. brcc32 pelikort.rc
- Komponentteja
- Kortti
- Pakka - tallettaa kortteja
- APakka - animoitu pakka (kortit lentävät pakasta toiseen)
- Liikkuva - kuljettaa komponenttia näytöllä
- raahattava - komponentti joka ottaa hiirellä raahattavaksi toisen komponentin
- Raahausp - pakka, josta voi ottaa kortin raahattavaksi
- SaantoP - pakka, johon voi laittaa vain tietyn ehdon täyttäviä kortteja
- Poyta - komponentti, johon voi laittaa monta pakkaa
- Poytap - pöydälle laitettava pakka
- Yksinkertainen esimerkki: hullun pasianssi
- Pöytä, ajakopakka ja raahauspakka
- lisätään raahauspakkaan kortti, joka pyydetään jakopakalta
- huom. randomize ja pakan sekoittaminen
- Peliä pelattaessa pelaaja laskee painallukset 1,2,3...13,1,2,... Jos jossakin kohti tulee sama numero kuin ollaan laskemassa, peli ei mene läpi.
- ohjauksissa annetun tehtävän korjattu ja kommentoitu versio lisätty korttipeliesimerkkiin
- Esimerkkiohjelma animoiduista pakoista ja VCL/CLX-käännöstä: järjestä
- projektia ladatessa täytyy olla käytettävissä paketit laskuri(vcl tai clx) ja jarj(vcl tai clx)
- $R-direktiivi, joka lataa DFM- (vcl) tai XFM-tiedoston (clx) täytyy merkitä lomaketiedostoihin käsin delphin ulkopuolella ennen latausta, muuten voi tulla ongelmia komponenttien latauksen kanssa
- ohjelma tarkoitettu järjestämisalgoritmien opetteluun
- Esimerkkiohjelma sääntöpakoista: napoleonin hauta
- säännöt: ensimmäisen kortin nro, muutos, lopetusehto, jatkamisehto lopetuksenj jälkeen
- "Räiskintä"peli
- Liikkuva auto -esimerkki edelleenkehitettynä
- Esimerkki komponenttien 'liimailusta' ja luokkahierarkiasta
- "Räiskintä" on tässä yleinimitys peleille, joissa on olioita, animaatioita ja törmäyksiä
- Vaihtoehtoisia toteutustapoja (ks. VL.n komp.txt)
- Itse liikkuvat kontrollit
- kontrollit sisältävät omat timerinsa
- kontrollin liikkumisen jälkeen tehdään törmäystarkistus muille kontrolleille
- ei skaalaudu suurille kontrollimäärille
- Avaruuden ohjaamat kontrollit
- timer vain avaruudessa, jokaisella "kierroksella" kutsutaan jokaisen kontrollin toimintametodia
- tarkastetaan jokaisella kierroksella kaikkien olioiden törmäykset
- Avaruuden ohjaamat komponentit, piirretään avaruuden piirtopinnalle ("Räiskintä"peli käyttää tätä tapaa)
- kuten edellinen, mutta avaruus vastaa piirrosta
- kevyempi ja nopeampi ratkaisu edelliseen verrattuna
- avaruutta ei voi editoida suunnittelun aikana (onko tarpeellista? pelin "kenttiä" varten voidaan tehdä oma editori...)
- Huom. ainakin 3D-koodaajille pitäisi olla tuttua tavaraa, myös muille hyödyllistä ajateltavaa vaikka ei pelejä tekisikään
- komponentit ovat suoraan projektissa (ei installoida, ei voi editoida object inspectorissa)
- huom. ikoni (tallentuu res-tiedostoon)
- pelikomponentit
- SpriteSpace
- sisältää polymorfisen listan spritejä, joka käydään läpi jokaisella timer-kierroksella
- piirto spacen omalle piirtopinnalle
- Sprite
- yliluokka kaikille avaruudessa näkyville olioille
- MovingSprite
- sprite-hierarkiaan sovitettu versio "Likkuva Auto"-kontrollista
- Auto
- liikkuva olio, joka voi hävitä törmäyksessä
- RusinaksiMuuttuvaAuto
- sisältää räjähdysanimaation, joka ajetaan törmäyksessä oman timerin avulla
- auto poistetaan avaruudesta räjähdyksen jälkeen
- TrafficLights
- paikallaan oleva olio
- ei sisällä erityistä reagointia
- Brain
- mahdollistaa mukautetun käyttäytymisen _samaa luokkaa_ oleville olioille
- DriversBrain
- "älykkyys": auto osaa pysähtyä törmätessään punaisiin liikennevaloihin
- kun valo on vihreä, auto jatkaa vanhalla nopeudellaan
- lähtökohta: liikkuva auto-esimerkki laajennettuna
- törmäykset (react-metodi)
- räjähdykset (rusinaksiMuuttuvaAuto)
- liikennevalot (oma spriteluokka)
- reagointi liikennevaloihin (driversBrain)
- 3d:tä Delphillä
- sinform: ohjelma funktion kuvaajien piirtämiseen (apua demoihin...)
- m3d: apuluokka 3d-muunnoksiin ja matriisien käsittelyyn
- piirto3d: pinnnan piirto 3d-rotatoituna
- Kertausta: komponentin tekemisestä
- Usein uusi komponentti syntyy siirtämällä omaan sovellukseen tehtyä 'yleiskäyttöistä' koodia uuteen komponenttiin
- Erityisesti, jos monen ikkunan tapahtumakäsittelijään tulee monta kertaa samaa koodia, on syytä harkita uutta komponenttia...
- Toki voi myös edetä vesiputousmallin mukaan analyysi->suunnittelu->toteutus
- käytännössä omia ohjelmia tehdessä suunnitelmat muuttuvat kuitenkin, kun koodatessa keksii parempia tapoja tehdä jokin asia => iteratiivista kehitystä
- Komponentteja tehtäessä on huomioitava, tehdäänkö VCL- vai CLX (Kylix-yhteensopiva) -komponenttia
- Usein on mahdollista käyttää samaa koodia molempiin (ks. Lappalaisen VCLCXL-komponentit)
- Sovellusta tehtäessä komponenttipaletissa näkyvät vain "oman" komponenttikirjaston komponentit
- Sovelluksessakin voi käyttää CLX-vakiota, mutta delphi ei välttämättä ymmärrä niitä suunnitteluaikana (ks. korttiesimerkki). tämä voi aiheuttaa 'component ??? is not installed-tyylisiä virheilmoituksia, vaikka komponentti oikeasti olisikin järjestelmässä (mutta 'väärän' komponenttikirjaston alla!)
- VCL-tiedostoja ei saa sisällyttää CLX-pakettiin (tai päinvastoin). ei, vaikka delphi tällaista ehdottaisi kääntämisen yhteydessä
- jos VCL/CLX-vakio ei ole ajan tasalla, touch-operaatio (pakotettu muutos) lähdekooditiedostoille ja uudelleenkääntö saattaa auttaa...
- Demoja tehdessä kysyttiin, kuinka omia komponentteja voi editoida "visuaalisesti"
- Vastaus: Delphissä ei voi (Javalla voi tietyin edellytyksin)
- kuitenkin: Framet helpottavat tilannetta jonkin verran käyttöliittymäkomponenttien osalta
- windowsin viestinkäsittelyn perusteita
- ks. delphin help (hae windows messages, overview)
- windowsin kannalta kaikki järjestelmän tapahtumat ovat viestejä
- jokaisella windows-komponentilla on oma viestisilmukka, jonne windows lähettää tiedon tapahtumista
- useampi komponentti voi vastaanottaa saman viestin
- c-kielisissä windows-ohjelmissa viestisilmukka piti kirjoittaa käsin (käytännössä valtava switch/case-hässäkkä)
- viestisilmukka on delhissäkin (wndproc), mutta piilotettu wincontrol-komponenttiin, joten kehittäjän ei tarvitse yleensä siitä välittää
- message-tyyppisillä metodeilla voi "kaapata" suoraan viestinkäsittelijän (delphin tapahtumat ovat peräisin Control-luokassa olevista message-tyypin metodeista)
- huom. yhden sovelluksen sisällä tapahtumankäsittelijä suoritetaan loppuun, ennen muiden tapahtumakäsittelijöiden (esim. komponentin piirto) suoritusta.
- jos tapahtumakäsittelijän suorituksen aikana tulee uusia viestejä, ne menevät windowsin viestisilmukkaan
- viestejä voi lähettää manuaalisesti winapin sendmessage- ja postmessage-metodeilla
- tarkemmin winapi-osuudessa...