1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-15 09:34:18 +02:00

#11 add loading screens

This commit is contained in:
XProger
2017-12-17 06:18:32 +03:00
parent bdac7c7a3e
commit 46ba25d9a4
8 changed files with 230 additions and 97 deletions

View File

@@ -1,9 +1,7 @@
#ifndef H_CORE
#define H_CORE
#ifndef __EMSCRIPTEN__
#define USE_INFLATE
#endif
#define USE_INFLATE
#include <stdio.h>
#ifdef WIN32

View File

@@ -52,14 +52,17 @@ namespace Game {
void init(char *lvlName = NULL, char *sndName = NULL) {
char fileName[255];
TR::Version version = TR::getGameVersion();
if (!lvlName && version != TR::VER_UNKNOWN) {
lvlName = fileName;
TR::getGameLevelFile(lvlName, version, TR::getTitleId(version));
}
if (!lvlName) {
lvlName = fileName;
strcpy(lvlName, "level/1/TITLE.PSX");
TR::Version version = TR::getGameVersion();
if (version != TR::VER_UNKNOWN)
TR::getGameLevelFile(lvlName, version, TR::getTitleId(version));
}
init(new Stream(lvlName));
}
@@ -123,9 +126,6 @@ namespace Game {
if (!level->level.isCutsceneLevel())
delta = min(0.2f, delta);
Core::deltaTime = delta;
UI::update();
while (delta > EPS) {
Core::deltaTime = min(delta, 1.0f / 30.0f);
Game::updateTick();

View File

@@ -669,46 +669,128 @@ namespace TR {
}
const char* getGameScreen(Version version, LevelID id) {
if (useEasyStart) {
#define CHECK_FILE(name) if (Stream::existsContent(name)) return name
#define CHECK_FILE(name) if (Stream::existsContent(name)) return name
switch (id) {
// TR1
case LVL_TR1_TITLE :
CHECK_FILE("TITLEH.png"); // Android
CHECK_FILE("DATA/TITLEH.PCX"); // PC
CHECK_FILE("DELDATA/AMERTIT.RAW"); // PSX
CHECK_FILE("BINDATA/USATIT.BIN"); // SEGA
return "level/1/AMERTIT.PNG"; // WEB
case LVL_TR1_GYM :
CHECK_FILE("DELDATA/GYMLOAD.RAW");
CHECK_FILE("BINDATA/GYM224.BIN");
return "level/1/GYMLOAD.PNG";
case LVL_TR1_1 :
case LVL_TR1_2 :
case LVL_TR1_3A :
case LVL_TR1_3B :
CHECK_FILE("DELDATA/AZTECLOA.RAW");
CHECK_FILE("BINDATA/AZTEC224.BIN");
return "level/1/AZTECLOA.PNG";
case LVL_TR1_4 :
case LVL_TR1_5 :
case LVL_TR1_6 :
case LVL_TR1_7A :
case LVL_TR1_7B :
CHECK_FILE("DELDATA/GREEKLOA.RAW");
CHECK_FILE("BINDATA/GREEK224.BIN");
return "level/1/GREEKLOA.PNG";
case LVL_TR1_8A :
case LVL_TR1_8B :
case LVL_TR1_8C :
CHECK_FILE("DELDATA/EGYPTLOA.RAW");
CHECK_FILE("BINDATA/EGYPT224.BIN");
return "level/1/EGYPTLOA.PNG";
case LVL_TR1_10A :
case LVL_TR1_10B :
case LVL_TR1_10C :
CHECK_FILE("DELDATA/ATLANLOA.RAW");
CHECK_FILE("BINDATA/ATLAN224.BIN");
return "level/1/ATLANLOA.PNG";
// TR2
case LVL_TR2_TITLE :
CHECK_FILE("TITLE.png"); // Android
CHECK_FILE("data/TITLE.PCX"); // PC
CHECK_FILE("pix/title.pcx"); // PC
CHECK_FILE("PIXUS/TITLEUS.RAW"); // PSX (TODO: add other languages)
return "level/2/TITLEUS.PNG"; // WEB
case LVL_TR2_ASSAULT :
case LVL_TR2_HOUSE :
CHECK_FILE("PIX/MANSION.RAW");
return "level/2/MANSION.PNG";
case LVL_TR2_WALL :
case LVL_TR2_EMPRTOMB :
case LVL_TR2_FLOATING :
case LVL_TR2_XIAN :
CHECK_FILE("PIX/CHINA.RAW");
return "level/2/CHINA.PNG";
case LVL_TR2_BOAT :
case LVL_TR2_VENICE :
case LVL_TR2_OPERA :
CHECK_FILE("PIX/VENICE.RAW");
return "level/2/VENICE.PNG";
case LVL_TR2_RIG :
case LVL_TR2_PLATFORM :
CHECK_FILE("PIX/RIG.RAW");
return "level/2/RIG.PNG";
case LVL_TR2_UNWATER :
case LVL_TR2_KEEL :
case LVL_TR2_LIVING :
case LVL_TR2_DECK :
CHECK_FILE("PIX/TITAN.RAW");
return "level/2/TITAN.PNG";
case LVL_TR2_SKIDOO :
case LVL_TR2_MONASTRY :
case LVL_TR2_CATACOMB :
case LVL_TR2_ICECAVE :
CHECK_FILE("PIX/TIBET.RAW");
return "level/2/TIBET.PNG";
// TR3
case LVL_TR3_TITLE :
CHECK_FILE("pix/TITLEUK.BMP"); // PC (TODO: add other languages)
return "level/3/TITLEUK.PNG"; // WEB
case LVL_TR3_HOUSE :
CHECK_FILE("pix/HOUSE.BMP");
return "level/3/HOUSE.PNG";
case LVL_TR3_JUNGLE :
case LVL_TR3_TEMPLE :
case LVL_TR3_QUADCHAS :
case LVL_TR3_TONYBOSS :
CHECK_FILE("pix/INDIA.BMP");
return "level/3/INDIA.PNG";
case LVL_TR3_SHORE :
case LVL_TR3_CRASH :
case LVL_TR3_RAPIDS :
case LVL_TR3_TRIBOSS :
CHECK_FILE("pix/SOUTHPAC.BMP");
return "level/3/SOUTHPAC.PNG";
case LVL_TR3_ROOFS :
case LVL_TR3_SEWER :
case LVL_TR3_TOWER :
case LVL_TR3_OFFICE :
case LVL_TR3_STPAUL :
CHECK_FILE("pix/LONDON.BMP");
return "level/3/LONDON.PNG";
case LVL_TR3_NEVADA :
case LVL_TR3_COMPOUND :
case LVL_TR3_AREA51 :
CHECK_FILE("pix/NEVADA.BMP");
return "level/3/NEVADA.PNG";
case LVL_TR3_ANTARC :
case LVL_TR3_MINES :
case LVL_TR3_CITY :
case LVL_TR3_CHAMBER :
CHECK_FILE("pix/ANTARC.BMP");
return "level/3/ANTARC.PNG";
switch (id) {
case LVL_TR1_TITLE :
CHECK_FILE("TITLEH.png"); // Android
CHECK_FILE("DATA/TITLEH.PCX"); // PC
CHECK_FILE("DELDATA/AMERTIT.RAW"); // PSX
CHECK_FILE("BINDATA/USATIT.BIN"); // SEGA
break;
case LVL_TR2_TITLE :
CHECK_FILE("TITLE.png"); // Android
CHECK_FILE("data/TITLE.PCX"); // PC
CHECK_FILE("pix/title.pcx"); // PC
CHECK_FILE("PIXUS/TITLEUS.RAW"); // PSX (TODO: add other languages)
break;
case LVL_TR3_TITLE :
CHECK_FILE("pix/TITLEUK.BMP"); // PC (TODO: add other languages)
break;
default : ;
}
#undef CHECK_FILE
} else {
switch (id) {
case LVL_TR1_TITLE : return "level/1/TITLEH.PCX";
case LVL_TR2_TITLE : return "level/2/TITLE.PCX";
case LVL_TR3_TITLE : return "level/3/TITLEUK.BMP";
default : ;
}
default : ;
}
#undef CHECK_FILE
return NULL;
}
}

View File

@@ -10,6 +10,8 @@
#define INVENTORY_BG_SIZE 512
#define INVENTORY_HEIGHT 2048.0f
#define TITLE_LOADING 64.0f
struct Inventory {
enum Page {
@@ -29,6 +31,7 @@ struct Inventory {
Page page, targetPage;
int itemsCount;
float titleTimer;
float changeTimer;
TR::LevelID nextLevel; // toggle result
ControlKey lastKey;
@@ -168,8 +171,12 @@ struct Inventory {
} *items[INVENTORY_MAX_ITEMS];
static void loadTitleBG(Stream *stream, void *userData) {
if (!stream) return;
Inventory *inv = (Inventory*)userData;
if (!stream) {
inv->titleTimer = 0.0f;
return;
}
inv->titleTimer = 3.0f;
inv->background[0] = Texture::Load(*stream);
delete stream;
@@ -214,21 +221,20 @@ struct Inventory {
TR::Level *level = game->getLevel();
memset(background, 0, sizeof(background));
const char *titleBG = TR::getGameScreen(level->version, level->id);
if (titleBG) {
titleTimer = TITLE_LOADING;
new Stream(titleBG, loadTitleBG, this);
} else
titleTimer = 0.0f;
if (level->isTitle()) {
add(TR::Entity::INV_HOME);
memset(background, 0, sizeof(background));
const char *titleBG = TR::getGameScreen(level->version, level->id);
if (titleBG)
new Stream(titleBG, loadTitleBG, this);
} else {
add(TR::Entity::INV_COMPASS);
add(TR::Entity::INV_STOPWATCH);
for (int i = 0; i < COUNT(background); i++)
background[i] = new Texture(INVENTORY_BG_SIZE, INVENTORY_BG_SIZE, Texture::RGBA, false);
}
phaseRing = phasePage = phaseChoose = phaseSelect = 0.0f;
@@ -582,6 +588,15 @@ struct Inventory {
}
void update() {
if (titleTimer != TITLE_LOADING && titleTimer > 0.0f) {
titleTimer -= Core::deltaTime;
if (titleTimer < 0.0f)
titleTimer = 0.0f;
}
if (!isActive())
return;
float lastChoose = phaseChoose;
if (phaseChoose == 0.0f)
@@ -737,6 +752,15 @@ struct Inventory {
}
void prepareBackground() {
if (background[0]->origWidth != INVENTORY_BG_SIZE || background[0]->origHeight != INVENTORY_BG_SIZE) {
delete background[0];
background[0] = NULL;
}
for (int i = 0; i < COUNT(background); i++)
if (!background[i])
background[i] = new Texture(INVENTORY_BG_SIZE, INVENTORY_BG_SIZE, Texture::RGBA, false);
Core::setDepthTest(false);
Core::setBlending(bmNone);
@@ -1008,9 +1032,11 @@ struct Inventory {
}
void render() {
if (!isActive() && titleTimer == 0.0f)
return;
// background
Core::setDepthTest(false);
Core::setBlending(bmNone);
if (background[0]) {
background[0]->bind(sDiffuse); // orignal image
@@ -1018,6 +1044,7 @@ struct Inventory {
game->setShader(Core::passFilter, Shader::FILTER_MIXER, false, false);
Core::active.shader->setParam(uParam, vec4(phaseRing, 1.0f - phaseRing * 0.4f, 0, 0));;
background[1]->bind(sNormal); // blured grayscale image
Core::setBlending(bmNone);
} else {
game->setShader(Core::passFilter, Shader::DEFAULT, false, false);
@@ -1026,17 +1053,23 @@ struct Inventory {
float aspectImg = aspectDst / aspectSrc;
float ax = background[0]->origWidth / float(background[0]->width);
float ay = background[0]->origHeight / float(background[0]->height);
Core::active.shader->setParam(uParam, vec4(ax * aspectImg, -ay, (0.5f - aspectImg * 0.5f) * ax, ay));
if (!isActive() && titleTimer > 0.0f && titleTimer < 1.0f) {
Core::setBlending(bmAlpha);
Core::active.shader->setParam(uMaterial, vec4(1, 1, 1, titleTimer));
} else {
Core::setBlending(bmNone);
Core::active.shader->setParam(uMaterial, vec4(1));
}
}
Core::setBlending(bmNone);
game->getMesh()->renderQuad();
}
Core::setDepthTest(true);
Core::setBlending(bmAlpha);
if (game->getLevel()->isCutsceneLevel())
if (game->getLevel()->isCutsceneLevel() || !isActive())
return;
// items

View File

@@ -609,7 +609,12 @@ struct Level : IGame {
sndSoundtrack = NULL;
playTrack(0);
sndCurrent = sndSoundtrack;
/*
if (level.id == TR::LVL_TR2_RIG) {
lara->animation.setAnim(level.models[level.extra.laraSpec].animation);
camera->doCutscene(lara->pos, lara->angle.y);
}
*/
Core::resetTime();
}
@@ -1254,9 +1259,15 @@ struct Level : IGame {
Sound::Sample *sndChanged = sndCurrent;
inventory.update();
if (inventory.titleTimer > 1.0f)
return;
UI::update();
if (inventory.isActive() || level.isTitle()) {
Sound::reverb.setRoomSize(vec3(1.0f));
inventory.update();
if (!level.isTitle())
sndChanged = NULL;
} else {
@@ -1855,8 +1866,8 @@ struct Level : IGame {
// lara->visibleMask = 0xFFFFFFFF; // catsuit test
}
void renderInventory() {
Core::setTarget(NULL, true);
void renderInventory(bool clear) {
Core::setTarget(NULL, clear);
if (Core::settings.detail.stereo) {
Core::setViewport(0, 0, Core::width / 2, Core::height);
Core::eye = -1.0f;
@@ -1871,7 +1882,7 @@ struct Level : IGame {
}
void renderUI() {
if (level.isCutsceneLevel()) return;
if (level.isCutsceneLevel() || inventory.titleTimer > 1.0f) return;
UI::begin();
@@ -1938,8 +1949,7 @@ struct Level : IGame {
if (!title)
renderGame();
if (title)
renderInventory();
renderInventory(title);
if (Core::settings.detail.stereo) {
Core::setViewport(0, 0, Core::width / 2, Core::height);

View File

@@ -1,8 +1,8 @@
@echo off
cls
set SRC=main.cpp ../../libs/stb_vorbis/stb_vorbis.c
set SRC=main.cpp ../../libs/stb_vorbis/stb_vorbis.c ../../libs/tinf/tinflate.c
set PROJ=OpenLara
set FLAGS=-O3 -Wno-deprecated-register --llvm-opts 2 -fmax-type-align=2 -std=c++11 -s ALLOW_MEMORY_GROWTH=1 -Wall -I../../
echo.
call em++ %SRC% %FLAGS% -o %PROJ%.js --preload-file ./level/1/TITLE.PSX --preload-file ./level/1/TITLEH.PCX --preload-file ./audio/1/dummy --preload-file ./audio/2/dummy --preload-file ./audio/3/dummy --preload-file ./level/2/dummy --preload-file ./level/3/dummy
call em++ %SRC% %FLAGS% -o %PROJ%.js --preload-file ./level/1/TITLE.PSX --preload-file ./level/1/AMERTIT.PNG --preload-file ./audio/1/dummy --preload-file ./audio/2/dummy --preload-file ./audio/3/dummy --preload-file ./level/2/dummy --preload-file ./level/3/dummy
gzip.exe -9 -f %PROJ%.data %PROJ%.js %PROJ%.js.mem

View File

@@ -5,7 +5,7 @@ R"====(
#endif
varying vec2 vTexCoord;
uniform vec4 uMaterial;
uniform vec4 uParam;
#ifdef VERTEX
@@ -95,7 +95,7 @@ uniform vec4 uParam;
return equirectangular();
#endif
return texture2D(sDiffuse, vTexCoord);
return texture2D(sDiffuse, vTexCoord) * uMaterial;
}
void main() {

View File

@@ -173,7 +173,40 @@ struct Texture {
struct Color32 {
uint8 r, g, b, a;
};
/*
static void SaveBMP(const char *name, const char *data32, int width, int height) {
BITMAPINFOHEADER BMIH;
BMIH.biSize = sizeof(BITMAPINFOHEADER);
BMIH.biSizeImage = width * height * 4;
BMIH.biSize = sizeof(BITMAPINFOHEADER);
BMIH.biWidth = width;
BMIH.biHeight = height;
BMIH.biPlanes = 1;
BMIH.biBitCount = 32;
BMIH.biCompression = BI_RGB;
BMIH.biSizeImage = width * height * 4;
BITMAPFILEHEADER bmfh;
int nBitsOffset = sizeof(BITMAPFILEHEADER) + BMIH.biSize;
LONG lImageSize = BMIH.biSizeImage;
LONG lFileSize = nBitsOffset + lImageSize;
bmfh.bfType = 'B' + ('M' << 8);
bmfh.bfOffBits = nBitsOffset;
bmfh.bfSize = lFileSize;
bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
char buf[256];
strcpy(buf, name);
strcat(buf, ".bmp");
FILE *f = fopen(buf, "wb");
fwrite(&bmfh, sizeof(bmfh), 1, f);
fwrite(&BMIH, sizeof(BMIH), 1, f);
fwrite(data32, width * height * 4, 1, f);
fclose(f);
}
*/
static Texture* LoadPCX(Stream &stream) {
struct PCX {
uint8 magic;
@@ -329,7 +362,6 @@ struct Texture {
};
}
static Texture* LoadPNG(Stream &stream) {
stream.seek(8);
@@ -614,8 +646,8 @@ struct Texture {
}
static Texture* LoadBIN(Stream &stream) {
int width = 352;
int height = 224;
int width = stream.size / height / 2;
int dw = Core::support.texNPOT ? width : nextPow2(width);
int dh = Core::support.texNPOT ? height : nextPow2(height);
@@ -836,30 +868,8 @@ struct Atlas {
void fillInstances() {
for (int i = 0; i < tilesCount; i++)
if (tiles[i].uv.x == 0x7FFF) {
if (tiles[i].uv.x == 0x7FFF)
callback(tiles[i].id, width, height, tiles[i].uv.y, 0, userData, NULL);
/*
TR::ObjectTexture &r = level.objectTextures[ref];
int minXr = min(min(r.texCoord[0].x, r.texCoord[1].x), r.texCoord[2].x);
int minYr = min(min(r.texCoord[0].y, r.texCoord[1].y), r.texCoord[2].y);
TR::ObjectTexture &t = level.objectTextures[tiles[i].id];
int minX = min(min(t.texCoord[0].x, t.texCoord[1].x), t.texCoord[2].x);
int maxX = max(max(t.texCoord[0].x, t.texCoord[1].x), t.texCoord[2].x);
int minY = min(min(t.texCoord[0].y, t.texCoord[1].y), t.texCoord[2].y);
int maxY = max(max(t.texCoord[0].y, t.texCoord[1].y), t.texCoord[2].y);
int cx = minXr - minX;
int cy = minYr - minY;
for (int i = 0; i < 4; i++) {
if (t.texCoord[i].x == maxX) t.texCoord[i].x++;
if (t.texCoord[i].y == maxY) t.texCoord[i].y++;
t.texCoord[i].x += cx;
t.texCoord[i].y += cy;
}
*/
}
}
};