Rysowanie okręgów i kół

Powrót do spisu treści

Wymagane jest zapoznanie się z następującymi podrozdziałami:

P019 - Pierwszy program dla Windows
OL031 - instalacja biblioteki SDL w środowisku Dev-C++
OL032 - inicjalizacja biblioteki SDL
OL033 - powierzchnie graficzne w SDL
OL034 - przygotowanie plików własnej biblioteki graficznej
OL035 - rysowanie po powierzchni graficznej
OL036 - algorytm Bresenhama rysowania odcinka
OL037 - obcinanie grafiki do prostokąta
OL038 - podstawowe algorytmy wypełniania obszarów
OL039 - algorytm Smitha
OL040 - praca w środowisku sterowanym zdarzeniami
OL041 - czcionka bitmapowa
OL042 - czcionka wektorowa
OL043 - przyciski poleceń
OL050 - macierze - podstawowe operacje na macierzach
OL051 - przekształcenia na płaszczyźnie
OL052 - algorytm wypełniania wielokątów

UWAGA!!!

Bieżące opracowanie NIE JEST KURSEM programowania biblioteki SDL. Są to materiały przeznaczone do zajęć na kole informatycznym w I LO w Tarnowie.

Przed pracą z tym rozdziałem utwórz w środowisku Dev-C++ nowy projekt SDL i dołącz do niego pliki SDL_gfx.cpp oraz SDL_gfx.h. Jeśli nie przeczytałeś zalecanych rozdziałów, koniecznie zrób to, a wszystko stanie się jasne. W przeciwnym razie odpuść sobie również ten rozdział. Opis funkcji bibliotecznych znajdziesz w podsumowaniu SDL011.

 

Artykuł nie jest już rozwijany


obrazek

Sposoby rysowania okręgu i elipsy poznaliśmy już w rozdziale OL036. Polegają one na wyznaczeniu n punktów leżących na obwodzie okręgu czy elipsy i połączeniu ich odcinkami linii prostej, przy czym ostatni punkt łączymy z pierwszym (lub generujemy n + 1 punktów), aby otrzymać figurę zamkniętą. Współrzędne kolejnych punktów możemy wyznaczyć przy pomocy funkcji trygonometrycznych:


 
Dla okręgu
obrazek
Dla elipsy
obrazek
n - liczba wierzchołków
i - numer wierzchołka
xi, yi - współrzędne i-tego wierzchołka
xs, ys - współrzędne środka okręgu lub elipsy
r - promień okręgu

rx - promień elipsy na osi OX
ry - promień elipsy na osi OY
obrazek

Program rysowania okręgu i elipsy może wyglądać następująco (utwórz nowy projekt SDL, dołącz do niego pliki SDL_gfx.h i SDL_gfx.cpp - opis w podsumowaniu SDL011 oraz SDL_gui.h i SDL_gui.cpp - opis w podsumowaniu GUI004, a na koniec nie zapomnij o skopiowaniu czcionki vecprop9x12.fnt do katalogu projektowego):

// I Liceum Ogólnokształcące
// w Tarnowie
// Koło informatyczne
//
// P042 - Okręgi i elipsy
//-----------------------

#include <SDL/SDL_gfx.h>
#include <SDL/SDL_gui.h>
#include <cmath>

const int SCRX = 320;      // stałe określające szerokość i wysokość
const int SCRY = 240;      // ekranu w pikselach
const int N    = 100;      // liczba punktów na obrysie okręgu/elipsy

SDL_Surface * screen;
gfxFont     * font = gfxOpenFont("vecprop9x12.fnt");

// Funkcja obsługująca przyciski poleceń
//--------------------------------------

void fnb(gfxGUIObject * sender)
{
  Sint32 xs, ys, rx, ry, x, y;
  
  xs = screen->w >> 1;
  ys = screen->h >> 1;
  
  switch(sender->tag)
  {
    case 0: rx = ry = ys - 16 - font->h; break;
    case 1: rx = xs - 12;
            ry = ys - 16 - font->h; break;
    case 2: exit(0);
  }
  
// rysujemy okrąg lub elipsę
  
  SDL_Rect r;

  r.x = r.y = 0;
  r.w = screen->w;
  r.h = screen->h - 16 - font->h;

  if(SDL_MUSTLOCK(screen)) SDL_LockSurface(screen);

  SDL_FillRect(screen, &r, 0);

  for(int i = 0; i <= N; i++)
  {
    x = xs + rx * cos(6.28318 * i / N);
    y = ys + ry * sin(6.28318 * i / N);
    if(i) gfxLineTo(screen, x, y, 0xffff00);
    else  gfxMoveTo(x, y);
  }

  gfxLine(screen, xs - 5, ys, xs + 5, ys, 0xff0000);
  gfxLine(screen, xs, ys - 5, xs, ys + 5, 0xff0000);

  if(SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen);

  SDL_UpdateRect(screen, r.x, r.y, r.w, r.h);
}

