diff --git a/Build_Release/ASSETS/ACTOR_PROTOTYPES/LEVEL1/LEVEL1_RAT.XML b/Build_Release/ASSETS/ACTOR_PROTOTYPES/LEVEL1/LEVEL1_RAT.XML index 3211dc8b..0b40b3f4 100644 --- a/Build_Release/ASSETS/ACTOR_PROTOTYPES/LEVEL1/LEVEL1_RAT.XML +++ b/Build_Release/ASSETS/ACTOR_PROTOTYPES/LEVEL1/LEVEL1_RAT.XML @@ -54,11 +54,8 @@ throweastwest 2 - 1 - /LEVEL1/IMAGES/RATBOMB/* - - - 20 + + ActorPrototype_Level1_RatBomb EnemyAIRangedSensor Rectangle @@ -69,7 +66,7 @@ 2 0.000000 0.000000 - -1.#QNAN0 + 0.000000 diff --git a/Build_Release/ASSETS/ACTOR_PROTOTYPES/LEVEL1/LEVEL1_RAT_BOMB.XML b/Build_Release/ASSETS/ACTOR_PROTOTYPES/LEVEL1/LEVEL1_RAT_BOMB.XML new file mode 100644 index 00000000..2a754bfd --- /dev/null +++ b/Build_Release/ASSETS/ACTOR_PROTOTYPES/LEVEL1/LEVEL1_RAT_BOMB.XML @@ -0,0 +1,22 @@ + + + true + /LEVEL1/IMAGES/RATBOMB/* + /LEVEL1/PALETTES/MAIN.PAL + + + /LEVEL1/ANIS/RATBOMB/FALLEASTWEST.ANI + + + 20 + DamageType_Explosion + + + + + 262144 + 1048834 + + + + \ No newline at end of file diff --git a/Build_Release/ASSETS/ACTOR_PROTOTYPES/LEVEL1/LEVEL1_SOLDIER.XML b/Build_Release/ASSETS/ACTOR_PROTOTYPES/LEVEL1/LEVEL1_SOLDIER.XML index 8f1217d2..1d84c45d 100644 --- a/Build_Release/ASSETS/ACTOR_PROTOTYPES/LEVEL1/LEVEL1_SOLDIER.XML +++ b/Build_Release/ASSETS/ACTOR_PROTOTYPES/LEVEL1/LEVEL1_SOLDIER.XML @@ -117,11 +117,13 @@ 5 - strike2 - 3 + + + strike + 2 1 /LEVEL1/IMAGES/MUSKETBALL/* - + 10 diff --git a/Build_Release/ASSETS/LEVEL_METADATA/LEVEL4.XML b/Build_Release/ASSETS/LEVEL_METADATA/LEVEL4.XML index 67ff5784..26e097e3 100644 --- a/Build_Release/ASSETS/LEVEL_METADATA/LEVEL4.XML +++ b/Build_Release/ASSETS/LEVEL_METADATA/LEVEL4.XML @@ -18,8 +18,8 @@ - - + + diff --git a/Build_Release/openclaw.html b/Build_Release/openclaw.html index 59e4c208..19ca0c33 100644 --- a/Build_Release/openclaw.html +++ b/Build_Release/openclaw.html @@ -1,14 +1,160 @@ - - + + + + + OpenClaw + + + + + + + + + + + - + + + + + + + Enable Fullscreen Mode + Debug Panel + + + + + Cheat codes: + Infinite Jumps + God Mode + Physics Debug + Infinite Ammo + + + Powerups: + Catnip + Fire Sword + Frost Sword + Lightning Sword + Invisible + Invulnerable + + + Clear Console + + + + - \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 65918341..c68abc7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 3.2) option(Android "Android" OFF) option(Emscripten "Build as WASM" OFF) +option(Extern_Config "Do not embed config file" ON) set(EMSCRIPTEN_PATH "CHANGE ME PLEASE!!!/emsdk") project(OpenClaw) @@ -64,7 +65,12 @@ list(APPEND TARGET_LIBS Box2D ) if (Emscripten) - set_target_properties(openclaw PROPERTIES LINK_FLAGS "-s WASM=1 -s BINARYEN_METHOD='native-wasm' -s EXPORTED_FUNCTIONS='[_main]' -s USE_SDL=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS='[\"pcx\",\"png\",\"tga\"]' -s USE_SDL_TTF=2 -s USE_SDL_GFX=2 -s ASYNCIFY=1 -s TOTAL_MEMORY=268435456 --preload-file ../Build_Release/config.xml@config.xml --preload-file ../Build_Release/CLAW.REZ@CLAW.REZ --preload-file ../Build_Release/ASSETS.ZIP@ASSETS.ZIP --preload-file ../Build_Release/SAVES.XML@SAVES.XML --preload-file ../Build_Release/console02.tga@console02.tga --preload-file ../Build_Release/clacon.ttf@clacon.ttf") + if (Extern_Config) + set(CONFIG_PRELOAD_FILE "") + else (Extern_Config) + set(CONFIG_PRELOAD_FILE "--preload-file ../Build_Release/config.xml@config.xml") + endif (Extern_Config) + set_target_properties(openclaw PROPERTIES LINK_FLAGS "-s WASM=1 -s BINARYEN_METHOD='native-wasm' -s EXPORTED_FUNCTIONS='[_main]' -s USE_SDL=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS='[\"pcx\",\"png\",\"tga\"]' -s USE_SDL_TTF=2 -s USE_SDL_GFX=2 -s ASYNCIFY=1 -s TOTAL_MEMORY=268435456 ${CONFIG_PRELOAD_FILE} --preload-file ../Build_Release/CLAW.REZ@CLAW.REZ --preload-file ../Build_Release/ASSETS.ZIP@ASSETS.ZIP --preload-file ../Build_Release/console02.tga@console02.tga --preload-file ../Build_Release/clacon.ttf@clacon.ttf") else (Emscripten) list(APPEND TARGET_LIBS SDL2 diff --git a/OpenClaw/ActorController.cpp b/OpenClaw/ActorController.cpp index 319cf195..44d6d7b8 100644 --- a/OpenClaw/ActorController.cpp +++ b/OpenClaw/ActorController.cpp @@ -312,9 +312,9 @@ bool ActorController::OnTap(int id, const Touch_TapEvent &evt) { event.type = SDL_KEYDOWN; event.key.keysym.sym = key; event.key.keysym.scancode = SDL_GetScancodeFromKey(key); - g_pApp->OnEvent(event); + SDL_PushEvent(&event); event.type = SDL_KEYUP; - g_pApp->OnEvent(event); + SDL_PushEvent(&event); return true; } case WEAPON_TAP_RECOGNIZER: diff --git a/OpenClaw/ClawGameLogic.cpp b/OpenClaw/ClawGameLogic.cpp index 2e4bf33a..fcdd3fbf 100644 --- a/OpenClaw/ClawGameLogic.cpp +++ b/OpenClaw/ClawGameLogic.cpp @@ -407,7 +407,7 @@ void ClawGameLogic::CheckpointReachedDelegate(IEventDataPtr pEventData) m_pGameSaveMgr->AddCheckpointSave(m_pCurrentLevel->GetLevelNumber(), checkpointSave); // If not in testing mode - if (!g_pApp->GetGlobalOptions()->loadAllLevelSaves) + if (m_pGameSaveMgr->IsSaveSupported() && !g_pApp->GetGlobalOptions()->loadAllLevelSaves) { TiXmlDocument saveGamesDoc; saveGamesDoc.LinkEndChild(m_pGameSaveMgr->ToXml()); diff --git a/OpenClaw/Engine/Actor/ActorTemplates.cpp b/OpenClaw/Engine/Actor/ActorTemplates.cpp index 140aa707..7dee7671 100644 --- a/OpenClaw/Engine/Actor/ActorTemplates.cpp +++ b/OpenClaw/Engine/Actor/ActorTemplates.cpp @@ -1530,6 +1530,7 @@ namespace ActorTemplates TiXmlElement* CreateXmlData_PowderKegActor(std::string imageSet, Point position, int32 damage, int32 zCoord) { + // TODO: create xml actor prototype and implement lift-throw logic TiXmlElement* pActor = new TiXmlElement("Actor"); pActor->SetAttribute("Type", imageSet.c_str()); diff --git a/OpenClaw/Engine/Actor/Components/AIComponents/TogglePegAIComponent.cpp b/OpenClaw/Engine/Actor/Components/AIComponents/TogglePegAIComponent.cpp index e68c1fac..9c2f8f11 100644 --- a/OpenClaw/Engine/Actor/Components/AIComponents/TogglePegAIComponent.cpp +++ b/OpenClaw/Engine/Actor/Components/AIComponents/TogglePegAIComponent.cpp @@ -90,36 +90,36 @@ void TogglePegAIComponent::VUpdate(uint32 msDiff) } -struct DelayEventInfo -{ - DelayEventInfo(IEventDataPtr pEvent, uint32 msDelay) - { - this->pEvent = pEvent; - this->msDelay = msDelay; - } - - IEventDataPtr pEvent; - uint32 msDelay; -}; - -static int SetupPlayMusicThread(void* pData) -{ - DelayEventInfo* pEventInfo = (DelayEventInfo*)pData; - - SDL_Delay(pEventInfo->msDelay); - IEventMgr::Get()->VTriggerEvent(pEventInfo->pEvent); - - return 0; -} - -static void DelayEvent(IEventDataPtr pEvent, uint32 msDelay) -{ - DelayEventInfo* pDelayEventInfo = new DelayEventInfo(pEvent, msDelay); - - // Playing music track takes ALOT of time for some reason so play it in another thread - SDL_Thread* pThread = SDL_CreateThread(SetupPlayMusicThread, "DelayedEventThread", (void*)pDelayEventInfo); - SDL_DetachThread(pThread); -} +//struct DelayEventInfo +//{ +// DelayEventInfo(IEventDataPtr pEvent, uint32 msDelay) +// { +// this->pEvent = pEvent; +// this->msDelay = msDelay; +// } +// +// IEventDataPtr pEvent; +// uint32 msDelay; +//}; +// +//static int SetupPlayMusicThread(void* pData) +//{ +// DelayEventInfo* pEventInfo = (DelayEventInfo*)pData; +// +// SDL_Delay(pEventInfo->msDelay); +// IEventMgr::Get()->VTriggerEvent(pEventInfo->pEvent); +// +// return 0; +//} +// +//static void DelayEvent(IEventDataPtr pEvent, uint32 msDelay) +//{ +// DelayEventInfo* pDelayEventInfo = new DelayEventInfo(pEvent, msDelay); +// +// // Playing music track takes ALOT of time for some reason so play it in another thread +// SDL_Thread* pThread = SDL_CreateThread(SetupPlayMusicThread, "DelayedEventThread", (void*)pDelayEventInfo); +// SDL_DetachThread(pThread); +//} void TogglePegAIComponent::VOnAnimationFrameChanged(Animation* pAnimation, AnimationFrame* pLastFrame, AnimationFrame* pNewFrame) { diff --git a/OpenClaw/Engine/Actor/Components/EnemyAI/EnemyAIComponent.cpp b/OpenClaw/Engine/Actor/Components/EnemyAI/EnemyAIComponent.cpp index 4a4f3aae..8386a1cb 100644 --- a/OpenClaw/Engine/Actor/Components/EnemyAI/EnemyAIComponent.cpp +++ b/OpenClaw/Engine/Actor/Components/EnemyAI/EnemyAIComponent.cpp @@ -123,10 +123,9 @@ void EnemyAIComponent::VUpdate(uint32 msDiff) shared_ptr pEvent(new EventData_Move_Actor(m_pOwner->GetGUID(), m_pPositionComponent->GetPosition())); IEventMgr::Get()->VTriggerEvent(pEvent); - SDL_Rect dummy; SDL_Rect renderRect = m_pRenderComponent->VGetPositionRect(); SDL_Rect cameraRect = pCamera->GetCameraRect(); - if (!SDL_IntersectRect(&renderRect, &cameraRect, &dummy)) + if (!SDL_HasIntersection(&renderRect, &cameraRect)) { shared_ptr pEvent(new EventData_Destroy_Actor(m_pOwner->GetGUID())); IEventMgr::Get()->VQueueEvent(pEvent); diff --git a/OpenClaw/Engine/Actor/Components/PhysicsComponent.cpp b/OpenClaw/Engine/Actor/Components/PhysicsComponent.cpp index 5befbefe..b325ca2c 100644 --- a/OpenClaw/Engine/Actor/Components/PhysicsComponent.cpp +++ b/OpenClaw/Engine/Actor/Components/PhysicsComponent.cpp @@ -259,7 +259,10 @@ void PhysicsComponent::VPostPostInit() double deltaY = raycastDown.deltaY - m_pPhysics->VGetAABB(m_pOwner->GetGUID(), true).h / 2; pPositionComponent->SetY(pPositionComponent->GetY() + deltaY - 1); - m_pPhysics->VSetPosition(m_pOwner->GetGUID(), pPositionComponent->GetPosition()); + const Point newPos = pPositionComponent->GetPosition(); + m_pPhysics->VSetPosition(m_pOwner->GetGUID(), newPos); + IEventMgr::Get()->VTriggerEvent(IEventDataPtr( + new EventData_Move_Actor(m_pOwner->GetGUID(), newPos))); } } diff --git a/OpenClaw/Engine/Actor/Components/PickupComponents/PickupComponent.cpp b/OpenClaw/Engine/Actor/Components/PickupComponents/PickupComponent.cpp index c18e4281..96a7bd88 100644 --- a/OpenClaw/Engine/Actor/Components/PickupComponents/PickupComponent.cpp +++ b/OpenClaw/Engine/Actor/Components/PickupComponents/PickupComponent.cpp @@ -196,10 +196,9 @@ void TreasurePickupComponent::VUpdate(uint32 msDiff) shared_ptr pEvent(new EventData_Move_Actor(m_pOwner->GetGUID(), m_pPositionComponent->GetPosition())); IEventMgr::Get()->VTriggerEvent(pEvent); - SDL_Rect dummy; SDL_Rect renderRect = m_pRenderComponent->VGetPositionRect(); SDL_Rect cameraRect = pCamera->GetCameraRect(); - if (!SDL_IntersectRect(&renderRect, &cameraRect, &dummy)) + if (!SDL_HasIntersection(&renderRect, &cameraRect)) { shared_ptr pEvent(new EventData_Destroy_Actor(m_pOwner->GetGUID())); IEventMgr::Get()->VQueueEvent(pEvent); diff --git a/OpenClaw/Engine/GameApp/BaseGameApp.cpp b/OpenClaw/Engine/GameApp/BaseGameApp.cpp index 596c35ff..03eb62fa 100644 --- a/OpenClaw/Engine/GameApp/BaseGameApp.cpp +++ b/OpenClaw/Engine/GameApp/BaseGameApp.cpp @@ -239,7 +239,7 @@ void BaseGameApp::StepLoop() { } // Artificially decrease fps. Configurable from console - SDL_Delay(m_DebugOptions.cpuDelayMs); + Util::Sleep(m_DebugOptions.cpuDelayMs); } else { Terminate(); #ifdef __EMSCRIPTEN__ @@ -443,6 +443,14 @@ bool BaseGameApp::LoadGameOptions(const char* inConfigFile) ParseValueFromXmlElem(&m_GameOptions.isFullscreenDesktop, displayElem->FirstChildElement("IsFullscreenDesktop")); } +#ifdef __EMSCRIPTEN__ + SDL_Point canvasSize; + if (Util::GetCanvasSize(canvasSize)) { + LOG(ToStr("Config window size is replaced by canvas size: ") + ToStr(canvasSize.x) + ToStr("x") + ToStr(canvasSize.y)); + m_GameOptions.windowWidth = canvasSize.x; + m_GameOptions.windowHeight = canvasSize.y; + } +#endif //------------------------------------------------------------------------- // Audio diff --git a/OpenClaw/Engine/GameApp/BaseGameLogic.cpp b/OpenClaw/Engine/GameApp/BaseGameLogic.cpp index 2f07eb18..f16653e2 100644 --- a/OpenClaw/Engine/GameApp/BaseGameLogic.cpp +++ b/OpenClaw/Engine/GameApp/BaseGameLogic.cpp @@ -83,6 +83,10 @@ bool BaseGameLogic::Initialize() { m_pActorFactory = VCreateActorFactory(); + if (!m_pGameSaveMgr->IsSaveSupported()) { + return m_pGameSaveMgr->Initialize(nullptr); + } + std::string savesFilePath = g_pApp->GetGameConfig()->userDirectory + g_pApp->GetGameConfig()->savesFile; TiXmlDocument gameSaves(savesFilePath.c_str()); @@ -170,7 +174,7 @@ void RenderLoadingScreen(shared_ptr pBackground, SDL_Rect& renderRect, Po SDL_RenderCopy(pRenderer, pTotalProgressBar, NULL, &totalProgressBarRect); SDL_RenderCopy(pRenderer, pRemainingProgressBar, NULL, &remainingProgressBarRect); - SDL_RenderPresent(pRenderer); + Util::RenderForcePresent(pRenderer); SDL_DestroyTexture(pTotalProgressBar); SDL_DestroyTexture(pRemainingProgressBar); @@ -494,7 +498,7 @@ bool BaseGameLogic::VLoadScoreScreen(const char* xmlScoreScreenResource) m_pGameSaveMgr->AddCheckpointSave(nextLevelNumber, nextLevelCheckpoint); // If not in testing mode - if (!g_pApp->GetGlobalOptions()->loadAllLevelSaves) + if (m_pGameSaveMgr->IsSaveSupported() && !g_pApp->GetGlobalOptions()->loadAllLevelSaves) { TiXmlDocument saveGamesDoc; saveGamesDoc.LinkEndChild(m_pGameSaveMgr->ToXml()); diff --git a/OpenClaw/Engine/GameApp/GameSaves.h b/OpenClaw/Engine/GameApp/GameSaves.h index e67ce888..a3fce7cd 100644 --- a/OpenClaw/Engine/GameApp/GameSaves.h +++ b/OpenClaw/Engine/GameApp/GameSaves.h @@ -199,7 +199,7 @@ class GameSaveMgr public: bool Initialize(TiXmlElement* pGameSaveData) { - if (g_pApp->GetGlobalOptions()->loadAllLevelSaves || !IS_SAVE_SUPPORTED) + if (g_pApp->GetGlobalOptions()->loadAllLevelSaves || !IsSaveSupported()) { InitializeWithAllLevels(); return true; @@ -358,6 +358,11 @@ class GameSaveMgr return (GetCheckpointSave(levelNumber, checkpointNumber) != NULL); } + bool IsSaveSupported() + { + return IS_SAVE_SUPPORTED; + } + private: LevelSaveMap m_LevelSaveMap; }; diff --git a/OpenClaw/Engine/GameApp/MainLoop.cpp b/OpenClaw/Engine/GameApp/MainLoop.cpp index e66c44b6..f5c616ee 100644 --- a/OpenClaw/Engine/GameApp/MainLoop.cpp +++ b/OpenClaw/Engine/GameApp/MainLoop.cpp @@ -7,6 +7,10 @@ #include #endif +#ifdef __EMSCRIPTEN__ +#include +#endif + int RunGameEngine(int argc, char** argv) { if (SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH) != 0) @@ -36,11 +40,10 @@ int RunGameEngine(int argc, char** argv) LOG("Looking for: " + userDirectory + "config.xml"); // Temporary hack - always prefer config in the same folder as binary to default config - std::ifstream f("config.xml"); - if (f.good()) + if (TryToFindFile("config.xml")) { + // File was found in a working directory userDirectory = ""; - f.close(); } LOG("Expecting config.xml in path: " + userDirectory + "config.xml"); @@ -67,3 +70,24 @@ int RunGameEngine(int argc, char** argv) // Run the game return g_pApp->Run(); } + +bool TryToFindFile(const char *path) { + { + std::ifstream f(path); + if (f.good()) { + return true; + } + } +#ifdef __EMSCRIPTEN__ + // File does not exist. Try to download + emscripten_wget(path, path); + { + // Check is file downloaded + std::ifstream f(path); + if (f.good()) { + return true; + } + } +#endif + return false; +} diff --git a/OpenClaw/Engine/GameApp/MainLoop.h b/OpenClaw/Engine/GameApp/MainLoop.h index a2abad77..54eccfd0 100644 --- a/OpenClaw/Engine/GameApp/MainLoop.h +++ b/OpenClaw/Engine/GameApp/MainLoop.h @@ -3,4 +3,6 @@ extern int RunGameEngine(int argc, char** argv); +extern bool TryToFindFile(const char *path); + #endif \ No newline at end of file diff --git a/OpenClaw/Engine/Graphics2D/Image.cpp b/OpenClaw/Engine/Graphics2D/Image.cpp index c0260b91..3f1c9349 100644 --- a/OpenClaw/Engine/Graphics2D/Image.cpp +++ b/OpenClaw/Engine/Graphics2D/Image.cpp @@ -79,23 +79,10 @@ SDL_Texture* Image::GetTextureFromPid(WapPid* pid, SDL_Renderer* renderer) assert(pid != NULL); assert(renderer != NULL); - uint32_t rmask, gmask, bmask, amask; uint32_t width = pid->width; uint32_t height = pid->height; -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - rmask = 0xff000000; - gmask = 0x00ff0000; - bmask = 0x0000ff00; - amask = 0x000000ff; -#else - rmask = 0x000000ff; - gmask = 0x0000ff00; - bmask = 0x00ff0000; - amask = 0xff000000; -#endif - - SDL_Surface* surface = SDL_CreateRGBSurface(0, width, height, 32, rmask, gmask, bmask, amask); + SDL_Surface* surface = Util::CreateRGBSurface(0, width, height, 32); assert(surface != NULL); uint32_t colorIdx; diff --git a/OpenClaw/Engine/Interfaces.cpp b/OpenClaw/Engine/Interfaces.cpp index 6768cb07..a616670b 100644 --- a/OpenClaw/Engine/Interfaces.cpp +++ b/OpenClaw/Engine/Interfaces.cpp @@ -62,6 +62,8 @@ std::string EnumToString_ActorPrototype(ActorPrototype actorProto) { ActorPrototype_Level2_TowerCannonRight, "ActorPrototype_Level2_TowerCannonRight" }, // Projectiles + { ActorPrototype_Level1_RatBomb, "ActorPrototype_Level1_RatBomb" }, + { ActorPrototype_Level2_CannonBall, "ActorPrototype_Level2_CannonBall" }, { ActorPrototype_Level2_RatProjectile, "ActorPrototype_Level2_RatProjectile" }, @@ -289,6 +291,8 @@ ActorPrototype StringToEnum_ActorPrototype(std::string actorProtoStr) { "ActorPrototype_Level2_TowerCannonRight", ActorPrototype_Level2_TowerCannonRight }, // Projectiles + { "ActorPrototype_Level1_RatBomb", ActorPrototype_Level1_RatBomb }, + { "ActorPrototype_Level2_CannonBall", ActorPrototype_Level2_CannonBall }, { "ActorPrototype_Level2_RatProjectile", ActorPrototype_Level2_RatProjectile }, diff --git a/OpenClaw/Engine/Interfaces.h b/OpenClaw/Engine/Interfaces.h index 579c30ad..37fe83fa 100644 --- a/OpenClaw/Engine/Interfaces.h +++ b/OpenClaw/Engine/Interfaces.h @@ -335,6 +335,7 @@ enum ActorPrototype ActorPrototype_Level2_TowerCannonRight, // Projectiles + ActorPrototype_Level1_RatBomb, ActorPrototype_Level2_CannonBall, ActorPrototype_Level2_RatProjectile, ActorPrototype_Level3_RatBomb, diff --git a/OpenClaw/Engine/Resource/Loaders/ResourceCorrection.cpp b/OpenClaw/Engine/Resource/Loaders/ResourceCorrection.cpp index e40ca3ce..2dbf944f 100644 --- a/OpenClaw/Engine/Resource/Loaders/ResourceCorrection.cpp +++ b/OpenClaw/Engine/Resource/Loaders/ResourceCorrection.cpp @@ -4,47 +4,35 @@ void OnPidLoaded(const char* resource, WapPid* pPid) { const std::string resourceName(resource); - if (resourceName == "/level2/images/towercannonleft/frame002.pid") + if (resourceName == "/level2/images/towercannonleft/frame002.pid" || + resourceName == "/level2/images/towercannonleft/frame004.pid" || + resourceName == "/level2/images/towercannonleft/frame005.pid") { pPid->offsetX -= 2; } - else if (resourceName == "/level2/images/towercannonleft/frame004.pid") - { - pPid->offsetX -= 2; - } - else if (resourceName == "/level2/images/towercannonleft/frame005.pid") - { - pPid->offsetX -= 2; - } - if (resourceName == "/level2/images/towercannonright/frame002.pid") - { - pPid->offsetX += 2; - } - else if (resourceName == "/level2/images/towercannonright/frame004.pid") - { - pPid->offsetX += 2; - } - else if (resourceName == "/level2/images/towercannonright/frame005.pid") + else if (resourceName == "/level2/images/towercannonright/frame002.pid" || + resourceName == "/level2/images/towercannonright/frame004.pid" || + resourceName == "/level2/images/towercannonright/frame005.pid") { pPid->offsetX += 2; } - else if (resourceName.find("/level2/images/powderkeg/frame") != std::string::npos) + else if (resourceName.find("/images/powderkeg/frame") != std::string::npos) { - pPid->offsetY += 20; + pPid->offsetY -= 45; } - else if (resourceName.find("/level9/images/powderkeg/frame") != std::string::npos) + else if (resourceName.find("/level2/images/cannon/frame") != std::string::npos) { - pPid->offsetY += 24; + pPid->offsetY -= 25; } - else if (resourceName.find("/level3/images/powderkeg/frame") != std::string::npos) + else if (resourceName.find("/level8/images/cannon/frame") != std::string::npos) { - pPid->offsetY -= 24; + pPid->offsetY -= 45; } - else if (resourceName.find("/level6/images/powderkeg/frame") != std::string::npos) + else if (resourceName.find("/level8/images/gabrielcannon/frame") != std::string::npos) { - pPid->offsetY += 4; + pPid->offsetY -= 80; } - else if (resourceName.find("/level3/images/ratbomb/") != std::string::npos) + else if (resourceName.find("/images/ratbomb/frame") != std::string::npos) { pPid->offsetY -= 40; } diff --git a/OpenClaw/Engine/Scene/ActorSceneNode.cpp b/OpenClaw/Engine/Scene/ActorSceneNode.cpp index e18d1269..b773016d 100644 --- a/OpenClaw/Engine/Scene/ActorSceneNode.cpp +++ b/OpenClaw/Engine/Scene/ActorSceneNode.cpp @@ -61,6 +61,14 @@ void SDL2ActorSceneNode::VRender(Scene* pScene) actorImage->GetHeight() }; + // Do not render anything which is not seen + if (renderRect.x > cameraRect.w || + renderRect.y > cameraRect.h || + renderRect.x + renderRect.w < 0 || + renderRect.y + renderRect.h < 0) { + return; + } + SDL_SetTextureAlphaMod(actorImage->GetTexture(), arc->GetAlpha()); SDL_Color colorMod = arc->GetColorMod(); diff --git a/OpenClaw/Engine/Scene/SceneNodes.cpp b/OpenClaw/Engine/Scene/SceneNodes.cpp index 1155643d..0c189f3c 100644 --- a/OpenClaw/Engine/Scene/SceneNodes.cpp +++ b/OpenClaw/Engine/Scene/SceneNodes.cpp @@ -74,6 +74,16 @@ void SceneNode::VRenderChildren(Scene* pScene) { // TODO: Huge overhead from testing visibility of every single actor each frame // Possible solution: Use Box2D Broadphase to retrieve all actors within AABB + + // P.S. I don't think it would work faster. + // Actor may not have a PhysicsComponent. And we will have to create fake physics objects + // for every actor and update AABB position properties each frame. + + // We can try to represent each actor as a Point from PositionComponent + // and use 2D grid to store and query it. + // In this case we will render only visible grids and near neighbors. + // As I understood b2DynamicTree will be useless + // for points (AABB rectangles with 0 width and height) if (childNode->VIsVisible(pScene)) { childNode->VPreRender(pScene); @@ -101,16 +111,8 @@ bool SceneNode::VIsVisible(Scene* pScene) const } const SDL_Rect cameraRect = pCamera->GetCameraRect(); - SDL_Rect actorRect = m_pRenderComponent->VGetPositionRect(); - - SDL_Rect result; - SDL_Rect position = m_pRenderComponent->VGetPositionRect(); - if (!SDL_IntersectRect(&cameraRect, &position, &result)) - { - return false; - } - - return true; + const SDL_Rect position = m_pRenderComponent->VGetPositionRect(); + return SDL_HasIntersection(&cameraRect, &position); } bool SceneNode::VAddChild(shared_ptr ikid) @@ -269,7 +271,7 @@ void CameraNode::SetViewPosition(Scene* pScene) } } -bool CameraNode::IntersectsWithPoint(const Point& point, float cameraScale) +bool CameraNode::IntersectsWithPoint(const Point& point, float cameraScale) const { SDL_Rect cameraRect = GetCameraRect(); diff --git a/OpenClaw/Engine/Scene/SceneNodes.h b/OpenClaw/Engine/Scene/SceneNodes.h index e6f794c0..aaa998fb 100644 --- a/OpenClaw/Engine/Scene/SceneNodes.h +++ b/OpenClaw/Engine/Scene/SceneNodes.h @@ -125,9 +125,14 @@ class CameraNode : public SceneNode public: CameraNode(Point position, uint32 width, uint32 height); - virtual void VRender(Scene* pScene); - virtual bool IsVisible(Scene* pScene) const { return m_Active; } + void VRender(Scene* pScene) override; + bool VIsVisible(Scene* pScene) const override { return m_Active; } + void VSetPosition(const Point &position) override { + SceneNode::VSetPosition(position); + CalcCameraRect(); + } + // Overridden but non-virtual. Be careful with it Point GetPosition() { return m_Properties.GetPosition() + m_CameraOffset; } void SetViewPosition(Scene* pScene); @@ -135,35 +140,32 @@ class CameraNode : public SceneNode shared_ptr GetTarget() { return m_pTarget; } void ClearTarget() { m_pTarget = shared_ptr(); } - void SetSize(uint32 width, uint32 height) { m_Width = width; m_Height = height; } + void SetSize(uint32 width, uint32 height) { m_Width = width; m_Height = height; CalcCameraRect(); } uint32 GetWidth() { return m_Width; } uint32 GetHeight() { return m_Height; } - // TODO: Calc this only when changes are performed, do not recalc it every single time + // Calc this only when changes are performed, and do not recalc it every single time // since this function is called A LOT inline SDL_Rect GetCameraRect() const { - return{ (int)(m_Properties.GetPosition().x + m_CameraOffset.x), - (int)(m_Properties.GetPosition().y + m_CameraOffset.y), - (int)(m_Width / m_ScaleX), - (int)(m_Height / m_ScaleY) }; + return m_CachedCameraRect; } - inline double GetCameraOffsetX() { return m_CameraOffset.x; } - inline double GetCameraOffsetY() { return m_CameraOffset.y; } + inline double GetCameraOffsetX() const { return m_CameraOffset.x; } + inline double GetCameraOffsetY() const { return m_CameraOffset.y; } - inline void SetCameraOffsetX(double offX) { m_CameraOffset.x = offX; } - inline void SetCameraOffsetY(double offY) { m_CameraOffset.y = offY; } + inline void SetCameraOffsetX(double offX) { SetCameraOffset(offX, m_CameraOffset.y); } + inline void SetCameraOffsetY(double offY) { SetCameraOffset(m_CameraOffset.x, offY); } - inline void AddCameraOffsetX(double offset) { m_CameraOffset.x += offset; } - inline void AddCameraOffsetY(double offset) { m_CameraOffset.y += offset; } + inline void AddCameraOffsetX(double offset) { SetCameraOffset(m_CameraOffset.x + offset, m_CameraOffset.y); } + inline void AddCameraOffsetY(double offset) { SetCameraOffset(m_CameraOffset.x, m_CameraOffset.y + offset); } - inline void SetCameraOffset(double offX, double offY) { m_CameraOffset.Set(offX, offY); } + inline void SetCameraOffset(double offX, double offY) { m_CameraOffset.Set(offX, offY); CalcCameraRect(); } - bool IntersectsWithPoint(const Point& point, float cameraScale = 1.0f); + bool IntersectsWithPoint(const Point& point, float cameraScale = 1.0f) const; - inline Point GetCenterPosition() + inline Point GetCenterPosition() const { return Point( m_Properties.GetPosition().x + m_CameraOffset.x + m_Width / 2, @@ -171,6 +173,13 @@ class CameraNode : public SceneNode } protected: + void CalcCameraRect() { + m_CachedCameraRect = {(int) (m_Properties.GetPosition().x + m_CameraOffset.x), + (int) (m_Properties.GetPosition().y + m_CameraOffset.y), + (int) (m_Width / m_ScaleX), + (int) (m_Height / m_ScaleY)}; + } + uint32 m_Width; uint32 m_Height; Point m_CameraOffset; @@ -181,6 +190,7 @@ class CameraNode : public SceneNode float m_ScaleY; shared_ptr m_pTarget; + SDL_Rect m_CachedCameraRect; }; #endif //__SCENENODE_H__ \ No newline at end of file diff --git a/OpenClaw/Engine/Scene/TilePlaneSceneNode.cpp b/OpenClaw/Engine/Scene/TilePlaneSceneNode.cpp index 1e1622de..3f3fc1c8 100644 --- a/OpenClaw/Engine/Scene/TilePlaneSceneNode.cpp +++ b/OpenClaw/Engine/Scene/TilePlaneSceneNode.cpp @@ -33,26 +33,22 @@ void SDL2TilePlaneSceneNode::VRender(Scene* pScene) int32 tilePixelWidth = pProperties->tilePixelWidth; int32 tilePixelHeight = pProperties->tilePixelHeight; - // TODO: Optimize so that we dont render anything which is not seen - // (older commit was better ?) - int32_t numTilesPadding = 2; + const int32_t numTilesPadding = 0; - Point scale = g_pApp->GetScale(); + const SDL_Rect cameraRect = camera->GetCameraRect(); float movementRatioX = pProperties->movementPercentX / 100.0f; float movementRatioY = pProperties->movementPercentY / 100.0f; - int32_t parallaxCameraPosX = (int32_t)(camera->GetPosition().x * movementRatioX); - int32_t parallaxCameraPosY = (int32_t)(camera->GetPosition().y * movementRatioY); + float parallaxCameraPosX = (float) cameraRect.x * movementRatioX; + float parallaxCameraPosY = (float) cameraRect.y * movementRatioY; - int32_t startCol = (parallaxCameraPosX / tilePixelWidth) - numTilesPadding; - int32_t startRow = parallaxCameraPosY / tilePixelHeight - numTilesPadding; + int32_t startCol = (int32_t)(parallaxCameraPosX / tilePixelWidth) - numTilesPadding; + int32_t startRow = (int32_t)(parallaxCameraPosY / tilePixelHeight) - numTilesPadding; - int32_t colTilesToRender = (uint32_t)((camera->GetWidth() / tilePixelWidth) / scale.x) + - 3 * numTilesPadding; - - int32_t rowTilesToRender = (uint32_t)((camera->GetHeight() / tilePixelHeight) / scale.y) + - 3 * numTilesPadding; + // We need to add 2 due to startCol/startRow + colTilesToRender/rowTilesToRender float->int casting + int32_t colTilesToRender = (uint32_t)(cameraRect.w / tilePixelWidth) + 2 + numTilesPadding; + int32_t rowTilesToRender = (uint32_t)(cameraRect.h / tilePixelHeight) + 2 + numTilesPadding; // Some planes (Back, Front) repeat themselves, which means they can be rendered // even when out of bounds @@ -73,25 +69,31 @@ void SDL2TilePlaneSceneNode::VRender(Scene* pScene) } int32_t row, col; - for (row = startRow; row < (startRow + rowTilesToRender); row++) + for (row = startRow; row < (startRow + rowTilesToRender) && row <= maxTileIdxY; row++) { - for (col = startCol; col < (startCol + colTilesToRender); col++) + if (row < minTileIdxY) + { + continue; + } + const int rowTileIndex = row % pProperties->tilesOnAxisY; + + for (col = startCol; col < (startCol + colTilesToRender) && col <= maxTileIdxX; col++) { // Dont render anything out of bounds - if ((col < minTileIdxX) || (col > maxTileIdxX) || - (row < minTileIdxY) || (row > maxTileIdxY)) + if (col < minTileIdxX) { continue; } + const int colTileIndex = col % pProperties->tilesOnAxisX; - int32_t x = (col - startCol - numTilesPadding) * tilePixelWidth; - int32_t y = (row - startRow - numTilesPadding) * tilePixelHeight; - Image* image = (*pImageList)[(row % pProperties->tilesOnAxisY) * pProperties->tilesOnAxisX + (col % pProperties->tilesOnAxisX)]; + Image* image = (*pImageList)[rowTileIndex * pProperties->tilesOnAxisX + colTileIndex]; if (image && image->GetTexture() != NULL) { - SDL_Rect tileRect = { x - (parallaxCameraPosX % tilePixelWidth), - y - (parallaxCameraPosY % tilePixelHeight), + int32_t x = col * tilePixelWidth - parallaxCameraPosX; + int32_t y = row * tilePixelHeight - parallaxCameraPosY; + SDL_Rect tileRect = { x, + y, tilePixelWidth, tilePixelHeight }; diff --git a/OpenClaw/Engine/UserInterface/Console.cpp b/OpenClaw/Engine/UserInterface/Console.cpp index d5cb23eb..9eb05075 100644 --- a/OpenClaw/Engine/UserInterface/Console.cpp +++ b/OpenClaw/Engine/UserInterface/Console.cpp @@ -600,7 +600,6 @@ void Console::RenderBackground(SDL_Renderer* renderer) void Console::RenderCommandHistory(SDL_Renderer* renderer) { - SDL_Rect intersect; SDL_Rect consoleRect = GetRenderRect(); // Render all visible console lines for (auto consoleLine : _consoleTextLines) @@ -609,7 +608,7 @@ void Console::RenderCommandHistory(SDL_Renderer* renderer) SDL_Rect lineRect = consoleLine.GetRenderRect(); //PrintRect(consoleRect, "ConsoleRect"); //PrintRect(lineRect, "LineRect"); - if (SDL_IntersectRect(&consoleRect, &lineRect, &intersect)) + if (SDL_HasIntersection(&consoleRect, &lineRect)) { //cout << "Rendering.." << endl; consoleLine.Render(renderer, _x, _y +(int16_t)_animationOffsetY); diff --git a/OpenClaw/Engine/UserInterface/HumanView.cpp b/OpenClaw/Engine/UserInterface/HumanView.cpp index aaadb3b6..ab5338a5 100644 --- a/OpenClaw/Engine/UserInterface/HumanView.cpp +++ b/OpenClaw/Engine/UserInterface/HumanView.cpp @@ -1020,6 +1020,7 @@ void DeathFadeInOutProcess::VRender(uint32 msDiff) // Render fade in/outs according to current state int referenceTime = 0; + Point *fadeSpeed = &m_FadeInSpeed; if (m_DeathFadeState == DeathFadeState_FadingIn) { referenceTime = m_CurrentTime; @@ -1027,10 +1028,11 @@ void DeathFadeInOutProcess::VRender(uint32 msDiff) else if (m_DeathFadeState == DeathFadeState_FadingOut) { referenceTime = m_FadeOutDuration - m_CurrentTime; + fadeSpeed = &m_FadeOutSpeed; } // Left -> right rect - int currentWidth = (int)((double)referenceTime * m_FadeInSpeed.x); + int currentWidth = (int)((double)referenceTime * fadeSpeed->x); //LOG("Current width: " + ToStr(currentWidth)); SDL_Rect leftRect = { 0, 0, currentWidth, (int)windowSize.y }; SDL_Texture* pLeftRectTexture = Util::CreateSDLTextureRect(leftRect.w, leftRect.h, COLOR_BLACK, pRenderer); @@ -1041,7 +1043,7 @@ void DeathFadeInOutProcess::VRender(uint32 msDiff) SDL_Texture* pRightRectTexture = Util::CreateSDLTextureRect(rightRect.w, rightRect.h, COLOR_BLACK, pRenderer); SDL_RenderCopy(pRenderer, pRightRectTexture, NULL, &rightRect); - int currentHeight = (int)((double)referenceTime * m_FadeInSpeed.y); + int currentHeight = (int)((double)referenceTime * fadeSpeed->y); // Top -> Down SDL_Rect topRect = { 0, 0, (int)windowSize.x, currentHeight }; SDL_Texture* pTopTexture = Util::CreateSDLTextureRect(topRect.w, topRect.h, COLOR_BLACK, pRenderer); @@ -1057,7 +1059,7 @@ void DeathFadeInOutProcess::VRender(uint32 msDiff) SDL_DestroyTexture(pTopTexture); SDL_DestroyTexture(pBottomTexture); - SDL_RenderPresent(pRenderer); + Util::RenderForcePresent(pRenderer); } //================================================================================================= @@ -1308,6 +1310,7 @@ void TeleportFadeInOutProcess::VRender(uint32 msDiff) // Render fade in/outs according to current state int referenceTime = 0; + Point *fadeSpeed = &m_FadeInSpeed; if (m_TeleportState == TeleportState_FadingIn) { referenceTime = m_CurrentTime; @@ -1315,12 +1318,13 @@ void TeleportFadeInOutProcess::VRender(uint32 msDiff) else if (m_TeleportState == TeleportState_FadingOut) { referenceTime = m_FadeOutDuration - m_CurrentTime; + fadeSpeed = &m_FadeOutSpeed; } referenceTime = max(0, referenceTime); // Left -> right rect - int currentWidth = (int)((double)referenceTime * m_FadeInSpeed.x); + int currentWidth = (int)((double)referenceTime * fadeSpeed->x); //LOG("Current width: " + ToStr(currentWidth)); SDL_Rect leftRect = { 0, 0, currentWidth, (int)windowSize.y }; SDL_Texture* pLeftRectTexture = Util::CreateSDLTextureRect(leftRect.w, leftRect.h, COLOR_BLACK, pRenderer); @@ -1334,5 +1338,5 @@ void TeleportFadeInOutProcess::VRender(uint32 msDiff) SDL_DestroyTexture(pLeftRectTexture); SDL_DestroyTexture(pRightRectTexture); - SDL_RenderPresent(pRenderer); + Util::RenderForcePresent(pRenderer); } \ No newline at end of file diff --git a/OpenClaw/Engine/UserInterface/UserInterface.cpp b/OpenClaw/Engine/UserInterface/UserInterface.cpp index 33b0db0d..d86fc230 100644 --- a/OpenClaw/Engine/UserInterface/UserInterface.cpp +++ b/OpenClaw/Engine/UserInterface/UserInterface.cpp @@ -770,12 +770,10 @@ bool ScreenElementMenuPage::VOnEvent(SDL_Event& evt) clickRect.w = 1; clickRect.h = 1; - SDL_Rect dummy; - // for (shared_ptr pMenuItem : m_MenuItems) { SDL_Rect itemRect = pMenuItem->GetMenuItemRect(); - if (SDL_IntersectRect(&clickRect, &itemRect, &dummy)) + if (SDL_HasIntersection(&clickRect, &itemRect)) { if (pMenuItem->CanBeFocused()) { diff --git a/OpenClaw/Engine/Util/Util.cpp b/OpenClaw/Engine/Util/Util.cpp index 8d49a412..98f94d09 100644 --- a/OpenClaw/Engine/Util/Util.cpp +++ b/OpenClaw/Engine/Util/Util.cpp @@ -498,18 +498,7 @@ namespace Util } #endif - SDL_Texture* CreateSDLTextureRect(int width, int height, SDL_Color color, SDL_Renderer* pRenderer) - { - SDL_Surface* pSurface = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0); - SDL_FillRect(pSurface, NULL, SDL_MapRGB(pSurface->format, color.r, color.g, color.b)); - SDL_Texture* pTextureRect = SDL_CreateTextureFromSurface(pRenderer, pSurface); - - SDL_FreeSurface(pSurface); - return pTextureRect; - } - - SDL_Texture* CreateSDLTextureRect(int width, int height, SDL_Color color, SDL_Renderer* pRenderer, uint8_t alpha) - { + SDL_Surface* CreateRGBSurface(Uint32 flags, int width, int height, int depth) { Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN @@ -523,7 +512,32 @@ namespace Util bmask = 0x00ff0000; amask = 0xff000000; #endif - SDL_Surface* pSurface = SDL_CreateRGBSurface(0, width, height, 32, rmask, gmask, bmask, amask); + return SDL_CreateRGBSurface(flags, width, height, depth, rmask, gmask, bmask, amask); + } + + SDL_Texture* CreateSDLTextureFromRenderer(int rendererWidth, int rendererHeight, SDL_Renderer* pRenderer) + { + SDL_Surface* pSurface = CreateRGBSurface(0, rendererWidth, rendererHeight, 32); + SDL_RenderReadPixels(pRenderer, NULL, SDL_PIXELFORMAT_ARGB8888, pSurface->pixels, pSurface->pitch); + SDL_Texture* pTextureRect = SDL_CreateTextureFromSurface(pRenderer, pSurface); + + SDL_FreeSurface(pSurface); + return pTextureRect; + } + + SDL_Texture* CreateSDLTextureRect(int width, int height, SDL_Color color, SDL_Renderer* pRenderer) + { + SDL_Surface* pSurface = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0); + SDL_FillRect(pSurface, NULL, SDL_MapRGB(pSurface->format, color.r, color.g, color.b)); + SDL_Texture* pTextureRect = SDL_CreateTextureFromSurface(pRenderer, pSurface); + + SDL_FreeSurface(pSurface); + return pTextureRect; + } + + SDL_Texture* CreateSDLTextureRect(int width, int height, SDL_Color color, SDL_Renderer* pRenderer, uint8_t alpha) + { + SDL_Surface* pSurface = CreateRGBSurface(0, width, height, 32); SDL_FillRect(pSurface, NULL, SDL_MapRGBA(pSurface->format, color.r, color.g, color.b, alpha)); SDL_Texture* pTextureRect = SDL_CreateTextureFromSurface(pRenderer, pSurface); @@ -532,6 +546,24 @@ namespace Util return pTextureRect; } + void RenderForcePresent(SDL_Renderer* pRenderer) { + SDL_RenderPresent(pRenderer); +#ifdef __EMSCRIPTEN__ + // Update screen manually. SDL_RenderPresent does nothing. + emscripten_sleep(0); +#endif + } + + void Sleep(Uint32 ms) { + if (ms > 0) { +#ifndef __EMSCRIPTEN__ + SDL_Delay(ms); +#else + emscripten_sleep(ms); +#endif + } + } + void PlayRandomHitSound() { static std::vector hitSounds = @@ -550,4 +582,21 @@ namespace Util crcu32 = ~crcu32; while (dataLen--) { uint8 b = *pData++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; } return ~crcu32; } + +#ifdef __EMSCRIPTEN__ + bool GetCanvasSize(SDL_Point &canvasSize) { + int width = EM_ASM_INT( + {return (Module && Module.canvas) ? Module.canvas.scrollWidth : -1;} + ); + int height = EM_ASM_INT( + {return (Module && Module.canvas) ? Module.canvas.scrollHeight : -1;} + ); + if (width >= 640 && height >= 480) { + canvasSize.x = width; + canvasSize.y = height; + return true; + } + return false; + } +#endif }; diff --git a/OpenClaw/Engine/Util/Util.h b/OpenClaw/Engine/Util/Util.h index cb94a2ad..149592ee 100644 --- a/OpenClaw/Engine/Util/Util.h +++ b/OpenClaw/Engine/Util/Util.h @@ -32,9 +32,16 @@ namespace Util int GetSoundDurationMs(const std::string& soundPath); int GetSoundDurationMs(Mix_Chunk* pSound); + SDL_Surface* CreateRGBSurface(Uint32 flags, int width, int height, int depth); + + SDL_Texture* CreateSDLTextureFromRenderer(int rendererWidth, int rendererHeight, SDL_Renderer* pRenderer); SDL_Texture* CreateSDLTextureRect(int width, int height, SDL_Color color, SDL_Renderer* pRenderer); SDL_Texture* CreateSDLTextureRect(int width, int height, SDL_Color color, SDL_Renderer* pRenderer, uint8_t alpha); + void RenderForcePresent(SDL_Renderer* pRenderer); + + void Sleep(Uint32 ms); + void PlayRandomHitSound(); uint32_t CalcCRC32(const char* pData, size_t dataLen); @@ -45,6 +52,10 @@ namespace Util int randIdx = GetRandomNumber(0, container.size() - 1); return container[randIdx]; } + +#ifdef __EMSCRIPTEN__ + bool GetCanvasSize(SDL_Point &canvasSize); +#endif } #endif \ No newline at end of file diff --git a/README.md b/README.md index 0a616e2c..690c894e 100644 --- a/README.md +++ b/README.md @@ -94,13 +94,14 @@ Zip all content inside `Build_Release/ASSETS` directory to `ASSETS.ZIP` file. mkdir build cd build emconfigure cmake -DEmscripten=1 .. + # -DExtern_Config=0 parameter includes config.xml file in game resources make ``` **Run:** You will need web server to run compiled project. There are 2 options: - - You can upload `openclaw.html`, `openclaw.js`, `openclaw.wasm` and `openclaw.data` files from `Build_Release` directory to any web server. + - You can upload `openclaw.html`, `openclaw.js`, `openclaw.wasm` and `openclaw.data` (and `config.xml` if you build the project without `-DExtern_Config=0` parameter) files from `Build_Release` directory to any web server. - Or run Python server: ```shell script cd Build_Release @@ -115,6 +116,11 @@ Zip all content inside `Build_Release/ASSETS` directory to `ASSETS.ZIP` file. - Some web browsers does not support `.wav` file formats. *Microsoft? Again?* - All web browsers does not support `.xmi` (MIDI) file formats. This files should be converted to another compatible formats. **All MIDI audio are disabled for now**. - Some specific `SDL_Mixer` audio functions aren't implemented (*you can find it by `TODO: [EMSCRIPTEN]` search query*) but the game is playable. + - Death and teleport fade in effects are broken. Emscripten erases graphic buffer after each draw call. Do not use buffer from previous calls. + - There is a [FireFox bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1292053) with a very long story which doesn't allow to prevent ALT default actions. ALT key presses will open window menu. Workarounds: + - Contribute to Mozilla and finally close this bug. + - Use fullscreen mode. + - Disable default ALT actions in FireFox `about:config` properties. # In-game images - **TODO** - add screenshots