diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/blupi.cxx | 181 | ||||
-rw-r--r-- | src/blupi.h | 14 | ||||
-rw-r--r-- | src/button.cxx | 6 | ||||
-rw-r--r-- | src/config.h.in | 1 | ||||
-rw-r--r-- | src/decblupi.cxx | 44 | ||||
-rw-r--r-- | src/decgoal.h | 4 | ||||
-rw-r--r-- | src/decio.cxx | 8 | ||||
-rw-r--r-- | src/decmap.cxx | 2 | ||||
-rw-r--r-- | src/decmove.cxx | 2 | ||||
-rw-r--r-- | src/decmove.h | 4 | ||||
-rw-r--r-- | src/decor.cxx | 39 | ||||
-rw-r--r-- | src/decor.h | 13 | ||||
-rw-r--r-- | src/decstat.cxx | 33 | ||||
-rw-r--r-- | src/def.h | 16 | ||||
-rw-r--r-- | src/display.cxx | 97 | ||||
-rw-r--r-- | src/display.h | 73 | ||||
-rw-r--r-- | src/event.cxx | 561 | ||||
-rw-r--r-- | src/event.h | 27 | ||||
-rw-r--r-- | src/fifo.cxx | 4 | ||||
-rw-r--r-- | src/menu.cxx | 6 | ||||
-rw-r--r-- | src/misc.cxx | 27 | ||||
-rw-r--r-- | src/misc.h | 17 | ||||
-rw-r--r-- | src/movie.cxx | 68 | ||||
-rw-r--r-- | src/movie.h | 8 | ||||
-rw-r--r-- | src/pixmap.cxx | 318 | ||||
-rw-r--r-- | src/pixmap.h | 34 | ||||
-rw-r--r-- | src/platform.h | 37 | ||||
-rw-r--r-- | src/platform/platform_js.cxx | 58 | ||||
-rw-r--r-- | src/platform/platform_sdl.cxx | 57 | ||||
-rw-r--r-- | src/progress.cxx | 2 | ||||
-rw-r--r-- | src/progress.h | 2 | ||||
-rw-r--r-- | src/sound.cxx | 61 | ||||
-rw-r--r-- | src/sound.h | 8 | ||||
-rw-r--r-- | src/text.cxx | 4 |
34 files changed, 1443 insertions, 393 deletions
diff --git a/src/blupi.cxx b/src/blupi.cxx index 8c294ad..8c986b5 100644 --- a/src/blupi.cxx +++ b/src/blupi.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -28,9 +28,10 @@ #include <stdlib.h> #include <string> #include <thread> +#include <unistd.h> #include <vector> -#include <SDL2/SDL_image.h> +#include <SDL_image.h> #include <argagg/argagg.hpp> #ifdef USE_CURL #include <curl/curl.h> @@ -47,6 +48,7 @@ #include "misc.h" #include "movie.h" #include "pixmap.h" +#include "platform.h" #include "progress.h" #include "sound.h" @@ -72,10 +74,12 @@ bool g_enableRecorder = false; std::string g_playRecord; bool g_restoreBugs = false; // restore original < v1.9 bugs bool g_restoreMidi = false; // restore music playback based on midi files +bool g_renderQuality = true; // use the best render quality with scaling int g_settingsOverload = 0; bool g_bTermInit = false; // initialisation en cours Uint32 g_lastPhase = 999; +RestartMode g_restart = RestartMode::NO; static bool g_pause; #ifdef USE_CURL @@ -84,7 +88,7 @@ struct url_data { char * buffer; size_t size; }; -#endif +#endif /* USE_CURL */ template <typename Out> static void @@ -179,6 +183,11 @@ ReadConfig () !(g_settingsOverload & SETTING_MIDI) && j.find ("restoremidi") != j.end ()) g_restoreMidi = j["restoremidi"].get<bool> (); + if ( + !(g_settingsOverload & SETTING_RENDERQUALITY) && + j.find ("renderquality") != j.end ()) + g_renderQuality = j["renderquality"].get<bool> (); + return true; } @@ -186,7 +195,7 @@ ReadConfig () * \brief Main frame update. */ static bool -UpdateFrame (void) +Update (void) { Rect clip, rcRect; Uint32 phase; @@ -202,8 +211,8 @@ UpdateFrame (void) rcRect.left = 0; rcRect.top = 0; - rcRect.right = LXIMAGE; - rcRect.bottom = LYIMAGE; + rcRect.right = LXIMAGE (); + rcRect.bottom = LYIMAGE (); g_pPixmap->DrawImage (-1, CHBACK, rcRect); // draw the background if (phase == EV_PHASE_INTRO1) @@ -232,7 +241,8 @@ UpdateFrame (void) g_pEvent->DecorAutoShift (); g_pDecor->Build (clip, posMouse); // build the environment - g_pDecor->NextPhase (1); // rebuild the map sometimes + g_pEvent->PlayMove (posMouse); + g_pDecor->NextPhase (1); // rebuild the map sometimes } if (phase == EV_PHASE_BUILD) @@ -251,6 +261,13 @@ UpdateFrame (void) g_pEvent->DemoStep (); // start automatically (eventually) the demo } + SDL_Event event = {0}; + event.type = SDL_MOUSEMOTION; + event.motion.x = posMouse.x; + event.motion.y = posMouse.y; + g_pEvent->EventButtons (event, posMouse); + g_pEvent->MouseSprite (posMouse); + g_pEvent->DrawButtons (); g_lastPhase = phase; @@ -387,7 +404,9 @@ HandleEvent (const SDL_Event & event) case SDL_RENDER_DEVICE_RESET: case SDL_RENDER_TARGETS_RESET: + g_pDecor->InvalidateGrounds (); g_pPixmap->ReloadTargetTextures (); + g_pEvent->LoadBackground (); break; case SDL_USEREVENT: @@ -400,7 +419,7 @@ HandleEvent (const SDL_Event & event) bool display = true; if (!g_pause) - display = UpdateFrame (); + display = Update (); if (!g_pEvent->IsMovie () && display) g_pPixmap->Display (); @@ -410,7 +429,10 @@ HandleEvent (const SDL_Event & event) case EV_WARPMOUSE: { const SDL_Point * coord = static_cast<SDL_Point *> (event.user.data1); - SDL_WarpMouseInWindow (g_window, coord->x, coord->y); + + Sint32 x = coord->x, y = coord->y; + g_pPixmap->FromGameToDisplay (x, y); + SDL_WarpMouseInWindow (g_window, x, y); delete coord; break; } @@ -501,10 +523,10 @@ progressCallback ( } #endif /* USE_CURL */ +#ifdef USE_CURL static void CheckForUpdates () { -#ifdef USE_CURL url_data chunk; chunk.buffer = nullptr; /* we expect realloc(NULL, size) to work */ @@ -548,8 +570,8 @@ CheckForUpdates () free (chunk.buffer); curl_easy_cleanup (curl); -#endif /* USE_CURL */ } +#endif /* USE_CURL */ static int parseArgs (int argc, char * argv[], bool & exit) @@ -573,6 +595,10 @@ parseArgs (int argc, char * argv[], bool & exit) {"-z", "--zoom"}, "change the window scale (only if fullscreen is off) [1;2] (default: 1)", 1}, + {"legacy", + {"-l", "--legacy"}, + "start the game in legacy display mode (640x480)", + 0}, {"renderer", {"-r", "--renderer"}, "set a renderer [auto;software;accelerated] (default: auto)", @@ -598,7 +624,12 @@ parseArgs (int argc, char * argv[], bool & exit) {"restoremidi", {"-m", "--restore-midi"}, "restore playback based on MIDI music instead of OGG", - 0}}}; + 0}, + {"renderquality", + {"-q", "--render-quality"}, + "enable anti-aliasing [on;off] (default: on, ignored if " + "windowed)", + 1}}}; argagg::parser_results args; try @@ -653,6 +684,12 @@ parseArgs (int argc, char * argv[], bool & exit) g_settingsOverload |= SETTING_ZOOM; } + if (args["legacy"]) + { + Display::getDisplay ().setDisplaySize (LXLOGIC (), LYLOGIC ()); + g_settingsOverload |= SETTING_LEGACY; + } + if (args["renderer"]) { if (args["renderer"].as<std::string> () == "auto") @@ -690,6 +727,13 @@ parseArgs (int argc, char * argv[], bool & exit) g_settingsOverload |= SETTING_MIDI; } + if (args["renderquality"]) + { + g_renderQuality = + args["renderquality"].as<std::string> () != std::string ("off"); + g_settingsOverload |= SETTING_RENDERQUALITY; + } + return EXIT_SUCCESS; } @@ -714,6 +758,15 @@ DoInit (int argc, char * argv[], bool & exit) return EXIT_FAILURE; } +#ifdef __LINUX__ + if (!getenv ("ALSA_CONFIG_DIR")) + { + static char env[256]; + snprintf (env, sizeof (env), "ALSA_CONFIG_DIR=/usr/share/alsa"); + putenv (env); + } +#endif /* __LINUX__ */ + #ifdef _WIN32 /* Fix laggy sounds on Windows by not using winmm driver. */ SDL_setenv ("SDL_AUDIODRIVER", "directsound", true); @@ -726,10 +779,13 @@ DoInit (int argc, char * argv[], bool & exit) return EXIT_FAILURE; } + if (!(g_settingsOverload & SETTING_LEGACY)) + Display::getDisplay ().readDisplaySize (); + // Create a window. g_window = SDL_CreateWindow ( gettext ("Planet Blupi"), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - LXIMAGE, LYIMAGE, 0); + LXIMAGE (), LYIMAGE (), 0); if (!g_window) { @@ -752,7 +808,7 @@ DoInit (int argc, char * argv[], bool & exit) return EXIT_FAILURE; } - SDL_RenderSetLogicalSize (g_renderer, LXIMAGE, LYIMAGE); + SDL_RenderSetLogicalSize (g_renderer, LXIMAGE (), LYIMAGE ()); const auto renders = SDL_GetNumRenderDrivers (); for (int i = 0; i < renders; ++i) @@ -779,16 +835,24 @@ DoInit (int argc, char * argv[], bool & exit) info.max_texture_height); } + // Create the event manager. + g_pEvent = new CEvent; + if (g_pEvent == nullptr) + { + InitFail ("New event"); + return EXIT_FAILURE; + } + // Create the main pixmap. - g_pPixmap = new CPixmap; + g_pPixmap = new CPixmap (g_pEvent); if (g_pPixmap == nullptr) { InitFail ("New pixmap"); return EXIT_FAILURE; } - totalDim.x = LXIMAGE; - totalDim.y = LYIMAGE; + totalDim.x = LXIMAGE (); + totalDim.y = LYIMAGE (); if (!g_pPixmap->Create (totalDim)) { InitFail ("Create pixmap"); @@ -796,8 +860,8 @@ DoInit (int argc, char * argv[], bool & exit) } OutputDebug ("Image: init\n"); - totalDim.x = LXIMAGE; - totalDim.y = LYIMAGE; + totalDim.x = LXLOGIC (); + totalDim.y = LYLOGIC (); iconDim.x = 0; iconDim.y = 0; #if _INTRO @@ -808,17 +872,15 @@ DoInit (int argc, char * argv[], bool & exit) return EXIT_FAILURE; OutputDebug ("Image: init\n"); - totalDim.x = LXIMAGE; - totalDim.y = LYIMAGE; - iconDim.x = 0; - iconDim.y = 0; - if (!g_pPixmap->Cache (CHGROUND, "image/init.png", totalDim, iconDim)) + totalDim.x = LXIMAGE (); + totalDim.y = LYIMAGE (); + if (!g_pPixmap->Cache (CHGROUND, totalDim)) return EXIT_FAILURE; rcRect.left = 0; rcRect.top = 0; - rcRect.right = LXIMAGE; - rcRect.bottom = LYIMAGE; + rcRect.right = LXIMAGE (); + rcRect.bottom = LYIMAGE (); g_pPixmap->DrawImage (-1, CHBACK, rcRect); // dessine le fond g_pPixmap->Display (); @@ -961,7 +1023,7 @@ DoInit (int argc, char * argv[], bool & exit) g_pSound->SetState (true); // Create the movie manager. - g_pMovie = new CMovie; + g_pMovie = new CMovie (g_pPixmap); if (g_pMovie == nullptr) { InitFail ("New movie"); @@ -981,27 +1043,24 @@ DoInit (int argc, char * argv[], bool & exit) g_pDecor->Create (g_pSound, g_pPixmap); g_pDecor->MapInitColors (); - // Create the event manager. - g_pEvent = new CEvent; - if (g_pEvent == nullptr) - { - InitFail ("New event"); - return EXIT_FAILURE; - } - const bool zoom = g_zoom; + const bool renderQuality = g_renderQuality; g_pEvent->Create (g_pPixmap, g_pDecor, g_pSound, g_pMovie); + if (renderQuality != g_renderQuality) + g_pPixmap->CreateMainTexture (); // Load all cursors - g_pPixmap->LoadCursors (g_zoom); + g_pPixmap->LoadCursors (); g_pPixmap->ChangeSprite (SPRITE_WAIT); +#ifdef USE_CURL g_updateThread = new std::thread (CheckForUpdates); - if (g_bFullScreen) - g_pEvent->SetFullScreen (true); - if (!g_bFullScreen && zoom != g_zoom) +#endif /* USE_CURL */ + + if (zoom != g_zoom) g_pEvent->SetWindowSize (g_zoom); + g_pEvent->SetFullScreen (g_bFullScreen); g_pEvent->ChangePhase (EV_PHASE_INTRO1); g_bTermInit = true; @@ -1027,23 +1086,8 @@ main (int argc, char * argv[]) if ((res = DoInit (argc, argv, exit)) || exit) return res; - SDL_TimerID updateTimer = SDL_AddTimer ( - g_timerInterval, - [](Uint32 interval, void * param) -> Uint32 { - CEvent::PushUserEvent (EV_UPDATE); - return interval; - }, - nullptr); + Platform::run (HandleEvent); - SDL_Event event; - while (SDL_WaitEvent (&event)) - { - HandleEvent (event); - if (event.type == SDL_QUIT) - break; - } - - SDL_RemoveTimer (updateTimer); FinishObjects (); if (g_renderer) @@ -1061,5 +1105,32 @@ main (int argc, char * argv[]) delete (g_updateThread); } + /* Restart the game when the fullscreen mode (ratio) has changed. */ + if (g_restart != RestartMode::NO) + { + std::vector<const char *> _argv; + std::string argv0; + std::string bin = basename (argv[0]); + + if (getenv ("APPIMAGE")) + argv0 = getenv ("APPIMAGE"); + else + argv0 = GetBinDir () + bin; + + _argv.push_back (bin.c_str ()); + if (g_restart == RestartMode::LEGACY) + { + _argv.push_back ("--legacy"); + _argv.push_back ("--fullscreen"); + _argv.push_back ("on"); + _argv.push_back ("--zoom"); + _argv.push_back ("2"); + } + _argv.push_back (nullptr); + + SDL_Log ("Reload the game from %s", argv0.c_str ()); + execv (argv0.c_str (), const_cast<char **> (&_argv[0])); + } + return 0; } diff --git a/src/blupi.h b/src/blupi.h index 950ea10..6b781cc 100644 --- a/src/blupi.h +++ b/src/blupi.h @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -20,20 +20,28 @@ #pragma once -#include <SDL2/SDL.h> +#include <SDL.h> #include <libintl.h> #include <string> #include "config.h" +class CEvent; + +enum RestartMode { NO = 0, LEGACY, DESKTOP }; + extern SDL_Window * g_window; extern SDL_Renderer * g_renderer; extern bool g_bFullScreen; extern Uint8 g_zoom; extern bool g_restoreBugs; extern bool g_restoreMidi; +extern bool g_renderQuality; extern bool g_enableRecorder; extern std::string g_playRecord; +extern CEvent * g_pEvent; +extern RestartMode g_restart; +extern Sint32 g_timerInterval; enum Settings { SETTING_FULLSCREEN = 1 << 0, @@ -43,6 +51,8 @@ enum Settings { SETTING_ZOOM = 1 << 4, SETTING_DRIVER = 1 << 5, SETTING_MIDI = 1 << 6, + SETTING_LEGACY = 1 << 7, + SETTING_RENDERQUALITY = 1 << 8, }; extern int g_settingsOverload; diff --git a/src/button.cxx b/src/button.cxx index d31ca01..7a09128 100644 --- a/src/button.cxx +++ b/src/button.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -274,8 +274,8 @@ CButton::TreatEvent (const SDL_Event & event) pos.x = event.button.x; pos.y = event.button.y; - if (MouseUp (pos)) - return false; // (*) + if (MouseUp (pos)) // (*) + return false; break; } diff --git a/src/config.h.in b/src/config.h.in index e1630ef..e242b04 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -22,3 +22,4 @@ #define PB_VERSION_MINOR @PB_VERSION_MINOR@ #define PB_VERSION_PATCH @PB_VERSION_PATCH@ #define PB_VERSION_EXTRA "@PB_VERSION_EXTRA@" +#define PB_BINDIR "@CMAKE_INSTALL_BINDIR@" diff --git a/src/decblupi.cxx b/src/decblupi.cxx index e236eba..e29513a 100644 --- a/src/decblupi.cxx +++ b/src/decblupi.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -200,6 +200,7 @@ void CDecor::BlupiDelete (Sint32 rank) { m_blupi[rank].bExist = false; + this->m_pSound->StopSound(true, rank); if ( !m_bBuild && // phase de jeu ? @@ -236,6 +237,7 @@ CDecor::BlupiKill (Sint32 exRank, Point cel, Sint32 type) if (type == 0) // explosion ? { m_blupi[rank].bExist = false; // mort instantannée + this->m_pSound->StopSound(true, rank); } if (type == 1) // électro ? @@ -467,9 +469,9 @@ CDecor::BlupiSound (Sint32 rank, Sounds sound, Point pos, bool bStop) } if (bStop) - m_pSound->PlayImage (sound, pos, rank); + m_pSound->PlayImage (sound, pos, rank, bStop); else - m_pSound->PlayImage (sound, pos); + m_pSound->PlayImage (sound, pos, rank); } // Sons associés à des actions. @@ -2184,7 +2186,9 @@ CDecor::GoalStop (Sint32 rank, bool bError, bool bSound) }; static Sounds table_sound_boing[] = { - SOUND_BOING1, SOUND_BOING2, SOUND_BOING3, + SOUND_BOING1, + SOUND_BOING2, + SOUND_BOING3, }; if (bError && bSound) @@ -2220,8 +2224,8 @@ CDecor::GoalStop (Sint32 rank, bool bError, bool bSound) { if (bError) { - pos.x = LXIMAGE / 2; - pos.y = LYIMAGE / 2; + pos.x = LXIMAGE () / 2; + pos.y = LYIMAGE () / 2; BlupiSound ( rank, table_sound_boing[Random (0, countof (table_sound_boing) - 1)], pos, true); @@ -3463,12 +3467,16 @@ CDecor::BlupiHiliUp (Point pos) static Sounds table_sound_okf[] = // si fatigué { - SOUND_OK1f, SOUND_OK2f, SOUND_OK3f, + SOUND_OK1f, + SOUND_OK2f, + SOUND_OK3f, }; static Sounds table_sound_oke[] = // si énervé { - SOUND_OK1e, SOUND_OK2e, SOUND_OK3e, + SOUND_OK1e, + SOUND_OK2e, + SOUND_OK3e, }; if (m_bHiliRect) // rectangle de sélection existe ? @@ -3757,6 +3765,8 @@ CDecor::GetDefButton (Point cel) if (icon == 61) button = BUTTON_CULTIVE; // cabane + if (icon == 81 || icon == 83 || icon == 94) + button = BUTTON_FLOWER; if (icon == 122) button = BUTTON_EXTRAIT; // extrait @@ -4102,11 +4112,15 @@ CDecor::BlupiGoal (Point cel, Buttons button) }; static Sounds table_sound_gom[] = { - SOUND_GO4, SOUND_GO5, SOUND_GO6, + SOUND_GO4, + SOUND_GO5, + SOUND_GO6, }; static Sounds table_sound_boing[] = { - SOUND_BOING1, SOUND_BOING2, SOUND_BOING3, + SOUND_BOING1, + SOUND_BOING2, + SOUND_BOING3, }; if (button == -1) @@ -4145,9 +4159,9 @@ CDecor::BlupiGoal (Point cel, Buttons button) } if (avg.x < 0) avg.x = 0; - if (avg.x > LXIMAGE) - avg.x = LXIMAGE; - avg.y = LYIMAGE / 2; + if (avg.x > LXIMAGE ()) + avg.x = LXIMAGE (); + avg.y = LYIMAGE () / 2; if (nb == 0 && nbHili > 0) { @@ -4588,8 +4602,8 @@ CDecor::IsTerminated () Sint32 nb, count, out; Point pos; - pos.x = LXIMAGE / 2; - pos.y = LYIMAGE / 2; + pos.x = LXIMAGE () / 2; + pos.y = LYIMAGE () / 2; count = m_winCount; m_winCount = 50; diff --git a/src/decgoal.h b/src/decgoal.h index e10b77d..94f87b8 100644 --- a/src/decgoal.h +++ b/src/decgoal.h @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -20,7 +20,7 @@ #pragma once -#include <SDL2/SDL_stdinc.h> +#include <SDL_stdinc.h> // Méta opérations (goal). diff --git a/src/decio.cxx b/src/decio.cxx index 1ad8929..7978f70 100644 --- a/src/decio.cxx +++ b/src/decio.cxx @@ -291,6 +291,14 @@ CDecor::Read ( } } + /* Restore the flagged state where flagged ground */ + for (size_t i = 0; i < countof (m_decor); ++i) + for (size_t j = 0; j < countof (m_decor[i]); ++j) + { + if (m_decor[i][j].objectIcon == 124) + m_decorMem[i][j].flagged = true; + } + if (majRev == 1 && minRev == 3) { memset (m_blupi, 0, sizeof (Blupi) * MAXBLUPI); diff --git a/src/decmap.cxx b/src/decmap.cxx index 9b68ca2..1366582 100644 --- a/src/decmap.cxx +++ b/src/decmap.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify diff --git a/src/decmove.cxx b/src/decmove.cxx index 5decaad..df62fff 100644 --- a/src/decmove.cxx +++ b/src/decmove.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify diff --git a/src/decmove.h b/src/decmove.h index 1ef4de0..9ed92f2 100644 --- a/src/decmove.h +++ b/src/decmove.h @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -20,7 +20,7 @@ #pragma once -#include <SDL2/SDL_stdinc.h> +#include <SDL_stdinc.h> Sint16 * GetListMoves (Sint32 rank); Sint16 * GetListIcons (Sint32 rank); diff --git a/src/decor.cxx b/src/decor.cxx index 2090904..42be5f3 100644 --- a/src/decor.cxx +++ b/src/decor.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -193,10 +193,11 @@ CDecor::Init (Sint32 channel, Sint32 icon) m_decor[x][y].objectChannel = -1; m_decor[x][y].objectIcon = -1; - m_decor[x][y].fog = FOGHIDE; // caché - m_decor[x][y].rankMove = -1; - m_decor[x][y].workBlupi = -1; - m_decor[x][y].fire = 0; + m_decor[x][y].fog = FOGHIDE; // caché + m_decor[x][y].rankMove = -1; + m_decor[x][y].workBlupi = -1; + m_decor[x][y].fire = 0; + m_decorMem[x][y].flagged = false; } } @@ -403,6 +404,10 @@ CDecor::PutObject (Point cel, Sint32 channel, Sint32 icon) m_decor[cel.x / 2][cel.y / 2].objectChannel = channel; m_decor[cel.x / 2][cel.y / 2].objectIcon = icon; + /* When flagged, it's possible to build a mine for iron */ + if (icon == 124) + m_decorMem[cel.x / 2][cel.y / 2].flagged = true; + SubDrapeau (cel); // on pourra de nouveau planter un drapeau return true; @@ -1272,7 +1277,7 @@ CDecor::Build (Rect clip, Point posMouse) rank = m_rankBlupi[x][y]; if ( rank != -1 && // un blupi sur cette cellule ? - !m_blupi[rank].bCache) + !m_blupi[rank].bCache && m_blupi[rank].bExist) { cel.x = m_blupi[rank].cel.x; cel.y = m_blupi[rank].cel.y; @@ -1835,13 +1840,13 @@ CDecor::CelOkForAction ( } } - if (action == EV_ACTION_BUILD4) // mine ? + GetFloor (cel, channel, icon); + if ( // mine ? + action == EV_ACTION_BUILD4 && + ((!g_restoreBugs && !m_decorMem[cel.x / 2][cel.y / 2].flagged) || // fixed + (g_restoreBugs && (channel != CHFLOOR || icon != 71)))) // funny bug { - GetFloor (cel, channel, icon); - if (channel != CHFLOOR || icon != 71) // terre à fer ? - { - error = Errors::GROUND; // sol pas adéquat - } + error = Errors::GROUND; // sol pas adéquat } if ( @@ -3315,8 +3320,8 @@ CDecor::MemoPos (Sint32 rank, bool bRecord) { Point pos; - pos.x = LXIMAGE / 2; - pos.y = LYIMAGE / 2; + pos.x = LXIMAGE () / 2; + pos.y = LYIMAGE () / 2; if (rank < 0 || rank >= 4) return; @@ -3494,3 +3499,9 @@ CDecor::IsUndo () { return (m_pUndoDecor != nullptr); } + +void +CDecor::InvalidateGrounds () +{ + m_bGroundRedraw = true; +}
\ No newline at end of file diff --git a/src/decor.h b/src/decor.h index 70ea98b..8011066 100644 --- a/src/decor.h +++ b/src/decor.h @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -52,6 +52,10 @@ typedef struct { // Cette structure doit être la plus petite possible, car // il en existe un tableau de 100x100 = 10'000 cellules ! +typedef struct : Cellule { + bool flagged; // when a flag has been built for the iron +} CellMem; + // Descripteur d'un blupi animé. #define MAXBLUPI 100 #define MAXUSED 50 @@ -366,9 +370,9 @@ public: void StatisticDraw (); void GenerateStatictic (); bool StatisticDown (Point pos); - bool StatisticMove (Point pos); + bool StatisticMove (Point pos, bool & disable); bool StatisticUp (Point pos); - Sint32 StatisticDetect (Point pos); + Sint32 StatisticDetect (Point pos, bool & disable); // Chemin.cpp void CheminMemPos (Sint32 exRank); @@ -457,6 +461,8 @@ public: void UndoBack (); bool IsUndo (); + void InvalidateGrounds (); + protected: bool GetSeeBits (Point cel, char * pBits, Sint32 index); Sint32 GetSeeIcon (char * pBits, Sint32 index); @@ -466,6 +472,7 @@ protected: CPixmap * m_pPixmap; Cellule * m_pUndoDecor; Cellule m_decor[MAXCELX / 2][MAXCELY / 2]; + CellMem m_decorMem[MAXCELX / 2][MAXCELY / 2]; Sint16 m_rankBlupi[MAXCELX][MAXCELY]; Blupi m_blupi[MAXBLUPI]; Move m_move[MAXMOVE]; diff --git a/src/decstat.cxx b/src/decstat.cxx index f4e8385..aed44bb 100644 --- a/src/decstat.cxx +++ b/src/decstat.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -807,8 +807,9 @@ CDecor::StatisticDown (Point pos) StatisticUpdate (); - hili = StatisticDetect (pos); - if (hili < 0) + bool disable; + hili = StatisticDetect (pos, disable); + if (hili < 0 || disable) return false; if (m_bStatUp && hili == 0) // flèche up ? @@ -817,8 +818,8 @@ CDecor::StatisticDown (Point pos) if (m_statFirst < STATNB - 1) m_statFirst = 0; StatisticUpdate (); - pos.x = LXIMAGE / 2; - pos.y = LYIMAGE / 2; + pos.x = LXIMAGE () / 2; + pos.y = LYIMAGE () / 2; m_pSound->PlayImage (SOUND_OPEN, pos); return true; } @@ -830,8 +831,8 @@ CDecor::StatisticDown (Point pos) else m_statFirst += STATNB - 2; StatisticUpdate (); - pos.x = LXIMAGE / 2; - pos.y = LYIMAGE / 2; + pos.x = LXIMAGE () / 2; + pos.y = LYIMAGE () / 2; m_pSound->PlayImage (SOUND_OPEN, pos); return true; } @@ -984,11 +985,11 @@ select: // Souris déplacée dans les statistiques. bool -CDecor::StatisticMove (Point pos) +CDecor::StatisticMove (Point pos, bool & disable) { Sint32 rank; - rank = StatisticDetect (pos); + rank = StatisticDetect (pos, disable); if (rank != m_statHili) // autre mise en évidence ? m_statHili = rank; @@ -1007,10 +1008,12 @@ CDecor::StatisticUp (Point pos) // Détecte dans quelle statistique est la souris. Sint32 -CDecor::StatisticDetect (Point pos) +CDecor::StatisticDetect (Point pos, bool & disable) { Sint32 rank; + disable = false; + // Dans un bouton stop/setup/write ? if (pos.x >= 10 && pos.x <= 10 + 42 * 3 && pos.y >= 422 && pos.y <= 422 + 40) { @@ -1029,12 +1032,18 @@ CDecor::StatisticDetect (Point pos) if (rank >= STATNB) return -1; - auto pStatistic = StatisticGet (rank); + if (rank == 11 && this->m_bStatDown) + return rank; + + if (rank == 0 && this->m_bStatUp) + return rank; + + auto pStatistic = StatisticGet (m_statFirst + rank - !!m_bStatUp); if ( this->GetSkill () >= 1 && pStatistic->perso >= 0 && (pStatistic->perso != 0 && pStatistic->perso != 8)) { - return -1; + disable = true; } return rank; @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -20,18 +20,16 @@ #pragma once -#include <SDL2/SDL_stdinc.h> +#include <SDL_stdinc.h> + +#include "display.h" // clang-format off #define _INTRO true // true for init screen -#define SCRFACTOR 4 / 3 -#define LXIMAGE (480 * SCRFACTOR + (480 * SCRFACTOR) % 2) // window size -#define LYIMAGE 480 - #define POSDRAWX 144 // draw surface #define POSDRAWY 15 -#define DIMDRAWX (LXIMAGE - (640 - 480)) +#define DIMDRAWX (LXIMAGE () - (LXLOGIC () - LYLOGIC ())) #define DIMDRAWY 450 #define POSMAPX 8 // map surface @@ -559,6 +557,8 @@ enum ShiftDirection { #define EV_READ8 (EV_OFFSET+308) #define EV_READ9 (EV_OFFSET+309) +#define EV_READ_EXIT (EV_OFFSET+320) + #define EV_WRITE0 (EV_OFFSET+310) #define EV_WRITE1 (EV_OFFSET+311) #define EV_WRITE2 (EV_OFFSET+312) @@ -611,6 +611,8 @@ enum ShiftDirection { #define EV_MUSIC_STOP (EV_OFFSET+550) +#define EV_SETUP_EXIT (EV_OFFSET+560) + #define EV_PREV (EV_OFFSET+600) #define EV_NEXT (EV_OFFSET+601) #define EV_MOVIE (EV_OFFSET+602) diff --git a/src/display.cxx b/src/display.cxx new file mode 100644 index 0000000..98c8040 --- /dev/null +++ b/src/display.cxx @@ -0,0 +1,97 @@ +/* + * This file is part of the planetblupi source code + * Copyright (C) 2018, Mathieu Schroeter + * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#include <SDL_video.h> + +#include "blupi.h" +#include "display.h" + +Display::Display () +{ + this->width = this->getLogicWidth (); + this->height = this->getLogicHeight (); +} + +Display & +Display::getDisplay () +{ + static Display display; + return display; +} + +bool +Display::isWide () +{ + return this->getWidth () > this->getLogicWidth (); +} + +void +Display::readDisplaySize () +{ + SDL_DisplayMode displayMode; + int res; + + if (g_window) + res = SDL_GetWindowDisplayMode (g_window, &displayMode); + else + res = SDL_GetCurrentDisplayMode (0, &displayMode); + + if (res < 0) + return; + + this->setDisplaySize (displayMode.w, displayMode.h); +} + +void +Display::setDisplaySize (Sint32 w, Sint32 h) +{ + this->width = w; + this->height = h; + + if (this->width < this->getLogicWidth ()) + this->width = this->getLogicWidth (); + if (this->height < this->getLogicHeight ()) + this->height = this->getLogicHeight (); +} + +Sint32 +Display::getWidth () +{ + return ( + this->getLogicHeight () * this->width / this->height + + (this->getLogicHeight () * this->width / this->height) % 2); +} + +Sint32 +Display::getHeight () +{ + return this->getLogicHeight (); +} + +Sint32 +Display::getLogicWidth () +{ + return 640; +} + +Sint32 +Display::getLogicHeight () +{ + return 480; +} diff --git a/src/display.h b/src/display.h new file mode 100644 index 0000000..4983cca --- /dev/null +++ b/src/display.h @@ -0,0 +1,73 @@ +/* + * This file is part of the planetblupi source code + * Copyright (C) 2018, Mathieu Schroeter + * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include <SDL_stdinc.h> + +class Display +{ +private: + Sint32 width; + Sint32 height; + +private: + Display (); + +public: + static Display & getDisplay (); + + bool isWide (); + void readDisplaySize (); + void setDisplaySize (Sint32 w, Sint32 h); + Sint32 getWidth (); + Sint32 getHeight (); + Sint32 getLogicWidth (); + Sint32 getLogicHeight (); +}; + +inline Sint32 +LXLOGIC () +{ + return Display::getDisplay ().getLogicWidth (); +} + +inline Sint32 +LYLOGIC () +{ + return Display::getDisplay ().getLogicHeight (); +} + +inline Sint32 +LXIMAGE () +{ + return Display::getDisplay ().getWidth (); +} + +inline Sint32 +LYIMAGE () +{ + return Display::getDisplay ().getHeight (); +} + +inline Sint32 +LXOFFSET () +{ + return ((LXIMAGE () - LXLOGIC ()) / 2); +} diff --git a/src/event.cxx b/src/event.cxx index 5201f93..618c424 100644 --- a/src/event.cxx +++ b/src/event.cxx @@ -37,6 +37,7 @@ #include "misc.h" #include "movie.h" #include "pixmap.h" +#include "platform.h" #include "progress.h" #include "sound.h" #include "text.h" @@ -74,8 +75,10 @@ typedef struct { Sint16 musicMidi; Sint16 fullScreen; Sint16 zoom; + // v1.3 + Sint16 renderQuality; - Sint16 reserve2[89]; + Sint16 reserve2[88]; } DescInfo; // Toutes les premières lettres doivent @@ -101,6 +104,8 @@ static Phase table[] = { EV_PHASE_TESTCD, "image/init.png", + "image/back-stars.png", + CPixmap::Mode::FIX, false, { { @@ -112,6 +117,8 @@ static Phase table[] = { EV_PHASE_INTRO1, "image/intro1.png", + "", + CPixmap::Mode::FIX, false, { { @@ -123,6 +130,8 @@ static Phase table[] = { EV_PHASE_INIT, "image/init.png", + "image/back-stars.png", + CPixmap::Mode::FIX, false, { { @@ -170,6 +179,8 @@ static Phase table[] = { EV_PHASE_HISTORY0, "image/history0.png", + "image/back-book.png", + CPixmap::Mode::FIX, true, { { @@ -193,6 +204,8 @@ static Phase table[] = { EV_PHASE_HISTORY1, "image/history1.png", + "image/back-book.png", + CPixmap::Mode::FIX, true, { { @@ -216,6 +229,8 @@ static Phase table[] = { EV_PHASE_INFO, "image/info%.3d.png", + "image/back-book.png", + CPixmap::Mode::FIX, false, { { @@ -281,6 +296,8 @@ static Phase table[] = { EV_PHASE_PLAY, "image/play.png", + "", + CPixmap::Mode::EXPAND, false, { { @@ -310,6 +327,8 @@ static Phase table[] = { EV_PHASE_STOP, "image/stop%.3d.png", + "image/back-book.png", + CPixmap::Mode::FIX, false, { { @@ -357,6 +376,8 @@ static Phase table[] = { EV_PHASE_HELP, "image/help.png", + "image/back-book.png", + CPixmap::Mode::FIX, true, { { @@ -398,6 +419,8 @@ static Phase table[] = { EV_PHASE_SETUP, "image/setup01.png", + "image/back-setup.png", + CPixmap::Mode::FIX, false, { { @@ -461,7 +484,7 @@ static Phase table[] = { translate ("Faster") }, }, { - EV_PHASE_STOP, + EV_SETUP_EXIT, 0, {1, 40}, 11, 424, { translate ("Finish") }, @@ -475,6 +498,8 @@ static Phase table[] = { EV_PHASE_SETUPp, "image/setup01.png", + "image/back-setup.png", + CPixmap::Mode::FIX, false, { { @@ -552,6 +577,8 @@ static Phase table[] = { EV_PHASE_READ, "image/read.png", + "image/back-chest-r.png", + CPixmap::Mode::FIX, false, { { @@ -615,7 +642,7 @@ static Phase table[] = {}, }, { - EV_PHASE_STOP, + EV_READ_EXIT, 0, {1, 40}, 16, 424, { translate ("Finish") }, @@ -629,6 +656,8 @@ static Phase table[] = { EV_PHASE_WRITE, "image/write.png", + "image/back-chest-w.png", + CPixmap::Mode::FIX, false, { { @@ -706,6 +735,8 @@ static Phase table[] = { EV_PHASE_WRITEp, "image/write.png", + "image/back-chest-w.png", + CPixmap::Mode::FIX, false, { { @@ -783,6 +814,8 @@ static Phase table[] = { EV_PHASE_LOST, "image/lost.png", + "image/back-lost.png", + CPixmap::Mode::FIX, true, { { @@ -800,6 +833,8 @@ static Phase table[] = { EV_PHASE_WIN, "image/win.png", + "image/back-win.png", + CPixmap::Mode::FIX, true, { { @@ -817,6 +852,8 @@ static Phase table[] = { EV_PHASE_LASTWIN, "image/last%.3d.png", + "", + CPixmap::Mode::FIX, true, { { @@ -834,6 +871,8 @@ static Phase table[] = { EV_PHASE_BUILD, "image/build.png", + "", + CPixmap::Mode::EXPAND, true, { { @@ -949,6 +988,8 @@ static Phase table[] = { EV_PHASE_BUTTON, "image/button.png", + "image/back-build.png", + CPixmap::Mode::FIX, true, { { @@ -1169,6 +1210,8 @@ static Phase table[] = { EV_PHASE_TERM, "image/term.png", + "image/back-build.png", + CPixmap::Mode::FIX, true, { { @@ -1258,6 +1301,8 @@ static Phase table[] = { EV_PHASE_MUSIC, "image/music.png", + "image/back-build.png", + CPixmap::Mode::FIX, true, { { @@ -1341,6 +1386,8 @@ static Phase table[] = { EV_PHASE_REGION, "image/region.png", + "image/back-build.png", + CPixmap::Mode::FIX, true, { { @@ -1382,6 +1429,8 @@ static Phase table[] = { EV_PHASE_PLAYMOVIE, "image/movie.png", + "", + CPixmap::Mode::FIX, false, { { @@ -1393,6 +1442,8 @@ static Phase table[] = { EV_PHASE_WINMOVIE, "image/movie.png", + "", + CPixmap::Mode::FIX, false, { { @@ -1404,6 +1455,8 @@ static Phase table[] = { EV_PHASE_H0MOVIE, "image/movie.png", + "", + CPixmap::Mode::FIX, false, { { @@ -1415,6 +1468,8 @@ static Phase table[] = { EV_PHASE_H1MOVIE, "image/movie.png", + "", + CPixmap::Mode::FIX, false, { { @@ -1426,6 +1481,8 @@ static Phase table[] = { EV_PHASE_H2MOVIE, "image/movie.png", + "", + CPixmap::Mode::FIX, false, { { @@ -1437,6 +1494,8 @@ static Phase table[] = { EV_PHASE_BYE, "image/bye.png", + "image/back-bye.png", + CPixmap::Mode::FIX, false, { { @@ -1448,6 +1507,8 @@ static Phase table[] = { EV_PHASE_INSERT, "image/insert.png", + "", + CPixmap::Mode::FIX, false, { { @@ -1465,6 +1526,8 @@ static Phase table[] = { EV_PHASE_SETTINGS, "image/setup00.png", + "image/back-setup.png", + CPixmap::Mode::FIX, false, { { @@ -1495,13 +1558,13 @@ static Phase table[] = EV_BUTTON5, 0, {1, 50}, 284, 330, - { translate ("Reduce window size") }, + { "" /* dynamic */ }, }, { EV_BUTTON6, 0, {1, 51}, 284 + 40, 330, - { translate ("Increase window size") }, + { "" /* dynamic */ }, }, { EV_BUTTON7, @@ -1516,6 +1579,18 @@ static Phase table[] = { translate ("Use Midi music (original)") }, }, { + EV_BUTTON9, + 0, {1, 50}, + 514, 330, + { translate ("Disable anti-aliasing") }, + }, + { + EV_BUTTON10, + 0, {1, 51}, + 514 + 40, 330, + { translate ("Enable anti-aliasing") }, + }, + { EV_PHASE_INIT, 0, {1, 40}, 42 + 42 * 0, 433, @@ -1628,6 +1703,7 @@ CEvent::CEvent () m_updateBlinking = 0; this->shiftDirection = 0; + this->statDisabled = false; } // Destructeur. @@ -1637,6 +1713,12 @@ CEvent::~CEvent () WriteInfo (); // lit le fichier "info.blp" } +bool +CEvent::IsDemoPlaying () +{ + return this->m_bDemoPlay; +} + // Retourne la position de la souris. Point @@ -1655,24 +1737,27 @@ CEvent::GetMousePos () // Initialise le mode full screen ou non. void -CEvent::SetFullScreen (bool bFullScreen) +CEvent::SetFullScreen (bool bFullScreen, double prevScale) { - int x, y; - SDL_GetMouseState (&x, &y); - x /= g_zoom; - y /= g_zoom; + g_bFullScreen = bFullScreen; - g_zoom = 1; - SDL_SetWindowSize (g_window, LXIMAGE, LYIMAGE); + if (Platform::getType () == Platform::Type::JS) + return; - g_bFullScreen = bFullScreen; + int x, y; + SDL_GetMouseState (&x, &y); + this->m_pPixmap->FromDisplayToGame (x, y, prevScale); - int displayIndex = 0; -#ifndef _WIN32 - displayIndex = SDL_GetWindowDisplayIndex (g_window); + int displayIndex = SDL_GetWindowDisplayIndex (g_window); +#ifdef _WIN32 + if (g_zoom == 2) + displayIndex = 0; #endif /* _WIN32 */ - if (g_bFullScreen) + SDL_RenderClear (g_renderer); + SDL_RenderPresent (g_renderer); + + if (g_bFullScreen && g_zoom == 2) { int displays = SDL_GetNumVideoDisplays (); @@ -1690,16 +1775,14 @@ CEvent::SetFullScreen (bool bFullScreen) g_window, displayBounds[displayIndex].x, displayBounds[displayIndex].y); } - SDL_SetWindowFullscreen (g_window, bFullScreen ? SDL_WINDOW_FULLSCREEN : 0); + SDL_SetWindowFullscreen ( + g_window, bFullScreen ? (g_zoom == 1 ? SDL_WINDOW_FULLSCREEN_DESKTOP + : SDL_WINDOW_FULLSCREEN) + : 0); SDL_SetWindowBordered (g_window, bFullScreen ? SDL_FALSE : SDL_TRUE); SDL_SetWindowGrab (g_window, bFullScreen ? SDL_TRUE : SDL_FALSE); - if (!g_bFullScreen) - SDL_SetWindowPosition ( - g_window, SDL_WINDOWPOS_CENTERED_DISPLAY (displayIndex), - SDL_WINDOWPOS_CENTERED_DISPLAY (displayIndex)); - - m_pPixmap->LoadCursors (g_zoom); + m_pPixmap->LoadCursors (); /* Force this update before otherwise the coordinates retrieved with * the Warp SDL function are corresponding to the previous size. @@ -1745,19 +1828,29 @@ CEvent::SetWindowSize (Uint8 newScale) * \param[in] newScale - The new scale. */ void -CEvent::SetWindowSize (Uint8 prevScale, Uint8 newScale) +CEvent::SetWindowSize (double prevScale, double newScale) { int x, y; SDL_GetMouseState (&x, &y); + this->m_pPixmap->FromDisplayToGame (x, y, prevScale); + + if (g_bFullScreen && newScale == 2) + newScale = 1; - SDL_SetWindowSize (g_window, LXIMAGE * newScale, LYIMAGE * newScale); + SDL_SetWindowSize (g_window, LXIMAGE () * newScale, LYIMAGE () * newScale); + SDL_RenderClear (g_renderer); + SDL_RenderPresent (g_renderer); int displayIndex = SDL_GetWindowDisplayIndex (g_window); SDL_SetWindowPosition ( g_window, SDL_WINDOWPOS_CENTERED_DISPLAY (displayIndex), SDL_WINDOWPOS_CENTERED_DISPLAY (displayIndex)); + SDL_Delay (100); - m_pPixmap->LoadCursors (newScale); + m_pPixmap->LoadCursors (); + + if (prevScale == newScale) + return; /* Force this update before otherwise the coordinates retrieved with * the Warp SDL function are corresponding to the previous size. @@ -1765,8 +1858,8 @@ CEvent::SetWindowSize (Uint8 prevScale, Uint8 newScale) CEvent::PushUserEvent (EV_UPDATE); auto coord = new SDL_Point; // Released by the event handler. - coord->x = newScale < prevScale ? x / prevScale : x * newScale; - coord->y = newScale < prevScale ? y / prevScale : x * newScale; + coord->x = x; + coord->y = y; CEvent::PushUserEvent (EV_WARPMOUSE, coord); } @@ -1912,7 +2005,7 @@ CEvent::SetMenu (Sint32 button, Sint32 menu) // Crée tous les boutons nécessaires à la phase en cours. bool -CEvent::CreateButtons () +CEvent::CreateButtons (Sint32 phase) { Sint32 i = 0, message; Point pos; @@ -1926,16 +2019,21 @@ CEvent::CreateButtons () pos.y = table[m_index].buttons[i].y; message = table[m_index].buttons[i].message; + if ( + phase != EV_PHASE_PLAY && phase != EV_PHASE_BUILD && + phase != EV_PHASE_INIT) + pos.x += LXOFFSET (); + if (m_bPrivate) { if (message == EV_PHASE_SKILL1) { - pos.x = 117; + pos.x = 117 + LXOFFSET (); pos.y = 115; } if (message == EV_PHASE_SKILL2) { - pos.x = 117; + pos.x = 117 + LXOFFSET (); pos.y = 115 + 42; } } @@ -2035,13 +2133,13 @@ CEvent::DrawButtons () snprintf ( res, sizeof (res), "%s %u.%u.%u%s", gettext ("Version"), PB_VERSION_MAJOR, PB_VERSION_MINOR, PB_VERSION_PATCH, PB_VERSION_EXTRA); - pos.x = LXIMAGE - GetTextWidth (res, FONTLITTLE) - 4; + pos.x = LXIMAGE () - GetTextWidth (res, FONTLITTLE) - 4; pos.y = 465; DrawText (m_pPixmap, pos, res, FONTLITTLE); if (!this->m_updateVersion.empty () && this->m_updateBlinking++ % 80 < 40) { - pos.x = 70; + pos.x = 70 + LXOFFSET (); pos.y = 465; snprintf ( res, sizeof (res), @@ -2115,11 +2213,20 @@ CEvent::DrawButtons () SetEnable (EV_BUTTON3, !g_bFullScreen); SetEnable (EV_BUTTON4, g_bFullScreen); - SetEnable (EV_BUTTON5, !g_bFullScreen && g_zoom > 1); - SetEnable (EV_BUTTON6, !g_bFullScreen && g_zoom < 2); + SetEnable (EV_BUTTON5, g_zoom > 1); + SetEnable (EV_BUTTON6, g_zoom < 2); SetEnable (EV_BUTTON7, g_restoreMidi && mid && ogg); SetEnable (EV_BUTTON8, !g_restoreMidi && mid && ogg); + + SetEnable (EV_BUTTON9, g_bFullScreen && g_zoom == 1 && g_renderQuality); + SetEnable (EV_BUTTON10, g_bFullScreen && g_zoom == 1 && !g_renderQuality); + + table[m_index].buttons[4].toolTips[0] = + g_bFullScreen ? gettext ("Desktop mode") : gettext ("Reduce window size"); + table[m_index].buttons[5].toolTips[0] = + g_bFullScreen ? gettext ("Legacy mode (640x480)") + : gettext ("Increase window size"); } assert (m_index >= 0); @@ -2185,7 +2292,7 @@ CEvent::DrawButtons () // Dessine la vitesse. pos.x = 64; - pos.y = LYIMAGE - 15; + pos.y = LYIMAGE () - 15; rect.left = pos.x; rect.right = pos.x + 20; rect.top = pos.y; @@ -2262,7 +2369,7 @@ CEvent::DrawButtons () else snprintf (res, sizeof (res), "%s", gettext ("Save this game")); - pos.x = 420; + pos.x = 420 + LXOFFSET (); pos.y = 8; DrawText (m_pPixmap, pos, res); @@ -2273,11 +2380,11 @@ CEvent::DrawButtons () snprintf (text, sizeof (text), "%d", i + 1); lg = GetTextWidth (text); - pos.x = (420 + 460) / 2 - lg / 2; + pos.x = (420 + 460) / 2 - lg / 2 + LXOFFSET (); pos.y = 30 + 12 + 42 * i; DrawText (m_pPixmap, pos, text, FONTSLIM); - pos.x = 420 + 50; + pos.x = 420 + 50 + LXOFFSET (); if (world >= 0) { @@ -2306,16 +2413,17 @@ CEvent::DrawButtons () { Term * pTerm = m_pDecor->GetTerminated (); - DrawTextCenter (gettext ("Ending conditions"), (10 + 134) / 2, 20); + DrawTextCenter ( + gettext ("Ending conditions"), (10 + 134) / 2 + LXOFFSET (), 20); - pos.x = 170 + 42 * 2 + 4; + pos.x = 170 + 42 * 2 + 4 + LXOFFSET (); pos.y = 30 + 12 + 42 * 4; snprintf ( text, sizeof (text), gettext ("Lost if less than %d Blupi"), pTerm->nbMinBlupi); DrawText (m_pPixmap, pos, text); - pos.x = 170 + 42 * 2 + 4; + pos.x = 170 + 42 * 2 + 4 + LXOFFSET (); pos.y = 30 + 12 + 42 * 5; snprintf ( text, sizeof (text), gettext ("Impossible to win if less than %d Blupi"), @@ -2325,15 +2433,17 @@ CEvent::DrawButtons () // Dessine les textes pour les choix des boutons. if (m_phase == EV_PHASE_BUTTON) - DrawTextCenter (gettext ("Available buttons"), (10 + 134) / 2, 20); + DrawTextCenter ( + gettext ("Available buttons"), (10 + 134) / 2 + LXOFFSET (), 20); // Dessine les textes pour le choix des musiques. if (m_phase == EV_PHASE_MUSIC) - DrawTextCenter (gettext ("Music choice"), (10 + 134) / 2, 20); + DrawTextCenter (gettext ("Music choice"), (10 + 134) / 2 + LXOFFSET (), 20); // Dessine les textes pour le choix de la région. if (m_phase == EV_PHASE_REGION) - DrawTextCenter (gettext ("Scenery choice"), (10 + 134) / 2, 20); + DrawTextCenter ( + gettext ("Scenery choice"), (10 + 134) / 2 + LXOFFSET (), 20); // Ajoute "Mission numéro". if (m_phase == EV_PHASE_INFO) @@ -2347,7 +2457,7 @@ CEvent::DrawButtons () snprintf (res, sizeof (res), "%s", gettext ("Construction number")); lg = GetTextWidth (res); - pos.x = (140 + 270) / 2 - lg / 2; + pos.x = (140 + 270) / 2 - lg / 2 + LXOFFSET (); pos.y = 70; if (m_bSchool) pos.x -= 40; @@ -2363,7 +2473,7 @@ CEvent::DrawButtons () { char * text = gettext ("Game paused"); lg = GetTextWidth (text); - pos.x = (140 + 270) / 2 - lg / 2; + pos.x = (140 + 270) / 2 - lg / 2 + LXOFFSET (); pos.y = 70; if (m_bSchool) pos.x -= 40; @@ -2379,7 +2489,7 @@ CEvent::DrawButtons () { char * text = gettext ("Help number"); lg = GetTextWidth (text); - pos.x = (140 + 270) / 2 - lg / 2; + pos.x = (140 + 270) / 2 - lg / 2 + LXOFFSET (); pos.y = 70; if (m_bSchool) pos.x -= 40; @@ -2403,7 +2513,7 @@ CEvent::DrawButtons () world = m_private; lg = GetBignumWidth (world + 1); - pos.x = (140 + 270) / 2 - lg / 2; + pos.x = (140 + 270) / 2 - lg / 2 + LXOFFSET (); pos.y = 100; if (m_bSchool) pos.x -= 40; @@ -2431,6 +2541,7 @@ CEvent::DrawButtons () pos.x = 150 + 50; pos.y = 230 + 13; } + pos.x += LXOFFSET (); DrawText (m_pPixmap, pos, gettext ("Easy"), FONTSLIM); } @@ -2446,6 +2557,7 @@ CEvent::DrawButtons () pos.x = 150 + 50; pos.y = 230 + 42 + 13; } + pos.x += LXOFFSET (); DrawText (m_pPixmap, pos, gettext ("Difficult"), FONTSLIM); } } @@ -2470,6 +2582,7 @@ CEvent::DrawButtons () pente = 0; else pente = 19; + pos.x += LXOFFSET (); DrawTextRect (m_pPixmap, pos, m_libelle, pente, FONTSLIM); } @@ -2484,7 +2597,7 @@ CEvent::DrawButtons () gettext ("No, not that way !"), }; - pos.x = 60; + pos.x = 60 + LXOFFSET (); pos.y = 443; DrawText (m_pPixmap, pos, list[GetWorld () % 5]); } @@ -2498,7 +2611,7 @@ CEvent::DrawButtons () gettext ("Mission over..."), }; - pos.x = 60; + pos.x = 60 + LXOFFSET (); pos.y = 443; DrawText (m_pPixmap, pos, list[GetWorld () % 5]); } @@ -2515,7 +2628,7 @@ CEvent::DrawButtons () if (m_bPrivate) text = gettext ("Last construction resolved !"); - pos.x = 60; + pos.x = 60 + LXOFFSET (); pos.y = 443; DrawText (m_pPixmap, pos, text); } @@ -2523,27 +2636,29 @@ CEvent::DrawButtons () // Draw the game settings. if (m_phase == EV_PHASE_SETUP || m_phase == EV_PHASE_SETUPp) { - DrawTextCenter (gettext ("Global game\nspeed"), 54 + 40, 80); - DrawTextCenter (gettext ("Scroll speed\nwith mouse"), 169 + 40, 80); - DrawTextCenter (gettext ("Sound effect\nvolume"), 284 + 40, 80); - DrawTextCenter (gettext ("Music\nvolume"), 399 + 40, 80); - DrawTextCenter (gettext ("Video\nsequences"), 514 + 40, 80); + DrawTextCenter (gettext ("Global game\nspeed"), 54 + 40 + LXOFFSET (), 80); + DrawTextCenter ( + gettext ("Scroll speed\nwith mouse"), 169 + 40 + LXOFFSET (), 80); + DrawTextCenter ( + gettext ("Sound effect\nvolume"), 284 + 40 + LXOFFSET (), 80); + DrawTextCenter (gettext ("Music\nvolume"), 399 + 40 + LXOFFSET (), 80); + DrawTextCenter (gettext ("Video\nsequences"), 514 + 40 + LXOFFSET (), 80); snprintf (res, sizeof (res), "x%d", m_speed); lg = GetTextWidth (res); - pos.x = (54 + 40) - lg / 2; + pos.x = (54 + 40) - lg / 2 + LXOFFSET (); pos.y = 330 - 20; DrawText (m_pPixmap, pos, res); snprintf (res, sizeof (res), "%d", m_pSound->GetAudioVolume ()); lg = GetTextWidth (res); - pos.x = (284 + 40) - lg / 2; + pos.x = (284 + 40) - lg / 2 + LXOFFSET (); pos.y = 330 - 20; DrawText (m_pPixmap, pos, res); snprintf (res, sizeof (res), "%d", m_pSound->GetMidiVolume ()); lg = GetTextWidth (res); - pos.x = (399 + 40) - lg / 2; + pos.x = (399 + 40) - lg / 2 + LXOFFSET (); pos.y = 330 - 20; DrawText (m_pPixmap, pos, res); @@ -2551,7 +2666,7 @@ CEvent::DrawButtons () if (m_pMovie->GetEnable () && m_bMovie) text = gettext ("Yes"); lg = GetTextWidth (text); - pos.x = (514 + 40) - lg / 2; + pos.x = (514 + 40) - lg / 2 + LXOFFSET (); pos.y = 330 - 20; DrawText (m_pPixmap, pos, text); @@ -2560,7 +2675,7 @@ CEvent::DrawButtons () else snprintf (res, sizeof (res), "%d", m_scrollSpeed); lg = GetTextWidth (res); - pos.x = (169 + 40) - lg / 2; + pos.x = (169 + 40) - lg / 2 + LXOFFSET (); pos.y = 330 - 20; DrawText (m_pPixmap, pos, res); } @@ -2568,10 +2683,18 @@ CEvent::DrawButtons () // Draw the settings if (m_phase == EV_PHASE_SETTINGS) { - DrawTextCenter (gettext ("Interface language\nand sounds"), 54 + 40, 80); - DrawTextCenter (gettext ("Select the\nwindow mode"), 169 + 40, 80); - DrawTextCenter (gettext ("Change the\nwindow size"), 284 + 40, 80); - DrawTextCenter (gettext ("Choose the\nmusic format"), 399 + 40, 80); + DrawTextCenter ( + gettext ("Interface language\nand sounds"), 54 + 40 + LXOFFSET (), 80); + DrawTextCenter ( + gettext ("Select the\nwindow mode"), 169 + 40 + LXOFFSET (), 80); + DrawTextCenter ( + g_bFullScreen ? gettext ("Change the\ndisplay mode") + : gettext ("Change the\nwindow size"), + 284 + 40 + LXOFFSET (), 80); + DrawTextCenter ( + gettext ("Choose the\nmusic format"), 399 + 40 + LXOFFSET (), 80); + DrawTextCenter ( + gettext ("Change the\nrender quality"), 514 + 40 + LXOFFSET (), 80); const auto locale = GetLocale (); std::string lang; @@ -2589,29 +2712,41 @@ CEvent::DrawButtons () lang = "Polski"; lg = GetTextWidth (lang.c_str ()); - pos.x = (54 + 40) - lg / 2; + pos.x = (54 + 40) - lg / 2 + LXOFFSET (); pos.y = 330 - 20; DrawText (m_pPixmap, pos, lang.c_str ()); const char * text = g_bFullScreen ? gettext ("Fullscreen") : gettext ("Windowed"); lg = GetTextWidth (text); - pos.x = (169 + 40) - lg / 2; + pos.x = (169 + 40) - lg / 2 + LXOFFSET (); pos.y = 330 - 20; DrawText (m_pPixmap, pos, text); if (!g_bFullScreen) - { snprintf (res, sizeof (res), "%dx", g_zoom); - lg = GetTextWidth (res); - pos.x = (284 + 40) - lg / 2; - pos.y = 330 - 20; - DrawText (m_pPixmap, pos, res); - } + else + snprintf ( + res, sizeof (res), "%s", + g_zoom == 2 ? gettext ("Legacy") : gettext ("Desktop")); + + lg = GetTextWidth (res); + pos.x = (284 + 40) - lg / 2 + LXOFFSET (); + pos.y = 330 - 20; + DrawText (m_pPixmap, pos, res); text = (g_restoreMidi && mid) || !ogg ? gettext ("Midi") : gettext ("Ogg"); lg = GetTextWidth (text); - pos.x = (399 + 40) - lg / 2; + pos.x = (399 + 40) - lg / 2 + LXOFFSET (); + pos.y = 330 - 20; + DrawText (m_pPixmap, pos, text); + + text = + g_bFullScreen && g_zoom == 1 + ? (g_renderQuality ? gettext ("Anti-aliasing") : gettext ("Aliasing")) + : gettext ("Not available"); + lg = GetTextWidth (text); + pos.x = (514 + 40) - lg / 2 + LXOFFSET (); pos.y = 330 - 20; DrawText (m_pPixmap, pos, text); } @@ -2623,14 +2758,14 @@ CEvent::DrawButtons () text = gettext ("You have played Planet Blupi."); lg = GetTextWidth (text); - pos.x = LXIMAGE / 2 - lg / 2; + pos.x = LXIMAGE () / 2 - lg / 2; pos.y = 20; DrawText (m_pPixmap, pos, text); text = gettext ("We hope you have had as much fun playing the game as we " "had making it !"); lg = GetTextWidth (text); - pos.x = LXIMAGE / 2 - lg / 2; + pos.x = LXIMAGE () / 2 - lg / 2; pos.y = 40; DrawText (m_pPixmap, pos, text); @@ -2654,7 +2789,7 @@ CEvent::DrawButtons () for (size_t i = 0; i < countof (libs); ++i) { - pos.x = 30; + pos.x = 30 + LXOFFSET (); pos.y = 120 + i * 20; DrawText (m_pPixmap, pos, libs[i].c_str ()); } @@ -2662,13 +2797,13 @@ CEvent::DrawButtons () text = gettext ("This game is an original creation of Epsitec SA, CH-1400 " "Yverdon-les-Bains"); lg = GetTextWidth (text); - pos.x = LXIMAGE / 2 - lg / 2; + pos.x = LXIMAGE () / 2 - lg / 2; pos.y = 430; DrawText (m_pPixmap, pos, text); text = gettext ("http://www.blupi.org info@blupi.org"); lg = GetTextWidth (text); - pos.x = LXIMAGE / 2 - lg / 2; + pos.x = LXIMAGE () / 2 - lg / 2; pos.y = 450; DrawText (m_pPixmap, pos, text); } @@ -2677,7 +2812,7 @@ CEvent::DrawButtons () if (m_phase == EV_PHASE_INSERT) DrawTextCenter ( gettext ("Insert CD-Rom Planet Blupi and wait a few seconds..."), - LXIMAGE / 2, 20); + LXIMAGE () / 2, 20); if (m_phase == EV_PHASE_BUILD) SetEnable (EV_PHASE_UNDO, m_pDecor->IsUndo ()); @@ -2715,13 +2850,13 @@ CEvent::MousePosToSprite (Point pos) if (pos.x <= 5 && pos.x >= -2) bLeft = true; - if (pos.x >= LXIMAGE - 5 && pos.x <= LXIMAGE + 2) + if (pos.x >= LXIMAGE () - 5 && pos.x <= LXIMAGE () + 2) bRight = true; if (pos.y <= 5 && pos.y >= -2) bUp = true; - if (pos.y >= LYIMAGE - 5 && pos.y <= LYIMAGE + 2) + if (pos.y >= LYIMAGE () - 5 && pos.y <= LYIMAGE () + 2) bDown = true; if (bLeft) @@ -2741,6 +2876,9 @@ CEvent::MousePosToSprite (Point pos) if (bRight && bDown) sprite = SPRITE_ARROWDR; } + + if (this->statDisabled) + sprite = SPRITE_ARROW; } else if (m_phase == EV_PHASE_INTRO1) sprite = SPRITE_POINTER; @@ -2830,35 +2968,33 @@ CEvent::HideMouse (bool bHide) bool CEvent::EventButtons (const SDL_Event & event, Point pos) { - Point test; Sint32 lg; - Sounds sound; // Cherche le tool tips à utiliser pour la souris. m_textToolTips[0] = 0; m_posToolTips.x = -1; - const auto progress = [&](CJauge & prog, const char * text) -> bool { - if (prog.GetHide ()) - return false; - - test = prog.GetPos (); - if ( - pos.x >= test.x && pos.x <= test.x + DIMJAUGEX && pos.y >= test.y && - pos.y <= test.y + DIMJAUGEY) - { - snprintf (m_textToolTips, sizeof (m_textToolTips), "%s", text); - lg = GetTextWidth (m_textToolTips); - test.x += (DIMJAUGEX - lg) / 2; - test.y += 4; - m_posToolTips = test; - return true; - } - return false; - }; - if (m_phase == EV_PHASE_PLAY) { + auto progress = [&](CJauge & prog, const char * text) -> bool { + if (prog.GetHide ()) + return false; + + Point test = prog.GetPos (); + if ( + pos.x >= test.x && pos.x <= test.x + DIMJAUGEX && pos.y >= test.y && + pos.y <= test.y + DIMJAUGEY) + { + snprintf (m_textToolTips, sizeof (m_textToolTips), "%s", text); + lg = GetTextWidth (m_textToolTips); + test.x += (DIMJAUGEX - lg) / 2; + test.y += 4; + m_posToolTips = test; + return true; + } + return false; + }; + const auto spotted = progress (m_jauges[0], gettext ("Blupi's energy")); if (!spotted) progress (m_jauges[1], gettext ("Work done")); @@ -2878,10 +3014,10 @@ CEvent::EventButtons (const SDL_Event & event, Point pos) lg = GetTextWidth (m_textToolTips); pos.x += 10; pos.y += 20; - if (pos.x > LXIMAGE - lg) - pos.x = LXIMAGE - lg; - if (pos.y > LYIMAGE - 14) - pos.y = LYIMAGE - 14; + if (pos.x > LXIMAGE () - lg) + pos.x = LXIMAGE () - lg; + if (pos.y > LYIMAGE () - 14) + pos.y = LYIMAGE () - 14; m_posToolTips = pos; break; } @@ -2901,21 +3037,13 @@ CEvent::EventButtons (const SDL_Event & event, Point pos) m_bHiliInfoButton = true; if ( - event.type == SDL_MOUSEBUTTONDOWN && - (event.button.button == SDL_BUTTON_LEFT || - event.button.button == SDL_BUTTON_RIGHT)) - { - if (m_pDecor->GetInfoMode ()) - sound = SOUND_CLOSE; - else - sound = SOUND_OPEN; - m_pSound->PlayImage (sound, pos); - } - if ( event.type == SDL_MOUSEBUTTONUP && (event.button.button == SDL_BUTTON_LEFT || event.button.button == SDL_BUTTON_RIGHT)) { + m_pSound->PlayImage ( + m_pDecor->GetInfoMode () ? SOUND_CLOSE : SOUND_OPEN, pos); + // Show or hide the informations at the top. m_pDecor->SetInfoMode (!m_pDecor->GetInfoMode ()); } @@ -3131,6 +3259,44 @@ CEvent::GetMusicLocation (Sint32 music) return absolute; } +bool +CEvent::LoadBackground () +{ + Point totalDim, iconDim; + std::string filename; + auto backWideName = table[m_index].backWideName; + + filename = table[m_index].backName; + if (filename.find ("%.3d") != std::string::npos) + { + auto id = GetImageWorld (); + filename = string_format (table[m_index].backName, id); + + if (table[m_index].phase == EV_PHASE_LASTWIN) + { + switch (id) + { + case 0: + backWideName = "image/back-disco.png"; + break; + case 1: + backWideName = "image/back-stars.png"; + break; + case 2: + backWideName = "image/back-win.png"; + break; + } + } + } + + totalDim.x = LXLOGIC (); + totalDim.y = LYLOGIC (); + iconDim.x = 0; + iconDim.y = 0; + return m_pPixmap->Cache ( + CHBACK, filename, totalDim, iconDim, table[m_index].mode, backWideName); +} + /** * \brief Change the phase. * @@ -3140,12 +3306,10 @@ CEvent::GetMusicLocation (Sint32 music) bool CEvent::ChangePhase (Uint32 phase) { - Sint32 index, world, time, total, music, i, max; - Point totalDim, iconDim; - std::string filename; - char * pButtonExist; - bool bEnable, bHide; - Term * pTerm; + Sint32 index, world, time, total, music, i, max; + char * pButtonExist; + bool bEnable, bHide; + Term * pTerm; if ( phase != EV_PHASE_SETUPp && phase != EV_PHASE_WRITEp && @@ -3208,14 +3372,7 @@ CEvent::ChangePhase (Uint32 phase) m_phase = phase; // change phase m_index = index; - filename = table[m_index].backName; - if (filename.find ("%.3d") != std::string::npos) - filename = string_format (table[m_index].backName, GetImageWorld ()); - totalDim.x = LXIMAGE; - totalDim.y = LYIMAGE; - iconDim.x = 0; - iconDim.y = 0; - if (!m_pPixmap->Cache (CHBACK, filename, totalDim, iconDim)) + if (!this->LoadBackground ()) { WaitMouse (false); m_tryInsertCount = 40; @@ -3301,7 +3458,7 @@ CEvent::ChangePhase (Uint32 phase) m_jauges[0].SetHide (true); m_jauges[1].SetHide (true); - CreateButtons (); // create the buttons accordingly to the phase + CreateButtons (phase); // create the buttons accordingly to the phase m_bMenu = false; m_pDecor->HideTooltips (false); m_menu.Delete (); @@ -3848,7 +4005,7 @@ CEvent::PlayMove (Point pos) return true; } - m_pDecor->StatisticMove (pos); + m_pDecor->StatisticMove (pos, this->statDisabled); if (m_bMouseDown) // bouton souris pressé ? { @@ -3965,8 +4122,10 @@ CEvent::SetLanguage (Language lang) { putenv (env); +#ifndef EMSCRIPTEN extern int _nl_msg_cat_cntr; ++_nl_msg_cat_cntr; +#endif /* EMSCRIPTEN */ } SDL_SetWindowTitle (g_window, gettext ("Planet Blupi")); @@ -4158,17 +4317,38 @@ CEvent::ChangeButtons (Sint32 message) SetLanguage (); break; case EV_BUTTON3: - SetFullScreen (true); + { + auto zoom = g_zoom; + g_zoom = g_settingsOverload & SETTING_LEGACY ? 2 : 1; + SetFullScreen (true, zoom); break; + } case EV_BUTTON4: + { + Sint32 w1; + SDL_GetWindowSize (g_window, &w1, nullptr); SetFullScreen (false); + SetWindowSize (g_zoom * static_cast<double> (w1) / LXIMAGE (), g_zoom); break; + } case EV_BUTTON5: { auto scale = g_zoom; if (g_zoom > 1) --g_zoom; + + if (g_bFullScreen && scale == 2) + { + SDL_Event ev; + ev.type = SDL_QUIT; + SDL_PushEvent (&ev); + g_restart = RestartMode::DESKTOP; + break; + } + SetWindowSize (scale, g_zoom); + if (g_bFullScreen) + SetFullScreen (g_bFullScreen); break; } case EV_BUTTON6: @@ -4176,7 +4356,19 @@ CEvent::ChangeButtons (Sint32 message) auto scale = g_zoom; if (g_zoom < 2) ++g_zoom; + + if (g_bFullScreen && g_zoom == 2) + { + SDL_Event ev; + ev.type = SDL_QUIT; + SDL_PushEvent (&ev); + g_restart = RestartMode::LEGACY; + break; + } + SetWindowSize (scale, g_zoom); + if (g_bFullScreen) + SetFullScreen (g_bFullScreen); break; } case EV_BUTTON7: @@ -4185,6 +4377,14 @@ CEvent::ChangeButtons (Sint32 message) case EV_BUTTON8: g_restoreMidi = true; break; + case EV_BUTTON9: + g_renderQuality = false; + this->m_pPixmap->CreateMainTexture (); + break; + case EV_BUTTON10: + g_renderQuality = true; + this->m_pPixmap->CreateMainTexture (); + break; } } } @@ -4742,7 +4942,7 @@ CEvent::WriteInfo () goto error; info.majRev = 1; - info.minRev = 2; + info.minRev = 3; info.prive = m_private; info.exercice = m_exercice; info.mission = m_mission; @@ -4761,9 +4961,10 @@ CEvent::WriteInfo () info.language = static_cast<Sint16> ( this->GetLanguage () != this->GetStartLanguage () ? this->GetLanguage () : Language::undef); - info.musicMidi = g_restoreMidi; - info.fullScreen = g_bFullScreen; - info.zoom = g_zoom; + info.musicMidi = g_restoreMidi; + info.fullScreen = g_bFullScreen; + info.zoom = g_zoom; + info.renderQuality = g_renderQuality; nb = fwrite (&info, sizeof (info), 1, file); if (nb < 1) @@ -4830,6 +5031,16 @@ CEvent::ReadInfo () g_bFullScreen = !!info.fullScreen; if (!(g_settingsOverload & SETTING_ZOOM)) g_zoom = info.zoom; + + /* Prefer the desktop fullscreen mode by default. */ + if (!(g_settingsOverload & SETTING_LEGACY) && g_bFullScreen && g_zoom == 2) + g_zoom = 1; + } + + if (((info.majRev == 1 && info.minRev >= 3) || info.majRev >= 2)) + { + if (!(g_settingsOverload & SETTING_RENDERQUALITY)) + g_renderQuality = !!info.renderQuality; } fclose (file); @@ -4884,7 +5095,9 @@ CEvent::DemoRecStart () InitRandom (); m_pDecor->SetTime (0); - m_speed = 1; + m_speed = 1; + this->m_scrollSpeedPrev = this->m_scrollSpeed; + this->m_scrollSpeed = 3; m_bStartRecording = true; } @@ -4925,9 +5138,10 @@ CEvent::DemoRecStop () } m_pDemoSDLBuffer.clear (); - m_bDemoRec = false; - m_demoTime = 0; - m_bStartRecording = false; + m_bDemoRec = false; + m_demoTime = 0; + m_bStartRecording = false; + this->m_scrollSpeed = this->m_scrollSpeedPrev; } // Début de la reproduction d'une démo. @@ -5006,6 +5220,10 @@ CEvent::DemoPlayStart (const std::string * demoFile) DemoPlayStop (); return false; } + + this->m_scrollSpeedPrev = m_scrollSpeed; + this->m_scrollSpeed = 3; + ChangePhase (EV_PHASE_PLAY); InitRandom (); m_pDecor->SetTime (0); @@ -5027,9 +5245,10 @@ CEvent::DemoPlayStop () m_pDemoSDLBuffer.clear (); - m_bDemoPlay = false; - m_bDemoRec = false; - m_demoTime = 0; + m_bDemoPlay = false; + m_bDemoRec = false; + m_demoTime = 0; + this->m_scrollSpeed = this->m_scrollSpeedPrev; ChangePhase (EV_PHASE_INIT); } @@ -5207,7 +5426,8 @@ CEvent::DemoStep () pos.y = event.motion.y; } - SDL_WarpMouseInWindow (g_window, pos.x * g_zoom, pos.y * g_zoom); + this->m_pPixmap->FromGameToDisplay (pos.x, pos.y); + SDL_WarpMouseInWindow (g_window, pos.x, pos.y); } if (m_pDemoBuffer) @@ -5259,6 +5479,7 @@ CEvent::DemoRecEvent (const SDL_Event & event) demoEvent.button = event.button.button; demoEvent.x = event.button.x; demoEvent.y = event.button.y; + this->m_pPixmap->FromDisplayToGame (demoEvent.x, demoEvent.y); break; case SDL_MOUSEMOTION: @@ -5266,6 +5487,7 @@ CEvent::DemoRecEvent (const SDL_Event & event) demoEvent.time = m_demoTime; demoEvent.x = event.motion.x; demoEvent.y = event.motion.y; + this->m_pPixmap->FromDisplayToGame (demoEvent.x, demoEvent.y); break; default: @@ -5401,8 +5623,8 @@ CEvent::TreatEventBase (const SDL_Event & event) if (m_phase != EV_PHASE_PLAY) ChangePhase (m_phase); - pos.x = LXIMAGE / 2; - pos.y = LYIMAGE / 2; + pos.x = LXIMAGE () / 2; + pos.y = LYIMAGE () / 2; if (bEnable) m_pSound->PlayImage (SOUND_GOAL, pos); else @@ -5447,15 +5669,19 @@ CEvent::TreatEventBase (const SDL_Event & event) switch (m_phase) { case EV_PHASE_PLAY: - case EV_PHASE_SETUP: case EV_PHASE_SETUPp: - case EV_PHASE_READ: case EV_PHASE_WRITE: case EV_PHASE_WRITEp: case EV_PHASE_HELP: ChangePhase (EV_PHASE_STOP); return true; + case EV_PHASE_SETUP: + case EV_PHASE_READ: + ChangePhase ( + this->m_pDecor->GetTime () ? EV_PHASE_STOP : EV_PHASE_INFO); + return true; + case EV_PHASE_STOP: ChangePhase (EV_PHASE_PLAY); return true; @@ -5498,12 +5724,16 @@ CEvent::TreatEventBase (const SDL_Event & event) return true; case EV_PHASE_PLAY: - case EV_PHASE_READ: case EV_PHASE_WRITE: - case EV_PHASE_SETUP: ChangePhase (EV_PHASE_STOP); return true; + case EV_PHASE_SETUP: + case EV_PHASE_READ: + ChangePhase ( + this->m_pDecor->GetTime () ? EV_PHASE_STOP : EV_PHASE_INFO); + return true; + case EV_PHASE_INIT: case EV_PHASE_LOST: case EV_PHASE_BUILD: @@ -5595,10 +5825,7 @@ CEvent::TreatEventBase (const SDL_Event & event) case SDLK_RCTRL: m_keymod |= KMOD_CTRL; if (m_phase == EV_PHASE_BUILD) - { m_bFillMouse = true; - MouseSprite (GetMousePos ()); - } else m_bFillMouse = false; return true; @@ -5610,8 +5837,8 @@ CEvent::TreatEventBase (const SDL_Event & event) sound = SOUND_CLOSE; else sound = SOUND_OPEN; - pos.x = LXIMAGE / 2; - pos.y = LYIMAGE / 2; + pos.x = LXIMAGE () / 2; + pos.y = LYIMAGE () / 2; m_pSound->PlayImage (sound, pos); m_pDecor->SetInfoMode (!m_pDecor->GetInfoMode ()); } @@ -5664,7 +5891,6 @@ CEvent::TreatEventBase (const SDL_Event & event) case SDLK_RCTRL: m_keymod &= ~KMOD_CTRL; m_bFillMouse = false; - MouseSprite (GetMousePos ()); return true; } break; @@ -5678,8 +5904,6 @@ CEvent::TreatEventBase (const SDL_Event & event) pos.x = event.button.x; pos.y = event.button.y; - MouseSprite (pos); - //? DecorAutoShift(pos); if (EventButtons (event, pos)) return true; if (m_phase == EV_PHASE_BUILD) @@ -5700,7 +5924,6 @@ CEvent::TreatEventBase (const SDL_Event & event) m_oldMousePos = pos; - MouseSprite (pos); if (EventButtons (event, pos)) return true; if (m_phase == EV_PHASE_BUILD) @@ -5709,10 +5932,7 @@ CEvent::TreatEventBase (const SDL_Event & event) return true; } if (m_phase == EV_PHASE_PLAY) - { - if (PlayMove (pos)) - return true; - } + return true; break; case SDL_MOUSEBUTTONUP: @@ -5985,6 +6205,11 @@ CEvent::TreatEventBase (const SDL_Event & event) ChangePhase (EV_PHASE_PLAY); // joue break; + case EV_SETUP_EXIT: + case EV_READ_EXIT: + ChangePhase (this->m_pDecor->GetTime () ? EV_PHASE_STOP : EV_PHASE_INFO); + break; + case EV_WRITE0: case EV_WRITE1: case EV_WRITE2: diff --git a/src/event.h b/src/event.h index e177afb..63ca037 100644 --- a/src/event.h +++ b/src/event.h @@ -24,9 +24,9 @@ #include <unordered_map> #include <vector> -#include "blupi.h" #include "button.h" #include "menu.h" +#include "pixmap.h" #include "progress.h" class CMovie; @@ -42,10 +42,12 @@ typedef struct { } Button; typedef struct { - Uint32 phase; - char backName[20]; - Sint32 bCDrom; - Button buttons[MAXBUTTON]; + Uint32 phase; + char backName[20]; + std::string backWideName; + CPixmap::Mode mode; + Sint32 bCDrom; + Button buttons[MAXBUTTON]; } Phase; typedef struct { @@ -92,16 +94,18 @@ public: CEvent (); ~CEvent (); + bool IsDemoPlaying (); Point GetMousePos (); void Create (CPixmap * pPixmap, CDecor * pDecor, CSound * pSound, CMovie * pMovie); - void SetFullScreen (bool bFullScreen); + void SetFullScreen (bool bFullScreen, double prevScale = 1); Sint32 GetWorld (); Sint32 GetPhysicalWorld (); Sint32 GetImageWorld (); bool IsHelpHide (); bool IsBaseMusicAvailable (Sint32 music, const std::string & format); std::string GetMusicLocation (Sint32 music); + bool LoadBackground (); bool ChangePhase (Uint32 phase); bool MovieToStart (); Uint32 GetPhase (); @@ -147,24 +151,25 @@ public: void SetWindowSize (Uint8 newScale); void SetUpdateVersion (const std::string & version); + bool EventButtons (const SDL_Event & event, Point pos); + bool PlayMove (Point pos); + static void PushUserEvent (Sint32 code, void * data = nullptr); protected: void DrawTextCenter (const char * text, Sint32 x, Sint32 y, Sint32 font = 0); - bool CreateButtons (); - bool EventButtons (const SDL_Event & event, Point pos); + bool CreateButtons (Sint32 phase); bool MouseOnButton (Point pos); Sint32 SearchPhase (Uint32 phase); void DecorShift (Sint32 dx, Sint32 dy); bool PlayDown (Point pos, const SDL_Event & event); - bool PlayMove (Point pos); bool PlayUp (Point pos); Language GetStartLanguage (); Language GetLanguage (); void SetLanguage (Language lang = Language::undef); - void SetWindowSize (Uint8 prevScale, Uint8 newScale); + void SetWindowSize (double prevScale, double newScale); void ChangeButtons (Sint32 message); @@ -241,6 +246,7 @@ protected: bool m_bHelp; bool m_bAllMissions; Sint32 m_scrollSpeed; + Sint32 m_scrollSpeedPrev; bool m_bPause; bool m_bShift; Sint32 m_shiftPhase; @@ -269,6 +275,7 @@ protected: Sint32 m_updateBlinking; std::string m_updateVersion; Uint32 shiftDirection; + bool statDisabled; }; ///////////////////////////////////////////////////////////////////////////// diff --git a/src/fifo.cxx b/src/fifo.cxx index b012964..d553767 100644 --- a/src/fifo.cxx +++ b/src/fifo.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -18,7 +18,7 @@ * along with this program. If not, see http://gnu.org/licenses */ -#include <SDL2/SDL_stdinc.h> +#include <SDL_stdinc.h> #include <stdlib.h> #include "fifo.h" diff --git a/src/menu.cxx b/src/menu.cxx index 19a242a..02ffb4e 100644 --- a/src/menu.cxx +++ b/src/menu.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -185,7 +185,9 @@ CMenu::Create ( pos = m_pos; pos.x += DIMBUTTONX / 2; pos.y += DIMBUTTONY / 2; - SDL_WarpMouseInWindow (g_window, pos.x * g_zoom, pos.y * g_zoom); + + this->m_pPixmap->FromGameToDisplay (pos.x, pos.y); + SDL_WarpMouseInWindow (g_window, pos.x, pos.y); } m_selRank = Detect (pos); diff --git a/src/misc.cxx b/src/misc.cxx index 3884ec7..7a814a6 100644 --- a/src/misc.cxx +++ b/src/misc.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -30,10 +30,11 @@ #include <sys/stat.h> #endif /*! _WIN32 */ -#include <SDL2/SDL_log.h> -#include <SDL2/SDL_mouse.h> +#include <SDL_log.h> +#include <SDL_mouse.h> #include "blupi.h" +#include "config.h" #include "def.h" #include "misc.h" @@ -105,8 +106,8 @@ GetBaseDir () return GetShareDir () + "planetblupi/"; } -std::string -GetShareDir () +static std::string +GetDataDir () { static std::string basePath; @@ -123,7 +124,21 @@ GetShareDir () SDL_free (sdlBasePath); } - return basePath + "share/"; + return basePath; +} + +std::string +GetShareDir () +{ + return GetDataDir () + "share/"; +} + +std::string +GetBinDir () +{ + std::string abs; + std::string bin = GetDataDir () + PB_BINDIR + "/"; + return bin; } // Ajoute le chemin permettant de lire un fichier @@ -23,6 +23,9 @@ #include <cstdio> #include <memory> #include <string> +#ifdef __APPLE__ +#include <libgen.h> +#endif /* __APPLE__ */ #include "blupi.h" @@ -35,6 +38,7 @@ extern Sint32 Random (Sint32 min, Sint32 max); std::string GetBaseDir (); std::string GetShareDir (); +std::string GetBinDir (); std::string GetLocale (); extern void AddUserPath (std::string & pFilename); @@ -52,3 +56,16 @@ string_format (const std::string & format, Args... args) snprintf (buf.get (), size, format.c_str (), args...); return std::string (buf.get (), buf.get () + size - 1); } + +#ifdef _WIN32 +static inline char * +basename (char * path) +{ + static char basename[_MAX_FNAME + _MAX_EXT]; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + _splitpath (path, nullptr, nullptr, fname, ext); + snprintf (basename, sizeof (basename), "%s%s", fname, ext); + return basename; +} +#endif /* _WIN32 */
\ No newline at end of file diff --git a/src/movie.cxx b/src/movie.cxx index 6d0074e..d0714ab 100644 --- a/src/movie.cxx +++ b/src/movie.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -22,10 +22,13 @@ #include <stdlib.h> #include <string.h> +#include <SDL_image.h> + #include "kitchensink/kitchensink.h" #include "blupi.h" #include "def.h" +#include "display.h" #include "event.h" #include "misc.h" #include "movie.h" @@ -69,6 +72,12 @@ CMovie::fileCloseMovie () m_videoTex = nullptr; } + if (this->backTexture) + { + SDL_DestroyTexture (this->backTexture); + this->backTexture = nullptr; + } + if (m_player) { SDL_CloseAudioDevice (m_audioDev); @@ -79,6 +88,7 @@ CMovie::fileCloseMovie () if (m_movie) { Kit_CloseSource (m_movie); + SDL_RWclose (this->rw_ops); m_movie = nullptr; } } @@ -98,17 +108,21 @@ CMovie::fileOpenMovie (const std::string & pFilename) if (m_fMovieOpen) fileCloseMovie (); + this->rw_ops = SDL_RWFromFile (path.c_str (), "rb"); + if (!this->rw_ops) + return false; + // Open up the sourcefile. // This can be a local file, network url, ... - m_movie = Kit_CreateSourceFromUrl (path.c_str ()); + m_movie = Kit_CreateSourceFromRW (rw_ops); if (m_movie) { // Create the player m_player = Kit_CreatePlayer ( m_movie, Kit_GetBestSourceStream (m_movie, KIT_STREAMTYPE_VIDEO), Kit_GetBestSourceStream (m_movie, KIT_STREAMTYPE_AUDIO), - Kit_GetBestSourceStream (m_movie, KIT_STREAMTYPE_SUBTITLE), LXIMAGE, - LYIMAGE); + Kit_GetBestSourceStream (m_movie, KIT_STREAMTYPE_SUBTITLE), LXIMAGE (), + LYIMAGE ()); if (m_player == nullptr) return false; @@ -124,13 +138,32 @@ CMovie::fileOpenMovie (const std::string & pFilename) m_audioDev = SDL_OpenAudioDevice (nullptr, 0, &wanted_spec, &audio_spec, 0); SDL_PauseAudioDevice (m_audioDev, 0); + if (g_bFullScreen && g_zoom == 1) + SDL_SetHint ( + SDL_HINT_RENDER_SCALE_QUALITY, g_renderQuality ? "best" : "nearest"); m_videoTex = SDL_CreateTexture ( g_renderer, info.video.output.format, SDL_TEXTUREACCESS_TARGET, info.video.output.width, info.video.output.height); + if (g_bFullScreen && g_zoom == 1) + SDL_SetHint (SDL_HINT_RENDER_SCALE_QUALITY, "nearset"); if (m_videoTex == nullptr) return false; + std::string backWideName = ""; + if (Display::getDisplay ().isWide ()) + { + if (path.rfind ("win005.mkv") != std::string::npos) + backWideName = "image/back-disco.png"; + else if (path.rfind ("win129.mkv") != std::string::npos) + backWideName = "image/back-stars.png"; + } + + std::string file = GetBaseDir () + backWideName; + SDL_Surface * surface = IMG_Load (file.c_str ()); + this->backTexture = SDL_CreateTextureFromSurface (g_renderer, surface); + SDL_FreeSurface (surface); + return true; } else @@ -158,8 +191,10 @@ CMovie::playMovie () Kit_PlayerPause (m_player); } -CMovie::CMovie () +CMovie::CMovie (CPixmap * pixmap) { + this->pixmap = pixmap; + m_bEnable = false; m_fPlaying = false; m_fMovieOpen = false; @@ -170,6 +205,8 @@ CMovie::CMovie () memset (m_audiobuf, 0, sizeof (m_audiobuf)); + this->rw_ops = nullptr; + m_ret = 0; } @@ -277,10 +314,6 @@ CMovie::Render () SDL_PauseAudioDevice (m_audioDev, 0); } - // Clear screen with black - SDL_SetRenderDrawColor (g_renderer, 0, 0, 0, 255); - SDL_RenderClear (g_renderer); - if (this->starting) { SDL_SetRenderTarget (g_renderer, m_videoTex); @@ -290,9 +323,24 @@ CMovie::Render () this->starting = false; } + if (!this->backTexture) + { + // Clear screen with black + SDL_SetRenderDrawColor (g_renderer, 0, 0, 0, 255); + SDL_RenderClear (g_renderer); + } + else + SDL_RenderCopy (g_renderer, this->backTexture, nullptr, nullptr); + // Refresh videotexture and render it Kit_GetPlayerVideoData (m_player, m_videoTex); - SDL_RenderCopy (g_renderer, m_videoTex, nullptr, nullptr); + + SDL_Rect dstRect; + dstRect.x = (LXIMAGE () - LXLOGIC ()) / 2; + dstRect.y = 0; + dstRect.w = LXLOGIC (); + dstRect.h = LYLOGIC (); + SDL_RenderCopy (g_renderer, m_videoTex, nullptr, &dstRect); SDL_RenderPresent (g_renderer); CEvent::PushUserEvent (EV_MOVIE_PLAY); diff --git a/src/movie.h b/src/movie.h index bd9098f..62837c8 100644 --- a/src/movie.h +++ b/src/movie.h @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -26,13 +26,14 @@ struct Kit_Source; struct Kit_Player; struct Kit_PlayerInfo; struct SDL_Texture; +class CPixmap; #define AUDIOBUFFER_SIZE (32768) class CMovie { public: - CMovie (); + CMovie (CPixmap * pixmap); ~CMovie (); bool Create (); @@ -52,11 +53,14 @@ protected: bool initAVI (); protected: + CPixmap * pixmap; Kit_Source * m_movie; Kit_Player * m_player; SDL_Texture * m_videoTex; + SDL_Texture * backTexture; Sint32 m_ret; SDL_AudioDeviceID m_audioDev; + SDL_RWops * rw_ops; char m_audiobuf[AUDIOBUFFER_SIZE]; bool m_bEnable; diff --git a/src/pixmap.cxx b/src/pixmap.cxx index d23181c..0fcf6d2 100644 --- a/src/pixmap.cxx +++ b/src/pixmap.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -29,10 +29,11 @@ #include <unistd.h> #endif /* !_WIN32 */ -#include <SDL2/SDL_image.h> +#include <SDL_image.h> #include "blupi.h" #include "def.h" +#include "event.h" #include "misc.h" #include "pixmap.h" @@ -40,7 +41,7 @@ // Constructeur. -CPixmap::CPixmap () +CPixmap::CPixmap (CEvent * event) { Sint32 i; @@ -56,6 +57,8 @@ CPixmap::CPixmap () m_lpSDLCursors[i] = nullptr; m_lpCurrentCursor = nullptr; + this->mainTexture = nullptr; + this->event = event; } // Destructeur. @@ -83,6 +86,9 @@ CPixmap::~CPixmap () if (m_lpSDLBlupi) SDL_FreeSurface (m_lpSDLBlupi); + + if (this->mainTexture) + SDL_DestroyTexture (this->mainTexture); } // Cr�e l'objet DirectDraw principal. @@ -101,13 +107,81 @@ CPixmap::Create (Point dim) return true; } +void +CPixmap::CreateMainTexture () +{ + if (!this->mainTexture) + return; + + SDL_DestroyTexture (this->mainTexture); + SDL_SetHint ( + SDL_HINT_RENDER_SCALE_QUALITY, + g_bFullScreen && g_renderQuality ? "best" : "nearest"); + this->mainTexture = SDL_CreateTexture ( + g_renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, LXIMAGE (), + LYIMAGE ()); + SDL_SetHint (SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); +} + +Sint32 +CPixmap::BltFast (Sint32 dstCh, size_t srcCh, Rect dstR, Rect srcR) +{ + Sint32 res; + + SDL_Rect srcRect, dstRect; + srcRect.x = srcR.left; + srcRect.y = srcR.top; + srcRect.w = srcR.right - srcR.left; + srcRect.h = srcR.bottom - srcR.top; + dstRect.x = dstR.left; + dstRect.y = dstR.top; + dstRect.w = dstR.right - dstR.left; + dstRect.h = dstR.bottom - dstR.top; + + auto target = SDL_GetRenderTarget (g_renderer); + + if (dstCh < 0) + { + if (!this->mainTexture && g_bFullScreen && g_zoom == 1) + { + SDL_SetHint ( + SDL_HINT_RENDER_SCALE_QUALITY, g_renderQuality ? "best" : "nearest"); + this->mainTexture = SDL_CreateTexture ( + g_renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, + LXIMAGE (), LYIMAGE ()); + SDL_SetHint (SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); + } + else if (this->mainTexture && !(g_bFullScreen && g_zoom == 1)) + { + SDL_DestroyTexture (this->mainTexture); + this->mainTexture = nullptr; + } + + if (this->mainTexture) + SDL_SetRenderTarget (g_renderer, target ? target : this->mainTexture); + res = SDL_RenderCopy ( + g_renderer, m_SDLTextureInfo[srcCh].texture, &srcRect, &dstRect); + if (this->mainTexture) + SDL_SetRenderTarget (g_renderer, target); + } + else + { + SDL_SetRenderTarget (g_renderer, m_SDLTextureInfo[dstCh].texture); + res = SDL_RenderCopy ( + g_renderer, m_SDLTextureInfo[srcCh].texture, &srcRect, &dstRect); + SDL_SetRenderTarget (g_renderer, target); + } + + return res; +} + // Effectue un appel BltFast. // Les modes sont 0=transparent, 1=opaque. Sint32 CPixmap::BltFast (Sint32 chDst, size_t channel, Point dst, Rect rcRect) { - Sint32 res, limit; + Sint32 limit; // Effectue un peu de clipping. if (dst.x < m_clipRect.left) @@ -130,38 +204,12 @@ CPixmap::BltFast (Sint32 chDst, size_t channel, Point dst, Rect rcRect) if (rcRect.left >= rcRect.right || rcRect.top >= rcRect.bottom) return 0; - if (chDst < 0) - { - SDL_Rect srcRect, dstRect; - srcRect.x = rcRect.left; - srcRect.y = rcRect.top; - srcRect.w = rcRect.right - rcRect.left; - srcRect.h = rcRect.bottom - rcRect.top; - dstRect = srcRect; - dstRect.x = dst.x; - dstRect.y = dst.y; - - res = SDL_RenderCopy ( - g_renderer, m_SDLTextureInfo[channel].texture, &srcRect, &dstRect); - } - else - { - SDL_Rect srcRect, dstRect; - srcRect.x = rcRect.left; - srcRect.y = rcRect.top; - srcRect.w = rcRect.right - rcRect.left; - srcRect.h = rcRect.bottom - rcRect.top; - dstRect = srcRect; - dstRect.x = dst.x; - dstRect.y = dst.y; - - SDL_SetRenderTarget (g_renderer, m_SDLTextureInfo[chDst].texture); - res = SDL_RenderCopy ( - g_renderer, m_SDLTextureInfo[channel].texture, &srcRect, &dstRect); - SDL_SetRenderTarget (g_renderer, nullptr); - } - - return res; + Rect dstRect; + dstRect.left = dst.x; + dstRect.top = dst.y; + dstRect.right = dstRect.left + rcRect.right - rcRect.left; + dstRect.bottom = dstRect.top + rcRect.bottom - rcRect.top; + return this->BltFast (chDst, channel, dstRect, rcRect); } // Effectue un appel BltFast. @@ -207,24 +255,75 @@ CPixmap::BltFast ( bool CPixmap::ReloadTargetTextures () { + if (this->mainTexture) + { + SDL_DestroyTexture (this->mainTexture); + this->mainTexture = nullptr; + } + for (auto & tex : m_SDLTextureInfo) { if (!tex.second.target) continue; - if (!Cache ( - tex.first, tex.second.file, tex.second.dimTotal, tex.second.dimIcon)) + if (tex.second.file.empty ()) + { + if (!Cache (tex.first, tex.second.dimTotal)) + return false; + } + else if (!Cache ( + tex.first, tex.second.file, tex.second.dimTotal, + tex.second.dimIcon, Mode::FIX, tex.second.wideName)) return false; } return true; } +bool +CPixmap::Cache (size_t channel, Point totalDim) +{ + if (m_SDLTextureInfo.find (channel) == m_SDLTextureInfo.end ()) + { + m_SDLTextureInfo[channel].texture = SDL_CreateTexture ( + g_renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, totalDim.x, + totalDim.y); + + if (!m_SDLTextureInfo[channel].texture) + { + SDL_LogError ( + SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s", + SDL_GetError ()); + return false; + } + + SDL_SetTextureBlendMode ( + m_SDLTextureInfo[channel].texture, SDL_BLENDMODE_BLEND); + } + else + { + SDL_SetRenderTarget (g_renderer, m_SDLTextureInfo[channel].texture); + SDL_SetRenderDrawColor (g_renderer, 0, 0, 0, 0); + SDL_RenderClear (g_renderer); + SDL_SetRenderTarget (g_renderer, nullptr); + } + + m_SDLTextureInfo[channel].texMask = nullptr; + m_SDLTextureInfo[channel].target = true; + m_SDLTextureInfo[channel].dimIcon = Point{0, 0}; + m_SDLTextureInfo[channel].dimTotal = totalDim; + m_SDLTextureInfo[channel].file = ""; + m_SDLTextureInfo[channel].wideName = ""; + + return true; +} + // Cache une image contenant des ic�nes. bool CPixmap::Cache ( - size_t channel, const std::string & pFilename, Point totalDim, Point iconDim) + size_t channel, const std::string & pFilename, Point totalDim, Point iconDim, + Mode mode, std::string wideName) { std::string file = GetBaseDir () + pFilename; SDL_Surface * surface = IMG_Load (file.c_str ()); @@ -238,8 +337,12 @@ CPixmap::Cache ( SDL_Texture * texture = SDL_CreateTextureFromSurface (g_renderer, surface); Uint32 format; - Sint32 access, w, h; - SDL_QueryTexture (texture, &format, &access, &w, &h); + Sint32 access, ow, w, oh, h; + SDL_QueryTexture (texture, &format, &access, &ow, &oh); + + auto m = mode == EXPAND || channel == CHBACK; + w = m ? LXIMAGE () : ow; + h = m ? LYIMAGE () : oh; if (m_SDLTextureInfo.find (channel) == m_SDLTextureInfo.end ()) { @@ -254,8 +357,9 @@ CPixmap::Cache ( return false; } - SDL_SetTextureBlendMode ( - m_SDLTextureInfo[channel].texture, SDL_BLENDMODE_BLEND); + if (channel != CHBACK) + SDL_SetTextureBlendMode ( + m_SDLTextureInfo[channel].texture, SDL_BLENDMODE_BLEND); } SDL_SetRenderTarget (g_renderer, m_SDLTextureInfo[channel].texture); @@ -268,9 +372,62 @@ CPixmap::Cache ( m_SDLTextureInfo[channel].dimIcon = iconDim; m_SDLTextureInfo[channel].dimTotal = totalDim; m_SDLTextureInfo[channel].file = pFilename; + m_SDLTextureInfo[channel].wideName = wideName; SDL_SetRenderTarget (g_renderer, m_SDLTextureInfo[channel].texture); - SDL_RenderCopy (g_renderer, texture, nullptr, nullptr); + + switch (mode) + { + case FIX: + { + if (channel == CHBACK && (ow < LXIMAGE () || oh < LYIMAGE ())) + { + if (!wideName.empty ()) + { + std::string file = GetBaseDir () + m_SDLTextureInfo[channel].wideName; + SDL_Surface * surface = IMG_Load (file.c_str ()); + SDL_Texture * texture = + SDL_CreateTextureFromSurface (g_renderer, surface); + SDL_FreeSurface (surface); + SDL_RenderCopy (g_renderer, texture, nullptr, nullptr); + SDL_DestroyTexture (texture); + } + + SDL_Rect dst; + dst.x = (LXIMAGE () - ow) / 2; + dst.y = 0; + dst.w = ow; + dst.h = oh; + SDL_RenderCopy (g_renderer, texture, nullptr, &dst); + } + else + SDL_RenderCopy (g_renderer, texture, nullptr, nullptr); + break; + } + + case EXPAND: + { + SDL_Rect src, dst; + src.x = 0; + src.y = 0; + src.w = POSDRAWX - 1; + src.h = LYIMAGE (); + dst = src; + SDL_RenderCopy (g_renderer, texture, &src, &dst); + src.x = ow - 16; + src.w = 16; + dst.x = LXIMAGE () - 16; + dst.w = src.w; + SDL_RenderCopy (g_renderer, texture, &src, &dst); + src.x = POSDRAWX - 1; + src.w = ow - src.x - 16; + dst.x = src.x; + dst.w = DIMDRAWX + 1; + SDL_RenderCopy (g_renderer, texture, &src, &dst); + break; + } + } + SDL_SetRenderTarget (g_renderer, nullptr); if (!m_SDLTextureInfo[channel].texMask) @@ -318,6 +475,16 @@ CPixmap::Cache (size_t channel, SDL_Surface * surface, Point totalDim) return true; } +SDL_Texture * +CPixmap::getTexture (size_t channel) +{ + auto it = this->m_SDLTextureInfo.find (channel); + if (it == this->m_SDLTextureInfo.end ()) + return nullptr; + + return it->second.texture; +} + // Modifie la r�gion de clipping. void @@ -599,6 +766,10 @@ bool CPixmap::Display () { m_bBackDisplayed = true; + + if (this->mainTexture) + SDL_RenderCopy (g_renderer, this->mainTexture, nullptr, nullptr); + SDL_RenderPresent (g_renderer); return true; } @@ -769,23 +940,26 @@ CPixmap::GetCursorRect (MouseSprites sprite) } void -CPixmap::LoadCursors (Uint8 scale) +CPixmap::LoadCursors () { Uint32 rmask, gmask, bmask, amask; -/* SDL interprets each pixel as a 32-bit number, so our masks must depend -on the endianness (byte order) of the machine */ + /* SDL interprets each pixel as a 32-bit number, so our masks must depend + * on the endianness (byte order) of the machine + */ #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; -#else +#else /* SDL_BYTEORDER == SDL_BIG_ENDIAN */ rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; -#endif +#endif /* SDL_BYTEORDER != SDL_BIG_ENDIAN */ + + auto scale = this->GetDisplayScale (); for (int i = SPRITE_BEGIN; i <= SPRITE_END; ++i) { @@ -817,3 +991,49 @@ CPixmap::ChangeSprite (MouseSprites sprite) SDL_SetCursor (m_lpSDLCursors[sprite - 1]); m_lpCurrentCursor = m_lpSDLCursors[sprite - 1]; } + +double +CPixmap::GetDisplayScale () +{ + Sint32 w, h; + SDL_GetWindowSize (g_window, &w, &h); + return static_cast<double> (h / LYIMAGE ()); +} + +void +CPixmap::FromDisplayToGame (Sint32 & x, Sint32 & y, double prevScale) +{ + if (this->event->IsDemoPlaying ()) + return; + + double factor = 1; + + if (!g_bFullScreen) + factor = prevScale; + + x /= factor; + y /= factor; +} + +void +CPixmap::FromGameToDisplay (Sint32 & x, Sint32 & y) +{ + double factor = 1; + + if (!g_bFullScreen) + factor = g_zoom; + + x *= factor; + y *= factor; + + if (!g_bFullScreen) + return; + + Sint32 w, h; + SDL_GetWindowSize (g_window, &w, &h); + + double _w = w, _h = h; + + x = x * _w / LXIMAGE (); + y = y * _h / LYIMAGE (); +} diff --git a/src/pixmap.h b/src/pixmap.h index 4f0950b..4468d9d 100644 --- a/src/pixmap.h +++ b/src/pixmap.h @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -20,7 +20,7 @@ #pragma once -#include <SDL2/SDL.h> +#include <SDL.h> #include <string> #include <unordered_map> @@ -34,6 +34,7 @@ struct TextureInfo { SDL_Texture * texture; bool target; // can be used as a render target std::string file; + std::string wideName; Point dimTotal; Point dimIcon; @@ -47,22 +48,32 @@ struct TextureInfo { } }; +class CEvent; + class CPixmap { public: - CPixmap (); + enum Mode { + FIX = 0, + EXPAND, + }; + + CPixmap (CEvent * event); ~CPixmap (); bool Create (Point dim); + void CreateMainTexture (); bool ReloadTargetTextures (); + bool Cache (size_t channel, Point totalDim); bool Cache ( size_t channel, const std::string & pFilename, Point totalDim, - Point iconDim); + Point iconDim, Mode mode = FIX, std::string wideName = ""); bool Cache (size_t channel, const std::string & pFilename, Point totalDim); bool Cache (size_t channel, SDL_Surface * surface, Point totalDim); - void SetClipping (Rect clip); - Rect GetClipping (); + SDL_Texture * getTexture (size_t channel); + void SetClipping (Rect clip); + Rect GetClipping (); bool IsIconPixel (size_t channel, Sint32 rank, Point pos); @@ -82,10 +93,16 @@ public: void SetMouseSprite (MouseSprites sprite); void MouseShow (bool bShow); - void LoadCursors (Uint8 scale); + void LoadCursors (); void ChangeSprite (MouseSprites sprite); +public: + double GetDisplayScale (); + void FromDisplayToGame (Sint32 & x, Sint32 & y, double prevScale = 1); + void FromGameToDisplay (Sint32 & x, Sint32 & y); + protected: + Sint32 BltFast (Sint32 dstCh, size_t srcCh, Rect dstR, Rect srcR); Sint32 BltFast (Sint32 chDst, size_t channel, Point dst, Rect rcRect); Sint32 BltFast ( SDL_Texture * lpSDL, size_t channel, Point dst, Rect rcRect, @@ -104,8 +121,11 @@ protected: MouseSprites m_mouseSprite; bool m_bBackDisplayed; + CEvent * event; + SDL_Cursor * m_lpCurrentCursor; SDL_Cursor * m_lpSDLCursors[MAXCURSORS]; SDL_Surface * m_lpSDLBlupi; + SDL_Texture * mainTexture; std::unordered_map<size_t, TextureInfo> m_SDLTextureInfo; }; diff --git a/src/platform.h b/src/platform.h new file mode 100644 index 0000000..51fa9ca --- /dev/null +++ b/src/platform.h @@ -0,0 +1,37 @@ +/* + * This file is part of the planetblupi source code + * Copyright (C) 2018, Mathieu Schroeter + * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include <functional> + +class Platform +{ +private: + static std::function<void(const SDL_Event &)> handleEvent; + +private: + static void timer (void *); + +public: + enum Type { JS, SDL }; + + static Platform::Type getType (); + static void run (std::function<void(const SDL_Event &)> handleEvent); +}; diff --git a/src/platform/platform_js.cxx b/src/platform/platform_js.cxx new file mode 100644 index 0000000..2917967 --- /dev/null +++ b/src/platform/platform_js.cxx @@ -0,0 +1,58 @@ +/* + * This file is part of the planetblupi source code + * Copyright (C) 2018, Mathieu Schroeter + * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#include <emscripten.h> +#include <functional> + +#include "../blupi.h" +#include "../event.h" +#include "../platform.h" + +std::function<void(const SDL_Event &)> Platform::handleEvent; + +Platform::Type +Platform::getType () +{ + return JS; +} + +void +Platform::run (std::function<void(const SDL_Event &)> handleEvent) +{ + Platform::handleEvent = handleEvent; + Platform::timer (nullptr); + emscripten_set_main_loop ( + []() { + SDL_Event event; + while (SDL_PollEvent (&event)) + { + Platform::handleEvent (event); + if (event.type == SDL_QUIT) + break; + } + }, + 0, 1); +} + +void +Platform::timer (void *) +{ + CEvent::PushUserEvent (EV_UPDATE); + emscripten_async_call (Platform::timer, nullptr, g_timerInterval); +} diff --git a/src/platform/platform_sdl.cxx b/src/platform/platform_sdl.cxx new file mode 100644 index 0000000..b0b44cb --- /dev/null +++ b/src/platform/platform_sdl.cxx @@ -0,0 +1,57 @@ +/* + * This file is part of the planetblupi source code + * Copyright (C) 2018, Mathieu Schroeter + * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#include "../blupi.h" +#include "../event.h" +#include "../platform.h" + +std::function<void(const SDL_Event &)> Platform::handleEvent; + +Platform::Type +Platform::getType () +{ + return SDL; +} + +void +Platform::run (std::function<void(const SDL_Event &)> handleEvent) +{ + SDL_TimerID updateTimer = SDL_AddTimer ( + g_timerInterval, + [](Uint32 interval, void * param) -> Uint32 { + CEvent::PushUserEvent (EV_UPDATE); + return interval; + }, + nullptr); + + SDL_Event event; + while (SDL_WaitEvent (&event)) + { + handleEvent (event); + if (event.type == SDL_QUIT) + break; + } + + SDL_RemoveTimer (updateTimer); +} + +void +Platform::timer (void *) +{ +} diff --git a/src/progress.cxx b/src/progress.cxx index 9eb049c..0b4713a 100644 --- a/src/progress.cxx +++ b/src/progress.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify diff --git a/src/progress.h b/src/progress.h index 3ac2184..120ccee 100644 --- a/src/progress.h +++ b/src/progress.h @@ -20,6 +20,8 @@ #pragma once +#include "blupi.h" + class CPixmap; class CDecor; class CSound; diff --git a/src/sound.cxx b/src/sound.cxx index 2969914..0a899bc 100644 --- a/src/sound.cxx +++ b/src/sound.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -23,8 +23,30 @@ #include "def.h" #include "event.h" #include "misc.h" +#include "platform.h" #include "sound.h" +void +CSound::StopSound (bool immediat, Sint32 rank) +{ + Sounds stopCh; + + if (rank >= 0 && rank < MAXBLUPI) + { + stopCh = m_channelBlupi[rank]; + if (stopCh >= 0 && m_lpSDL[stopCh] != nullptr) + { + /* FIXME: add support of fade out with emscripten */ + if (immediat || Platform::getType () == Platform::Type::JS) + Mix_HaltChannel (stopCh + 1); + else + Mix_FadeOutChannel (stopCh + 1, 500); + } + + m_channelBlupi[rank] = SOUND_NONE; + } +} + // Stops all sounds. bool @@ -40,7 +62,8 @@ CSound::StopAllSounds (bool immediat, const std::set<Sint32> * except) if (Mix_Playing (i + 1) == SDL_TRUE) { - if (immediat) + /* FIXME: add support of fade out with emscripten */ + if (immediat || Platform::getType () == Platform::Type::JS) Mix_HaltChannel (i + 1); else Mix_FadeOutChannel (i + 1, 500); @@ -176,7 +199,12 @@ CSound::Cache (Sint32 channel, const std::string & pFilename) if (m_lpSDL[channel] && m_sndFiles[channel] == sound) return true; - Mix_Chunk * chunk = Mix_LoadWAV (file.c_str ()); + Mix_Chunk * chunk = nullptr; + std::string absolute; + + if (FileExists (file, absolute, Location::LOCATION_ABSOLUTE)) + chunk = Mix_LoadWAV (file.c_str ()); + if (!chunk) { if (GetLocale () != "en") @@ -262,18 +290,18 @@ CSound::Play (Sint32 channel, Sint32 volume, Uint8 panLeft, Uint8 panRight) // �ventuellement stopper le dernier son en cours ! bool -CSound::PlayImage (Sounds channel, Point pos, Sint32 rank) +CSound::PlayImage (Sounds channel, Point pos, Sint32 rank, bool stop) { Sint32 volumex, volumey, volume; - Sounds stopCh; if (rank >= 0 && rank < MAXBLUPI) { - stopCh = m_channelBlupi[rank]; - if (stopCh >= 0 && m_lpSDL[stopCh] != nullptr) - Mix_FadeOutChannel (stopCh + 1, 500); + bool immediat = channel == SOUND_DYNAMITE; - m_channelBlupi[rank] = channel; + if (stop || immediat) + this->StopSound (immediat, rank); + else + m_channelBlupi[rank] = channel; } Uint8 panRight, panLeft; @@ -288,17 +316,17 @@ CSound::PlayImage (Sounds channel, Point pos, Sint32 rank) if (volumex < 0) volumex = 0; } - else if (pos.x > LXIMAGE) + else if (pos.x > LXIMAGE ()) { panRight = 255; panLeft = 0; - volumex -= pos.x - LXIMAGE; + volumex -= pos.x - LXIMAGE (); if (volumex < 0) volumex = 0; } else { - panRight = 255 * static_cast<Uint16> (pos.x) / LXIMAGE; + panRight = 255 * static_cast<Uint16> (pos.x) / LXIMAGE (); panLeft = 255 - panRight; } @@ -308,9 +336,9 @@ CSound::PlayImage (Sounds channel, Point pos, Sint32 rank) if (volumey < 0) volumey = 0; } - else if (pos.y > LYIMAGE) + else if (pos.y > LYIMAGE ()) { - volumey -= pos.y - LYIMAGE; + volumey -= pos.y - LYIMAGE (); if (volumey < 0) volumey = 0; } @@ -338,7 +366,10 @@ CSound::PlayMusic (const std::string & lpszMIDIFilename) if (m_pMusic) Mix_FreeMusic (m_pMusic); - m_pMusic = Mix_LoadMUS (lpszMIDIFilename.c_str ()); + std::string absolute; + if (FileExists (lpszMIDIFilename, absolute, Location::LOCATION_ABSOLUTE)) + m_pMusic = Mix_LoadMUS (lpszMIDIFilename.c_str ()); + if (!m_pMusic) { printf ("%s\n", Mix_GetError ()); diff --git a/src/sound.h b/src/sound.h index 1237c37..ccf3f18 100644 --- a/src/sound.h +++ b/src/sound.h @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -25,7 +25,7 @@ #include <string> #include <vector> -#include <SDL2/SDL_mixer.h> +#include <SDL_mixer.h> #include "blupi.h" @@ -56,7 +56,8 @@ public: bool Play ( Sint32 channel, Sint32 volume = 0, Uint8 panLeft = 255, Uint8 panRight = 255); - bool PlayImage (Sounds channel, Point pos, Sint32 rank = -1); + bool + PlayImage (Sounds channel, Point pos, Sint32 rank = -1, bool stop = false); bool PlayMusic (const std::string & lpszMIDIFilename); bool RestartMusic (); void SuspendMusic (); @@ -65,6 +66,7 @@ public: bool IsStoppedOnDemand (); void AdaptVolumeMusic (); void SetSuspendSkip (Sint32 nb); + void StopSound (bool immediat, Sint32 rank); bool StopAllSounds (bool immediat, const std::set<Sint32> * except = nullptr); protected: diff --git a/src/text.cxx b/src/text.cxx index 7a96d2d..222c165 100644 --- a/src/text.cxx +++ b/src/text.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -21,7 +21,9 @@ #include <stdio.h> #include <stdlib.h> +#include "blupi.h" #include "def.h" +#include "event.h" #include "misc.h" #include "pixmap.h" #include "text.h" |