Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emscripten: Support command line, transitions and saves #425

Merged
merged 9 commits into from Feb 23, 2015
26 changes: 26 additions & 0 deletions src/emscripten-post.js
@@ -0,0 +1,26 @@
function parseargs() {
var tmp = [];
var ret = [];
var items = location.search.substr(1).split("&");
for (var index = 0; index < items.length; index++) {
tmp = items[index].split("=");
ret.push("--" + tmp[0]);
if (tmp.length > 1) {
arg = decodeURI(tmp[1]);
// split except if it's a string
if (arg.length > 0) {
if (arg.slice(0) == "\"" && arg.slice(-1) == "\"") {
ret.push(arg.slice(1, -1));
} else {
var spl = arg.split(" ");
ret = ret.concat(spl);
}
}

}
}
return ret;
}

Module.arguments.push("easyrpg-player");
Module.arguments = Module.arguments.concat(parseargs());
10 changes: 10 additions & 0 deletions src/filefinder.cpp
Expand Up @@ -421,6 +421,16 @@ std::string FileFinder::FindDefault(std::string const& name) {
return FindDefault(GetProjectTree(), name);
}

std::string FileFinder::FindDefault(const ProjectTree& tree, const std::string& dir, const std::string& name) {
static const char* no_exts[] = { "", NULL };

boost::optional<std::string> file = FindFile(tree, dir, name, no_exts);
if (file != boost::none) {
return *file;
}
return "";
}

