#include #include #include "SDL.h" #include "time.h" #define WINDOW_WIDTH 640 #define WINDOW_HEIGHT 480 #define METABALL_COUNT 3 SDL_Surface *screen; struct Metaball { int x, y; float size; int dx, dy; }; Metaball g_Metaballs[METABALL_COUNT]; inline int clamp(int value, int min, int max) { return (value < min) ? min : ((value > max) ? max : value); } void render() { // Lock surface if needed if (SDL_MUSTLOCK(screen)) if (SDL_LockSurface(screen) < 0) return; // Clear screen SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0)); // Draw metaballs int x, y, i, c; int xDiff, yDiff, iPow; float fMetaballValue; for(x = 0; x < WINDOW_WIDTH; x++) for(y = 0; y < WINDOW_HEIGHT; y++) { fMetaballValue = 0.0f; for(i = 0; i < METABALL_COUNT; i++) { xDiff = g_Metaballs[i].x - x; yDiff = g_Metaballs[i].y - y; iPow = xDiff * xDiff + yDiff * yDiff; fMetaballValue += g_Metaballs[i].size / ((float)iPow * (float)iPow); } c = clamp(fMetaballValue * 255.0f * 20.0f, 0, 256); ((unsigned int*)screen->pixels)[y * WINDOW_WIDTH + x] = (0 << 16) + (c << 8) + 0; } // Unlock if needed if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); // Tell SDL to update the whole screen SDL_UpdateRect(screen, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); } void tick() { // Ask SDL for the time in milliseconds static int lastTick = SDL_GetTicks() - 100; int iDelta = SDL_GetTicks() - lastTick; lastTick = SDL_GetTicks(); if(iDelta > 33) iDelta = 33; // Move the metaballs for(int i = 0; i < METABALL_COUNT; i++) { g_Metaballs[i].x += g_Metaballs[i].dx * iDelta / 20.0f; g_Metaballs[i].y += g_Metaballs[i].dy * iDelta / 20.0f; if(g_Metaballs[i].x < 0 || g_Metaballs[i].x > WINDOW_WIDTH -1) g_Metaballs[i].dx = -g_Metaballs[i].dx; if(g_Metaballs[i].y < 0 || g_Metaballs[i].y > WINDOW_HEIGHT -1) g_Metaballs[i].dy = -g_Metaballs[i].dy; } } // Entry point int main(int argc, char *argv[]) { srand((unsigned)time(NULL)); // Initialize SDL's subsystems - in this case, only video. if(SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); exit(1); } // Register SDL_Quit to be called at exit; makes sure things are // cleaned up when we quit. atexit(SDL_Quit); // Attempt to create a 640x480 window with 32bit pixels. screen = SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, 32, SDL_SWSURFACE); // If we fail, return error. if(!screen) { fprintf(stderr, "Unable to set video: %s\n", SDL_GetError()); exit(1); } // Init metaballs for(int i = 0; i < METABALL_COUNT; i++) { g_Metaballs[i].x = rand() % WINDOW_WIDTH; g_Metaballs[i].y = rand() % WINDOW_HEIGHT; g_Metaballs[i].size = 2500000; g_Metaballs[i].dx = rand() % 10 - 5; g_Metaballs[i].dy = rand() % 10 - 5; } // Main loop: loop forever. while(true) { // Tick stuff; tick(); // Render stuff render(); // Poll for events, and handle the ones we care about. SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: break; case SDL_KEYUP: // If escape is pressed, return (and thus, quit) if(event.key.keysym.sym == SDLK_ESCAPE) return 0; break; case SDL_QUIT: return 0; } } } return 0; }