//***********************
// *** Program główny ***
//***********************

int main(int argc, char * argv[])
{

// tablica tekstów opisujących przyciski
  
  char * t[] = {"Okrąg", "Elipsa", "Zakończ"};
  
// tablica 3 wskaźników do przycisków

  gfxButton * b[3];

  if(SDL_Init(SDL_INIT_VIDEO)) exit(-1);

  atexit(SDL_Quit);
  
  if(!(screen = SDL_SetVideoMode(SCRX, SCRY, 32, SDL_HWSURFACE))) exit(-1);

// tworzymy przyciski akcji

  SDL_Rect r;
  
  r.x = r.w = 0; r.h = font->h + 8; r.y = screen->h - r.h - 4;
  
  for(int i = 0; i < 3; i++) r.w += 20 + gfxTextLength(font, t[i]);  

  r.x = (screen->w - r.w - 4) >> 1;

  for(int i = 0; i < 3; i++)
  {
    r.w = 16 + gfxTextLength(font, t[i]);
    b[i] = new gfxButton(i, true, screen, font, &r, t[i], fnb);
    r.x += r.w + 4;
  }

// Obsługujemy zdarzenia

  SDL_Event event;
  bool running = true;  

  while(running)
  {
    while(SDL_WaitEvent(&event))
    {
      bool eventfree;

      for(int i = 0; i < 3; i++)
        if(!(eventfree = b[i]->DoEvents(&event))) break;

      if(eventfree && (event.type == SDL_QUIT))
      {
        running = false;
        break;
      }
    }
  }
  
// zamykamy czcionkę

  gfxCloseFont(font);

// Usuwamy przyciski

  for(int i = 0; i < 3; i++) delete b[i];
  
  return 0;
}    
  
obrazek obrazek

Przyjrzyj się dokładnie rysowanym figurom. Nie są one specjalnie ładne. Spowodowane to jest zaokrągleniami wyliczonych wartości x i y punktów okręgu oraz elipsy. Opiszemy teraz znacznie lepszy algorytm rysowania okręgu oraz elipsy, który nie wymaga stosowania funkcji trygonometrycznych i działa na liczbach całkowitych - algorytm Bresenhama.

Algorytm Bresenhama rysowania okręgu

Okrąg jest figurą symetryczną. Fakt ten możemy wykorzystać do ograniczenia liczby wyznaczanych punktów leżących tylko w 1/8 obwodu:

obrazek

Pozostałe punkty otrzymamy przez prostą symetrię względem osi OX i OY - zakładamy, iż środek okręgu znajduje się w środku układu współrzędnych. Jeśli jest inaczej, to wyznaczone punkty należy poddać translacji o wektor (xs,ys) określający współrzędne środka:

P1 = (x + xs, y + ys),  x, y - współrzędne okręgu o środku w punkcie (0,0)
P2 = (y + xs, x + ys)   xs, ys - współrzędne środka
P3 = (y + xs, -x + ys)
P4 = (x + xs, -y + ys)
P5 = (-x + xs, -y + ys)
P6 = (-y + xs, -x + ys)
P7 = (-y + xs, x + ys)
P8 = (-x + xs, y + ys)

Nasz algorytm będzie wyznaczał kolejne współrzędne x,y, które wg powyższych wzorów przekształcimy w celu otrzymania współrzędnych docelowych punktów P1...P8. Wyjdziemy z podstawowego równania okręgu:

x2 + y2 - r2 = 0
gdzie x,y - współrzędne punktu na obrysie okręgu, a r - promień okręgu.

Rysowanie okręgu rozpoczynamy w punkcie (0,r). Kolejne punkty będziemy wyznaczali poruszając się w kierunku zgodnym z ruchem wskazówek zegara aż do osiągnięcia pozycji, dla której x = y.

