Efecto linterna (sdl)

Solicite, consulte o publique recursos de referencia para desarrolladores.

Efecto linterna (sdl)

Notapor endaramiz » Dom Feb 15, 2009 5:18 pm

En este ejemplo, se intenta conseguir un efecto linterna. Para conseguirlo, simplemente se utiliza una matriz del tipo bool que actúa de máscara de bits. En esta matriz, se ponen a true ciertos valores dibujando una circunferencia dada la posición en la que se encuentra el ratón en cada frame. A la hora de imprimir la imagen de fondo, se comprueba píxel por píxel si está activada su misma posición en la matriz. En caso afirmativo, se copia el píxel a la pantalla. En caso contrario, se pone el píxel de la pantalla a negro.
Código: Seleccionar todo
#include <iostream>
#include <SDL/SDL.h>
using namespace std;

#define S_W 800
#define S_H 600


void draw_circle(bool m[S_H][S_W], int x, int y, int r) {
    int i = r;
    int j = 0;
    int d = 3 - 2*r;
    while (j <= i) {
        for (int ii = 0; ii <= i and y+ii < S_H and x+j < S_W; ++ii)
            m[y+ii][x+j] = true;
        for (int ii = 0; ii <= i and y+ii < S_H and x-j >= 0; ++ii)
            m[y+ii][x-j] = true;
        for (int ii = 0; ii <= i and y-ii >= 0 and x+j < S_W; ++ii)
            m[y-ii][x+j] = true;
        for (int ii = 0; ii <= i and y-ii >= 0 and x-j >= 0; ++ii)
            m[y-ii][x-j] = true;

        for (int jj = 0; jj <= j and y+jj < S_H and x+i < S_W; ++jj)
            m[y+jj][x+i] = true;
        for (int jj = 0; jj <= j and y+jj < S_H and x-i >= 0; ++jj)
            m[y+jj][x-i] = true;
        for (int jj = 0; jj <= j and y-jj >= 0 and x+i < S_W; ++jj)
            m[y-jj][x+i] = true;
        for (int jj = 0; jj <= j and y-jj >= 0 and x-i >= 0; ++jj)
            m[y-jj][x-i] = true;
        ++j;
        if (d < 0) d = d + 4*j + 6;
        else {
            d = d + 4*(j - i) + 10;
            --i;
        }
    }
}

void blit_bitmask(SDL_Surface *dest, SDL_Surface *sour, bool m[S_H][S_W]) {
    Uint32 bpp = dest->format->BytesPerPixel;
    Uint32 black = SDL_MapRGB(dest->format, 0, 0, 0);
    Uint8 *pdest = (Uint8 *) dest->pixels;
    Uint8 *psour = (Uint8 *) sour->pixels;
    for (int i = 0; i < S_H; ++i) {
        for (int j = 0; j < S_W; ++j) {
             if (m[i][j]) memcpy(pdest, psour, bpp);
             else memcpy(pdest, &black, bpp);
             pdest += bpp;
             psour += bpp;
        }
    }
}

int main(int argc, char** argv) {
    cerr << SDL_Init(SDL_INIT_VIDEO);
    SDL_Surface *screen = SDL_SetVideoMode(S_W, S_H, 16, SDL_HWSURFACE);
    SDL_ShowCursor(SDL_DISABLE);

    SDL_Surface *tile = SDL_DisplayFormat(SDL_LoadBMP("tile.bmp"));
    SDL_Surface *image = SDL_DisplayFormat(SDL_CreateRGBSurface(SDL_HWSURFACE, S_W, S_H, 16, 0, 0, 0, 0));
    for (int i = 0; i <= image->h/tile->h; ++i) {
        for (int j = 0; j <= image->w/tile->w; ++j) {
            SDL_Rect dest;
            dest.x = j*tile->w;
            dest.y = i*tile->h;
            SDL_BlitSurface(tile, NULL, image, &dest);
        }
    }

    SDL_Event event;
    bool salir = false;
    while(not salir) {
        bool bitmask[S_H][S_W];
        memset(bitmask, 0, S_H*S_W*sizeof(bool));

        int x, y;
        SDL_GetMouseState(&x, &y);
        draw_circle(bitmask, x, y, 49);
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
                case SDL_KEYDOWN:
                    salir = true;
                break;
                case SDL_QUIT:
                    salir = true;
                break;
            }
        }
        int t0 = SDL_GetTicks();
        blit_bitmask(screen, image, bitmask);
        int t1 = SDL_GetTicks();
        cerr << "\rt. blit: " << t1-t0 << "  ";
        SDL_Flip(screen);
        SDL_Delay(2);
    }
    cerr << endl;
    SDL_Quit();
}


Es probable que haya errores ya que recién comienzo con el tema de SDL y blit a bajo nivel. Si veis algo raro, no dudeis en avisar.

Saludos.
Avatar de Usuario
endaramiz
 
Mensajes: 283
Registrado: Vie Ago 31, 2007 9:25 am
Ubicación: Barcelona

Notapor Geo » Mar Feb 17, 2009 12:53 am

Estaría bien que incluyeras el archivo tile.bmp para el ejemplo :P.
La imaginación es el límite.
Visita mi blog en inglés o en español.
Geo
 
Mensajes: 244
Registrado: Jue Ago 10, 2006 3:51 am
Ubicación: México

Notapor endaramiz » Mar Feb 17, 2009 9:56 pm

Geo escribió:Estaría bien que incluyeras el archivo tile.bmp para el ejemplo :P.

Tienes razón, pero la verdad es que eso me resulta bastante complicado ya que tendría que buscar algún servidor donde alojarlo.
Para facilitar la tarea al lector, creé el código de manera genérica para que pudiera funcionar con cualquier tamaño. Suponiendo que todos tenemos algún bmp a mano.
Código: Seleccionar todo
    SDL_Surface *tile = SDL_DisplayFormat(SDL_LoadBMP("tile.bmp"));
    SDL_Surface *image = SDL_DisplayFormat(SDL_CreateRGBSurface(SDL_HWSURFACE, S_W, S_H, 16, 0, 0, 0, 0));
    for (int i = 0; i <= image->h/tile->h; ++i) {
        for (int j = 0; j <= image->w/tile->w; ++j) {
            SDL_Rect dest;
            dest.x = j*tile->w;
            dest.y = i*tile->h;
            SDL_BlitSurface(tile, NULL, image, &dest);
        }
    }


Saludos y disculpen las molestias.
Avatar de Usuario
endaramiz
 
Mensajes: 283
Registrado: Vie Ago 31, 2007 9:25 am
Ubicación: Barcelona

Notapor Geo » Dom Feb 22, 2009 5:36 am

Precisamente, eso hice, crear mi propio tile.bmp :).

Gracias por el ejemplo.
La imaginación es el límite.
Visita mi blog en inglés o en español.
Geo
 
Mensajes: 244
Registrado: Jue Ago 10, 2006 3:51 am
Ubicación: México


Volver a Artículos, traducciones y documentación

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 2 invitados