std::string FileFinder::FindDefault(const ProjectTree& tree, const std::string& name) {
ProjectTree const& p = tree;
string_map const& files = p.files;
Expand Down
10 changes: 10 additions & 0 deletions src/filefinder.h
Expand Up @@ -90,6 +90,16 @@ namespace FileFinder {
*/
std::string FindDefault(const std::string& name);

/**
* Finds a file in a custom project tree.
*
* @param tree Project tree to search
* @param dir directory to check
* @param name the path and name
* @return path to file.
*/
std::string FindDefault(const ProjectTree& tree, const std::string& dir, const std::string& name);

/**
* Finds a file in a custom project tree.
*
Expand Down
11 changes: 9 additions & 2 deletions src/game_interpreter.cpp
Expand Up @@ -216,7 +216,13 @@ void Game_Interpreter::Update() {
}

if (continuation) {
bool result = (this->*continuation)(list[index]);
bool result;
if (index >= list.size()) {
result = (this->*continuation)(RPG::EventCommand());
} else {
result = (this->*continuation)(list[index]);
}

if (result)
continue;
else
Expand Down Expand Up @@ -1308,5 +1314,6 @@ bool Game_Interpreter::CommandGameOver(RPG::EventCommand const& /* com */) { //
// Dummy Continuations

bool Game_Interpreter::ContinuationOpenShop(RPG::EventCommand const& /* com */) { return true; }
bool Game_Interpreter::ContinuationShowInn(RPG::EventCommand const& /* com */) { return true; }
bool Game_Interpreter::ContinuationShowInnStart(RPG::EventCommand const& /* com */) { return true; }
bool Game_Interpreter::ContinuationShowInnFinish(RPG::EventCommand const& /* com */) { return true; }
bool Game_Interpreter::ContinuationEnemyEncounter(RPG::EventCommand const& /* com */) { return true; }
3 changes: 2 additions & 1 deletion src/game_interpreter.h
Expand Up @@ -158,7 +158,8 @@ class Game_Interpreter
virtual bool DefaultContinuation(RPG::EventCommand const& com);
virtual bool ContinuationChoices(RPG::EventCommand const& com);
virtual bool ContinuationOpenShop(RPG::EventCommand const& com);
virtual bool ContinuationShowInn(RPG::EventCommand const& com);
virtual bool ContinuationShowInnStart(RPG::EventCommand const& com);
virtual bool ContinuationShowInnFinish(RPG::EventCommand const& com);
virtual bool ContinuationEnemyEncounter(RPG::EventCommand const& com);

int debug_x;
Expand Down
19 changes: 15 additions & 4 deletions src/game_interpreter_map.cpp
Expand Up @@ -1083,7 +1083,8 @@ bool Game_Interpreter_Map::CommandShowInn(RPG::EventCommand const& com) { // cod
if (Game_Temp::inn_price == 0) {
// Skip prompt.
Game_Message::choice_result = 0;
return ContinuationShowInn(com);
SetContinuation(static_cast<ContinuationFunction>(&Game_Interpreter_Map::ContinuationShowInnStart));
return true;
}

Game_Message::message_waiting = true;
Expand Down Expand Up @@ -1136,11 +1137,11 @@ bool Game_Interpreter_Map::CommandShowInn(RPG::EventCommand const& com) { // cod
Game_Temp::inn_calling = true;
Game_Message::choice_result = 4;

SetContinuation(static_cast<ContinuationFunction>(&Game_Interpreter_Map::ContinuationShowInn));
SetContinuation(static_cast<ContinuationFunction>(&Game_Interpreter_Map::ContinuationShowInnStart));
return true;
}

bool Game_Interpreter_Map::ContinuationShowInn(RPG::EventCommand const& /* com */) {
bool Game_Interpreter_Map::ContinuationShowInnStart(RPG::EventCommand const& /* com */) {
if (Game_Message::visible) {
CloseMessageWindow();
return false;
Expand All @@ -1167,7 +1168,8 @@ bool Game_Interpreter_Map::ContinuationShowInn(RPG::EventCommand const& /* com *
actor->RemoveAllStates();
}
Graphics::Transition(Graphics::TransitionFadeOut, 36, true);
Graphics::Transition(Graphics::TransitionFadeIn, 36, false);
SetContinuation(static_cast<ContinuationFunction>(&Game_Interpreter_Map::ContinuationShowInnFinish));
return false;
}
index++;
return true;
Expand All @@ -1179,6 +1181,15 @@ bool Game_Interpreter_Map::ContinuationShowInn(RPG::EventCommand const& /* com *
return true;
}

bool Game_Interpreter_Map::ContinuationShowInnFinish(RPG::EventCommand const& /* com */) {
continuation = NULL;

Graphics::Transition(Graphics::TransitionFadeIn, 36, false);

index++;
return false;
}

bool Game_Interpreter_Map::CommandEnterHeroName(RPG::EventCommand const& com) { // code 10740
Game_Temp::hero_name_id = com.parameters[0];
Game_Temp::hero_name_charset = com.parameters[1];
Expand Down
3 changes: 2 additions & 1 deletion src/game_interpreter_map.h
Expand Up @@ -128,7 +128,8 @@ class Game_Interpreter_Map : public Game_Interpreter
bool CommandHaltAllMovement(RPG::EventCommand const& com);

bool ContinuationOpenShop(RPG::EventCommand const& com);
bool ContinuationShowInn(RPG::EventCommand const& com);
bool ContinuationShowInnStart(RPG::EventCommand const& com);
bool ContinuationShowInnFinish(RPG::EventCommand const& com);
bool ContinuationEnemyEncounter(RPG::EventCommand const& com);

private:
Expand Down
60 changes: 32 additions & 28 deletions src/graphics.cpp
Expand Up @@ -54,6 +54,7 @@ namespace Graphics {
bool frozen;
TransitionType transition_type;
int transition_duration;
int transition_frames_left;
int transition_frame;
bool screen_erased;

Expand All @@ -64,6 +65,7 @@ namespace Graphics {
std::list<Drawable*> drawable_list;
bool zlist_dirty;
};

EASYRPG_SHARED_PTR<State> state;
std::vector<EASYRPG_SHARED_PTR<State> > stack;
EASYRPG_SHARED_PTR<State> global_state;
Expand All @@ -79,23 +81,26 @@ unsigned SecondToFrame(float const second) {
}

void Graphics::Init() {
#ifdef EMSCRIPTEN
overlay_visible = false;
#else
overlay_visible = true;
#endif
fps_on_screen = false;
fps = 0;
framerate = DEFAULT_FPS;
framecount = 0;
fps_mode = 0;
timer_wait = 0;
frozen_screen = BitmapRef();
screen_erased = false;
transition_frames_left = 0;

black_screen = Bitmap::Create(DisplayUi->GetWidth(), DisplayUi->GetHeight(), Color(0,0,0,255));

frozen = false;
drawable_creation = 0;
state.reset(new State());
global_state.reset(new State());
screen_erased = false;

}

void Graphics::Quit() {
Expand All @@ -122,8 +127,6 @@ void Graphics::Quit() {
}

void Graphics::Update() {
if (frozen) return;

switch(fps_mode) {
case 1:
InternUpdate2();
Expand Down Expand Up @@ -262,11 +265,26 @@ void Graphics::UpdateTitle() {
}

void Graphics::DrawFrame() {
if (transition_duration > 0) {
std::list<Drawable*>::iterator it_list;

if (transition_frames_left > 0) {
UpdateTransition();

for (it_list = global_state->drawable_list.begin(); it_list != global_state->drawable_list.end(); ++it_list) {
(*it_list)->Draw();
}

if (overlay_visible) {
DrawOverlay();
}

DisplayUi->UpdateDisplay();
return;
}

if (screen_erased) {
return;
}
if (screen_erased) return;

if (state->zlist_dirty) {
state->drawable_list.sort(SortDrawableList);
Expand All @@ -280,7 +298,6 @@ void Graphics::DrawFrame() {

DisplayUi->CleanDisplay();

std::list<Drawable*>::iterator it_list;
for (it_list = state->drawable_list.begin(); it_list != state->drawable_list.end(); ++it_list) {
(*it_list)->Draw();
}
Expand Down Expand Up @@ -321,16 +338,14 @@ BitmapRef Graphics::SnapToBitmap() {

void Graphics::Freeze() {
frozen_screen = SnapToBitmap();
frozen = true;
}

void Graphics::Transition(TransitionType type, int duration, bool erase) {
if (erase && screen_erased) return;

if (type != TransitionNone) {
transition_type = type;
transition_frame = 0;
transition_duration = type == TransitionErase ? 1 : duration;
transition_frames_left = transition_duration;

if (state->zlist_dirty) {
state->drawable_list.sort(SortDrawableList);
Expand All @@ -342,7 +357,7 @@ void Graphics::Transition(TransitionType type, int duration, bool erase) {
global_state->zlist_dirty = false;
}

if (!frozen) Freeze();
Freeze();

if (erase) {
screen1 = frozen_screen;
Expand All @@ -356,24 +371,13 @@ void Graphics::Transition(TransitionType type, int duration, bool erase) {
else
screen1 = screen2;
}

#ifndef EMSCRIPTEN
// Fixme: Refactor how transitions work, they should return to the main loop
for (int i = 1; i <= transition_duration; i++) {
Player::Update();
InternUpdate1();
}
#endif
}

if (!erase) frozen_screen = BitmapRef();

frozen = false;
screen_erased = erase;
}

transition_duration = 0;

FrameReset();
bool Graphics::IsTransitionPending() {
return transition_frames_left > 0;
}

void Graphics::UpdateTransition() {
Expand All @@ -386,6 +390,8 @@ void Graphics::UpdateTransition() {

int percentage = transition_frame * 100 / transition_duration;

transition_frames_left--;

// Fallback to FadeIn/Out for not implemented transition types:
// (Remove from here when implemented below)
switch (transition_type) {
Expand Down Expand Up @@ -534,8 +540,6 @@ void Graphics::UpdateTransition() {
DisplayUi->CleanDisplay();
break;
}

DisplayUi->UpdateDisplay();
}

void Graphics::FrameReset() {
Expand Down
5 changes: 5 additions & 0 deletions src/graphics.h
Expand Up @@ -113,6 +113,11 @@ namespace Graphics {
*/
void Transition(TransitionType type, int duration, bool erase = false);

/**
* Gets if a screen transition is executing.
*/
bool IsTransitionPending();

/**
* Freezes the screen, and prepares it for a
* transition.
Expand Down
20 changes: 18 additions & 2 deletions src/player.cpp
Expand Up @@ -111,6 +111,15 @@ void Player::Init(int argc, char *argv[]) {
Output::IgnorePause(true);

emscripten_set_canvas_size(SCREEN_TARGET_WIDTH * 2, SCREEN_TARGET_HEIGHT * 2);

// Retrieve save directory from persistent storage
EM_ASM(
FS.mkdir('/Save');
FS.mount(IDBFS, {}, '/Save');

FS.syncfs(true, function(err) {
});
);
#endif

srand(time(NULL));
Expand Down Expand Up @@ -152,7 +161,7 @@ void Player::Run() {
#ifdef EMSCRIPTEN
emscripten_set_main_loop(Player::MainLoop, 0, 0);
#else
while (Scene::instance->type != Scene::Null)
while (Graphics::IsTransitionPending() || Scene::instance->type != Scene::Null)
Player::MainLoop();
#endif
}
Expand All @@ -164,7 +173,7 @@ void Player::MainLoop() {
}
Scene::old_instances.clear();

if (Scene::instance->type == Scene::Null) {
if (!Graphics::IsTransitionPending() && Scene::instance->type == Scene::Null) {
Player::Exit();
}
}
Expand Down Expand Up @@ -205,7 +214,14 @@ void Player::Update() {
void Player::Exit() {
#ifdef EMSCRIPTEN
emscripten_cancel_main_loop();

BitmapRef surface = DisplayUi->GetDisplaySurface();
std::string error = "You can turn off your browser now.";

Text::Draw(*surface, 55, DisplayUi->GetHeight() / 2 - 6, Color(255, 255, 255, 255), error);
DisplayUi->UpdateDisplay();
#endif

Main_Data::Cleanup();
Graphics::Quit();
FileFinder::Quit();
Expand Down