- Código: Seleccionar todo
#include <iostream>
#include <cmath>
#include <list>
#include <SDL/SDL.h>
using namespace std;
#define S_W 1024
#define S_H 768
#define bpp 2
int pow(int n, int e) {
if (e == 0) return 1;
return n*pow(n, e-1);
}
double min(double a, double b) {
if (a <= b) return a;
return b;
}
void draw_circle3(int x, int y, int r, double alp0, SDL_Surface* s);
void draw_circle3(int x, int y, int r, double alp0, SDL_Surface* s);
class Atomo {
public:
Atomo(int x, int y);
void update(double ax);
void draw(SDL_Surface* screen);
bool finished();
int prior;
private:
double x, y, dy;
double dx;
double r, dr;
double alpha, dalpha;
};
Atomo :: Atomo(int x, int y) {
prior = rand();
this->x = x+rand()%5-2; this->y = y+rand()%5-2;
dx = rand()%10/10.0-0.5; dy = 4;
alpha = 0.3 + rand()%10/100.0; dalpha = 0.015;
r = 2 + rand()%3; dr = 2.5;
}
void Atomo :: update(double ax) {
dx += ax + rand()%10/10.0-0.5;
x += dx;
y -= dy + rand()%3-1;
alpha += dalpha + rand()%5/100;
r += dr + rand()%3-1;
}
void Atomo :: draw(SDL_Surface* screen) {
draw_circle3(x, y, r, alpha, screen);
}
bool Atomo :: finished() {
return alpha >= 0.93 or x >= S_W or x < 0 or y < 0;
}
void put_pixel(SDL_Surface* screen, int row, int col, unsigned int color, double alp) {
if (alp >= 1) return;
Uint16 *pdest = (Uint16*)screen->pixels;
pdest += screen->pitch/2*row;
pdest += col;
Uint16 c = *pdest;
unsigned int r = (c&0x0000F800)>>11;
unsigned int g = (c&0x000007E0)>>5;
unsigned int b = (c&0x0000001F);
unsigned int rgb_color = (int(r*alp + color*(1-alp))<<11) | (int(g*alp + ((color<<1)|1)*(1-alp))<<5) | (int(b*alp + color*(1-alp)));
*pdest = rgb_color;
}
void draw_circle3(int x, int y, int r, double alp0, SDL_Surface* s) {
int j = 0;
for (int ii = 1; ii <= r and y+ii < S_H; ++ii)
put_pixel(s, y+ii,x,31-(1-cos((M_PI/2)*(pow(ii,2)+pow(j,2))/double(pow(r,2))))*20, 0);
for (int ii = 1; ii <= r and y+ii >= 0; ++ii)
put_pixel(s, y-ii,x,31-(1-cos((M_PI/2)*(pow(ii,2)+pow(j,2))/double(pow(r,2))))*20, 0);
for (int ii = 1; ii <= r and x-ii >= 0; ++ii)
put_pixel(s, y,x-ii,31-(1-cos((M_PI/2)*(pow(ii,2)+pow(j,2))/double(pow(r,2))))*20, 0);
for (int ii = 1; ii <= r and x+ii < S_W; ++ii)
put_pixel(s, y,x+ii,31-(1-cos((M_PI/2)*(pow(ii,2)+pow(j,2))/double(pow(r,2))))*20, 0);
put_pixel(s, y,x,31-(1-cos((M_PI/2)*(pow(j,2)+pow(j,2))/double(pow(r,2))))*25, 0);
for ( j = 1; j <= r; ++j) {
int i = sqrt(r*r-(j*j));
for (int ii = 1; ii <= i and y+ii < S_H and x+j < S_W; ++ii)
put_pixel(s, y+ii,x+j,31-(1-cos((M_PI/2)*(pow(ii,2)+pow(j,2))/double(pow(r,2))))*20, min((1-cos((M_PI/2)*(pow(ii,2)+pow(j,2))/double(pow(r,2))))*0.99 + alp0, 1));
for (int ii = 1; ii <= i and y+ii < S_H and x-j >= 0; ++ii)
put_pixel(s, y+ii,x-j,31-(1-cos((M_PI/2)*(pow(ii,2)+pow(j,2))/double(pow(r,2))))*20, min((1-cos((M_PI/2)*(pow(ii,2)+pow(j,2))/double(pow(r,2))))*0.99 + alp0, 1));
for (int ii = 1; ii <= i and y-ii >= 0 and x+j < S_W; ++ii)
put_pixel(s, y-ii,x+j,31-(1-cos((M_PI/2)*(pow(ii,2)+pow(j,2))/double(pow(r,2))))*20, min((1-cos((M_PI/2)*(pow(ii,2)+pow(j,2))/double(pow(r,2))))*0.99 + alp0, 1));
for (int ii = 1; ii <= i and y-ii >= 0 and x-j >= 0; ++ii)
put_pixel(s, y-ii,x-j,31-(1-cos((M_PI/2)*(pow(ii,2)+pow(j,2))/double(pow(r,2))))*20, min((1-cos((M_PI/2)*(pow(ii,2)+pow(j,2))/double(pow(r,2))))*0.99 + alp0, 1));
}
}
int main(int argc, char** argv) {
cerr << SDL_Init(SDL_INIT_VIDEO);
SDL_Surface *screen = SDL_SetVideoMode(S_W, S_H, bpp*8, SDL_HWSURFACE);
SDL_ShowCursor(SDL_DISABLE);
list<Atomo*> atomos;
SDL_FillRect(screen, &screen->clip_rect, 0xF800);
SDL_Event event;
bool salir = false;
int frame;
while(not salir) {
SDL_FillRect(screen, &screen->clip_rect, 0xF800);
int t0 = SDL_GetTicks();
if (!(++frame%5)) {
Atomo* patomo = new Atomo(S_W/2, S_H - 20);
list<Atomo*>::iterator ita = atomos.begin();
while (ita != atomos.end() and (*ita)->prior > patomo->prior)
++ita;
atomos.insert(--ita, patomo);
}
list<Atomo*>::iterator ita = atomos.begin();
while (ita != atomos.end()) {
if ((*ita)->finished()) {
delete *ita;
ita = atomos.erase(ita);
}
else {
(*ita)->update(0.2);
(*ita)->draw(screen);
++ita;
}
}
int t1 = SDL_GetTicks();
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
salir = true;
break;
}
break;
case SDL_QUIT:
salir = true;
break;
}
}
cerr << "\rt. blit: " << t1-t0 << " ";
SDL_Flip(screen);
SDL_Delay(2);
}
cerr << endl;
SDL_Quit();
}
Las cruces que salen no son un bug, sirven para comprobar el efecto alfa. El código no es una versión definitiva, es más bien para juguetear un poco.
Saludos.