obrazek

W rozważanej 1/8 obwodu okręgu z piksela P przechodzimy (zapalamy) do jednego z dwóch pikseli P1 lub P2. Oznaczmy wyrażenie błędu przez:

e = x2 + y2 - r2

Zachodzą następujące zależności:

e < 0 , punkt (x,y) leży wewnątrz okręgu
e = 0 , punkt (x,y) leży dokładnie na obwodzie okręgu
e > 0 , punkt (x,y) leży na zewnątrz okręgu

Dla każdego z punktów P1 i P2 wyznaczamy wyrażenie błędu:

P1 = (x + 1, y)
e1 = e + (x + 1)2 + y2 - r2,   r2 wyliczamy z równania okręgu: r2 = x2 + y2 i wstawiamy do wzoru na e1.
e1 = e + (x + 1)2 + y2 - x2 - y2
e1 = e + x2 + 2x + 1 + y2 - x2 - y2,  upraszczamy wzór i otrzymujemy:

e1 = e + 2x + 1

 

P2 = (x + 1, y - 1)
e2 = e + (x + 1)2 + (y - 1)2 - r2
e2 = e + (x + 1)2 + (y - 1)2 - x2 - y2
e2 = e + x2 + 2x + 1 + y2 - 2y + 1 - x2 - y2
e2 = e + 2x - 2y + 2

e2 = e1 - 2y + 1

Gdy wyznaczymy błędy dla obu punktów, obliczamy odchyłkę e12:

e12 = e1 + e2
e12 = e + 2x + 1 + e + 2x - 2y + 2

e12 = 2e + 4x - 2y + 3

Badając znak odchyłki wybieramy:

e12 < 0 - punkt P1, czyli x → x + 1,  y → y

e12 ≥ 0 - punkt P2, czyli x → x + 1, y → y - 1

Powód takiego postępowania wyjaśnia poniższa tabelka:

e1 e2 e12 = e1 + e2 Następny
piksel
Uwagi
< 0 < 0 < 0 P1 = (x + 1, y) P1 i P2 są wewnątrz okręgu, lecz P1 jest bliżej brzegu
< 0 ≥ 0 ? ? Ta sytuacja nie może wystąpić, gdyż oznaczałoby to, iż bliższy środkowi okręgu punkt P2 jest na zewnątrz lub na obrysie, a dalszy P1 jest wewnątrz okręgu.
≥ 0 < 0 < 0 P1 = (x + 1, y) Punkt P2 jest wewnątrz okręgu, a P1 na zewnątrz lub na obrysie. Jednakże P1 jest bliżej obrysu lub w takiej samej odległości od niego jak punkt P2
≥ 0 ≥ 0 ≥ 0 P2 = (x + 1, y - 1) Oba punkty są albo na zewnątrz okręgu, albo na zewnątrz jest P1, a P2 leży na obrysie. W każdym przypadku P2 jest bliżej obrysu.

Wartość początkową e przyjmujemy równą 0.

Po wyborze punktu P1 za nowe e przyjmujemy e1, a po wyborze P2 wyrażenie błędu e przyjmuje wartość e2.

Po tych rozważaniach możemy podać pełny algorytm Bresenhama rysowania okręgu:

Wejście

xs, ys  -  współrzędne środka okręgu
r  - promień okręgu
color  - kolor obrysu okręgu

Wyjście

Narysowanie na powierzchni graficznej okręgu o środku w punkcie (xs, ys), o promieniu r i w kolorze color

Dane pomocnicze

x, y  -  współrzędne punktów na obwodzie okręgu o środku w początku układu współrzędnych
e  - wyrażenie błędu dla narysowanego punktu P = (x, y.)
e1  - wyrażenie błędu dla punktu P1 = (x + 1, y)
e2  - wyrażenie błędu dla punktu P2 = (x + 1, y - 1)

Lista kroków

