From: Daniel Karbach Date: Tue, 19 Feb 2013 17:59:02 +0000 (+0100) Subject: added basic defeat state X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=9a7ac49b7e3b7cd4a09b016ceec116830a3458f9;p=l2e.git added basic defeat state refs #4 --- diff --git a/src/battle/BattleState.cpp b/src/battle/BattleState.cpp index 1f68acf..c6f07cd 100644 --- a/src/battle/BattleState.cpp +++ b/src/battle/BattleState.cpp @@ -1,6 +1,7 @@ #include "BattleState.h" #include "PartyLayout.h" +#include "states/DefeatState.h" #include "states/SelectMoveAction.h" #include "states/PerformAttacks.h" #include "states/VictoryState.h" @@ -129,7 +130,12 @@ void BattleState::OnResumeState(SDL_Surface *screen) { return; } if (battle.Defeat()) { - Ctrl().PopState(); + if (alreadyPushed) { + Ctrl().PopState(); + } else { + Ctrl().PushState(new DefeatState(&battle, this)); + alreadyPushed = true; + } return; } // TODO: this should not push a state while quitting diff --git a/src/battle/Resources.cpp b/src/battle/Resources.cpp index 9db29e1..3e61cf5 100644 --- a/src/battle/Resources.cpp +++ b/src/battle/Resources.cpp @@ -61,6 +61,7 @@ Resources::Resources() , noEquipmentText("MISSING TRANSLATION") , escapeText("MISSING TRANSLATION") +, defeatText("MISSING TRANSLATION") , numberAnimationPrototype(0) , bigNumberSprite(0) @@ -152,6 +153,7 @@ void Resources::CreateTypeDescription() { td.AddField("noEquipmentText", FieldDescription(((char *)&r.noEquipmentText) - ((char *)&r), Interpreter::STRING_ID).SetReferenced().SetDescription("text to show for missing equipment")); td.AddField("escapeText", FieldDescription(((char *)&r.escapeText) - ((char *)&r), Interpreter::STRING_ID).SetReferenced().SetDescription("displayed when the party escapes")); + td.AddField("defeatText", FieldDescription(((char *)&r.defeatText) - ((char *)&r), Interpreter::STRING_ID).SetReferenced().SetDescription("displayed when the party was defeated")); td.AddField("numberAnimationPrototype", FieldDescription(((char *)&r.numberAnimationPrototype) - ((char *)&r), Animation::TYPE_ID).SetReferenced().SetDescription("animation of an attack's result digit")); diff --git a/src/battle/Resources.h b/src/battle/Resources.h index 0a8a1e8..6624910 100644 --- a/src/battle/Resources.h +++ b/src/battle/Resources.h @@ -62,6 +62,7 @@ struct Resources { const char *noEquipmentText; const char *escapeText; + const char *defeatText; const graphics::Animation *numberAnimationPrototype; diff --git a/src/battle/states/DefeatState.cpp b/src/battle/states/DefeatState.cpp new file mode 100644 index 0000000..77b3f8e --- /dev/null +++ b/src/battle/states/DefeatState.cpp @@ -0,0 +1,111 @@ +#include "DefeatState.h" + +#include "../Battle.h" +#include "../BattleState.h" +#include "../Resources.h" +#include "../../app/Application.h" +#include "../../app/Input.h" +#include "../../math/Vector.h" +#include "../../graphics/ColorFade.h" +#include "../../graphics/Font.h" +#include "../../graphics/Frame.h" +#include "../../sdl/Desaturate.h" + +using app::Application; +using app::Input; +using graphics::ColorFade; +using graphics::Font; +using graphics::Frame; +using math::Vector; +using std::vector; + +namespace battle { + +DefeatState::DefeatState( + Battle *battle, + BattleState *parent) +: battle(battle) +, parent(parent) +, cache(0) +, format(0) { + +} + + +void DefeatState::OnEnterState(SDL_Surface *screen) { + timer = GraphicsTimers().StartCountdown(1500); + format = screen->format; + OnResize(screen->w, screen->h); +} + +void DefeatState::OnExitState(SDL_Surface *screen) { + if (cache) { + SDL_FreeSurface(cache); + cache = 0; + } +} + +void DefeatState::OnResumeState(SDL_Surface *screen) { + +} + +void DefeatState::OnPauseState(SDL_Surface *screen) { + +} + + +void DefeatState::OnResize(int width, int height) { + const Resources &res = parent->Res(); + const Frame &frame = *res.titleFrame; + const Font &font = *res.titleFont; + + framePosition = parent->ScreenOffset(); + frameSize = Vector ( + parent->Width(), + frame.BorderHeight() * 2 + font.CharHeight()); + + textPosition = Vector( + (parent->Width() - strlen(res.defeatText) * font.CharWidth()) / 2, + frame.BorderHeight()); + + parent->Resize(width, height); + if (cache) { + SDL_FreeSurface(cache); + } + cache = SDL_CreateRGBSurface(0, width, height, format->BitsPerPixel, + format->Rmask, format->Gmask, format->Bmask, format->Amask); + parent->Render(cache); + parent->RenderHeroes(cache); + RenderTitleBar(cache); +} + + +void DefeatState::HandleEvents(const Input &input) { + if (timer.Finished()) { + Ctrl().PopState(); + } +} + + +void DefeatState::UpdateWorld(Uint32 deltaT) { + +} + +void DefeatState::Render(SDL_Surface *screen) { + if (screen->format->palette + || cache->format->palette) { + // I refuse to desaturate an indexed color urface + SDL_BlitSurface(cache, 0, screen, 0); + return; + } + + sdl::Desaturate(cache, screen, timer.Remaining() * 255 / 1500); +} + +void DefeatState::RenderTitleBar(SDL_Surface *screen) { + const Resources &res = parent->Res(); + res.titleFrame->Draw(screen, framePosition, frameSize.X(), frameSize.Y()); + res.titleFont->DrawString(res.defeatText, screen, textPosition); +} + +} diff --git a/src/battle/states/DefeatState.h b/src/battle/states/DefeatState.h new file mode 100644 index 0000000..998bff4 --- /dev/null +++ b/src/battle/states/DefeatState.h @@ -0,0 +1,54 @@ +#ifndef BATTLE_DEFEATSTATE_H_ +#define BATTLE_DEFEATSTATE_H_ + +namespace battle { + class Battle; + class BattleState; +} + +#include "../../app/State.h" +#include "../../math/Vector.h" + +#include + +namespace battle { + +class DefeatState +: public app::State { + +public: + DefeatState( + Battle *battle, + BattleState *parent); + +public: + virtual void HandleEvents(const app::Input &); + virtual void UpdateWorld(Uint32 deltaT); + virtual void Render(SDL_Surface *); + +private: + virtual void OnEnterState(SDL_Surface *screen); + virtual void OnExitState(SDL_Surface *screen); + virtual void OnResumeState(SDL_Surface *screen); + virtual void OnPauseState(SDL_Surface *screen); + + virtual void OnResize(int width, int height); + +private: + void RenderTitleBar(SDL_Surface *screen); + +private: + Battle *battle; + BattleState *parent; + SDL_Surface *cache; + SDL_PixelFormat *format; + app::Timer timer; + math::Vector framePosition; + math::Vector frameSize; + math::Vector textPosition; + +}; + +} + +#endif diff --git a/src/sdl/Desaturate.cpp b/src/sdl/Desaturate.cpp new file mode 100644 index 0000000..175e1b9 --- /dev/null +++ b/src/sdl/Desaturate.cpp @@ -0,0 +1,127 @@ +#include "Desaturate.h" + +#include + +using std::runtime_error; + + +namespace sdl { + +template +void DesaturatePixel( + SrcType *src, SDL_PixelFormat *srcFmt, + DestType *dest, SDL_PixelFormat *destFmt, + Uint8 amount) { + + Uint8 srcRed = (((*src) & srcFmt->Rmask) + >> srcFmt->Rshift) << srcFmt->Rloss; + Uint8 srcGreen = (((*src) & srcFmt->Gmask) + >> srcFmt->Gshift) << srcFmt->Gloss; + Uint8 srcBlue = (((*src) & srcFmt->Bmask) + >> srcFmt->Bshift) << srcFmt->Bloss; + + Uint8 srcGrey = (srcRed * 76 + srcGreen * 150 + srcBlue * 29) / 255; + + Uint8 destRed = (srcRed * amount + srcGrey * (255 - amount)) / 255; + Uint8 destGreen = (srcGreen * amount + srcGrey * (255 - amount)) / 255; + Uint8 destBlue = (srcBlue * amount + srcGrey * (255 - amount)) / 255; + + *dest + = ((destRed >> destFmt->Rloss) << destFmt->Rshift) + | ((destGreen >> destFmt->Gloss) << destFmt->Gshift) + | ((destBlue >> destFmt->Bloss) << destFmt->Bshift) + | (*dest & destFmt->Amask); +} + +void Desaturate( + SDL_Surface *src, + SDL_Surface *dest, + Uint8 amount) { + Uint32 size = src->w * src->h; + SDL_LockSurface(src); + SDL_LockSurface(dest); + SDL_PixelFormat *srcFmt = src->format; + SDL_PixelFormat *destFmt = dest->format; + Uint8 srcBPP = srcFmt->BytesPerPixel; + Uint8 destBPP = destFmt->BytesPerPixel; + switch (srcBPP) { + default: + SDL_UnlockSurface(dest); + SDL_UnlockSurface(src); + throw runtime_error("unable to read src format"); + case 2: { + Uint16 *srcIter = reinterpret_cast( + src->pixels); + Uint16 *srcEnd = srcIter + size; + switch (destBPP) { + default: + SDL_UnlockSurface(dest); + SDL_UnlockSurface(src); + throw runtime_error("unable to read src format"); + case 2: { + Uint16 *destIter = reinterpret_cast( + dest->pixels); + Uint16 *destEnd = destIter + size; + for (;srcIter < srcEnd && destIter < destEnd; + ++srcIter, ++destIter) { + DesaturatePixel( + srcIter, srcFmt, + destIter, destFmt, + amount); + } + break; } + case 4: { + Uint32 *destIter = reinterpret_cast( + dest->pixels); + Uint32 *destEnd = destIter + size; + for (;srcIter < srcEnd && destIter < destEnd; + ++srcIter, ++destIter) { + DesaturatePixel( + srcIter, srcFmt, + destIter, destFmt, + amount); + } + break; } + } + break; } + case 4: { + Uint32 *srcIter = reinterpret_cast( + src->pixels); + Uint32 *srcEnd = srcIter + size; + switch (destBPP) { + default: + SDL_UnlockSurface(dest); + SDL_UnlockSurface(src); + throw runtime_error("unable to read src format"); + case 2: { + Uint16 *destIter = reinterpret_cast( + dest->pixels); + Uint16 *destEnd = destIter + size; + for (;srcIter < srcEnd && destIter < destEnd; + ++srcIter, ++destIter) { + DesaturatePixel( + srcIter, srcFmt, + destIter, destFmt, + amount); + } + break; } + case 4: { + Uint32 *destIter = reinterpret_cast( + dest->pixels); + Uint32 *destEnd = destIter + size; + for (;srcIter < srcEnd && destIter < destEnd; + ++srcIter, ++destIter) { + DesaturatePixel( + srcIter, srcFmt, + destIter, destFmt, + amount); + } + break; } + } + break; } + } + SDL_UnlockSurface(dest); + SDL_UnlockSurface(src); +} + +} diff --git a/src/sdl/Desaturate.h b/src/sdl/Desaturate.h new file mode 100644 index 0000000..45dff7c --- /dev/null +++ b/src/sdl/Desaturate.h @@ -0,0 +1,16 @@ +#ifndef SDL_DESATURATE_H_ +#define SDL_DESATURATE_H_ + +#include + +namespace sdl { + +/// Copy src to dest, desaturated by amount/255. +void Desaturate( + SDL_Surface *src, + SDL_Surface *dest, + Uint8 amount); + +} + +#endif diff --git a/test-data/test.l2s b/test-data/test.l2s index 500039f..59de524 100644 --- a/test-data/test.l2s +++ b/test-data/test.l2s @@ -651,6 +651,7 @@ export BattleResources battleResources { noEquipmentText: "No equip", escapeText: "Escapes.", + defeatText: "Total Defeat.", victoryGetsText: "Gets", victoryExpText: "EXP",