Mercurial > hg > demos > krapula
view krapula.c @ 25:98dcf1847e75
Cleanups, add the debug mode enabling option.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 02 Oct 2012 18:17:52 +0300 |
parents | 01f3af410abb |
children | 077d08c442f7 |
line wrap: on
line source
#include "dmsimple.h" #include "dmvecmat.h" #include <math.h> DMOptArg optList[] = { { 0, '?', "help", "Show this help", OPT_NONE }, { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, { 2, 'f', "fs", "Fullscreen", OPT_NONE }, #ifdef DM_DEBUG { 3, 'd', "debug", "Debug mode", OPT_NONE }, #endif }; const int optListN = sizeof(optList) / sizeof(optList[0]); void argShowHelp() { dmPrintBanner(stdout, dmProgName, "[options]"); dmArgsPrintHelp(stdout, optList, optListN); } BOOL argHandleOpt(const int optN, char *optArg, char *currArg) { (void) optArg; switch (optN) { case 0: argShowHelp(); exit(0); break; case 1: dmVerbosity++; break; case 2: engine.optVFlags |= SDL_FULLSCREEN; break; #ifdef DM_DEBUG case 3: engine.optDebug = TRUE; break; #endif default: dmError("Unknown option '%s'.\n", currArg); return FALSE; } return TRUE; } #define DM_COLORS (256) void dmMakePalette(SDL_Surface *scr) { SDL_Color pal[DM_COLORS]; int n; for (n = 0; n < 256; n++) { pal[n].r = n; pal[n].g = n; pal[n].b = n; } SDL_SetColors(scr, pal, 0, DM_COLORS); } void dmRandom(SDL_Surface *screen, int q) { Uint8 *pix = screen->pixels; int xc, yc; for (yc = 0; yc < screen->h; yc++) { Uint8 *dp = pix; for (xc = 0; xc < screen->w; xc++) *dp++ = yc + (xc ^ q) + (yc & q); pix += screen->pitch; } } #define QWIDTH 256 #define QHEIGHT 160 typedef Uint8 DMBlockMap[QHEIGHT][QWIDTH]; static DMFloat dmClip(DMFloat a) { return (a < 0.0f ? 0.0f : (a > 1.0f ? 1.0f : a)); } void dmMakeBumpMap(DMBlockMap map, DMFloat q, DMFloat m) { int x, y; for (y = 0; y < QHEIGHT; y++) { for (x = 0; x < QWIDTH; x++) { DMFloat f = 0.40f + dmPerlinNoise2D(x, y, 1.1f, q, 2); map[y][x] = (int) (dmClip(f) * m); } } } void dmShadowTraceHeightMap(DMBlockMap lightMap, DMBlockMap pheightMap, DMVector *light) { int i, j; for (j = 0; j < QHEIGHT; j++) for (i = 0; i < QWIDTH; i++) { DMVector vr, vl, va; DMFloat vrayLen, vfactor; int vlen; BOOL wasHit; /* Perform shadow occlusion via simplistic raytracing */ vr.x = i; vr.y = j; vr.z = light->z; // - 10.0; // vr.z = pheightMap[j][i]; /* Calculate light vector vector */ dm_vector_sub_r(&vl, &vr, light); vrayLen = dm_vector_length(&vl); #if 1 dm_vector_copy(&va, &vl); dm_vector_normalize(&va); dm_vector_scale(&va, 0.6f); dm_vector_copy(&vr, light); vlen = 0; wasHit = FALSE; do { float h; /* If ray is inside the heightmap, get value */ if (vr.x >= 0 && vr.y >= 0 && vr.x < QWIDTH && vr.y < QHEIGHT) h = pheightMap[(int) vr.y][(int) vr.x]; else break; /* Check for hits */ if (h > vr.z) wasHit = TRUE; else { /* Move forwards */ dm_vector_add(&vr, &va); vlen++; } } while (!wasHit && vlen <= vrayLen); /* Check if the ray hit something, e.g. is this point occluded? */ if (wasHit && vlen < vrayLen) { vfactor = vlen * 0.01; } else vfactor = vlen * 0.02; #endif #if 1 { /* Calculate light's intensity based on the angle it "hits" * * 1) Calculate the vectors that form the imaginary "plane" * 2) Cross-product -> normal vector of the plane * 2) Normalize the normal vector * 3) Calculate light vector's hit angle by dot product */ DMVector v1, v2; DMFloat c; v1.x = 2.0f; v1.y = 0.0f; v1.z = (DMFloat) (pheightMap[j][i] - pheightMap[j][i + 1]); v2.x = 0.0f; v2.y = 2.0f; v2.z = (DMFloat) (pheightMap[j][i] - pheightMap[j + 1][i]); dm_vector_cross(&vr, &v1, &v2); dm_vector_normalize(&vr); dm_vector_normalize(&vl); c = dm_vector_dot(&vl, &vr); vrayLen = 255 - (vrayLen * 0.1) * vrayLen + (c * 128.0f) + (vfactor * vfactor * 1255); } #else vrayLen = 255 - vrayLen * vrayLen * (vfactor * vfactor); if (vrayLen < 0) vrayLen = 0; vrayLen += pheightMap[j][i]; #endif /* Clip result */ if (vrayLen < 0) vrayLen = 0; else if (vrayLen > 255.0f) vrayLen = 255.0f; lightMap[j][i] = vrayLen; } } void dmShadowTraceHeightMap2(DMBlockMap lightMap, DMBlockMap pheightMap, DMVector *light) { int i, j; light->z = 150; for (j = 0; j < QHEIGHT; j++) for (i = 0; i < QWIDTH; i++) { DMVector vr, vl, va; DMFloat vrayLen, vfactor; int vlen; BOOL wasHit; /* Perform shadow occlusion via simplistic raytracing */ vr.x = i; vr.y = j; vr.z = 200; //light->z; // - 10.0; /* Calculate light vector vector */ dm_vector_sub_r(&vl, &vr, light); vrayLen = dm_vector_length(&vl); #if 1 dm_vector_copy(&va, &vl); dm_vector_normalize(&va); dm_vector_copy(&vr, light); vlen = 0; wasHit = FALSE; do { float h; /* If ray is inside the heightmap, get value */ if (vr.x >= 0 && vr.y >= 0 && vr.x < QWIDTH && vr.y < QHEIGHT) h = pheightMap[(int) vr.y][(int) vr.x]; else break; /* Check for hits */ if (h > vr.z) wasHit = TRUE; else { /* Move forwards */ dm_vector_add(&vr, &va); vlen++; } } while (!wasHit && vlen <= vrayLen); /* Check if the ray hit something, e.g. is this point occluded? */ if (wasHit && vlen < vrayLen) { vfactor = vlen * 0.05; } else vfactor = vlen * 0.001; #endif #if 0 { /* Calculate light's intensity based on the angle it "hits" * * 1) Calculate the vectors that form the imaginary "plane" * 2) Cross-product -> normal vector of the plane * 2) Normalize the normal vector * 3) Calculate light vector's hit angle by dot product */ DMVector v1, v2; DMFloat c; v1.x = 2.0f; v1.y = 0.0f; v1.z = (DMFloat) (pheightMap[j][i] - pheightMap[j][i + 1]); v2.x = 0.0f; v2.y = 2.0f; v2.z = (DMFloat) (pheightMap[j][i] - pheightMap[j + 1][i]); dm_vector_cross(&vr, &v1, &v2); dm_vector_normalize(&vr); dm_vector_normalize(&vl); c = dm_vector_dot(&vl, &vr); vrayLen = 255 - (vrayLen * 0.1) * vrayLen + (c * 128.0f) + (vfactor * vfactor * 1255); } #else vrayLen = 255 - vrayLen * vrayLen * (vfactor * vfactor); if (vrayLen < 0) vrayLen = 0; vrayLen -= pheightMap[j][i]; #endif /* Clip result */ if (vrayLen < 0) vrayLen = 0; else if (vrayLen > 255.0f) vrayLen = 255.0f; lightMap[j][i] = vrayLen; } } #define CREDITS_SPEED 1000 #define CREDITS_RAND 4 typedef struct { int x, y; } DMCoords; typedef struct { int x, y; char *filename; SDL_Surface *img; } DMCredits; static const DMCoords randomCoords[] = { { -300, -430 }, { 700, -550 }, { -200, 600 }, { 700, 600 } }; const int nrandomCoords = sizeof(randomCoords) / sizeof(randomCoords[0]); static DMCredits credits[] = { { 91, 223, "g4014.png", NULL }, { 151, 250, "g4026.png", NULL }, { 217, 227, "g4020.png", NULL }, { 173, 268, "g4032.png", NULL }, { 115, 359, "g4038.png", NULL }, { 437, 130, "g4062.png", NULL }, { 457, 102, "g4068.png", NULL }, { 450, 210, "g4056.png", NULL }, { 420, 320, "g4044.png", NULL }, { 486, 381, "g4050.png", NULL }, }; const int ncredits = sizeof(credits) / sizeof(credits[0]); #define NOSFE_MIN 1 #define NOSFE_MAX 269 SDL_Surface *bmap; SDL_Surface *nosfe[NOSFE_MAX - NOSFE_MIN + 1]; int demoPreInit(int argc, char *argv[]) { dmInitProg("krapula", "Lauantai Aamun Krapula", "0.2", "(c) 2012 Anciat Prodz & TNSP", "PENIS."); engine.optScrWidth = 640; engine.optScrHeight = 480; engine.optBitDepth = 32; engine.optVFlags = SDL_SWSURFACE | SDL_HWPALETTE; #ifdef DM_DEBUG engine.demoDuration = 150; #endif if (!dmArgsProcess(argc, argv, optList, optListN, argHandleOpt, NULL, FALSE)) return DMERR_INIT_FAIL; dmPrint(0, "%s\n", dmProgDesc); dmPrint(0, "%s\n", dmProgAuthor); dmPrint(0, "TNSP PIERUPASKA engine 2012 'passeli professional' loading.\n"); return DMERR_OK; } int demoInit() { int i; // Initialize effect stuff dmPerlinInit(); for (i = 0; i < NOSFE_MAX; i++) { char fname[32]; snprintf(fname, sizeof(fname), "%08d.jpg", NOSFE_MIN + i); engineGetResImage(nosfe[i], fname); } for (i = 0; i < ncredits; i++) engineGetResImage(credits[i].img, credits[i].filename); bmap = SDL_CreateRGBSurface(SDL_SWSURFACE, QWIDTH, QHEIGHT, 8, 0, 0, 0, 0); // Initialize music player JSSModule *mod = NULL; engineGetResModule(mod, "krapula.xm"); if ((i = jssConvertModuleForPlaying(mod)) != DMERR_OK) { dmError("Could not convert module for playing, %d: %s\n", i, dmErrorStr(i)); return DMERR_INIT_FAIL; } jvmSetCallback(engine.dev, jmpExec, engine.plr); jmpSetModule(engine.plr, mod); jmpPlayOrder(engine.plr, 0); jvmSetGlobalVol(engine.dev, 55); return DMERR_OK; } void demoShutdown() { SDL_FreeSurface(bmap); } void demoQuit() { dmPrint(0, "Krapulassa on kivaa.\n"); } int demoMainTick() { float t = engineGetTimeDT(); if (t < 5) { int dt = engineGetTime(0); static SDL_Surface *anciat; static DMLerpContext lerpX, lerpY, lerpD; static DMScaledBlitFunc nblit; DMVector light; static BOOL nollattu = FALSE; if (!nollattu) { engineGetResImage(anciat, "anciat.png"); nblit = dmGetScaledBlitFunc(bmap->format, engine.screen->format, DMD_NONE); dmMakePalette(bmap); dmLerpInit(&lerpX, 0, QWIDTH, 5000); dmLerpInit(&lerpY, QHEIGHT * 0.25, QHEIGHT * 0.75, 5000); dmLerpInit(&lerpD, 0.04, 0.08, 5000); nollattu = TRUE; } light.x = dmLerpSCurve(&lerpX, dt); light.y = dmLerp1(&lerpY, dt); light.z = 128; dmShadowTraceHeightMap2(bmap->pixels, anciat->pixels, &light); nblit(bmap, 0, 0, engine.screen->w, engine.screen->h, engine.screen); } else if (t < 10) { int dt = engineGetTime(5); static SDL_Surface *logobg, *logolayer1, *logolayer2; static DMScaledBlitFunc nblit, kblit; static DMLerpContext lerpD; static BOOL nollattu = FALSE; if (!nollattu) { engineGetResImage(logobg, "logobg.png"); engineGetResImage(logolayer1, "logolayer1.png"); engineGetResImage(logolayer2, "logolayer2.png"); nblit = dmGetScaledBlitFunc(logobg->format, engine.screen->format, DMD_TRANSPARENT); kblit = dmGetScaledBlitFunc(logobg->format, engine.screen->format, DMD_NONE); dmLerpInit(&lerpD, 0.01, 500, 10000); nollattu = TRUE; } float q = dmLerpSCurve(&lerpD, dt); float t = sin((float) dt / 150.0f); int x = t * 25.0f + q, y = t * 35.0f + q*2.0f, w = t * 70.0f + q, h = t * 40.0f + q*2.0f; float t2 = sin((float) dt / 150.0f + 0.2f); int x2 = t2 * 25.0f + q, y2 = t * 35.0f + q*2.0f, w2 = t2 * 70.0f + q, h2 = t * 40.0f + q*2.0f; kblit(logobg, 0, 0, engine.screen->w, engine.screen->h, engine.screen); nblit(logolayer1, -x, -y, engine.screen->w+w, engine.screen->h+h, engine.screen); nblit(logolayer2, -x2, -y2, engine.screen->w+w2, engine.screen->h+h2, engine.screen); } else if (t < 20) { int dt = engineGetTime(10); static SDL_Surface *gay, *logobg; static DMLerpContext lerpX, lerpY, lerpD; static DMScaledBlitFunc nblit, kblit; static BOOL nollattu = FALSE; DMVector light; DMBlockMap heightMap; if (!nollattu) { engineGetResImage(gay, "gay.png"); engineGetResImage(logobg, "logobg.png"); nblit = dmGetScaledBlitFunc(bmap->format, engine.screen->format, DMD_NONE); kblit = dmGetScaledBlitFunc(logobg->format, engine.screen->format, DMD_TRANSPARENT); dmMakePalette(bmap); dmLerpInit(&lerpX, QWIDTH, 0, 10000); dmLerpInit(&lerpY, QHEIGHT * 0.25, QHEIGHT * 0.75, 10000); dmLerpInit(&lerpD, 0.04, 0.08, 10000); nollattu = TRUE; } light.x = dmLerpSCurve(&lerpX, dt); light.y = QHEIGHT * 0.5 + sin(dmLerp1(&lerpY, dt)) * 0.5; light.z = 128; dmMakeBumpMap(heightMap, dmLerpSCurve(&lerpD, dt), 254); dmShadowTraceHeightMap(bmap->pixels, heightMap, &light); nblit(bmap, 0, 0, engine.screen->w, engine.screen->h, engine.screen); if ((dt / 100) % 10 < 5) { kblit(gay, 0, 0, engine.screen->w, engine.screen->h, engine.screen); } } else if (t < 45) { static SDL_Surface *ruutu; static int currState, currCredit, creditStartTime; static DMLerpContext lerpX, lerpY, lerpZ; static DMScaledBlitFunc nblit, kblit; static BOOL stateChange, nollattu = FALSE; int currFrame = engineGetTime(20) * 15 / 1000; if (!nollattu) { engineGetResImage(ruutu, "ruutu.png"); dmClearSurface(ruutu, dmMapRGBA(ruutu, 0,0,0,0)); nblit = dmGetScaledBlitFunc(nosfe[0]->format, engine.screen->format, DMD_NONE); kblit = dmGetScaledBlitFunc(credits[0].img->format, engine.screen->format, DMD_TRANSPARENT); currCredit = -1; currState = -1; stateChange = TRUE; nollattu = TRUE; } float gt = 1.0f + sin(engineGetTime(0) / 250.0f); int g1 = gt * 25.0f, g2 = gt * 50.0f; nblit(nosfe[currFrame % NOSFE_MAX], -g1, -g1, engine.screen->w+g2, engine.screen->h+g2, engine.screen); if (t >= 30) { int qtime = engineGetTime(30); int creditTime = (engineGetTime(0) - creditStartTime); float zscale; if ( ( (qtime / (CREDITS_SPEED + 500)) % 2) == 0 && currState == -1) stateChange = TRUE; if (stateChange && currCredit < ncredits) { stateChange = FALSE; switch (currState) { case 0: { int qt = (qtime / 100) % nrandomCoords; creditStartTime = engineGetTime(0); creditTime = 0; dmLerpInit(&lerpX, randomCoords[qt].x, credits[currCredit].x - 50, CREDITS_SPEED); dmLerpInit(&lerpY, randomCoords[qt].y, credits[currCredit].y - 50, CREDITS_SPEED); dmLerpInit(&lerpZ, 5.0f, 0.0f, CREDITS_SPEED); currState = 1; } break; case 2: if (creditTime >= CREDITS_SPEED) creditTime = CREDITS_SPEED - 1; zscale = dmLerpSCurve(&lerpZ, creditTime); dmScaledBlitSurface32to32TransparentX( credits[currCredit].img, dmLerpSCurve(&lerpX, creditTime) - (zscale * credits[currCredit].img->w), dmLerpSCurve(&lerpY, creditTime) - (zscale * credits[currCredit].img->h), credits[currCredit].img->w * (1.0f + zscale), credits[currCredit].img->h * (1.0f + zscale), ruutu); currState = -1; break; default: currCredit++; currState = 0; stateChange = TRUE; break; } } if (currCredit > 0) { kblit(ruutu, 0, 0, engine.screen->w, engine.screen->h, engine.screen); } if (currState == 1) { if (creditTime >= CREDITS_SPEED) { creditTime = CREDITS_SPEED; stateChange = TRUE; currState = 2; } zscale = dmLerpSCurve(&lerpZ, creditTime); kblit(credits[currCredit].img, dmLerpSCurve(&lerpX, creditTime) - (zscale * credits[currCredit].img->w), dmLerpSCurve(&lerpY, creditTime) - (zscale * credits[currCredit].img->h), credits[currCredit].img->w * (1.0f + zscale), credits[currCredit].img->h * (1.0f + zscale), engine.screen); } } } else if (t < 60) { int dt = engineGetTime(45); static SDL_Surface *logobg, *greets; static DMScaledBlitFunc nblit, kblit; static DMLerpContext lerpD; static BOOL nollattu = FALSE; if (!nollattu) { engineGetResImage(logobg, "logobg.png"); engineGetResImage(greets, "greetings.png"); nblit = dmGetScaledBlitFunc(logobg->format, engine.screen->format, DMD_TRANSPARENT); kblit = dmGetScaledBlitFunc(logobg->format, engine.screen->format, DMD_NONE); dmLerpInit(&lerpD, 0.01, 500, 10000); nollattu = TRUE; } float q = dmLerpSCurve(&lerpD, dt); float t = sin((float) dt / 150.0f), j = (1.0 + t) * 15; int x = t * 25.0f + q, y = t * 35.0f + q, w = t * 70.0f + q*2.0f, h = t * 40.0f + q*2.0f; kblit(logobg, -j, -j, engine.screen->w+j*2.0f, engine.screen->h+j*2.0f, engine.screen); nblit(greets, -x, -y, engine.screen->w+w, engine.screen->h+h, engine.screen); } else engine.exitFlag = TRUE; { static SDL_Surface *feidi; static int fadeStartTime; static BOOL fadeActive, nollattu = FALSE; static DMLerpContext fadeLerp; BOOL hit; int ch; if (!nollattu) { engineGetResImage(feidi, "feidi.png"); dmLerpInit(&fadeLerp, 255, 0, 250); nollattu = TRUE; } JSS_LOCK(engine.plr); for (hit = FALSE, ch = 0; ch < 6; ch++) if (engine.plr->channels[ch].iCExtInstrumentN == 0) { hit = TRUE; break; } JSS_UNLOCK(engine.plr); if (hit && !fadeActive) { fadeActive = TRUE; fadeStartTime = engineGetTime(0); } if (fadeActive) { int fadeTime = engineGetTime(0) - fadeStartTime; if (fadeTime < 250) { dmScaledBlitSurface32to32TransparentGA(feidi, 0, 0, engine.screen->w, engine.screen->h, engine.screen, dmLerpSCurve(&fadeLerp, fadeTime)); } else fadeActive = FALSE; } } return DMERR_OK; }