K01: x ← 0 ; ustalamy współrzędne punktu startowego
K02: y ← r  
K03: e ← 0 ; wstępne wyrażenie błędu
K04: Dopóki x ≤ y, wykonuj kroki K05...K19  
K05:     Zapal piksel (x + xs, y + ys) w kolorze color ; zapalamy 8 pikseli
K06:     Zapal piksel (y + xs,-x + ys) w kolorze color  
K07:     Zapal piksel (-x + xs,-y + ys) w kolorze color  
K08:     Zapal piksel (-y + xs, x + ys) w kolorze color  
K09:     Zapal piksel (y + xs, x + ys) w kolorze color  
K10:     Zapal piksel (x + xs,-y + ys) w kolorze color  
K11:     Zapal piksel (-y + xs,-x + ys) w kolorze color  
K12     Zapal piksel (-x + xs, y + ys) w kolorze color  
K13:     e1 ← e  + 2x + 1 ; wyliczamy wyrażenie błędu dla P1
K14:     e2 ←  e1 - 2y + 1 ; wyliczamy wyrażenie błędu dla P2
K15:     x ← x + 1 ; współrzędna x jest zawsze zwiększana o 1
K16:     Jeśli e1 + e2 < 0, idź do kroku K19  
K17:     y ← y - 1 ; współrzędną y zmniejszamy tylko wtedy, gdy suma e1 i e2 jest nieujemna
K18:     e ← e2 i kontynuuj następny obieg pętli K04 ; za nowe e przyjmujemy e2 dla P2
K19:     e ← e1 ; za nowe e przyjmujemy e1 dla P1
K20: Zakończ  

Utwórz nowy projekt SDL. Dołącz do niego pliki SDL_gfx.h i SDL_gfx.cpp (ich opis  znajdziesz w podsumowaniu SDL011). Ponieważ będziemy testować utworzone funkcje, dodaj do projektu również pliki interfejsu GUI: SDL_gui.h i SDL_gui.cpp (opis w podsumowaniu GUI004). Nie zapomnij również o przekopiowaniu do katalogu projektowego czcionki wektorowej vecprop9x12.fnt.

Na końcu pliku nagłówkowego SDL_gfx.h dopisz:


void gfxCircle(SDL_Surface * s, Sint32 xs, Sint32 ys, Sint32 r, Uint32 color);

void gfxClipCircle(SDL_Surface * s, Sint32 xs, Sint32 ys, Sint32 r, Uint32 color);

Obie funkcje rysują okręgi. Różnica pomiędzy nimi polega na tym, iż gfxCircle() rysuje bez obcinania, ale bardzo szybko - wykorzystuje wskaźniki. Okrąg w całości musi się mieścić na powierzchni graficznej. Druga funkcja gfxClipCircle() do rysowania pikseli wykorzystuje funkcję gfxClipPlot, która pomija piksele leżące poza prostokątem obcinania. Okrąg nie musi się w całości mieścić na powierzchni graficznej - zostanie obcięty do prostokąta s->clip_rect. Wadą tego rozwiązania jest mniejsza szybkość rysowania okręgu w porównaniu do gfxCircle()  (lecz wciąż operacja jest wystarczająco szybka dla większości zastosowań).

Parametry funkcji gfxCircle() i gfxClipCircle() są następujące:

s  -  wskaźnik struktury SDL_Surface.
xs ys  - współrzędne środka okręgu
r  - promień okręgu
color  - kolor obrysu

Na końcu pliku SDL_gfx.cpp dopisz poniższy kod:

// Rysuje okrąg
// s     - wskaźnik struktury SDL_Surface
// xs,ys - współrzędne środka
// r     - promień okręgu
// color - kolor obrysu
//---------------------------------------

void gfxCircle(SDL_Surface * s, Sint32 xs, Sint32 ys, Sint32 r, Uint32 color)
{
  Sint32 x = 0, y = r, wx, wy;
  Sint32 e = 0, e1, e2;
  Uint32 w = s->w;
  Uint32 * p = (Uint32 *)(s->pixels) + ys * w + xs;

  wx = x * w;
  wy = y * w;
  while(x <= y)
  {
    * (p + x + wy) = color;
    * (p + y - wx) = color;
    * (p - x - wy) = color;
    * (p - y + wx) = color;
    * (p + y + wx) = color;
    * (p + x - wy) = color;
    * (p - y - wx) = color;
    * (p - x + wy) = color;          
    e1 = e  + (x << 1) + 1;
    e2 = e1 - (y << 1) + 1;
    x++; wx += w;
    if(e1 + e2 >= 0)
    {
      e = e2; y--; wy -= w;
    }
    else e = e1;
  } 
}

// Rysuje okrąg z obcinaniem
// s     - wskaźnik struktury SDL_Surface
// xs,ys - współrzędne środka
// r     - promień okręgu
// color - kolor obrysu
//---------------------------------------

