Dzisiejsza lekcja będzie nieporównywalnie trudniejsza od poprzednich(przynajmniej w pisaniu : >), więc czytajcie uważnie. ;p Obsługa myszy oraz tekst Korzystanie z myszki oraz wyświetlanie tekstu na przykładzie prostej klasy buttona. : ) Należy stworzyć sobie bitmapkę z kursorem naszej myszki, po czym wczytać do niej obrazek z pliku. W funkcji init() trzeba także dopisać 'install_mouse()' aby poinformować allegro, że będziemy korzystać z myszki. W funkcji draw() trzeba oczywiście wyświetlić nasz kursor w pozycji (mouse_x,mouse_y): draw_sprite(bufor,kursor,mouse_x,mouse_y); I już mamy działającą myszkę. Prawda, że proste? :) Następnie napiszmy sobie klasę przyciskuprzecież ta myszka musi nam się do czegoś przydać. Trzeba się nad nią trochę zastanowić-czego będziemy potrzebowali? Guziczek na pewno musi mieć jakiś napis. Dlatego będziemy potrzebować tablicy charów. Includujemy nagłówek cstring(przyda się później). Niezbędna będzie również pozycja-x i y- oraz wymiary-szerokość oraz wysokość. Aby guziczek został 'wciśnięty' przycisk myszy musi zostać wciśnięty oraz zwolniony nad nim. Więc będziemy musieli znać stan lpm z poprzedniej klatki-także tworzymy sobie flagę mouselpressed. Niezbędna będzie funkcja sprawdzająca, czy kursor myszy znajduje się w danym prostokącie: bool Kolizja(float x1, float y1, float x2, float y2) if((mouse_x >= x1 && mouse_x <= x2)&&(mouse_y >= y1 && mouse_y <= y2)) return true; return false; Funkcja jako argumenty przyjmuje współrzędne lewego górnego oraz prawego dolnego rogu prostokąta, zwraca true jeśli myszka znajduje się w środku tego prostokąta, w przeciwnym wypadku false. Przyda nam się również kilka pomocniczych flag: mouseon(informująca, czy myszka jest nad przyciskiem), touched(informująca, czy przycisk myszy został naciśnięty nad naszym buttonem) oraz clicked(informująca, czy lpm został wciśnięty i zwolniony nad buttonem-czyli czy zostało wykonane pełne kliknięcie). Tak będzie więc wyglądała nasza klasa: class BUTTON public: float x,y; float width,height; bool mouseon; bool touched; bool clicked; char text[255]; BUTTON(float _x, float _y, float w, float h, char txt[255]) x=_x; y=_y; width=w; height=h; strcat(text,txt); mouseon=false; clicked=false; touched=false; ; void Draw(); void Operate();
Teraz uzupełnimy sobie nasze metody. Najpierw Draw(): Tutaj rysujemy nasz guziczek. Jeśli przycisk nie jest ani wciśnięty, ani myszka nie jest nad nim to rysujemy w jego miejscu czarny prostokąt(o odpowiednich wymiarach rzecz jasna). W przeciwnym razie rysujemy szary prostokąt. Jeśli przycisk nie jest wciśnięty wypisujemy wyśrodkowany tekst w pozycji (x,y-5). Jeśli jest, to tekst piszemy w pozycji (x-3,y-8) aby stworzyć złudzenie przestrzenności. :) void BUTTON::Draw() if(!mouseon &&!touched) rectfill(bufor,x-width/2,y-height/2,x+width/2,y+height/2,makecol(0,0,0)); rectfill(bufor,x-width/2,y-height/2,x+width/2,y+height/2,makecol(100,100,100)); if(touched) textprintf_centre_ex(bufor,font,x-3,y-8,makecol(255,255,255),-1,text); textprintf_centre_ex(bufor,font,x,y-5,makecol(255,255,255),-1,text); Wypadałoby w tym miejscu omówić funkcję textprintf_centre_ex: void textprintf_centre_ex(bitmap *bmp, const FONT *f, int x, int y, int color, int bg, const char *fmt,...) Jest to allegrowski odpowiednik funkcji z cstdio-printf. Rysuje on wyśrodkowany tekst o podanym kolorze, tle w podanym miejscu. Jako pierwszy argument pobiera bitmapę docelową, jako drugi czcionkę którą narysowany ma być tekst. Później są współrzędne w których ma zostać narysowany. Dalej kolor oraz kolor tła(-1 oznacza brak tła), a na końcu tablica charów-nasz tekst. Po więcej funkcji rysujących tekst odsyłam do dokumentacji ( dla niepelnosprytnych link: http://www.allegro.cc/manual/api/text-output/ ). Co do metody Operate(): Tutaj jest cała obsługa przycisku-sprawdzanie, czy jest wciśnięty itp. Jeśli myszka jest nad naszym przyciskiem to ustawiamy mouseon na true, w przeciwnym razie na false: if(kolizja(x-width/2,y-height/2,x+width/2,y+height/2)) mouseon=true; mouseon=false; Następnie należy sprawdzić, czy przycisk został zwolniony nad naszym buttonem. Jeśli mouse_b&1==true, to znaczy, że lpm został wciśnięty. mouse_b&2 zaś oznacza ppm. if(touched && mouseon && mouselpressed &&!mouse_b&1)clicked=true; clicked=false; Na polski to będzie mniejwięcej tak: Jeśli przycisk został wciśnięty, myszka jest nad nim i w poprzedniej klatce lpm był wciśnięty, a teraz nie jest(prościej: lpm właśnie został zwolniony) to znaczy, że przycisk został kliknięty. Pod koniec sprawdzamy czy przycisk został wciśnięty: if(mouseon && mouse_b & 1) touched=true; touched=false; Tego tłumaczyć już chyba nie muszę. Tak będzie wyglądała cała nasza metoda: void BUTTON::Operate() if(kolizja(x-width/2,y-height/2,x+width/2,y+height/2)) mouseon=true; mouseon=false; if(touched && mouseon && mouselpressed &&!mouse_b&1)clicked=true; clicked=false;
if(mouseon && mouse_b & 1) touched=true; touched=false; Ok, klasa gotowa. Teraz stwórzmy sobie jakiś obiekt tejże klasy. Tworząc go można posłużyć się naszym konstruktorem. Ja stworzyłem taki guziczek: BUTTON guzik(400,300,200,32,"guziczek xd"); Teraz narysujmy go w funkcji draw(): guzik.draw(); oraz obsłużmy w funkcji logic(): guzik.operate(); dodatkowo po naciśnięciu nasz program ma się wyłączyć: if(guzik.clicked) wyjscie=true; Na końcu funkcji logic() trzeba odpowiednio ustawić naszą flagę mouselpressed: if(mouse_b & 1) mouselpressed=true; mouselpressed=false; Ok. Wszystko już działa. Ale standardowy font allegro jest brzydki. Zmieńmy go sobie-wystarczy do tego tylko jedna instrukcja! W funkcji load dopiszmy font=load_font("font.bmp",null,null); Jako pierwszy argument podajemy nazwę fonta, później paletę(u nas NULL-nie korzystamy z palet) oraz dodatkowe argumenty-u nas NULL. Od teraz tekst rysowany czcionką font będzie zawierał czcionkę z pliku. Aby stworzyć sobie własną czcionkę należy pobrać program Allegro FontEd. Do znalezienia w googlach. Tak wygląda kod naszego dzisiejszego programu i sam program:
#include <allegro.h> #include <cstring> #pragma comment(lib,"alleg.lib") #define WIDTH 800 #define HEIGHT 600 BITMAP *bufor; BITMAP *kursor; bool mouselpressed; bool Kolizja(float x1, float y1, float x2, float y2) if((mouse_x >= x1 && mouse_x <= x2)&&(mouse_y >= y1 && mouse_y <= y2)) return true; return false; class BUTTON public: float x,y; float width,height; bool mouseon; bool touched; bool clicked; char text[255];
BUTTON(float _x, float _y, float w, float h, char txt[255]) x=_x; y=_y; width=w; height=h; strcat(text,txt); mouseon=false; clicked=false; touched=false; ; void Draw(); void Operate(); void BUTTON::Draw() if(!mouseon &&!touched) rectfill(bufor,x-width/2,y-height/2,x+width/2,y+height/2,makecol(0,0,0)); rectfill(bufor,x-width/2,y-height/2,x+width/2,y+height/2,makecol(100,100,100)); if(touched) textprintf_centre_ex(bufor,font,x-3,y-8,makecol(255,255,255),-1,text); textprintf_centre_ex(bufor,font,x,y-5,makecol(255,255,255),-1,text); void BUTTON::Operate() if(kolizja(x-width/2,y-height/2,x+width/2,y+height/2)) mouseon=true; mouseon=false; if(touched && mouseon && mouselpressed &&!mouse_b&1)clicked=true; clicked=false; if(mouseon && mouse_b & 1) touched=true; touched=false; BUTTON guzik(400,300,200,32,"guziczek xd"); bool wyjscie; void init() allegro_init(); install_keyboard(); install_mouse(); set_color_depth(32); set_gfx_mode(gfx_autodetect_windowed, WIDTH, HEIGHT, 0, 0); void load() bufor=create_bitmap(width,height); kursor=load_bitmap("kursor.bmp",null); font=load_font("font.bmp",null,null); void draw()
clear_to_color(bufor,makecol(0,0,255)); guzik.draw(); draw_sprite(bufor,kursor,mouse_x,mouse_y); blit(bufor,screen,0,0,0,0,width,height); void logic() guzik.operate(); if(guzik.clicked) wyjscie=true; if(mouse_b & 1) mouselpressed=true; mouselpressed=false; void release() destroy_bitmap(kursor); destroy_bitmap(bufor); int main() init(); load(); while(!wyjscie) draw(); logic(); release(); return 0; END_OF_MAIN()