#include #include #include "SDL.h" #include "time.h" #define WINDOW_WIDTH 640 #define WINDOW_HEIGHT 480 #define STAR_COUNT 400 SDL_Surface *screen; struct Star { float x, y, speed; }; Star g_Stars[STAR_COUNT]; int g_midX, g_midY; bool g_Hyperspeed; inline bool PlotPixel(int x, int y, int color) { if(x < 0 || y < 0 || x > WINDOW_WIDTH -1 || y > WINDOW_HEIGHT -1) return false; ((unsigned int*)screen->pixels)[y * WINDOW_WIDTH + x] = color; return true; } inline void swap(int *x, int *y) { int tmp = *x; *x = *y; *y = tmp; } // Bresenham's line algorithm as explained by wikipedia void DrawLine(int color, int x0, int y0, int x1, int y1) { bool steep = abs(y1 - y0) > abs(x1 - x0); if(steep) { swap(&x0, &y0); swap(&x1, &y1); } if(x0 > x1) { swap(&x0, &x1); swap(&y0, &y1); } signed int y = y0; int deltax = x1 - x0; int deltay = abs(y1 - y0); int error = -deltax / 2; int ystep = (y0 < y1) ? 1 : -1; for(int x = x0; x <= x1; x++) { if(steep) { if(!PlotPixel(y, x, color)) return; } else { if(!PlotPixel(x, y, color)) return; } error = error + deltay; if(error > 0) { y = y + ystep; error = error - deltax; } } } 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 stars for(int i = 0; i < STAR_COUNT; i++) { int c = 0xff * g_Stars[i].speed; int x2 = g_Stars[i].x - (g_midX - g_Stars[i].x) * g_Stars[i].speed / (20.0f - (g_Hyperspeed * 15.0f)); int y2 = g_Stars[i].y - (g_midY - g_Stars[i].y) * g_Stars[i].speed / (20.0f - (g_Hyperspeed * 15.0f)); DrawLine((c << 16) + (c << 8) + c, g_Stars[i].x, g_Stars[i].y, x2, y2); } // 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 stars for(int i = 0; i < STAR_COUNT; i++) { g_Stars[i].x -= (g_midX - g_Stars[i].x) * iDelta * g_Stars[i].speed / (200.0f - (g_Hyperspeed * 150.0f)); g_Stars[i].y -= (g_midY - g_Stars[i].y) * iDelta * g_Stars[i].speed / (200.0f - (g_Hyperspeed * 150.0f)); // If the star is outside screen or in the exact middle, move them somewhere if((g_Stars[i].x < 0 || g_Stars[i].y < 0 || g_Stars[i].x > WINDOW_WIDTH -1 || g_Stars[i].y > WINDOW_HEIGHT -1) || (g_Stars[i].x == g_midX && g_Stars[i].y == g_midY)) { g_Stars[i].x = rand() % WINDOW_WIDTH; g_Stars[i].y = rand() % WINDOW_HEIGHT; } } } // Entry point int main(int argc, char *argv[]) { srand((unsigned)time(NULL)); g_midX = WINDOW_WIDTH / 2; g_midY = WINDOW_HEIGHT / 2; g_Hyperspeed = false; // 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); } // Initialize stars, place them randomly for(int i = 0; i < STAR_COUNT; i++) { g_Stars[i].x = rand() % WINDOW_WIDTH; g_Stars[i].y = rand() % WINDOW_HEIGHT; g_Stars[i].speed = (rand() % 90) / 100.0f; } // 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; else if(event.key.keysym.sym == SDLK_SPACE) g_Hyperspeed = !g_Hyperspeed; break; case SDL_MOUSEMOTION: g_midX = event.motion.x; g_midY = event.motion.y; break; case SDL_QUIT: return 0; } } } return 0; }