void gfxClipCircle(SDL_Surface * s, Sint32 xs, Sint32 ys, Sint32 r, Uint32 color)
{
  Sint32 x = 0, y = r;
  Sint32 e = 0, e1, e2;

  while(x <= y)
  {
    gfxClipPlot(s, x + xs, y + ys, color);
    gfxClipPlot(s, y + xs,-x + ys, color);
    gfxClipPlot(s,-x + xs,-y + ys, color);
    gfxClipPlot(s,-y + xs, x + ys, color);
    gfxClipPlot(s, y + xs, x + ys, color);
    gfxClipPlot(s, x + xs,-y + ys, color);
    gfxClipPlot(s,-y + xs,-x + ys, color);
    gfxClipPlot(s,-x + xs, y + ys, color);          
    e1 = e  + (x << 1) + 1;
    e2 = e1 - (y << 1) + 1;
    x++;
    if(e1 + e2 >= 0)
    {
      e = e2; y--;
    }
    else e = e1;
  }  
}

Algorytm Bresenhama wypełniania okręgu

Operacja wypełniania okręgu algorytmem Bresenhama jest bardzo podobna do rysowania okręgu - znajdujemy początki i końce linii poziomych, które sukcesywnie zamalowują wnętrze okręgu. Oczywiście wykorzystujemy symetrię tej figury:

Wejście

xs, ys  -  współrzędne środka okręgu
r  - promień okręgu
color  - kolor wypełnienia koła

Wyjście

Narysowanie na powierzchni graficznej wypełnionego koła o środku w punkcie (xs, ys), o promieniu r i w kolorze color

Dane pomocnicze

x, y  -  współrzędne punktów na obwodzie okręgu o środku w początku układu współrzędnych
e  - wyrażenie błędu dla narysowanego punktu P = (x, y.)
e1  - wyrażenie błędu dla punktu P1 = (x + 1, y)
e2  - wyrażenie błędu dla punktu P2 = (x + 1, y - 1)

Lista kroków

K01: x ← 0 ; ustalamy współrzędne punktu startowego
K02: y ← r  
K03: e ← 0 ; wstępne wyrażenie błędu
K04: Dopóki x ≤ y, wykonuj kroki K05...K16  
K05:     Rysuj linię od (-y,x) do (y,x) w kolorze color ; linia wewnętrzna górna
K06:     Rysuj linię od (-y,-x) do (y,-x) w kolorze color ; linia wewnętrzna dolna
K07:     e1 ← e + 2x + 1 ; wyliczamy wyrażenie błędu dla P1
K08:     e2 ← e1 - 2y + 1 ; wyliczamy wyrażenie błędu dla P2
K09:     Jeśli e1 + e2 < 0, idź do kroku K14  
K10:     Rysuj linię od (-x,y) do (x,y) w kolorze color ; rysujemy linię zewnętrzną górną
K11:     Rysuj linię od (-x,-y) do (x,-y) w kolorze color ; oraz zewnętrzną dolną
K12:     y ← y - 1 ; współrzędną y zmniejszamy tylko wtedy, gdy suma e1 i e2 jest nieujemna
K13:     e ← e2 i idź do kroku K15 ; za nowe e przyjmujemy e2 dla P2
K14:     e ← e1 ; za nowe e przyjmujemy e1 dla P1
K15:     x ← x + 1 ; x musimy zwiększać na końcu, aby linie zewnętrzne były rysowane prawidłowo
K16: Zakończ  

Na końcu pliku nagłówkowego SDL_gfx.h dopisz:


void gfxFillCircle(SDL_Surface * s, Sint32 xs, Sint32 ys, Sint32 r, Uint32 color);

Parametry funkcji gfxFillCircle() są następujące:

s  -  wskaźnik struktury SDL_Surface.
xs ys  - współrzędne środka koła
r  - promień koła
color  - kolor wypełnienia

Na końcu pliku SDL_gfx.cpp dopisz poniższy kod:

// Rysuje pełne koło
// s     - wskaźnik struktury SDL_Surface
// xs,ys - współrzędne środka
// r     - promień okręgu
// color - kolor wypełnienia
//---------------------------------------

