Grafika C++ nyelven
Ezen az oldalon egy nagyon egyszerű C++ nyelvű grafikus könyvtár leírását olvashatod. A könyvtár célja, hogy a programozás tanulásához egy érdekes, ugyanakkor könnyen használható környezetet nyújtson.
Letöltés:
kezdők csomagja Windows + Code::Blocks környezethez, verziófüggetlen
kezdők csomagja Windows + Code::Blocks 20.03 (64bit) környezethez
(utolsó módosítás:
2020.02.07.)
Használat
A kezdőcsomaggal
A kezdőcsomag Code::Blocks környezetben működik. Első nekifutásra mindenkinek ezt ajánljuk, és később, ha másik környezettel, vagy linuxon szeretnél fordítani, nézd meg a többi leírást.Letöltés után csomagold ki egy könyvtárba, ahol a Code::Blocks project fájlra kattintva bejön a környezet, és azonmód futtatható a példaprogram. A csomagban egy Hello World példaprogram, a szükséges fejléc, könyvtár és dll fájlok, és a project fájlt van. A project fordítható debug és release módokban.
Máshol, Windows/MinGW környezetben
- Töltsd le az SDL könyvtárat, és csomagold ki valahova.
- Töltsd le a csomaggal a graphics.hpp libgraphics.a fájlt valahova.
- Állítsd be a környezetedet úgy, hogy a linker könyvtárai között legyen mind az SDL lib könyvtára, mind a libgraphics.a könyvtára.
- Állítsd be, hogy az include könyvtárak között legyen a graphics.hpp könyvtára.
- Állítsd be, hogy a linker használja a graphics és az SDL librarykat (fontos ez a sorrend!).
- Ezek után le kell tudnod fordítani a programjaidat. A jó beállítások ilyen
parancssori kapcsolóknak felelnek meg:
g++ -L SDL-lib-dir -L genv-dir -I genv-dir -lgraphics -lSDL
Egyéb környezetben
- Töltsd le az SDL könyvtárat, és csomagold ki valahova, esetleg telepítsd csomagból (libsdl-dev, libsdl_ttf2.0-dev).
- Töltsd le Linuxos csomagot és csomagold ki valahova.
- Állítsd be a környezetedet úgy, hogy a linker könyvtárai között legyen az SDL lib könyvtára.
- Állítsd be a környezetedet úgy, hogy az include könyvtárak között legyen az SDL include könyvtára és a graphics.hpp könyvtára.
- Állítsd be, hogy a linker használja az SDL libraryt.
- Add hozzá a projectedhez a graphics.cpp fájlt.
- Ezek után le kell tudnod fordítani a programjaidat.
Debug és Release mód
A félév során felmerülhet, hogy a hibakeresést valaki esetleg nyomkövetéssel szeretné megoldani. Ehhez a könyvtárnak egy olyan példányára van szükség, amelyik tartalmazza az azonosítók neveit, ezért viszonylag nagyméretű, és emellett nem optimalizálással lett lefordítva. A kezdőcsomag is tartalmazza a libgraphicsd.a könyvtárat, ahol a "d" a debug-ot jelenti. Ezzel fordítva lehetséges lesz a nyomkövetés. Ugyanakkor a release módú könyvtár tartalmaz optimalizálást, ami gyorsabb működést jelent.
Ha még nem próbáltad a nyomkövetést, Code::Blocks alatt fordíts a bármit Debug módban, és az F7 gomb nyomásával soronként tudsz haladni a program végrehajtásában, akár menet közben a változók értékeinek nyomon követése mellett. Sok platformon sokféle nyomkövető felület van, még nem tudjuk, hogy a félév során lesz-e alkalmunk egyet komolyabban tárgyalni.
Programozói felület
A könyvtár összes eleme a genv névtérben található. Ezt a legegyszerűbben a using namespace genv; direktíva használatával lehet elérni.
A könyvtárnak két fő eleme van, a rajzoló és az eseményfogadó rész. Meg tud jeleníteni egy ablakot a képernyőn, a rajzoló műveletek ebbe az ablakba rajzolnak, és az ebbe az ablakba érkező eseményeket lehet fogadni.
A rajzfelületen egy derékszögű koordinátarendszer segítségével tudunk pontokat megadni. A koordinátarendszer origója az ablak bal felső sarkában van, és lefelé illetve jobba nőnek a koordináták értékei. A felületen kívül eső pontok használhatóak. A koordináták nulláról indulnak, és minden egész értékű koordinátapár a rajtfelület egy-egy pixelének felel meg.
Rajzoló műveletek
A rajzolás a groutput típuson keresztül történik, ennek egyetlen értéke van, aminek gout a neve, ezen keresztül lehet elérni az ablakot. A következő műveleteket lehet rá használni:
gout.open(width, height [, fs]); | Létrehozza az ablakot, width pixel széles és height pixel magas lesz a rajzolásra alkalmas felülete (mindkettő pozitív egész szám lehet). Ha a harmadik paraméter true, és a megadott felbontást a rendszer teljes képernyőn meg tudja jeleníteni, úgy a kijelző teljes képernyős módban indul. Az átváltás bizonyos rendszereken akár több másodpercig is eltarthat. | ||||||
gout.save(filename); | Lementi az ablak tartalmát egy filename nevű Windows BMP típusú fájlként. | ||||||
A rajzfelületen nyilvántartunk egy pontot, a rajzoló műveletek ebből a pontból
indulnak ki, és a rajzolás végén ott hagyják, ahol a rajzolás véget ért. Ez a
pont sosem hagyja el az open műveletnél megadott rajzfelületet.
| |||||||
gout << move(x, y); | Eltolja a rajzpontot vízszintesen x, függőlegesen y pixellel, rajzolás nélkül. Ha a végpont kívül esik a rajzolási felületen, nem mozgatja a pontot. | ||||||
gout << move_to(x, y); | Eltolja a rajzpontot az (x,y) koordinátájú pontba (amennyiben az a rajzolási felületre esik, különben nem csinál semmit). | ||||||
gout << color(r, g, b); | Megváltoztatja a további rajzolások színét. Az új színt vörös (r), zöld (g) és kék (b) komponensekből állítja elő, mindhárom komponens egy 0 és 255 közötti egész szám lehet. | ||||||
gout << refresh; | Frissíti a képet: megjeleníti a legutóbbi frissítés óta történt rajzolások eredményét. Frissítés nélkül a rajzoló műveletek hatása nem jelenik meg! | ||||||
gout << dot; | Az aktuális rajzpont színét megváltoztatja az aktuális rajzolási színre. A rajzpontot nem mozgatja. | ||||||
gout << line(x, y); | Egyenes szakaszt rajzol a rajzpontból kiindulva az aktuális színnel, a végpont vízszintesen x, függőlegesen y pixel távolságra lesz a kiindulási ponttól. A rajzolási pontot a végpontban hagyja. | ||||||
gout << line_to(x, y); | Egyenes szakaszt rajzol a rajzpontból kiindulva az aktuális színnel az (x,y) koordinátájú pontba. A rajzpontot a végpontban hagyja. | ||||||
gout << box(x, y); | A rajzpontból kiindulva x szélességű és y magasságú, vízszintes alapú téglalapot rajzol aktuális színnel kiszínezve. A rajzpontot a kiindulási pontból induló átló túlsó végén hagyja. | ||||||
gout << box_to(x, y); | Az aktuális színnel kiszínezett, vízszintes alapú téglalapot rajzol, amelynek az egyik átlója a rajzpontból indul és az (x,y) pontban ér véget. A rajzpontot az (x,y) pontban hagyja. | ||||||
![]()
| |||||||
gout << text(t); | Kirajzolja a t szöveget a rajzpontból vízszintesen induló alapvonalra. A szövegben található '\n' karaktereket sorvége jelként értelmezi, és a szöveget a kiindulási pont vonalában, de a következő sorban folytatja. A rajzpontot a szöveg végén, az alapvonalon hagyja. A t típusa lehet string és char is. | ||||||
gout.showmouse(bool); | Az egér mutatójának megjelenítését, elrejtését lehet kapcsolni. true értéknél az egérmutatómegjelentik false értéknél az egérmutató az ablakon belül nem látható | ||||||
gout.movemouse(x, y); | Az egér helyének meghatározása. Egéreseményt generál. Időzítőre kötve akkor is befolyásolja az egér pozícióját, ha nem az alkalmazás az aktív ablak, ezért körültekintéssel használandó. |
Rajzvászon műveletek
Lehetőség van olyan felületre is rajzolni, ami nem a képernyő, hanem egy másik rajzvászon típus, a canvas. Ennek tartalmát gyorsan lehet rámásolni a gout-ra, vagy másik canvas-ra.
Technikailag a gout egy a kijelzőhöz kötött canvas leszármazott.
canvas(width, height); canvas c; c.open(width, height); | Konstruktor, egy adott canvas méretét beállítja, width pixel szélesre és height pixel magasra. |
gout << stamp(pattern, x, y); | Másoló művelet, ami a gout-ra rámásolja a pattern-t, aminek canvas & pattern a típusa. Az x, y egész számokkal lehet szabályozni, hogy a képernyőn hová kerüljön a másolat. |
gout << stamp(pattern, sx, sy, mx, my, x, y); | Másoló művelet, ami a gout-ra rámásolja a pattern-t, aminek canvas & pattern a típusa. Az x, y egész számokkal lehet szabályozni, hogy a képernyőn hová kerüljön a másolat. Az előzőhöz képest itt megadhatjuk azt a tartományt, amit ki akarunk másolni, nem az egész pattern kerül a képernyőre.![]() |
canvas C;
C.save(filename); C << move(x,y); C << move_to(x,y); C << color(r, g, b); C << dot; C << line(x, y); C << line_to(x, y); C << box(x, y); C << box_to(x, y); C << text(t); | A rajzvászonra működik minden művelet, ami a gout-ra, kivéve a refresh, aminek nincs hatása. Minden rajzvászonnak saját kurzora és aktuális színe van, tehát a rajzműveleteknek a hatása csak azon a rajzvászonon jelentkezik, amikre meghívjuk. |
c.transparent(bool); | Beállítja az átlátszóságot. Az átlátszó rajzvászon amikor átmásoljuk valahová, a vászon fekete (r=g=b=0) pixelei nem írják felül a célkép vonatkozó pixeleit. Ha true, akkor átlátszó, egyébként nem. Alapértelmezésben a rajzvászon nem átlátszó. |
c.load_font(filename, fontsize, antialias); | Beállítja a fontkészletet. TTF fontokat támogat. A .ttf fájl nevét és elérési útját kell megadni az első paraméterben. A betűméretet a másodikban. A harmadik paraméter nem kötelező, kikapcsolható vele az antialias, ami akkor fontos, ha kétszer ugyanazt a szöveget egymásra más színnel akarod rajzolni, ilyenkor csak antialias nélkül lesz tökéletes a fedés.
Érdemes a kiadott fontokat használni, úgy, hogy a ttf fájl a program könyvtárában legyen, így elég fájlnevet megadni, egyéb esetben elérési úttal együtt kell. Ne felejts el Windows alatt dupla backslash karaktert használni az elérési útban. Beadandókban csak a kiadott fontokat használd, abban a könyvtárban, ahol a project van, és ne töltsd fel a font fájlt. |
c.antialias(bool); | Beállítja az élsimítást TTF font esetében, a font újratöltése nélkül. Ha true, akkor az élsimítás be van kapcsolva, egyébként nem. Alapértelmezésben az élsimítás aktív. Akkor van értelme kikapcsolni, ha pontos fedést szeretnél, például ugyanazt a szöveget más színnel újraírni ugyanott. Élsimítással ez a betűk szélén problémás lehet. Ha átlátszó canvasra írsz szöveget, élsimítással esetleg sötét aurát kaphat a betű világos háttérre stampelve. |
Eseményfogadó műveletek
Az események kezelése úgy történik, hogy van egy eseményfogadó művelet, ami addig várakozik, amíg valamilyen esemény nem történik a programban. Az első esemény bekövetkeztekor rögtön visszaadja az eseményt. Ha több esemény is történik, azokat egyesével adja vissza (ilyenkor tulajdonképpen nem is várakozik, hanem rögtön visszaadja a következő eseményt).
Egy eseményt egy event típusú rekord ír le. A rekord mezői a következők:
keycode | Billentyű lenyomása vagy felengedése esetén ez a mező tárolja a billentyű
kódját. Pozitív érték jelzi a lenyomást, negatív a felengedést. A billentyű
kódja a következő lehet:
|
button | Egérgomb lenyomása vagy felengedése esetén ez a mező tárolja a gomb kódját, lenyomás esetén pozitív, felengedés esetén negatív értékkel. A lehetséges kódok a következők: btn_left, btn_middle, btn_right, btn_wheelup, btn_wheeldown |
pos_x, pos_y | Egérrel kapcsolatos eseményekhez ezek a mezők tárolják az egér aktuális koordinátáit az ablakban. |
time | Időzítési esemény esetén ez a mező tárolja, hogy a program indulása óta hány ezredmásodperc telt el. |
type | Az esemény típusát tárolja, lehet ev_key, ev_mouse és ev_timer |
Az eseményekkel kapcsolatos műveletek a grinput típuson keresztül érhetőek el, ennek a típusnak egyetlen értéke van, a gin. A műveletek a következők:
gin | A gin változó önmagában használható feltételként, ami addig igaz, amíg az ablak nyitva van. Az ablak bezárása után hamis lesz, ami azt jelzi, hogy több esemény nem következhet be a programban. |
gin >> ev; | Az eseményfogadó művelet: várakozik egy eseményre, majd beteszi azt az event típusú ev változóba. Eredményként a gin-t adja vissza. Az ablak bezárása esemény kivételével mindig érvényes eseményt tesz ev-be. |
gin.timer(wait); | Beállítja az időzítőt úgy, hogy minden wait ezredmásodperc elteltével küldjön egy időzítési eseményt. Ha a wait értéke nulla, kikapcsolja az időzítőt. |
Végül egy összefoglaló táblázat arról, hogy milyen események következhetnek be a program futása során, és hogyan állítják be az eseményrekord mezőit:
Billentyű lenyomása | keycode: a billentyű kódja (pozitív szám) type==ev_key A többi mező értéke 0 |
Billentyű felengedése | keycode: a billentyű kódjának negáltja (negatív szám) type==ev_key A többi mező értéke 0 |
Egérgomb lenyomása | button: a gomb kódja (pozitív szám) pos_x, pos_y: a gomb megnyomásának helye type==ev_mouse A többi mező értéke 0 |
Egérgomb felengedése | button: a gomb kódjának negáltja (negatív szám) pos_x, pos_y: a gomb felengedésének helye type==ev_mouse A többi mező értéke 0 |
Egér mozgatása | button = 0 pos_x, pos_y: az egérkurzor új helye type==ev_mouse A többi mező értéke 0 |
Időzítő esemény | time: a program indítása óta eltelt ezredmásodpercek száma type==ev_timer A többi mező értéke 0 |
Változások naplója
- 2020.02.07. 12:55 - SDL2 port, 64bit. Ismert jelenség a billentyűkezelés leegyszerűsödése.
- 2012.03.04. 18:01 - canvas constructor, copy constructor bugfix
- 2012.02.27. 11:05 - move(1,0) bug javítva
- 2011.02.13. 22:20 - font betöltés, kikapcsolható antialias támogatással
- 2009.03.18. 15:10 - memóriafolyás probléma kiküszöbölése, relatív mozgás átalakítása úgy, hogy a line(0,0), box(0,0), move(0,0) nem csinál semmit, és más esetekben a paraméter abszolútértékének megfelelő számú pixelt rajzol. Egér kurzorával kapcsolatos műveletek bevezetése.
- 2009.02.12. 21:10 - event type bevezetése, debug módban fordított lib kiadása
- 2009.02.10. 11:50 - Linux kompatibilitási problémák kezelése
- 2008.02.12. 18:10 - rajzvászon műveletek hozzáadása, gout fullscreen lehetőség, szövegek betűinek átmenetességének megszüntetése.
- 2007.03.21. 22:10 - színes szövegek megjelenítésének javítása
- 2007.02.15. 10:50 - első letölthető változat