Mercurial > hg > demos > krapula
view demo.c @ 68:aa06f72f6557
optDataPath not used anymore.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 24 Oct 2019 08:20:15 +0300 |
parents | cdd817cb0e44 |
children | f0b26daba6a9 |
line wrap: on
line source
#include "dmengine.h" #include "dmvecmat.h" #include "dmperlin.h" #include <math.h> static int demoInit(); static void demoShutdown(); static void demoQuit(); static int demoRender(); static DMPerlinContext perlinCtx; #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); } #define QWIDTH 256 #define QHEIGHT 160 typedef Uint8 DMBlockMap[QHEIGHT][QWIDTH]; 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(&perlinCtx, x, y, 1.1f, q, 2); map[y][x] = (int) (dmClamp10(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(DMEngineData *engine) { dmInitProg("krapula", "Lauantai Aamun Krapula", "0.2", "(c) 2012 Anciat Prodz & TNSP", "PENIS."); engine->optPackFilename = "orvellys.dat"; engine->optResFlags = DRF_USE_PACK | DRF_PRELOAD_RES #ifdef DM_USE_STDIO | DRF_USE_STDIO #endif ; engine->optAudioSetup = DM_ASETUP_JSS; engine->optVidSetup = DM_VSETUP_ASPECT; engine->optVidWidth = 640; engine->optVidHeight = 480; engine->optVidDepth = 32; engine->optVFlags = SDL_SWSURFACE; engine->demoInit = demoInit; engine->demoRender = demoRender; engine->demoShutdown = demoShutdown; engine->demoQuit = demoQuit; return DMERR_OK; } static int demoInit(DMEngineData *engine) { int i; // Initialize effect stuff dmPerlinInit(&perlinCtx, 1234); for (i = 0; i < NOSFE_MAX; i++) { char fname[32]; snprintf(fname, sizeof(fname), "%08d.jpg", NOSFE_MIN + i); engineGetResImage(engine, nosfe[i], fname); } for (i = 0; i < ncredits; i++) engineGetResImage(engine, 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(engine, mod, "krapula.xm"); if ((i = jssConvertModuleForPlaying(mod)) != DMERR_OK) { dmErrorMsg("Could not convert module for playing, %d: %s\n", i, dmErrorStr(i)); return DMERR_INIT_FAIL; } jvmSetCallback(engine->jssDev, jmpExec, engine->jssPlr); jmpSetModule(engine->jssPlr, mod); jmpPlayOrder(engine->jssPlr, 0); jvmSetGlobalVol(engine->jssDev, 55); return DMERR_OK; } static void demoShutdown(DMEngineData *engine) { (void) engine; SDL_FreeSurface(bmap); } static void demoQuit() { dmPrint(0, "Krapulassa on kivaa.\n"); } static int demoRender(DMEngineData *engine) { float t = engineGetTimeDT(engine); if (t < 5) { // // Anciat prodz logo // int dt = engineGetTime(engine, 0); static SDL_Surface *anciat; static DMLerpContext lerpX, lerpY, lerpD; static DMScaledBlitFunc nblit; DMVector light; static BOOL nollattu = FALSE; if (!nollattu) { engineGetResImage(engine, 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) { // // Demo "logo" texts // int dt = engineGetTime(engine, 5); static SDL_Surface *logobg, *logolayer1, *logolayer2; static DMScaledBlitFunc nblit, kblit; static DMLerpContext lerpD; static BOOL nollattu = FALSE; if (!nollattu) { engineGetResImage(engine, logobg, "logobg.png"); engineGetResImage(engine, logolayer1, "logolayer1.png"); engineGetResImage(engine, 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) { // // "Gaytracing" // int dt = engineGetTime(engine, 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(engine, gay, "gay.png"); engineGetResImage(engine, 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) { // // Nosfe video/animation + credits // 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(engine, 20) * 15 / 1000; if (!nollattu) { engineGetResImage(engine, 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(engine, 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(engine, 30); int creditTime = engineGetTime(engine, 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(engine, 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) { int zk = cos(engineGetTime(engine, 0) / 250.0f) * 25; kblit(ruutu, -zk, -zk, engine->screen->w + zk*2, engine->screen->h + zk*2, 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) { // // Greetings // int dt = engineGetTime(engine, 45); static SDL_Surface *logobg, *greets; static DMScaledBlitFunc nblit, kblit; static DMLerpContext lerpD; static BOOL nollattu = FALSE; if (!nollattu) { engineGetResImage(engine, logobg, "logobg.png"); engineGetResImage(engine, 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; // // Flash/fade thingy // { static SDL_Surface *feidi; static int fadeStartTime; static BOOL fadeActive, nollattu = FALSE; static DMLerpContext fadeLerp; BOOL hit; int ch; if (!nollattu) { engineGetResImage(engine, feidi, "feidi.png"); dmLerpInit(&fadeLerp, 255, 0, 250); nollattu = TRUE; } JSS_LOCK(engine->jssPlr); for (hit = FALSE, ch = 0; ch < 6; ch++) if (engine->jssPlr->channels[ch].nextInstrument == 0) { hit = TRUE; break; } JSS_UNLOCK(engine->jssPlr); if (hit && !fadeActive) { fadeActive = TRUE; fadeStartTime = engineGetTime(engine, 0); } if (fadeActive) { int fadeTime = engineGetTime(engine, 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; }