void gfxFillCircle(SDL_Surface * s, Sint32 xs, Sint32 ys, Sint32 r, Uint32 color)
{
  Sint32 x = 0, y = r;
  Sint32 e = 0, e1, e2;

  while(x <= y)
  {
    gfxClipHLine(s,-y + xs, x + ys, color, (y << 1) + 1);
    gfxClipHLine(s,-y + xs, -x + ys, color, (y << 1) + 1);
    e1 = e  + (x << 1) + 1;
    e2 = e1 - (y << 1) + 1;
    if(e1 + e2 >= 0)
    {
      gfxClipHLine(s,-x + xs, y + ys, color, (x << 1) + 1);
      gfxClipHLine(s,-x + xs, -y + ys, color, (x << 1) + 1);
      y--; e = e2;
    }
    else e = e1;
    x++;
  }   
}

Poniższy program testuje nowe funkcje.

// I Liceum Ogólnokształcące
// w Tarnowie
// Koło informatyczne
//
// P043 - Okręgi i koła
//---------------------

#include <SDL/SDL_gfx.h>
#include <SDL/SDL_gui.h>

const int SCRX = 320;      // stałe określające szerokość i wysokość
const int SCRY = 240;      // ekranu w pikselach

SDL_Surface * screen;
gfxFont     * font = gfxOpenFont("vecprop9x12.fnt");

// Funkcja obsługująca przyciski poleceń
//--------------------------------------

void fnb(gfxGUIObject * sender)
{
  Sint32 xs, ys, rx, ry, rr;
  SDL_Rect r;

  r.x = r.y = 0;
  r.w = screen->w;
  r.h = screen->h - 16 - font->h;

  if(SDL_MUSTLOCK(screen)) SDL_LockSurface(screen);

  SDL_FillRect(screen, &r, 0);

  xs = screen->w >> 1;
  ys = (screen->h >> 1) - 8;
  
  rr = ys - 12 - font->h;
  rx = xs - 8;
  ry = ys - 12 - font->h;
  
  switch(sender->tag)
  {
    case 0: gfxCircle(screen, xs, ys, rr, 0xffff00); break;
    case 1: gfxFillCircle(screen, xs, ys, rr, 0x007f00) ;break;
    case 2: if(SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen);
            exit(0);
  }
  gfxLine(screen, xs - 5, ys, xs + 5, ys, 0xff0000);
  gfxLine(screen, xs, ys - 5, xs, ys + 5, 0xff0000);

  if(SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen);

  SDL_UpdateRect(screen, r.x, r.y, r.w, r.h);
}

//***********************
// *** Program główny ***
//***********************

int main(int argc, char * argv[])
{

// tablica tekstów opisujących przyciski
  
  char * t[] = {"Okrąg", "Koło", "Zakończ"};
  
// tablica 3 wskaźników do przycisków

  gfxButton * b[3];

  if(SDL_Init(SDL_INIT_VIDEO)) exit(-1);

  atexit(SDL_Quit);
  
  if(!(screen = SDL_SetVideoMode(SCRX, SCRY, 32, SDL_HWSURFACE))) exit(-1);

// tworzymy przyciski akcji

  SDL_Rect r;
  
  r.x = r.w = 0; r.h = font->h + 8; r.y = screen->h - r.h - 4;
  
  for(int i = 0; i < 3; i++) r.w += 20 + gfxTextLength(font, t[i]);  
  r.x = (screen->w - r.w - 4) >> 1;
  for(int i = 0; i < 3; i++)
  {
    r.w = 16 + gfxTextLength(font, t[i]);
    b[i] = new gfxButton(i, true, screen, font, &r, t[i], fnb);
    r.x += r.w + 4;
  }

// Obsługujemy zdarzenia

  SDL_Event event;
  bool running = true;  

  while(running)
  {
    while(SDL_WaitEvent(&event))
    {
      bool eventfree;

      for(int i = 0; i < 3; i++)
        if(!(eventfree = b[i]->DoEvents(&event))) break;
      if(eventfree && (event.type == SDL_QUIT))
      {
        running = false;
        break;
      }
    }
  }
  
// zamykamy czcionkę

  gfxCloseFont(font);

// Usuwamy przyciski

  for(int i = 0; i < 3; i++) delete b[i];
  
  return 0;
}    
obrazek obrazek

Podsumowanie


   I Liceum Ogólnokształcące   
im. Kazimierza Brodzińskiego
w Tarnowie

©2024 mgr Jerzy Wałaszek

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.

Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl

W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe