diff --git a/CHANGELOG.md b/CHANGELOG.md index 3df3ecdc..0249975c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,185 +1,185 @@ -Legend -====== - - * `[+]` a feature was added - * `[*]` some changes in existing features were made - * `[!]` a bug was fixed - - -Upcoming release ----------------- - - * `[*]` [Improved `CMakeLists.txt` readability](https://github.com/ooxi/violetland/pull/93) - * `[*]` [Refactored window handlers to use `boost::function`](https://github.com/ooxi/violetland/pull/91) - * `[+]` [Automatic Windows build using Travis CI and MXE](https://github.com/ooxi/violetland/pull/90) - * `[*]` [Misc code cleanup](https://github.com/ooxi/violetland/pull/87) - * `[!]` [Fixed minor bugs](https://github.com/ooxi/violetland/pull/83) enabling Violetland to be build by both GCC and Clang with extra warnings enabled - * `[!]` [Changing the font to Xolonium-Regular](https://github.com/ooxi/violetland/pull/82) fixed [display issues of german umlauts](https://github.com/ooxi/violetland/issues/81) - * `[*]` [Changing the font to Xolonium-Regular](https://github.com/ooxi/violetland/pull/82) resolved [probable licensing issues](https://github.com/ooxi/violetland/issues/73) - * `[+]` [Added german translation](https://github.com/ooxi/violetland/pull/80) - -Release 0.5 (2016-01-04) ------------------------- - - * `[!]` Fixed game startup crash when `USER` environment variable is not found in [issue 71](https://github.com/ooxi/violetland/issues/71) - * `[!]` Improved OpenBSD Support - * `[+]` As of [issue 64](https://github.com/ooxi/violetland/pull/64) the control style can be toggled between "classic" and "modern" - * `[*]` Added more available video modes in [issue 63](https://github.com/ooxi/violetland/pull/63), since auto detection doesn't seam to work - * `[!]` Fixed i18n support in [issue 62](https://github.com/ooxi/violetland/pull/62) - -Release 0.4.3 (2011-10-10) --------------------------- - - * `[+]` integrated inventory sidebar (additional to HUD) - * `[!]` image of nuke bonus - -Release 0.4.2 -------------- - - * `[*]` significant changes in strength-agility-vitality balance - * `[*]` widesight now fairy increase sight area by 20% - * `[*]` poison perk is 2 times stronger - * `[!]` few major bugz - -Release 0.4.1 -------------- - - * `[+]` new perk "magneto" - * `[*]` game messages are written to stdout - * `[*]` telekinesis perk now behaves like in original crimsonland, a status (percentage) can be seen on top-center of the screen - * `[*]` more realistic laser aim will be helpful at night - * `[!]` bug with changing the controls - * `[!]` few errors in game messages - -Release 0.4.0 -------------- - - * `[+]` new graphics for flamethrower and sawed-off shotgun - * `[*]` moved to boost library - * `[*]` small performance improvements - * `[!]` [issue 49](https://github.com/ooxi/violetland/issues/49) (changing bindings is broken) - * `[!]` [issue 51](https://github.com/ooxi/violetland/issues/51) (vitality does not affect health regeneration) - * `[!]` [issue 52](https://github.com/ooxi/violetland/issues/52) (controls definitions not loads when starting program) - * `[!]` [issue 53](https://github.com/ooxi/violetland/issues/53) (wrong values in highscores screen) - * `[!]` issue with path to resources after install with cmake - -Release 0.3.2 -------------- - - * `[+]` support of internationalization: english, french, russian, galician, spain - * `[+]` new game mode "attack waves" - * `[+]` new weapon "flamethrower" - * `[+]` new perk "wide sight" - * `[*]` new font - * `[*]` more animations: teleportation, nuclear explosion - * `[*]` some monsters have now the parameter "stamina" - they can't run all the time - * `[*]` default player name is the system user name on linux platform - * `[*]` [issue 19](https://github.com/ooxi/violetland/issues/19) (xp and item will drop out immediately after kill monster) - * `[!]` [issue 36](https://github.com/ooxi/violetland/issues/36) and other fixes around movements of player and monsters - * `[!]` [issue 38](https://github.com/ooxi/violetland/issues/38) (light is placed wrong for sawed-off shotgun) - * `[!]` [issue 40](https://github.com/ooxi/violetland/issues/40) (blue cursor after death in teleportation mode) - * `[!]` issues [45](https://github.com/ooxi/violetland/issues/45), [48](https://github.com/ooxi/violetland/issues/48) and other undocumented fixes to improve performance and reliability - -Release 0.3.1 -------------- - - * `[+]` new weapon "SawedOff-Shotgun" - * `[+]` game controls are changeable from game menu - * `[+]` new perk "looting" - * `[+]` support of 1366*768 resolution - * `[*]` strength affects maximum health - * `[*]` new HUD animation - -Release 0.3.0 -------------- - - * `[+]` bonuses timers - * `[!]` invalid volume of sound at options screen - * `[!]` extra shot after teleportation - -Release 0.2.10 --------------- - - * `[+]` new perk "night vision" - * `[+]` new bonus "nuke" - * `[+]` new bonus "strength boost" - * `[+]` new bonus "agility boost" - * `[+]` new bonus "vitality boost" - * `[+]` new bonus "teleport" and a possibility to switch action mode (fire/teleport) - * `[+]` possibility to change some input binding (now in test mode, see comment for the commit r198) - * `[*]` new HUD (Head-Up Display) - * `[!]` fixed [issue 32](https://github.com/ooxi/violetland/issues/32) (pressing C when the player is dead will crash the game) - * `[!]` fixed issues [29](https://github.com/ooxi/violetland/issues/29) and [33](https://github.com/ooxi/violetland/issues/33) (problems with adding of new weapons) - -Release 0.2.9 -------------- - - * `[+]` new bonus "penetration bullets" - * `[+]` death animations of player - * `[+]` explantation of perks on char stats screen - * `[*]` loading screen between pressing "new survival" and starting the game - * `[*]` view of flashlight - * `[!]` last entry of high scores table was always zero - * `[!]` death animations of monsters were played above player - * `[!]` rendering of main menu on wide resolutions - -Release 0.2.8 -------------- - - * `[+]` mac os x support (10.5 or later) - * `[+]` possibility to change graphic settings from options screen (there are issues on windows - see README) - * `[+]` new graphics - image of weapon in the arms will change, animation of shells - * `[*]` structure of a weapon store - * `[*]` monsters can have any number of sounds of death - * `[!]` fixed sound issues by explicit sound mixing - * `[!]` issues of loading resources in *nix systems - -Release 0.2.7 -------------- - - * `[*]` improved animation of monsters - * `[!]` error on updating highscores - -Release 0.2.6 -------------- - - * `[+]` new monster animation (spider) - * `[+]` in-game information line about monster which cursor points to - * `[*]` parameters of monsters are loaded from files - * `[*]` names of monsters directories are names of monsters - * `[*]` redesign of some game images - * `[!]` sound issues are fixed by temporary turning off music fading - -Release 0.2.5 -------------- - - * `[+]` new freeze bonus - * `[+]` animation of monsters death - * `[+]` corpses of monsters don't disappear - * `[+]` master sound volume can be adjusted at options screen - * `[+]` the resume item to main menu - * `[*]` new separate directory tree for monsters - * `[!]` game window couldn't be closed with the window close button - * `[!]` issues of game installing in *nix systems - -Release 0.2.4 -------------- - - * `[+]` hand grenades were added in addition to main weapon - * `[+]` ability to select any directory for data at installation - * `[+]` this file is added to the package - * `[+]` new weapon M32 (sort of grenade launcher) - * `[+]` ability to adjusting whether explosions can damage player (friendly fire) - * `[*]` telekinesis is now more visible and funny - * `[*]` medical kit can be small, medium or large - * `[*]` music changer algorithm is changed, so music playback should be more smooth - * `[*]` game window has cool icon on title bar - * `[*]` bonuses animation - -Release 0.2.3 and earlier -------------------------- - -Ancient history was once available at -[Google Code](http://code.google.com/p/violetland/updates/list) and -[nike.homelinux.com](http://nike.homeunix.com/violetland/) but are lost by now. - +Legend +====== + + * `[+]` a feature was added + * `[*]` some changes in existing features were made + * `[!]` a bug was fixed + + +Upcoming release +---------------- + + * `[*]` [Improved `CMakeLists.txt` readability](https://github.com/ooxi/violetland/pull/93) + * `[*]` [Refactored window handlers to use `boost::function`](https://github.com/ooxi/violetland/pull/91) + * `[+]` [Automatic Windows build using Travis CI and MXE](https://github.com/ooxi/violetland/pull/90) + * `[*]` [Misc code cleanup](https://github.com/ooxi/violetland/pull/87) + * `[!]` [Fixed minor bugs](https://github.com/ooxi/violetland/pull/83) enabling Violetland to be build by both GCC and Clang with extra warnings enabled + * `[!]` [Changing the font to Xolonium-Regular](https://github.com/ooxi/violetland/pull/82) fixed [display issues of german umlauts](https://github.com/ooxi/violetland/issues/81) + * `[*]` [Changing the font to Xolonium-Regular](https://github.com/ooxi/violetland/pull/82) resolved [probable licensing issues](https://github.com/ooxi/violetland/issues/73) + * `[+]` [Added german translation](https://github.com/ooxi/violetland/pull/80) + +Release 0.5 (2016-01-04) +------------------------ + + * `[!]` Fixed game startup crash when `USER` environment variable is not found in [issue 71](https://github.com/ooxi/violetland/issues/71) + * `[!]` Improved OpenBSD Support + * `[+]` As of [issue 64](https://github.com/ooxi/violetland/pull/64) the control style can be toggled between "classic" and "modern" + * `[*]` Added more available video modes in [issue 63](https://github.com/ooxi/violetland/pull/63), since auto detection doesn't seam to work + * `[!]` Fixed i18n support in [issue 62](https://github.com/ooxi/violetland/pull/62) + +Release 0.4.3 (2011-10-10) +-------------------------- + + * `[+]` integrated inventory sidebar (additional to HUD) + * `[!]` image of nuke bonus + +Release 0.4.2 +------------- + + * `[*]` significant changes in strength-agility-vitality balance + * `[*]` widesight now fairy increase sight area by 20% + * `[*]` poison perk is 2 times stronger + * `[!]` few major bugz + +Release 0.4.1 +------------- + + * `[+]` new perk "magneto" + * `[*]` game messages are written to stdout + * `[*]` telekinesis perk now behaves like in original crimsonland, a status (percentage) can be seen on top-center of the screen + * `[*]` more realistic laser aim will be helpful at night + * `[!]` bug with changing the controls + * `[!]` few errors in game messages + +Release 0.4.0 +------------- + + * `[+]` new graphics for flamethrower and sawed-off shotgun + * `[*]` moved to boost library + * `[*]` small performance improvements + * `[!]` [issue 49](https://github.com/ooxi/violetland/issues/49) (changing bindings is broken) + * `[!]` [issue 51](https://github.com/ooxi/violetland/issues/51) (vitality does not affect health regeneration) + * `[!]` [issue 52](https://github.com/ooxi/violetland/issues/52) (controls definitions not loads when starting program) + * `[!]` [issue 53](https://github.com/ooxi/violetland/issues/53) (wrong values in highscores screen) + * `[!]` issue with path to resources after install with cmake + +Release 0.3.2 +------------- + + * `[+]` support of internationalization: english, french, russian, galician, spain + * `[+]` new game mode "attack waves" + * `[+]` new weapon "flamethrower" + * `[+]` new perk "wide sight" + * `[*]` new font + * `[*]` more animations: teleportation, nuclear explosion + * `[*]` some monsters have now the parameter "stamina" - they can't run all the time + * `[*]` default player name is the system user name on linux platform + * `[*]` [issue 19](https://github.com/ooxi/violetland/issues/19) (xp and item will drop out immediately after kill monster) + * `[!]` [issue 36](https://github.com/ooxi/violetland/issues/36) and other fixes around movements of player and monsters + * `[!]` [issue 38](https://github.com/ooxi/violetland/issues/38) (light is placed wrong for sawed-off shotgun) + * `[!]` [issue 40](https://github.com/ooxi/violetland/issues/40) (blue cursor after death in teleportation mode) + * `[!]` issues [45](https://github.com/ooxi/violetland/issues/45), [48](https://github.com/ooxi/violetland/issues/48) and other undocumented fixes to improve performance and reliability + +Release 0.3.1 +------------- + + * `[+]` new weapon "SawedOff-Shotgun" + * `[+]` game controls are changeable from game menu + * `[+]` new perk "looting" + * `[+]` support of 1366*768 resolution + * `[*]` strength affects maximum health + * `[*]` new HUD animation + +Release 0.3.0 +------------- + + * `[+]` bonuses timers + * `[!]` invalid volume of sound at options screen + * `[!]` extra shot after teleportation + +Release 0.2.10 +-------------- + + * `[+]` new perk "night vision" + * `[+]` new bonus "nuke" + * `[+]` new bonus "strength boost" + * `[+]` new bonus "agility boost" + * `[+]` new bonus "vitality boost" + * `[+]` new bonus "teleport" and a possibility to switch action mode (fire/teleport) + * `[+]` possibility to change some input binding (now in test mode, see comment for the commit r198) + * `[*]` new HUD (Head-Up Display) + * `[!]` fixed [issue 32](https://github.com/ooxi/violetland/issues/32) (pressing C when the player is dead will crash the game) + * `[!]` fixed issues [29](https://github.com/ooxi/violetland/issues/29) and [33](https://github.com/ooxi/violetland/issues/33) (problems with adding of new weapons) + +Release 0.2.9 +------------- + + * `[+]` new bonus "penetration bullets" + * `[+]` death animations of player + * `[+]` explantation of perks on char stats screen + * `[*]` loading screen between pressing "new survival" and starting the game + * `[*]` view of flashlight + * `[!]` last entry of high scores table was always zero + * `[!]` death animations of monsters were played above player + * `[!]` rendering of main menu on wide resolutions + +Release 0.2.8 +------------- + + * `[+]` mac os x support (10.5 or later) + * `[+]` possibility to change graphic settings from options screen (there are issues on windows - see README) + * `[+]` new graphics - image of weapon in the arms will change, animation of shells + * `[*]` structure of a weapon store + * `[*]` monsters can have any number of sounds of death + * `[!]` fixed sound issues by explicit sound mixing + * `[!]` issues of loading resources in *nix systems + +Release 0.2.7 +------------- + + * `[*]` improved animation of monsters + * `[!]` error on updating highscores + +Release 0.2.6 +------------- + + * `[+]` new monster animation (spider) + * `[+]` in-game information line about monster which cursor points to + * `[*]` parameters of monsters are loaded from files + * `[*]` names of monsters directories are names of monsters + * `[*]` redesign of some game images + * `[!]` sound issues are fixed by temporary turning off music fading + +Release 0.2.5 +------------- + + * `[+]` new freeze bonus + * `[+]` animation of monsters death + * `[+]` corpses of monsters don't disappear + * `[+]` master sound volume can be adjusted at options screen + * `[+]` the resume item to main menu + * `[*]` new separate directory tree for monsters + * `[!]` game window couldn't be closed with the window close button + * `[!]` issues of game installing in *nix systems + +Release 0.2.4 +------------- + + * `[+]` hand grenades were added in addition to main weapon + * `[+]` ability to select any directory for data at installation + * `[+]` this file is added to the package + * `[+]` new weapon M32 (sort of grenade launcher) + * `[+]` ability to adjusting whether explosions can damage player (friendly fire) + * `[*]` telekinesis is now more visible and funny + * `[*]` medical kit can be small, medium or large + * `[*]` music changer algorithm is changed, so music playback should be more smooth + * `[*]` game window has cool icon on title bar + * `[*]` bonuses animation + +Release 0.2.3 and earlier +------------------------- + +Ancient history was once available at +[Google Code](http://code.google.com/p/violetland/updates/list) and +[nike.homelinux.com](http://nike.homeunix.com/violetland/) but are lost by now. + diff --git a/README_RU.TXT b/README_RU.TXT index e7a937d3..9b06fe45 100644 --- a/README_RU.TXT +++ b/README_RU.TXT @@ -1,71 +1,71 @@ - -Violetland - -1. ИНФОРМАЦИЯ - + +Violetland + +1. ИНФОРМАЦИЯ + Violetland - это кроссплатформенный клон игры crimsonland с открытым исходным кодом. -Программа имеет ряд аргументов командной строки. +Программа имеет ряд аргументов командной строки. Список можно просмотреть по команде violetland --help. -Программа имеет файл конфигурации. -Его местонахождение зависит от операционной системы. - -irc.freenode.net, #violetland. -http://code.google.com/p/violetland/ -http://groups.google.com/group/violetland - -2. СИСТЕМНЫЕ ТРЕБОВАНИЯ - -Прежде чем скачивать игру, убедитесь, что у вас установлена видеокарта и свежие драйвера для нее с поддержкой аппаратного ускорения OpenGL. - -На данный момент поддерживаются операционные системы gnu/linux, windows, freebsd и mac os x. - -3. WINDOWS - -ВНИМАНИЕ! В настоящее время не доработано горячее переключение видеорежимов из экрана настроек. При применении настроек программа завершит свою работу. Необходимо вручную перезапустить программу. - -Файл конфигурации находится в папке с программой. - -Программа собрана с помощью MSVC++ 2010, поэтому может потребоваться установка Microsoft Visual C++ 2010 Redistributable Package. -Загрузите его по адресу http://www.microsoft.com/downloads/ru-ru/details.aspx?FamilyID=a7b7a05e-6de6-4d3a-a423-37bf0912db84. - -Программа не запускается (так как не находит свои данные), если путь к ним содержит кириллические символы. - -Есть временный способ для обхода этой проблемы. Запускайте программу с помощью сценария start.cmd. - -2. LINUX - -Файл конфигурации находится в директории ~/.config/violetland. - -Существуют пакеты для различных дистрибутивов. -Ознакомится со списком можно на странице по адресу http://code.google.com/p/violetland/wiki/ThirdParyPackages. -Если пакет для вашего дистрибутива не существует, программу придется собрать (скомпилировать) самому. - -Проще всего это сделать, используя систему сборки cmake. -Скорее всего, вы сможете найти ее в репозитории своего дистрибутива. -Кроме того, для сборки потребуются пакеты SDL (SDL, SDL_image, SDL_ttf, SDL_mixer), одноименные пакеты для разработки (devel) и компилятор (gcc). - -После того, как все будет подготовлено, нужно выполнить следующие действия: - -Сначала скачайте и распакуйте архив с программой или получите файлы из SVN. - -Затем войдите в директорию пакета прораммы и соберите ее с помощью cmake (по-умолчанию установка осуществляется в директорию /usr/local): - -$ mkdir build -$ cd build -$ cmake .. -$ sudo make install - -Затем запустите программу: - -$ violetland - -Вместо того, чтобы ставить программу в /usr/local вы можете установить ее в домашнюю папку или еще куда-нибудь. В таком случае вам не нужно знать пароль пользователя root и не обязателен доступ в /usr/local. Используйте следующий пример: - -$ mkdir build -$ cd build -$ cmake -DCMAKE_INSTALL_PREFIX=../dist .. -$ make install -$ cd ../dist/bin/ -$ ./violetland +Программа имеет файл конфигурации. +Его местонахождение зависит от операционной системы. + +irc.freenode.net, #violetland. +http://code.google.com/p/violetland/ +http://groups.google.com/group/violetland + +2. СИСТЕМНЫЕ ТРЕБОВАНИЯ + +Прежде чем скачивать игру, убедитесь, что у вас установлена видеокарта и свежие драйвера для нее с поддержкой аппаратного ускорения OpenGL. + +На данный момент поддерживаются операционные системы gnu/linux, windows, freebsd и mac os x. + +3. WINDOWS + +ВНИМАНИЕ! В настоящее время не доработано горячее переключение видеорежимов из экрана настроек. При применении настроек программа завершит свою работу. Необходимо вручную перезапустить программу. + +Файл конфигурации находится в папке с программой. + +Программа собрана с помощью MSVC++ 2010, поэтому может потребоваться установка Microsoft Visual C++ 2010 Redistributable Package. +Загрузите его по адресу http://www.microsoft.com/downloads/ru-ru/details.aspx?FamilyID=a7b7a05e-6de6-4d3a-a423-37bf0912db84. + +Программа не запускается (так как не находит свои данные), если путь к ним содержит кириллические символы. + +Есть временный способ для обхода этой проблемы. Запускайте программу с помощью сценария start.cmd. + +2. LINUX + +Файл конфигурации находится в директории ~/.config/violetland. + +Существуют пакеты для различных дистрибутивов. +Ознакомится со списком можно на странице по адресу http://code.google.com/p/violetland/wiki/ThirdParyPackages. +Если пакет для вашего дистрибутива не существует, программу придется собрать (скомпилировать) самому. + +Проще всего это сделать, используя систему сборки cmake. +Скорее всего, вы сможете найти ее в репозитории своего дистрибутива. +Кроме того, для сборки потребуются пакеты SDL (SDL, SDL_image, SDL_ttf, SDL_mixer), одноименные пакеты для разработки (devel) и компилятор (gcc). + +После того, как все будет подготовлено, нужно выполнить следующие действия: + +Сначала скачайте и распакуйте архив с программой или получите файлы из SVN. + +Затем войдите в директорию пакета прораммы и соберите ее с помощью cmake (по-умолчанию установка осуществляется в директорию /usr/local): + +$ mkdir build +$ cd build +$ cmake .. +$ sudo make install + +Затем запустите программу: + +$ violetland + +Вместо того, чтобы ставить программу в /usr/local вы можете установить ее в домашнюю папку или еще куда-нибудь. В таком случае вам не нужно знать пароль пользователя root и не обязателен доступ в /usr/local. Используйте следующий пример: + +$ mkdir build +$ cd build +$ cmake -DCMAKE_INSTALL_PREFIX=../dist .. +$ make install +$ cd ../dist/bin/ +$ ./violetland diff --git a/src/game/MusicManager.h b/src/game/MusicManager.h index b1406e8a..c103831d 100644 --- a/src/game/MusicManager.h +++ b/src/game/MusicManager.h @@ -1,26 +1,26 @@ -#ifndef MUSICMANAGER_H_ -#define MUSICMANAGER_H_ - -#include "../system/sound/SoundManager.h" -#include "GameState.h" -#include "lifeforms/Player.h" - -namespace violetland { -class MusicManager { -private: - FileUtility* m_fileUtility; - SoundManager* m_soundManager; - Configuration* m_config; - Mix_Music* m_current; - std::string m_currentPlaying; -public: - MusicManager(FileUtility* fileUtility, SoundManager* soundManager, - Configuration* config); - void process(Player* player, GameState* gameState); - void play(); - void play(std::string name, bool now); - ~MusicManager(); -}; -} - -#endif /* MUSICMANAGER_H_ */ +#ifndef MUSICMANAGER_H_ +#define MUSICMANAGER_H_ + +#include "../system/sound/SoundManager.h" +#include "GameState.h" +#include "lifeforms/Player.h" + +namespace violetland { +class MusicManager { +private: + FileUtility* m_fileUtility; + SoundManager* m_soundManager; + Configuration* m_config; + Mix_Music* m_current; + std::string m_currentPlaying; +public: + MusicManager(FileUtility* fileUtility, SoundManager* soundManager, + Configuration* config); + void process(Player* player, GameState* gameState); + void play(); + void play(std::string name, bool now); + ~MusicManager(); +}; +} + +#endif /* MUSICMANAGER_H_ */ diff --git a/src/game/bullets/Flame.cpp b/src/game/bullets/Flame.cpp index e9aaf5cb..37449f87 100644 --- a/src/game/bullets/Flame.cpp +++ b/src/game/bullets/Flame.cpp @@ -1,59 +1,59 @@ -#include "Flame.h" - -#ifdef _WIN32 -#define _USE_MATH_DEFINES -#include -#endif - -namespace violetland { - -Flame::Flame(float x, float y, Texture* tex) : - Bullet(x, y, x, y, BULLET_FLAME) { - m_img = new StaticObject(x, y, 128, 128, tex, false); - m_img->RMask = 1.0; - m_img->GMask = (float) (rand() % 50) / 100 + 0.4; - m_img->BMask = 0.3f; - m_img->Scale = 0.001f; -} - -void Flame::process(int deltaTime) { - const float dist = m_range / MaxRange; - - if (m_active && dist >= 0.7) - m_active = false; - - if (dist >= 1.0) - m_readyToRemove = true; - - const float relSpeed = (1.0 - dist) * Speed; - - X -= (float)cos((Angle + 90) * M_PI / 180) * deltaTime * relSpeed; - Y -= (float)sin((Angle + 90) * M_PI / 180) * deltaTime * relSpeed; - - m_img->X = X; - m_img->Y = Y; - - m_range += relSpeed * deltaTime; - - m_img->Scale = 2.5f * dist; - - if (dist < 0.5) - m_img->AMask = dist; - else - m_img->AMask = 1.0f - dist; -} - -void Flame::draw() { - m_img->draw(false, false); -} - -bool Flame::checkHit(Object* objRef) { - bool hit = m_active && objRef->detectCollide(m_img); - return hit; -} - -Flame::~Flame() { - delete m_img; -} - -} +#include "Flame.h" + +#ifdef _WIN32 +#define _USE_MATH_DEFINES +#include +#endif + +namespace violetland { + +Flame::Flame(float x, float y, Texture* tex) : + Bullet(x, y, x, y, BULLET_FLAME) { + m_img = new StaticObject(x, y, 128, 128, tex, false); + m_img->RMask = 1.0; + m_img->GMask = (float) (rand() % 50) / 100 + 0.4; + m_img->BMask = 0.3f; + m_img->Scale = 0.001f; +} + +void Flame::process(int deltaTime) { + const float dist = m_range / MaxRange; + + if (m_active && dist >= 0.7) + m_active = false; + + if (dist >= 1.0) + m_readyToRemove = true; + + const float relSpeed = (1.0 - dist) * Speed; + + X -= (float)cos((Angle + 90) * M_PI / 180) * deltaTime * relSpeed; + Y -= (float)sin((Angle + 90) * M_PI / 180) * deltaTime * relSpeed; + + m_img->X = X; + m_img->Y = Y; + + m_range += relSpeed * deltaTime; + + m_img->Scale = 2.5f * dist; + + if (dist < 0.5) + m_img->AMask = dist; + else + m_img->AMask = 1.0f - dist; +} + +void Flame::draw() { + m_img->draw(false, false); +} + +bool Flame::checkHit(Object* objRef) { + bool hit = m_active && objRef->detectCollide(m_img); + return hit; +} + +Flame::~Flame() { + delete m_img; +} + +} diff --git a/src/game/bullets/GrenadeBullet.h b/src/game/bullets/GrenadeBullet.h index 34867cae..9c888f31 100644 --- a/src/game/bullets/GrenadeBullet.h +++ b/src/game/bullets/GrenadeBullet.h @@ -1,28 +1,28 @@ -#ifndef GRENADEBULLET_H_ -#define GRENADEBULLET_H_ - -#ifdef _WIN32 -#define _USE_MATH_DEFINES -#endif //_WIN32W -#include "../../system/graphic/DynamicObject.h" -#include "Bullet.h" - -namespace violetland { - -class GrenadeBullet: public Bullet { -private: - float m_targetX, m_targetY; - float m_distance; - float m_scale; - DynamicObject* m_image; -public: - GrenadeBullet(float x, float y, float targetX, float targetY, - Sprite* sprite); - virtual void process(int deltaTime); - virtual void draw(); - virtual ~GrenadeBullet(); -}; - -} - -#endif /* GRENADEBULLET_H_ */ +#ifndef GRENADEBULLET_H_ +#define GRENADEBULLET_H_ + +#ifdef _WIN32 +#define _USE_MATH_DEFINES +#endif //_WIN32W +#include "../../system/graphic/DynamicObject.h" +#include "Bullet.h" + +namespace violetland { + +class GrenadeBullet: public Bullet { +private: + float m_targetX, m_targetY; + float m_distance; + float m_scale; + DynamicObject* m_image; +public: + GrenadeBullet(float x, float y, float targetX, float targetY, + Sprite* sprite); + virtual void process(int deltaTime); + virtual void draw(); + virtual ~GrenadeBullet(); +}; + +} + +#endif /* GRENADEBULLET_H_ */ diff --git a/src/game/bullets/LaserBullet.cpp b/src/game/bullets/LaserBullet.cpp index be98bef3..687bed56 100644 --- a/src/game/bullets/LaserBullet.cpp +++ b/src/game/bullets/LaserBullet.cpp @@ -1,52 +1,52 @@ -#include "LaserBullet.h" - -#ifdef _WIN32 -#define _USE_MATH_DEFINES -#include -#endif - -namespace violetland { - -LaserBullet::LaserBullet(float x, float y, float dX, float dY) : - Bullet(x, y, dX, dY, BULLET_LASER) { - Speed = 3; - Damage = 1; - MaxRange = 1000; - Alpha = 0.75f; - m_hit = false; -} - -void LaserBullet::process(int deltaTime) { - X = startX - cos((Angle + 90) * M_PI / 180) * MaxRange; - Y = startY - sin((Angle + 90) * M_PI / 180) * MaxRange; - - m_active = !m_hit && Alpha > 0.15f; - - m_readyToRemove = !m_active && Alpha == 0; - - Alpha -= 0.002f * deltaTime; - if (Alpha < 0) - Alpha = 0; -} - -void LaserBullet::draw() { - glDisable(GL_TEXTURE_2D); - - glLineWidth(2.0f); - glBegin(GL_LINES); - glColor4f(0.3f, 1.0f, 0.3f, Alpha / 3.0f); - glVertex3f(X, Y, 0); - glColor4f(0.3f, 1.0f, 0.3f, Alpha); - glVertex3f(dStartX, dStartY, 0); - glEnd(); - - glEnable(GL_TEXTURE_2D); -} - -bool LaserBullet::checkHit(Object* objRef) { - bool hit = m_active && objRef->detectCollide(startX, startY, X, Y); - m_hit = m_hit || hit; - return hit; -} - -} +#include "LaserBullet.h" + +#ifdef _WIN32 +#define _USE_MATH_DEFINES +#include +#endif + +namespace violetland { + +LaserBullet::LaserBullet(float x, float y, float dX, float dY) : + Bullet(x, y, dX, dY, BULLET_LASER) { + Speed = 3; + Damage = 1; + MaxRange = 1000; + Alpha = 0.75f; + m_hit = false; +} + +void LaserBullet::process(int deltaTime) { + X = startX - cos((Angle + 90) * M_PI / 180) * MaxRange; + Y = startY - sin((Angle + 90) * M_PI / 180) * MaxRange; + + m_active = !m_hit && Alpha > 0.15f; + + m_readyToRemove = !m_active && Alpha == 0; + + Alpha -= 0.002f * deltaTime; + if (Alpha < 0) + Alpha = 0; +} + +void LaserBullet::draw() { + glDisable(GL_TEXTURE_2D); + + glLineWidth(2.0f); + glBegin(GL_LINES); + glColor4f(0.3f, 1.0f, 0.3f, Alpha / 3.0f); + glVertex3f(X, Y, 0); + glColor4f(0.3f, 1.0f, 0.3f, Alpha); + glVertex3f(dStartX, dStartY, 0); + glEnd(); + + glEnable(GL_TEXTURE_2D); +} + +bool LaserBullet::checkHit(Object* objRef) { + bool hit = m_active && objRef->detectCollide(startX, startY, X, Y); + m_hit = m_hit || hit; + return hit; +} + +} diff --git a/src/game/bullets/LaserBullet.h b/src/game/bullets/LaserBullet.h index 9d483f1b..b7eef832 100644 --- a/src/game/bullets/LaserBullet.h +++ b/src/game/bullets/LaserBullet.h @@ -1,22 +1,22 @@ -#ifndef LASERBULLET_H_ -#define LASERBULLET_H_ - -#include "SDL_opengl.h" -#include "Bullet.h" - -namespace violetland { - -class LaserBullet: public Bullet { -private: - float Alpha; - bool m_hit; -public: - LaserBullet(float x, float y, float dX, float dY); - virtual void process(int deltaTime); - virtual void draw(); - virtual bool checkHit(Object* objRef); -}; - -} - -#endif /* LASERBULLET_H_ */ +#ifndef LASERBULLET_H_ +#define LASERBULLET_H_ + +#include "SDL_opengl.h" +#include "Bullet.h" + +namespace violetland { + +class LaserBullet: public Bullet { +private: + float Alpha; + bool m_hit; +public: + LaserBullet(float x, float y, float dX, float dY); + virtual void process(int deltaTime); + virtual void draw(); + virtual bool checkHit(Object* objRef); +}; + +} + +#endif /* LASERBULLET_H_ */ diff --git a/src/game/bullets/StandardBullet.cpp b/src/game/bullets/StandardBullet.cpp index 6d221a05..ca2324f2 100644 --- a/src/game/bullets/StandardBullet.cpp +++ b/src/game/bullets/StandardBullet.cpp @@ -1,75 +1,75 @@ -#include "StandardBullet.h" - +#include "StandardBullet.h" + #ifdef _WIN32 -#define _USE_MATH_DEFINES +#define _USE_MATH_DEFINES #include -#endif - -namespace violetland { - -StandardBullet::StandardBullet(float x, float y, float dX, float dY, - bool explosive) : - Bullet(x, y, dX, dY, BULLET_STANDARD) { - Speed = 3; - Damage = 1; - MaxRange = 1000; - Alpha = 1.0f; - prevX = x; - prevY = y; - m_explosive = explosive; -} - -bool StandardBullet::isExplosive() { - return m_explosive; -} - -void StandardBullet::process(int deltaTime) { - if (m_active) { - prevX = X; - prevY = Y; - X -= cos((Angle + 90) * M_PI / 180) * deltaTime * Speed; - Y -= sin((Angle + 90) * M_PI / 180) * deltaTime * Speed; - } - - m_range += Speed * deltaTime; - Alpha = MaxRange - m_range; - if (Alpha <= 0) { - Alpha = 0; - m_active = 0; - m_readyToRemove = 1; - } else { - Alpha /= MaxRange; - m_readyToRemove = 0; - } -} - -void StandardBullet::draw() { - glDisable(GL_TEXTURE_2D); - - glLineWidth(BigCalibre || Penetrating ? 3.0f : 1.0f); - glBegin(GL_LINES); - glColor4f(1.0f, Penetrating ? 0.5f : 1.0f, Penetrating ? 0.2f : 1.0f, Alpha); - glVertex3f(X, Y, 0); - glColor4f(1.0f, Penetrating ? 0.5f : 1.0f, Penetrating ? 0.2f : 1.0f, 0.0f); - glVertex3f(dStartX, dStartY, 0); - glEnd(); - - glEnable(GL_TEXTURE_2D); -} - -bool StandardBullet::checkHit(Object* objRef) { - float hx, hy; - if (m_active && objRef->detectCollide(prevX, prevY, X, Y, &hx, &hy)) { - - X = hx; - Y = hy; - - if (!(BigCalibre || Penetrating)) - deactivate(); - return true; - } else { - return false; - } -} - -} +#endif + +namespace violetland { + +StandardBullet::StandardBullet(float x, float y, float dX, float dY, + bool explosive) : + Bullet(x, y, dX, dY, BULLET_STANDARD) { + Speed = 3; + Damage = 1; + MaxRange = 1000; + Alpha = 1.0f; + prevX = x; + prevY = y; + m_explosive = explosive; +} + +bool StandardBullet::isExplosive() { + return m_explosive; +} + +void StandardBullet::process(int deltaTime) { + if (m_active) { + prevX = X; + prevY = Y; + X -= cos((Angle + 90) * M_PI / 180) * deltaTime * Speed; + Y -= sin((Angle + 90) * M_PI / 180) * deltaTime * Speed; + } + + m_range += Speed * deltaTime; + Alpha = MaxRange - m_range; + if (Alpha <= 0) { + Alpha = 0; + m_active = 0; + m_readyToRemove = 1; + } else { + Alpha /= MaxRange; + m_readyToRemove = 0; + } +} + +void StandardBullet::draw() { + glDisable(GL_TEXTURE_2D); + + glLineWidth(BigCalibre || Penetrating ? 3.0f : 1.0f); + glBegin(GL_LINES); + glColor4f(1.0f, Penetrating ? 0.5f : 1.0f, Penetrating ? 0.2f : 1.0f, Alpha); + glVertex3f(X, Y, 0); + glColor4f(1.0f, Penetrating ? 0.5f : 1.0f, Penetrating ? 0.2f : 1.0f, 0.0f); + glVertex3f(dStartX, dStartY, 0); + glEnd(); + + glEnable(GL_TEXTURE_2D); +} + +bool StandardBullet::checkHit(Object* objRef) { + float hx, hy; + if (m_active && objRef->detectCollide(prevX, prevY, X, Y, &hx, &hy)) { + + X = hx; + Y = hy; + + if (!(BigCalibre || Penetrating)) + deactivate(); + return true; + } else { + return false; + } +} + +} diff --git a/src/game/bullets/StandardBullet.h b/src/game/bullets/StandardBullet.h index 7b5e1cb0..7ccd52ca 100644 --- a/src/game/bullets/StandardBullet.h +++ b/src/game/bullets/StandardBullet.h @@ -1,24 +1,24 @@ -#ifndef STANDARDBULLET_H_ -#define STANDARDBULLET_H_ - -#include "SDL_opengl.h" -#include "Bullet.h" - -namespace violetland { - -class StandardBullet: public Bullet { -private: - float Alpha; - float prevX, prevY; - bool m_explosive; -public: - StandardBullet(float x, float y, float dX, float dY, bool explosive); - bool isExplosive(); - virtual void process(int deltaTime); - virtual void draw(); - virtual bool checkHit(Object* objRef); -}; - -} - -#endif /* STANDARDBULLET_H_ */ +#ifndef STANDARDBULLET_H_ +#define STANDARDBULLET_H_ + +#include "SDL_opengl.h" +#include "Bullet.h" + +namespace violetland { + +class StandardBullet: public Bullet { +private: + float Alpha; + float prevX, prevY; + bool m_explosive; +public: + StandardBullet(float x, float y, float dX, float dY, bool explosive); + bool isExplosive(); + virtual void process(int deltaTime); + virtual void draw(); + virtual bool checkHit(Object* objRef); +}; + +} + +#endif /* STANDARDBULLET_H_ */ diff --git a/src/game/lifeforms/LifeForm.cpp b/src/game/lifeforms/LifeForm.cpp index 8dbc6c2d..2e8fa09a 100644 --- a/src/game/lifeforms/LifeForm.cpp +++ b/src/game/lifeforms/LifeForm.cpp @@ -1,154 +1,154 @@ -#include - -#include "LifeForm.h" - -using namespace violetland; - -LifeForm::LifeForm(float x, float y, int w, int h) : - Object(x, y, w, h) { - std::ostringstream buf; - buf << UidGenerator::getInstance()->getId(); - Id = buf.str(); - Strength = 1.0f; - Agility = 1.0f; - Vitality = 1.0f; - m_health = MaxHealth(); - State = LIFEFORM_STATE_ALIVE; - m_lastAttackTime = SDL_GetTicks(); - TargetX = TargetY = 0.0f; - Poisoned = false; - m_walking = false; - Frozen = 0; - Burning = false; - Level = 1; - Name = "Unknown lifeform"; -} - -void LifeForm::draw() { - // nothing -} - -Sound* LifeForm::hit(float damage, bool poison) { - setHealth(getHealth() - damage); - - if (getHealth() == 0 && State == LIFEFORM_STATE_ALIVE) { - State = LIFEFORM_STATE_SMITTEN; - } - - return NULL; -} - -void LifeForm::process(int deltaTime) { - if (Frozen > 0) { - Frozen -= deltaTime; - if (Frozen < 0) - Frozen = 0; - } - - if (State == LIFEFORM_STATE_ALIVE && Frozen == 0) { - setHealth(getHealth() + HealthRegen() * deltaTime); - - if (Poisoned) - setHealth(getHealth() - 0.0004f * deltaTime); - - if (Burning) { - RMask -= 0.02 / MaxHealth(); - if (RMask < 0) - RMask = 0; - GMask -= 0.02 / MaxHealth(); - if (GMask < 0) - GMask = 0; - BMask -= 0.02 / MaxHealth(); - if (BMask < 0) - BMask = 0; - AMask += 0.01 / MaxHealth(); - if (AMask > 1) - AMask = 1; - - setHealth(getHealth() - 0.0005f * deltaTime); - } - - if (!m_walking) { - Speed -= Acceleration * deltaTime; - if (Speed < 0) - Speed = 0; - } - - m_walking = false; - - Object::move(deltaTime); - } -} - -void LifeForm::move(float direction, int deltaTime) { - if (m_walkDelay > 0) - return; - - m_walking = true; - - Speed += Acceleration * deltaTime; - if (Speed > MaxSpeed()) - Speed = MaxSpeed(); - - turn(direction, MaxSpeed(), deltaTime); -} - -const float LifeForm::MaxHealth() const { - return getVitality() > 0.8f ? 1.0f + (getVitality() - 1.0f) * 2.0f - + (getStrength() - 1.0f) : 0.4f; -} - -const float LifeForm::ChanceToEvade() const { - float chance = (getAgility() - 1.0f) / 4.0f + (getStrength() - 1.0f) / 4.0f; - if (chance < 0) chance = 0; - return chance; -} - -const bool LifeForm::Attack() { - int now = SDL_GetTicks(); - - if (now - m_lastAttackTime > AttackDelay()) { - m_lastAttackTime = now; - return true; - } else { - return false; - } -} - -const float LifeForm::Damage() const { - return getStrength() / 8.0f; -} - -const int LifeForm::AttackDelay() const { - return (1.0f - (getAgility() - 1.0f) / 2.0f) * 1000; -} - -const float LifeForm::MaxSpeed() const { - return getAgility() / 5.0f; -} - -const float LifeForm::HealthRegen() const { - return getVitality() > 1.0f ? (getVitality() - 1.0f) * 0.000006f : 0.0f; -} - -const float LifeForm::ReloadSpeedMod() const { - return 1.0f / getAgility(); -} - -const float LifeForm::WeaponRetForceMod() const { - return getStrength() > 1.0f ? 1.0f - (getStrength() - 1.0f) * 1.1f : 1.0f; -} - -const float LifeForm::fixHealth(float health) const { - if (health > MaxHealth()) - return MaxHealth(); - else if (health < 0) - return 0; - else - return health; -} - -LifeForm::~LifeForm() -{ - // nothing -} +#include + +#include "LifeForm.h" + +using namespace violetland; + +LifeForm::LifeForm(float x, float y, int w, int h) : + Object(x, y, w, h) { + std::ostringstream buf; + buf << UidGenerator::getInstance()->getId(); + Id = buf.str(); + Strength = 1.0f; + Agility = 1.0f; + Vitality = 1.0f; + m_health = MaxHealth(); + State = LIFEFORM_STATE_ALIVE; + m_lastAttackTime = SDL_GetTicks(); + TargetX = TargetY = 0.0f; + Poisoned = false; + m_walking = false; + Frozen = 0; + Burning = false; + Level = 1; + Name = "Unknown lifeform"; +} + +void LifeForm::draw() { + // nothing +} + +Sound* LifeForm::hit(float damage, bool poison) { + setHealth(getHealth() - damage); + + if (getHealth() == 0 && State == LIFEFORM_STATE_ALIVE) { + State = LIFEFORM_STATE_SMITTEN; + } + + return NULL; +} + +void LifeForm::process(int deltaTime) { + if (Frozen > 0) { + Frozen -= deltaTime; + if (Frozen < 0) + Frozen = 0; + } + + if (State == LIFEFORM_STATE_ALIVE && Frozen == 0) { + setHealth(getHealth() + HealthRegen() * deltaTime); + + if (Poisoned) + setHealth(getHealth() - 0.0004f * deltaTime); + + if (Burning) { + RMask -= 0.02 / MaxHealth(); + if (RMask < 0) + RMask = 0; + GMask -= 0.02 / MaxHealth(); + if (GMask < 0) + GMask = 0; + BMask -= 0.02 / MaxHealth(); + if (BMask < 0) + BMask = 0; + AMask += 0.01 / MaxHealth(); + if (AMask > 1) + AMask = 1; + + setHealth(getHealth() - 0.0005f * deltaTime); + } + + if (!m_walking) { + Speed -= Acceleration * deltaTime; + if (Speed < 0) + Speed = 0; + } + + m_walking = false; + + Object::move(deltaTime); + } +} + +void LifeForm::move(float direction, int deltaTime) { + if (m_walkDelay > 0) + return; + + m_walking = true; + + Speed += Acceleration * deltaTime; + if (Speed > MaxSpeed()) + Speed = MaxSpeed(); + + turn(direction, MaxSpeed(), deltaTime); +} + +const float LifeForm::MaxHealth() const { + return getVitality() > 0.8f ? 1.0f + (getVitality() - 1.0f) * 2.0f + + (getStrength() - 1.0f) : 0.4f; +} + +const float LifeForm::ChanceToEvade() const { + float chance = (getAgility() - 1.0f) / 4.0f + (getStrength() - 1.0f) / 4.0f; + if (chance < 0) chance = 0; + return chance; +} + +const bool LifeForm::Attack() { + int now = SDL_GetTicks(); + + if (now - m_lastAttackTime > AttackDelay()) { + m_lastAttackTime = now; + return true; + } else { + return false; + } +} + +const float LifeForm::Damage() const { + return getStrength() / 8.0f; +} + +const int LifeForm::AttackDelay() const { + return (1.0f - (getAgility() - 1.0f) / 2.0f) * 1000; +} + +const float LifeForm::MaxSpeed() const { + return getAgility() / 5.0f; +} + +const float LifeForm::HealthRegen() const { + return getVitality() > 1.0f ? (getVitality() - 1.0f) * 0.000006f : 0.0f; +} + +const float LifeForm::ReloadSpeedMod() const { + return 1.0f / getAgility(); +} + +const float LifeForm::WeaponRetForceMod() const { + return getStrength() > 1.0f ? 1.0f - (getStrength() - 1.0f) * 1.1f : 1.0f; +} + +const float LifeForm::fixHealth(float health) const { + if (health > MaxHealth()) + return MaxHealth(); + else if (health < 0) + return 0; + else + return health; +} + +LifeForm::~LifeForm() +{ + // nothing +} diff --git a/src/game/lifeforms/LifeForm.h b/src/game/lifeforms/LifeForm.h index 629b0add..e2317f10 100644 --- a/src/game/lifeforms/LifeForm.h +++ b/src/game/lifeforms/LifeForm.h @@ -1,80 +1,80 @@ -#ifndef LIFEFORM_H_ -#define LIFEFORM_H_ - -#ifdef _WIN32 -#include "windows.h" -#endif //_WIN32W -#include "../../system/graphic/StaticObject.h" -#include "../../system/graphic/DynamicObject.h" -#include "../../system/sound/Sound.h" -#include "../../system/utility/UidGenerator.h" - -namespace violetland { -enum LifeFormType { - LIFEFORM_PLAYER = 0, LIFEFORM_MONSTER -}; - -enum LifeFormState { - LIFEFORM_STATE_ALIVE = 0, - LIFEFORM_STATE_SMITTEN, - LIFEFORM_STATE_DYING, - LIFEFORM_STATE_DIED, - LIFEFORM_STATE_BURST -}; - -class LifeForm: public Object { -private: - int m_lastAttackTime; - float m_health; - const float fixHealth(float health) const; -protected: - DynamicObject *m_body; - bool m_walking; - int m_walkTime; - int m_walkDelay; -public: - LifeFormType Type; - LifeForm(float x, float y, int w, int h); - - virtual void process(int deltaTime); - virtual void draw(); - virtual Sound* hit(float damage, bool poison); - - void move(float direction, int deltaTime); - - std::string Id; - std::string Name; - float TargetX, TargetY; - LifeFormState State; - - // Attributes - - int Level; - float Strength; - float Agility; - float Vitality; - - bool Poisoned; - bool Burning; - int Frozen; - - void setHealth(float value) { m_health = fixHealth(value); } - const float getHealth() { return m_health = fixHealth(m_health); } - virtual float getStrength() const { return Strength; } - virtual float getAgility() const { return Agility; } - virtual float getVitality() const { return Vitality; } - const float MaxHealth() const; - const float MaxSpeed() const; - const float ChanceToEvade() const; - const bool Attack(); - const float Damage() const; - const int AttackDelay() const; - const float ReloadSpeedMod() const; - const float WeaponRetForceMod() const; - const float HealthRegen() const; - virtual StaticObject* getCorpse() = 0; - virtual ~LifeForm(); -}; -} - -#endif /* LIFEFORM_H_ */ +#ifndef LIFEFORM_H_ +#define LIFEFORM_H_ + +#ifdef _WIN32 +#include "windows.h" +#endif //_WIN32W +#include "../../system/graphic/StaticObject.h" +#include "../../system/graphic/DynamicObject.h" +#include "../../system/sound/Sound.h" +#include "../../system/utility/UidGenerator.h" + +namespace violetland { +enum LifeFormType { + LIFEFORM_PLAYER = 0, LIFEFORM_MONSTER +}; + +enum LifeFormState { + LIFEFORM_STATE_ALIVE = 0, + LIFEFORM_STATE_SMITTEN, + LIFEFORM_STATE_DYING, + LIFEFORM_STATE_DIED, + LIFEFORM_STATE_BURST +}; + +class LifeForm: public Object { +private: + int m_lastAttackTime; + float m_health; + const float fixHealth(float health) const; +protected: + DynamicObject *m_body; + bool m_walking; + int m_walkTime; + int m_walkDelay; +public: + LifeFormType Type; + LifeForm(float x, float y, int w, int h); + + virtual void process(int deltaTime); + virtual void draw(); + virtual Sound* hit(float damage, bool poison); + + void move(float direction, int deltaTime); + + std::string Id; + std::string Name; + float TargetX, TargetY; + LifeFormState State; + + // Attributes + + int Level; + float Strength; + float Agility; + float Vitality; + + bool Poisoned; + bool Burning; + int Frozen; + + void setHealth(float value) { m_health = fixHealth(value); } + const float getHealth() { return m_health = fixHealth(m_health); } + virtual float getStrength() const { return Strength; } + virtual float getAgility() const { return Agility; } + virtual float getVitality() const { return Vitality; } + const float MaxHealth() const; + const float MaxSpeed() const; + const float ChanceToEvade() const; + const bool Attack(); + const float Damage() const; + const int AttackDelay() const; + const float ReloadSpeedMod() const; + const float WeaponRetForceMod() const; + const float HealthRegen() const; + virtual StaticObject* getCorpse() = 0; + virtual ~LifeForm(); +}; +} + +#endif /* LIFEFORM_H_ */ diff --git a/src/game/lifeforms/Monster.cpp b/src/game/lifeforms/Monster.cpp index bdd27e1a..c4555ab7 100755 --- a/src/game/lifeforms/Monster.cpp +++ b/src/game/lifeforms/Monster.cpp @@ -1,148 +1,148 @@ -#ifdef _WIN32 -#define _USE_MATH_DEFINES -#endif //_WIN32W -#include "Monster.h" - -violetland::Monster::Monster(MonsterTemplate* base, int lvl) : - LifeForm(0, 0, 128, 128) { - Id = "10-" + Id; - - Base = base; - Level = lvl; - - float t = Base->Strength + Base->Agility + Base->Vitality; - float sp = Base->Strength / t; - float ap = Base->Agility / t; - float vp = Base->Vitality / t; - - Strength = Base->Strength + 0.03f * Level * sp; - Agility = Base->Agility + 0.03f * Level * ap; - Vitality = Base->Vitality + 0.03f * Level * vp; - - if ((rand() % 100) > 95) { - Strength *= 2.0f; - setMask(0.2f, 0.7f, 0.2f, 1.0f); - Name = "Strong " + Base->Name; - } else if ((rand() % 100) > 95) { - Agility *= 1.8f; - setMask(0.3f, 0.4f, 0.7f, 1.0f); - Name = "Fast " + Base->Name; - } else if ((rand() % 100) > 95) { - Vitality *= 2.0f; - setMask(1.0f, 0.2f, 0.2f, 1.0f); - Name = "Healthy " + Base->Name; - } else { - setMask(0.8f, 0.7f, 0.4f, 1.0f); - Name = "Regular " + Base->Name; - } - - setHealth(MaxHealth()); - - HitR = 0.3; - Acceleration = 0.0004f; - - if (Base->WalkTime > 0) - m_walkTime = (rand() % Base->WalkTime); - else - m_walkTime = 0; - - m_walkDelay = 0; - - m_body = new DynamicObject(0, 0, Base->WalkSprite); - m_hitSoundChannel = 0; - m_bleedDelay = 0; - m_bleedCount = 0; - Angry = false; - targetId = "ambient"; - Type = LIFEFORM_MONSTER; -} - -void violetland::Monster::rollFrame(bool forward) { - m_body->rollFrame(forward); -} - -Sound* violetland::Monster::hit(float damage, bool poison, bool stop) { - LifeForm::hit(damage, poison); - - m_bleedCount += damage * 5; - Poisoned = poison || Poisoned; - - if (stop) - Speed = 0.0f; - - Angle += ((rand() % 50) - 25) * damage; - - if (m_walkDelay > 0) - m_walkDelay = 1; - - if (!Base->HitSounds.empty()) { - int s = rand() % (int) Base->HitSounds.size(); - return Base->HitSounds[s]; - } - - return NULL; -} - -bool violetland::Monster::isBleeding() { - if (m_bleedCount > 0 && m_bleedDelay > 600) { - m_bleedDelay = 0; - m_bleedCount--; - return true; - } else { - return false; - } -} - -void violetland::Monster::process(int deltaTime) { - LifeForm::process(deltaTime); - - if (m_walkTime > 0) { - m_walkTime -= deltaTime; - if (m_walkTime <= 0) { - m_walkTime = 0; - m_walkDelay = Base->WalkDelay; - } - } - - if (m_walkDelay > 0) { - m_walkDelay -= deltaTime; - if (m_walkDelay <= 0) { - m_walkTime = Base->WalkTime; - m_walkDelay = 0; - } - } - - if (m_bleedCount > 0) - m_bleedDelay += deltaTime; - - if (State == LIFEFORM_STATE_DYING) { - if (m_body->Frame == m_body->AnimSprite->getFramesCount() - 1) { - State = LIFEFORM_STATE_DIED; - } else { - m_body->rollFrame(true); - } - } - - if (State == LIFEFORM_STATE_SMITTEN) { - delete m_body; - m_body = new DynamicObject(X, Y, Base->DeathSprite); - State = LIFEFORM_STATE_DYING; - } -} - -StaticObject* violetland::Monster::getCorpse() { - StaticObject * corpse = new StaticObject(X, Y, m_width, m_height, - m_body->getFrame(), false); - corpse->Scale = Scale; - corpse->Angle = Object::fixAngle(180 - Angle); - corpse->setMask(RMask, GMask, BMask, AMask); - return corpse; -} - -void violetland::Monster::draw() { - m_body->draw(X, Y, Angle, Scale, RMask, GMask, BMask, AMask); -} - -violetland::Monster::~Monster() { - delete m_body; -} +#ifdef _WIN32 +#define _USE_MATH_DEFINES +#endif //_WIN32W +#include "Monster.h" + +violetland::Monster::Monster(MonsterTemplate* base, int lvl) : + LifeForm(0, 0, 128, 128) { + Id = "10-" + Id; + + Base = base; + Level = lvl; + + float t = Base->Strength + Base->Agility + Base->Vitality; + float sp = Base->Strength / t; + float ap = Base->Agility / t; + float vp = Base->Vitality / t; + + Strength = Base->Strength + 0.03f * Level * sp; + Agility = Base->Agility + 0.03f * Level * ap; + Vitality = Base->Vitality + 0.03f * Level * vp; + + if ((rand() % 100) > 95) { + Strength *= 2.0f; + setMask(0.2f, 0.7f, 0.2f, 1.0f); + Name = "Strong " + Base->Name; + } else if ((rand() % 100) > 95) { + Agility *= 1.8f; + setMask(0.3f, 0.4f, 0.7f, 1.0f); + Name = "Fast " + Base->Name; + } else if ((rand() % 100) > 95) { + Vitality *= 2.0f; + setMask(1.0f, 0.2f, 0.2f, 1.0f); + Name = "Healthy " + Base->Name; + } else { + setMask(0.8f, 0.7f, 0.4f, 1.0f); + Name = "Regular " + Base->Name; + } + + setHealth(MaxHealth()); + + HitR = 0.3; + Acceleration = 0.0004f; + + if (Base->WalkTime > 0) + m_walkTime = (rand() % Base->WalkTime); + else + m_walkTime = 0; + + m_walkDelay = 0; + + m_body = new DynamicObject(0, 0, Base->WalkSprite); + m_hitSoundChannel = 0; + m_bleedDelay = 0; + m_bleedCount = 0; + Angry = false; + targetId = "ambient"; + Type = LIFEFORM_MONSTER; +} + +void violetland::Monster::rollFrame(bool forward) { + m_body->rollFrame(forward); +} + +Sound* violetland::Monster::hit(float damage, bool poison, bool stop) { + LifeForm::hit(damage, poison); + + m_bleedCount += damage * 5; + Poisoned = poison || Poisoned; + + if (stop) + Speed = 0.0f; + + Angle += ((rand() % 50) - 25) * damage; + + if (m_walkDelay > 0) + m_walkDelay = 1; + + if (!Base->HitSounds.empty()) { + int s = rand() % (int) Base->HitSounds.size(); + return Base->HitSounds[s]; + } + + return NULL; +} + +bool violetland::Monster::isBleeding() { + if (m_bleedCount > 0 && m_bleedDelay > 600) { + m_bleedDelay = 0; + m_bleedCount--; + return true; + } else { + return false; + } +} + +void violetland::Monster::process(int deltaTime) { + LifeForm::process(deltaTime); + + if (m_walkTime > 0) { + m_walkTime -= deltaTime; + if (m_walkTime <= 0) { + m_walkTime = 0; + m_walkDelay = Base->WalkDelay; + } + } + + if (m_walkDelay > 0) { + m_walkDelay -= deltaTime; + if (m_walkDelay <= 0) { + m_walkTime = Base->WalkTime; + m_walkDelay = 0; + } + } + + if (m_bleedCount > 0) + m_bleedDelay += deltaTime; + + if (State == LIFEFORM_STATE_DYING) { + if (m_body->Frame == m_body->AnimSprite->getFramesCount() - 1) { + State = LIFEFORM_STATE_DIED; + } else { + m_body->rollFrame(true); + } + } + + if (State == LIFEFORM_STATE_SMITTEN) { + delete m_body; + m_body = new DynamicObject(X, Y, Base->DeathSprite); + State = LIFEFORM_STATE_DYING; + } +} + +StaticObject* violetland::Monster::getCorpse() { + StaticObject * corpse = new StaticObject(X, Y, m_width, m_height, + m_body->getFrame(), false); + corpse->Scale = Scale; + corpse->Angle = Object::fixAngle(180 - Angle); + corpse->setMask(RMask, GMask, BMask, AMask); + return corpse; +} + +void violetland::Monster::draw() { + m_body->draw(X, Y, Angle, Scale, RMask, GMask, BMask, AMask); +} + +violetland::Monster::~Monster() { + delete m_body; +} diff --git a/src/game/lifeforms/Player.cpp b/src/game/lifeforms/Player.cpp index 7b01811e..4063d815 100644 --- a/src/game/lifeforms/Player.cpp +++ b/src/game/lifeforms/Player.cpp @@ -1,315 +1,315 @@ -#ifdef _WIN32 -#define _USE_MATH_DEFINES -#endif //_WIN32W -#include "Player.h" -#include "../../system/utility/Templates.h" - -namespace violetland { - -Player::Player(float x, float y, Sprite *legsSprite, Sprite *deathSprite, - std::vector hitSounds, Sound* dyingSound) : - LifeForm(x, y, 128, 128) { - Id = "20-" + Id; - Xp = 0; - LastLevelXp = 0; - NextLevelXp = 100; - Kills = 0; - LevelPoints = 0; - ActionMode = PLAYER_ACT_MODE_FIRE; - AccuracyDeviation = 0.0f; - Grenades = 2; - Teleports = 1; - Acceleration = 0.0004f; - Type = LIFEFORM_PLAYER; - m_hitSndPlaying = 0; - m_walkTime = 0; - m_walkDelay = 0; - - m_weapon = NULL; - - m_light = m_laser = false; - - Unstoppable = PoisonBullets = BigCalibre = Telekinesis = NightVision - = Looting = WideSight = Magneto = false; - - for (int i = PLAYER_BONUS_FIRST; i < PLAYER_BONUS_COUNT; i++) - bonusTimes[i] = 0; - - processTelekinesis(0, true); - - TargetX = x; - TargetY = y; - - m_weapon = NULL; - m_arms = NULL; - m_body = new DynamicObject(x, y, legsSprite); - m_body->Frame = 8; - m_deathSprite = deathSprite; - m_hitSounds = hitSounds; - m_dyingSound = dyingSound; -} - -float Player::getStrength() const { - return Strength * ((bonusTimes[PLAYER_BONUS_STRENGTHBOOST] > 0) ? 1.2f - : 1.0f); -} - -float Player::getAgility() const { - return Agility - * ((bonusTimes[PLAYER_BONUS_AGILITYBOOST] > 0) ? 1.2f : 1.0f); -} - -float Player::getVitality() const { - return Vitality * ((bonusTimes[PLAYER_BONUS_VITALITYBOOST] > 0) ? 1.2f - : 1.0f); -} - -Sound* Player::hit(float damage, bool poison) { - LifeForm::hit(damage, poison); - - setMask(1.0f, 0.0f, 0.0f, 1.0f); - - if (!Unstoppable) - Speed = 0.0f; - - if (!m_hitSounds[m_hitSndPlaying]->isPlaying()) { - m_hitSndPlaying = (getHealth() < MaxHealth() ? getHealth() - : getHealth() - 0.01f) / MaxHealth() * m_hitSounds.size(); - return m_hitSounds[m_hitSndPlaying]; - } - - return NULL; -} - -std::vector* Player::fire() { - const float rad = (getArmsAngle() - 90) * M_PI / 180; - std::vector *newBullets = m_weapon->fire(m_arms->X, m_arms->Y, - m_arms->X + m_weapon->XDiff * cos(rad) + m_weapon->YDiff - * sin(-rad), m_arms->Y + m_weapon->XDiff * sin(rad) - + m_weapon->YDiff * cos(-rad)); - - if (!newBullets->empty()) { - std::vector::iterator it; - - if (AccuracyDeviation < 25) - AccuracyDeviation - += m_weapon->BulletsAtOnce > 1 ? m_weapon->ReturnForce - : m_weapon->ReturnForce * WeaponRetForceMod(); - - for (it = newBullets->begin(); it != (newBullets->end()); it++) { - Bullet* bullet = *(it); - bullet->Poisoned = m_weapon->Type == BULLET_STANDARD - && PoisonBullets; - bullet->BigCalibre = m_weapon->Type == BULLET_STANDARD - && BigCalibre; - if (BigCalibre) { - bullet->Damage *= 1.1f; - } - bullet->Penetrating = m_weapon->Type == BULLET_STANDARD - && bonusTimes[PLAYER_BONUS_PENBULLETS] > 0; - bullet->Angle = AccuracyDeviation < 1 ? m_arms->Angle - : m_arms->Angle + (rand() % (int) (AccuracyDeviation * 2)) - - AccuracyDeviation; - bullet->OwnerId = Id; - } - - if (m_weapon->BulletsAtOnce > 1) - AccuracyDeviation = 0; - - if (m_weapon->ShellSprite) - { - DynamicObject* shell = new DynamicObject(X, Y, m_weapon->ShellSprite); - shell->Angle = m_arms->Angle; - m_shells.push_back(shell); - } - } - - return newBullets; -} - -Bullet* Player::throwGrenade(Sprite* grenadeSprite) { - Bullet* newBullet = - new GrenadeBullet(X, Y, TargetX, TargetY, grenadeSprite); - - newBullet->Damage = 5.0f; - newBullet->Speed = MaxSpeed() * 5.0f; - newBullet->MaxRange = 1500; - - Grenades--; - - return newBullet; -} - -void Player::reload() { - if (m_weapon->reload(ReloadSpeedMod())) - AccuracyDeviation = 0; -} - -void Player::processState(int deltaTime) { - if (State == LIFEFORM_STATE_ALIVE) { - m_arms->X = m_body->X = X; - m_arms->Y = m_body->Y = Y; - m_body->Angle = Angle; - - if (Speed > MaxSpeed() / 4) { - m_body->rollFrame(true); - } else { - if (!(m_body->Frame == 8 || m_body->Frame == 20)) { - if ((m_body->Frame > 8 && m_body->Frame < 16) || m_body->Frame - > 20) - m_body->rollFrame(false); - else - m_body->rollFrame(true); - } - } - } - - if (State == LIFEFORM_STATE_DYING) { - if (m_body->Frame == m_body->AnimSprite->getFramesCount() - 1) - State = LIFEFORM_STATE_DIED; - - m_body->rollFrame(true); - } - - if (State == LIFEFORM_STATE_SMITTEN) { - const float angle = m_body->Angle; - delete m_body; - m_body = new DynamicObject(X, Y, m_deathSprite); - m_body->Angle = angle; - State = LIFEFORM_STATE_DYING; - if (m_hitSounds[m_hitSndPlaying]->isPlaying()) - m_hitSounds[m_hitSndPlaying]->stop(0); - - m_dyingSound->play(5, 0, 0); - } -} - -void Player::processArms(int deltaTime) { - m_arms->Angle = Object::calc_angle(X, Y, TargetX, TargetY); - m_weapon->process(deltaTime); - AccuracyDeviation -= deltaTime * 0.01f; - if (AccuracyDeviation < 0) - AccuracyDeviation = 0; - -} -void Player::process(int deltaTime) { - // Base processing - LifeForm::process(deltaTime); - - // State and animation - processState(deltaTime); - - // Hit animation - fadeColor(deltaTime); - - // Weapon and targeting - processArms(deltaTime); - - // Bonuses - processBonus(deltaTime); -} - -void Player::processBonus(int deltaTime) { - for (int i = PLAYER_BONUS_FIRST; i < PLAYER_BONUS_COUNT; i++) { - bonusTimes[i] -= deltaTime; - if (bonusTimes[i] < 0) - bonusTimes[i] = 0; - } -} - -void Player::fadeColor(int deltaTime) { - m_arms->setMask(RMask, GMask, BMask, AMask); - m_body->setMask(RMask, GMask, BMask, AMask); - if (RMask < 1.0f) - RMask += 0.01f; - if (GMask < 1.0f) - GMask += 0.01f; - if (BMask < 1.0f) - BMask += 0.01f; - if (AMask < 1.0f) - AMask += 0.01f; -} - -void Player::draw() { - m_body->draw(X, Y, Angle, Scale, RMask, GMask, BMask, AMask); - - if (State == LIFEFORM_STATE_ALIVE) - m_arms->draw(false, false); - - for (int i = m_shells.size() - 1; i >= 0; i--) { - m_shells[i]->draw(); - if (m_shells[i]->Frame == m_shells[i]->AnimSprite->getFramesCount() - 1) { - delete m_shells[i]; - m_shells .erase(m_shells.begin() + i); - continue; - } - m_shells[i]->rollFrame(true); - } -} - -StaticObject* Player::getCorpse() { - StaticObject * corpse = new StaticObject(X, Y, m_width, m_height, - m_body->getFrame(), false); - corpse->Scale = m_body->Scale; - corpse->Angle = Object::fixAngle(180 - m_body->Angle); - return corpse; -} - -void Player::setX(float value) { - X = m_arms->X = m_body->X = value; -} - -void Player::setY(float value) { - Y = m_arms->Y = m_body->Y = value; -} - -void Player::teleport() { - Teleports--; - setX(TargetX); - setY(TargetY); -} - -void Player::setWeapon(Weapon *value) { - float angle = 0; - if (m_weapon) { - angle = getArmsAngle(); - delete m_arms; - delete m_weapon; - } - m_weapon = new Weapon(*value); - m_arms = new StaticObject(X, Y, 128, 128, m_weapon->getPlayerTex(), false); - m_arms->Angle = angle; - AccuracyDeviation = 0; -} - -// Controls telekinesis ability -// Reset = true to reset timer (obvious!), deltaTime will be ignored, will return 0 -// Reset = false and deltaTime >= 0 to evaluate timer, returns percentage of telekinesis process (100 or more to complete) -unsigned Player::processTelekinesis(int deltaTime, bool reset) -{ - if (reset) - { - m_telekinesisDelay = TELEKINESIS_DELAY; - return 0; - } - else - { - m_telekinesisDelay -= deltaTime; - return (unsigned)((float)(TELEKINESIS_DELAY - m_telekinesisDelay) / TELEKINESIS_DELAY * 10) * 10; - } -} - -Player::~Player() { - if (m_body) - delete m_body; - - if (m_arms) - delete m_arms; - - if (m_weapon) - delete m_weapon; - - clearVector (&m_shells); -} - -} +#ifdef _WIN32 +#define _USE_MATH_DEFINES +#endif //_WIN32W +#include "Player.h" +#include "../../system/utility/Templates.h" + +namespace violetland { + +Player::Player(float x, float y, Sprite *legsSprite, Sprite *deathSprite, + std::vector hitSounds, Sound* dyingSound) : + LifeForm(x, y, 128, 128) { + Id = "20-" + Id; + Xp = 0; + LastLevelXp = 0; + NextLevelXp = 100; + Kills = 0; + LevelPoints = 0; + ActionMode = PLAYER_ACT_MODE_FIRE; + AccuracyDeviation = 0.0f; + Grenades = 2; + Teleports = 1; + Acceleration = 0.0004f; + Type = LIFEFORM_PLAYER; + m_hitSndPlaying = 0; + m_walkTime = 0; + m_walkDelay = 0; + + m_weapon = NULL; + + m_light = m_laser = false; + + Unstoppable = PoisonBullets = BigCalibre = Telekinesis = NightVision + = Looting = WideSight = Magneto = false; + + for (int i = PLAYER_BONUS_FIRST; i < PLAYER_BONUS_COUNT; i++) + bonusTimes[i] = 0; + + processTelekinesis(0, true); + + TargetX = x; + TargetY = y; + + m_weapon = NULL; + m_arms = NULL; + m_body = new DynamicObject(x, y, legsSprite); + m_body->Frame = 8; + m_deathSprite = deathSprite; + m_hitSounds = hitSounds; + m_dyingSound = dyingSound; +} + +float Player::getStrength() const { + return Strength * ((bonusTimes[PLAYER_BONUS_STRENGTHBOOST] > 0) ? 1.2f + : 1.0f); +} + +float Player::getAgility() const { + return Agility + * ((bonusTimes[PLAYER_BONUS_AGILITYBOOST] > 0) ? 1.2f : 1.0f); +} + +float Player::getVitality() const { + return Vitality * ((bonusTimes[PLAYER_BONUS_VITALITYBOOST] > 0) ? 1.2f + : 1.0f); +} + +Sound* Player::hit(float damage, bool poison) { + LifeForm::hit(damage, poison); + + setMask(1.0f, 0.0f, 0.0f, 1.0f); + + if (!Unstoppable) + Speed = 0.0f; + + if (!m_hitSounds[m_hitSndPlaying]->isPlaying()) { + m_hitSndPlaying = (getHealth() < MaxHealth() ? getHealth() + : getHealth() - 0.01f) / MaxHealth() * m_hitSounds.size(); + return m_hitSounds[m_hitSndPlaying]; + } + + return NULL; +} + +std::vector* Player::fire() { + const float rad = (getArmsAngle() - 90) * M_PI / 180; + std::vector *newBullets = m_weapon->fire(m_arms->X, m_arms->Y, + m_arms->X + m_weapon->XDiff * cos(rad) + m_weapon->YDiff + * sin(-rad), m_arms->Y + m_weapon->XDiff * sin(rad) + + m_weapon->YDiff * cos(-rad)); + + if (!newBullets->empty()) { + std::vector::iterator it; + + if (AccuracyDeviation < 25) + AccuracyDeviation + += m_weapon->BulletsAtOnce > 1 ? m_weapon->ReturnForce + : m_weapon->ReturnForce * WeaponRetForceMod(); + + for (it = newBullets->begin(); it != (newBullets->end()); it++) { + Bullet* bullet = *(it); + bullet->Poisoned = m_weapon->Type == BULLET_STANDARD + && PoisonBullets; + bullet->BigCalibre = m_weapon->Type == BULLET_STANDARD + && BigCalibre; + if (BigCalibre) { + bullet->Damage *= 1.1f; + } + bullet->Penetrating = m_weapon->Type == BULLET_STANDARD + && bonusTimes[PLAYER_BONUS_PENBULLETS] > 0; + bullet->Angle = AccuracyDeviation < 1 ? m_arms->Angle + : m_arms->Angle + (rand() % (int) (AccuracyDeviation * 2)) + - AccuracyDeviation; + bullet->OwnerId = Id; + } + + if (m_weapon->BulletsAtOnce > 1) + AccuracyDeviation = 0; + + if (m_weapon->ShellSprite) + { + DynamicObject* shell = new DynamicObject(X, Y, m_weapon->ShellSprite); + shell->Angle = m_arms->Angle; + m_shells.push_back(shell); + } + } + + return newBullets; +} + +Bullet* Player::throwGrenade(Sprite* grenadeSprite) { + Bullet* newBullet = + new GrenadeBullet(X, Y, TargetX, TargetY, grenadeSprite); + + newBullet->Damage = 5.0f; + newBullet->Speed = MaxSpeed() * 5.0f; + newBullet->MaxRange = 1500; + + Grenades--; + + return newBullet; +} + +void Player::reload() { + if (m_weapon->reload(ReloadSpeedMod())) + AccuracyDeviation = 0; +} + +void Player::processState(int deltaTime) { + if (State == LIFEFORM_STATE_ALIVE) { + m_arms->X = m_body->X = X; + m_arms->Y = m_body->Y = Y; + m_body->Angle = Angle; + + if (Speed > MaxSpeed() / 4) { + m_body->rollFrame(true); + } else { + if (!(m_body->Frame == 8 || m_body->Frame == 20)) { + if ((m_body->Frame > 8 && m_body->Frame < 16) || m_body->Frame + > 20) + m_body->rollFrame(false); + else + m_body->rollFrame(true); + } + } + } + + if (State == LIFEFORM_STATE_DYING) { + if (m_body->Frame == m_body->AnimSprite->getFramesCount() - 1) + State = LIFEFORM_STATE_DIED; + + m_body->rollFrame(true); + } + + if (State == LIFEFORM_STATE_SMITTEN) { + const float angle = m_body->Angle; + delete m_body; + m_body = new DynamicObject(X, Y, m_deathSprite); + m_body->Angle = angle; + State = LIFEFORM_STATE_DYING; + if (m_hitSounds[m_hitSndPlaying]->isPlaying()) + m_hitSounds[m_hitSndPlaying]->stop(0); + + m_dyingSound->play(5, 0, 0); + } +} + +void Player::processArms(int deltaTime) { + m_arms->Angle = Object::calc_angle(X, Y, TargetX, TargetY); + m_weapon->process(deltaTime); + AccuracyDeviation -= deltaTime * 0.01f; + if (AccuracyDeviation < 0) + AccuracyDeviation = 0; + +} +void Player::process(int deltaTime) { + // Base processing + LifeForm::process(deltaTime); + + // State and animation + processState(deltaTime); + + // Hit animation + fadeColor(deltaTime); + + // Weapon and targeting + processArms(deltaTime); + + // Bonuses + processBonus(deltaTime); +} + +void Player::processBonus(int deltaTime) { + for (int i = PLAYER_BONUS_FIRST; i < PLAYER_BONUS_COUNT; i++) { + bonusTimes[i] -= deltaTime; + if (bonusTimes[i] < 0) + bonusTimes[i] = 0; + } +} + +void Player::fadeColor(int deltaTime) { + m_arms->setMask(RMask, GMask, BMask, AMask); + m_body->setMask(RMask, GMask, BMask, AMask); + if (RMask < 1.0f) + RMask += 0.01f; + if (GMask < 1.0f) + GMask += 0.01f; + if (BMask < 1.0f) + BMask += 0.01f; + if (AMask < 1.0f) + AMask += 0.01f; +} + +void Player::draw() { + m_body->draw(X, Y, Angle, Scale, RMask, GMask, BMask, AMask); + + if (State == LIFEFORM_STATE_ALIVE) + m_arms->draw(false, false); + + for (int i = m_shells.size() - 1; i >= 0; i--) { + m_shells[i]->draw(); + if (m_shells[i]->Frame == m_shells[i]->AnimSprite->getFramesCount() - 1) { + delete m_shells[i]; + m_shells .erase(m_shells.begin() + i); + continue; + } + m_shells[i]->rollFrame(true); + } +} + +StaticObject* Player::getCorpse() { + StaticObject * corpse = new StaticObject(X, Y, m_width, m_height, + m_body->getFrame(), false); + corpse->Scale = m_body->Scale; + corpse->Angle = Object::fixAngle(180 - m_body->Angle); + return corpse; +} + +void Player::setX(float value) { + X = m_arms->X = m_body->X = value; +} + +void Player::setY(float value) { + Y = m_arms->Y = m_body->Y = value; +} + +void Player::teleport() { + Teleports--; + setX(TargetX); + setY(TargetY); +} + +void Player::setWeapon(Weapon *value) { + float angle = 0; + if (m_weapon) { + angle = getArmsAngle(); + delete m_arms; + delete m_weapon; + } + m_weapon = new Weapon(*value); + m_arms = new StaticObject(X, Y, 128, 128, m_weapon->getPlayerTex(), false); + m_arms->Angle = angle; + AccuracyDeviation = 0; +} + +// Controls telekinesis ability +// Reset = true to reset timer (obvious!), deltaTime will be ignored, will return 0 +// Reset = false and deltaTime >= 0 to evaluate timer, returns percentage of telekinesis process (100 or more to complete) +unsigned Player::processTelekinesis(int deltaTime, bool reset) +{ + if (reset) + { + m_telekinesisDelay = TELEKINESIS_DELAY; + return 0; + } + else + { + m_telekinesisDelay -= deltaTime; + return (unsigned)((float)(TELEKINESIS_DELAY - m_telekinesisDelay) / TELEKINESIS_DELAY * 10) * 10; + } +} + +Player::~Player() { + if (m_body) + delete m_body; + + if (m_arms) + delete m_arms; + + if (m_weapon) + delete m_weapon; + + clearVector (&m_shells); +} + +} diff --git a/src/game/lifeforms/Player.h b/src/game/lifeforms/Player.h index 0dec2216..ecbb989d 100644 --- a/src/game/lifeforms/Player.h +++ b/src/game/lifeforms/Player.h @@ -1,103 +1,103 @@ -#ifndef PLAYER_H_ -#define PLAYER_H_ - -#include "LifeForm.h" -#include "../Weapon.h" - -namespace violetland { - -enum PlayerActionMode { - PLAYER_ACT_MODE_FIRE = 0, PLAYER_ACT_MODE_TELEPORT -}; - -enum PlayerBonusType { - PLAYER_BONUS_FIRST = 0, - PLAYER_BONUS_PENBULLETS = PLAYER_BONUS_FIRST, - PLAYER_BONUS_VITALITYBOOST, - PLAYER_BONUS_AGILITYBOOST, - PLAYER_BONUS_STRENGTHBOOST, - PLAYER_BONUS_FREEZE, - PLAYER_BONUS_COUNT -}; - -class Player: public LifeForm { -private: - static const unsigned TELEKINESIS_DELAY = 2000; - - Sprite *m_deathSprite; - StaticObject *m_arms; - std::vector m_shells; - std::vector m_hitSounds; - Sound* m_dyingSound; - Weapon *m_weapon; - bool m_light, m_laser; - int m_hitSndPlaying; - int m_telekinesisDelay; - - void processBonus(int deltaTime); - void processState(int deltaTime); - void processArms(int deltaTime); -public: - float AccuracyDeviation; - int LevelPoints; - int Xp; - int NextLevelXp; - int LastLevelXp; - int Kills; - int Grenades; - int Teleports; - - // Perks - - bool Unstoppable; - bool PoisonBullets; - bool BigCalibre; - bool Telekinesis; - bool Magneto; - bool NightVision; - bool Looting; - bool WideSight; - - // Fire with gun or use teleport - PlayerActionMode ActionMode; - - int bonusTimes[PLAYER_BONUS_COUNT]; - - Player(float x, float y, - Sprite *legsSprite, - Sprite *deathSprite, - std::vector hitSounds, - Sound* dyingSound); - virtual ~Player(); - - virtual void process(int deltaTime); - virtual void draw(); - virtual Sound* hit(float damage, bool poison); - - virtual float getStrength() const; - virtual float getAgility() const; - virtual float getVitality() const; - - void hit(); - void setX(float value); - void setY(float value); - const float getLegsAngle() const { return m_body->Angle; } - const float getArmsAngle() const { return m_arms->Angle; } - void setWeapon(Weapon *value); - const Weapon* getWeapon() const { return m_weapon; } - std::vector *fire(); - void reload(); - void toggleLight() { m_light = !m_light; } - const bool getLight() const { return m_light; } - void toggleLaser() { m_laser = !m_laser; } - const bool getLaser() const { return m_laser; } - Bullet* throwGrenade(Sprite* grenadeSprite); - virtual StaticObject* getCorpse(); - void teleport(); - void fadeColor(int deltaTime); - unsigned processTelekinesis(int deltaTime, bool reset); -}; - -} - -#endif /* PLAYER_H_ */ +#ifndef PLAYER_H_ +#define PLAYER_H_ + +#include "LifeForm.h" +#include "../Weapon.h" + +namespace violetland { + +enum PlayerActionMode { + PLAYER_ACT_MODE_FIRE = 0, PLAYER_ACT_MODE_TELEPORT +}; + +enum PlayerBonusType { + PLAYER_BONUS_FIRST = 0, + PLAYER_BONUS_PENBULLETS = PLAYER_BONUS_FIRST, + PLAYER_BONUS_VITALITYBOOST, + PLAYER_BONUS_AGILITYBOOST, + PLAYER_BONUS_STRENGTHBOOST, + PLAYER_BONUS_FREEZE, + PLAYER_BONUS_COUNT +}; + +class Player: public LifeForm { +private: + static const unsigned TELEKINESIS_DELAY = 2000; + + Sprite *m_deathSprite; + StaticObject *m_arms; + std::vector m_shells; + std::vector m_hitSounds; + Sound* m_dyingSound; + Weapon *m_weapon; + bool m_light, m_laser; + int m_hitSndPlaying; + int m_telekinesisDelay; + + void processBonus(int deltaTime); + void processState(int deltaTime); + void processArms(int deltaTime); +public: + float AccuracyDeviation; + int LevelPoints; + int Xp; + int NextLevelXp; + int LastLevelXp; + int Kills; + int Grenades; + int Teleports; + + // Perks + + bool Unstoppable; + bool PoisonBullets; + bool BigCalibre; + bool Telekinesis; + bool Magneto; + bool NightVision; + bool Looting; + bool WideSight; + + // Fire with gun or use teleport + PlayerActionMode ActionMode; + + int bonusTimes[PLAYER_BONUS_COUNT]; + + Player(float x, float y, + Sprite *legsSprite, + Sprite *deathSprite, + std::vector hitSounds, + Sound* dyingSound); + virtual ~Player(); + + virtual void process(int deltaTime); + virtual void draw(); + virtual Sound* hit(float damage, bool poison); + + virtual float getStrength() const; + virtual float getAgility() const; + virtual float getVitality() const; + + void hit(); + void setX(float value); + void setY(float value); + const float getLegsAngle() const { return m_body->Angle; } + const float getArmsAngle() const { return m_arms->Angle; } + void setWeapon(Weapon *value); + const Weapon* getWeapon() const { return m_weapon; } + std::vector *fire(); + void reload(); + void toggleLight() { m_light = !m_light; } + const bool getLight() const { return m_light; } + void toggleLaser() { m_laser = !m_laser; } + const bool getLaser() const { return m_laser; } + Bullet* throwGrenade(Sprite* grenadeSprite); + virtual StaticObject* getCorpse(); + void teleport(); + void fadeColor(int deltaTime); + unsigned processTelekinesis(int deltaTime, bool reset); +}; + +} + +#endif /* PLAYER_H_ */ diff --git a/src/program.cpp b/src/program.cpp index 9568f5bc..3e0cdc3a 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -1,2311 +1,2311 @@ -// MS Windows compatibility -#ifdef _WIN32 -#pragma comment(lib, "SDL") -#pragma comment(lib, "SDLmain") -#pragma comment(lib, "SDL_image") -#pragma comment(lib, "SDL_ttf") -#pragma comment(lib, "SDL_mixer") -#pragma comment(lib, "opengl32") -#pragma comment(lib, "libintl") -#define _USE_MATH_DEFINES -#include -#include -#include -#else -#include "pwd.h" -#endif - -#include - -// Apple Mac OS X compatibility -#ifdef __APPLE__ -#include "system/utility/macBundlePath.h" -#endif - -// SDL -#include "SDL.h" -#include "SDL_image.h" -#include "SDL_opengl.h" -#include "SDL_ttf.h" - -// Boost -#include -#include -#include - -//~ Internationalization Dependances -#include -#include -#define _(STRING) gettext(STRING) - -// The Game -#include "game/Game.h" -#include "system/Configuration.h" -#include "system/InputHandler.h" -#include "system/utility/ImageUtility.h" -#include "system/utility/FileUtility.h" -#include "system/graphic/text/TextManager.h" -#include "system/graphic/Texture.h" -#include "system/graphic/Aim.h" -#include "system/graphic/Camera.h" -#include "system/graphic/Particle.h" -#include "system/graphic/VideoManager.h" -#include "system/graphic/Explosion.h" -#include "system/sound/SoundManager.h" -#include "game/GameState.h" -#include "game/Powerup.h" -#include "game/Resources.h" -#include "game/lifeforms/MonsterFactory.h" -#include "game/lifeforms/Monster.h" -#include "game/lifeforms/Player.h" -#include "game/Terrain.h" -#include "game/MusicManager.h" -#include "game/WeaponManager.h" -#include "game/Highscores.h" -#include "game/HUD.h" -#include "windows/Window.h" -#include "windows/MainMenuWindow.h" -#include "windows/CharStatsWindow.h" - -using namespace std; -using namespace violetland; - -const string PROJECT = "violetland"; -const string VERSION = VIOLETLAND_VERSION; -const string DEFAULT_CHAR_NAME = "Violet"; - -Configuration* config; -Configuration* tempConfig; -VideoManager* videoManager; -Camera* cam; - -Aim* aim; -HUD* hud; -StaticObject* splash; - -FileUtility* fileUtility = NULL; -InputHandler* input; -SoundManager* sndManager; -Resources* resources; -MusicManager* musicManager; -WeaponManager* weaponManager; -MonsterFactory* monsterFactory; - -vector particleSystems; -vector bloodStains; -Terrain* terrain; - -GameState* gameState; -Game* game; -string playerId; - -map windows; - -GameMode gameMode; - -bool roulette(float eventProbability) { - return (float) (rand() % 100000) < eventProbability * 100000.0f; -} - -// Creation of clear squares of an earth surface -void createTerrain() { - if (terrain) - delete terrain; - - cout << "Forming terrain..." << endl; - - boost::filesystem::path tilesDir = fileUtility->getFullPath( - FileUtility::image, "terrain"); - unsigned baseTex = rand() % fileUtility->getFilesCountFromDir(tilesDir); - - ostringstream oss; - oss << baseTex; - unsigned tilesCount = fileUtility->getFilesCountFromDir( - boost::filesystem::path(tilesDir) /= oss.str()); - - oss.str(""); - oss << "base_" << baseTex << ".png"; - SDL_Surface *terrainSurface = ImageUtility::loadImage( - boost::filesystem::path(tilesDir) /= oss.str()); - - vector tiles; - for (unsigned i = 0; i < tilesCount; i++) { - oss.str(""); - oss << baseTex << '/' << i << ".png"; - SDL_Surface *tile = ImageUtility::loadImage( - boost::filesystem::path(tilesDir) /= oss.str()); - tiles.push_back(tile); - } - - terrain = new Terrain(terrainSurface, tiles, gameState->GameAreaSize); - - SDL_FreeSurface(terrainSurface); - for (unsigned int i = 0; i < tilesCount; i++) { - SDL_FreeSurface(tiles[i]); - } - tiles.clear(); -} - -// Creation of a new monster -void spawnEnemy(float x, float y, float r, int baseLvl, int lvl) { - float spawnAngle = (rand() % 6300) / 1000.0f; - - Monster* newMonster = monsterFactory->create(baseLvl, lvl); - - newMonster->X = x + r * cos(spawnAngle); - newMonster->Y = y + r * sin(spawnAngle); - - switch (gameState->Mode) { - case GAMEMODE_SURVIVAL: - case GAMEMODE_WAVES: - LifeForm* player = gameState->getLifeForm(playerId); - - newMonster->TargetX = player->X; - newMonster->TargetY = player->Y; - break; - } - - gameState->lifeForms.insert( - map::value_type(newMonster->Id, newMonster)); -} - -// Start the game in selected mode -void startGame(std::string elementName) { - cam->setW(1600); - - hud->reset(); - - // TODO: encapsulate the aim in the HUD - if (aim) - delete aim; - aim = new Aim(config); - - glClear(GL_COLOR_BUFFER_BIT); - - cam->X = cam->Y = 0.0f; - - cam->applyGLOrtho(); - - splash->draw(false, false); - - videoManager->RegularText->draw(_("Please wait..."), 0, 0, - TextManager::CENTER, TextManager::MIDDLE); - - SDL_GL_SwapBuffers(); - - gameState->start(gameMode); - - clearVector (&bloodStains); - clearVector (&particleSystems); - - Player* player = new Player( - 0, - 0, - resources->PlayerWalkSprite, - resources->PlayerDeathSprites[(rand() - % (int) resources->PlayerDeathSprites.size())], - resources->PlayerHitSounds, resources->PlayerDeathSound); - - // TODO: add "default weapon" parameter to config file - player->setWeapon(weaponManager->getWeaponByName("PM")); - player->HitR = 0.28f; - - gameState->lifeForms.insert( - map::value_type(player->Id, player)); - - playerId = player->Id; - - createTerrain(); - - SDL_ShowCursor(0); - - for (unsigned int i = 0; i < config->MonstersAtStart; i++) { - spawnEnemy(0, 0, (float) cam->getW(), 1, 1); - } - - windows["mainmenu"]->CloseFlag = true; - - hud->addMessage(_("Try to survive as long as you can.")); - hud->addMessage( - _("Shoot monsters to receive experience and other bonuses.")); -} - -// Creation of a string for the window title -inline string getProjectTitle() { - return PROJECT + " v" + VERSION; -} - -// Outputs the inboost::formation on the program and the runtime environment -void printVersion() { - string env = "UNKNOWN"; -#ifdef _WIN32 - env = "WINDOWS"; -#endif //_WIN32W -#ifdef __linux__ - env = "GNU/LINUX"; -#endif //__linux__ -#ifdef __FreeBSD__ - env = "BSD"; -#endif //__FreeBSD__ -#ifdef __APPLE__ - env = "MAC"; -#endif //__APPLE__ - cout << getProjectTitle() << " @ " << env << endl; -} - -string getDefaultName() { -#ifdef _WIN32 - return DEFAULT_CHAR_NAME; -#else - - // Try to read username from system environment - char* user = getenv("USER"); - - // `user' can be null if `USER' environment property not found - // - // @see http://linux.die.net/man/3/getenv - // @see https://github.com/ooxi/violetland/issues/71 - if (!user) { - return DEFAULT_CHAR_NAME; - } - - string name = user; - if (name.empty()) { - struct passwd *p; - uid_t uid; - - uid = geteuid(); - if ((p = getpwuid(uid))) - name = p->pw_name; - - if (name.empty()) { - return DEFAULT_CHAR_NAME; - } - } - - return name; -#endif -} - -void initInternationlization() { - //~ - //~ Internationalization Initialization - //~ - - //~ i18n: initializes the entire current locale of the program as per environment variables set by the user - setlocale(LC_ALL, ""); - - //~ i18n: Indicate the path of the i18n catalog file - bindtextdomain("violetland", LOCALE_DIR); - - //~ i18n: sets the message domain - textdomain("violetland"); - - InputHandler::initEventNames(); -} - -// Creation of system objects and their customization -void initSystem() { - std::cout << (boost::format(_("Name found : %s")) % getDefaultName()) - << std::endl; - - initInternationlization(); - - srand((unsigned) time(NULL)); - - TTF_Init(); - atexit(TTF_Quit); - atexit(SDL_Quit); - - cout << "SDL_Init..." << endl; - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { - cerr << "Couldn't initialize SDL: " << SDL_GetError() << endl; - exit(1); - } - - videoManager = new VideoManager(fileUtility); - - cam = new Camera(); - videoManager->setMode(config->Screen, cam); - - cout << _("Preparing window...") << endl; - - SDL_WM_SetCaption(getProjectTitle().c_str(), NULL); - - SDL_Surface* icon = ImageUtility::loadImage( - fileUtility->getFullPath(FileUtility::common, "icon-light.png")); - SDL_WM_SetIcon(icon, NULL); - SDL_FreeSurface(icon); - - SDL_EnableUNICODE(1); - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glEnable(GL_COLOR_MATERIAL); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glEnable(GL_TEXTURE_2D); - - glDisable(GL_DEPTH_TEST); - - cout << _("Drawing splash screen...") << endl; - - ostringstream oss; - oss << "splash_" << rand() % 2 << ".png"; - Texture* tex = new Texture( - ImageUtility::loadImage( - fileUtility->getFullPath(FileUtility::image, oss.str())), - GL_TEXTURE_2D, GL_LINEAR, true); - - splash = new StaticObject(0, 0, tex->getWidth(), tex->getHeight(), tex, - true); - - glClear(GL_COLOR_BUFFER_BIT); - - cam->X = cam->Y = 0.0f; - - cam->applyGLOrtho(); - - splash->draw(false, false); - - videoManager->RegularText->draw(_("Please wait..."), 0, 0, - TextManager::CENTER, TextManager::MIDDLE); - - SDL_GL_SwapBuffers(); - - cout << _("Preparing sound systems...") << endl; - - sndManager = new SoundManager(fileUtility, config); - musicManager = new MusicManager(fileUtility, sndManager, config); - - musicManager->play(); - - GLfloat lightColor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; - - // flashlight - glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor); - glLightfv(GL_LIGHT0, GL_AMBIENT, lightColor); - glLightfv(GL_LIGHT0, GL_SPECULAR, lightColor); - glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.6f); - glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0001f); - - GLfloat nvColor[] = { 0.3f, 1.0f, 0.3f, 1.0f }; - - // night vision perk - glLightfv(GL_LIGHT1, GL_DIFFUSE, nvColor); - glLightfv(GL_LIGHT1, GL_AMBIENT, nvColor); - glLightfv(GL_LIGHT1, GL_SPECULAR, nvColor); - glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 0.5f); - glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.00001f); - - glEnable(GL_LINE_SMOOTH); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - - input = new InputHandler(config->PlayerInputBinding); - - gameState = new GameState(); - game = new Game(input, hud, config, gameState, resources, particleSystems); -} - -void loseGame(Player* player) { - gameState->Lost = true; - - hud->addMessage(_("You are gobbled up.")); - - Highscores s(fileUtility); - gameState->HighScore = s.isHighscore(player->Xp); - - if (gameState->HighScore) { - gameState->PlayerName = getDefaultName(); - input->setInputModeText(true, gameState->PlayerName); - } - - SDL_ShowCursor(1); -} - -// Switches a pause mode -void switchGamePause() { - gameState->Paused = !gameState->Paused; - if (gameState->Paused) - SDL_ShowCursor(1); - else - SDL_ShowCursor(0); -} - -void refreshCharStatsWindow() { - CharStatsWindow* charStats = - (CharStatsWindow*) windows.find("charstats")->second; - charStats->refresh(); -} - -void createCharStatWindow() { - CharStatsWindow *charStats = new CharStatsWindow(config, videoManager, - (Player*) gameState->getLifeForm(playerId)); - windows["charstats"] = charStats; -} - -void shutdownSystem() { - clearVector (&particleSystems); - clearVector (&bloodStains); - - delete terrain; - delete videoManager; - delete gameState; - delete musicManager; - delete sndManager; - delete input; - delete fileUtility; - delete splash; -} - -void backFromOptionsAndSave(std::string elementName); - -void refreshOptionsWindow() { - const int l = videoManager->getVideoMode().Width * 0.1f; - const int r = videoManager->getVideoMode().Width * 0.6f; - const int h = videoManager->RegularText->getHeight(); - - Window* w = windows.find("options")->second; - - if (config->AutoReload) - w->addElement("+autoreload", "+", videoManager->RegularText, l, 6 * h, - TextManager::LEFT, TextManager::MIDDLE); - else - w->removeElement("+autoreload", false); - - if (config->AutoWeaponPickup) - w->addElement("+autopickup", "+", videoManager->RegularText, l, 7 * h, - TextManager::LEFT, TextManager::MIDDLE); - else - w->removeElement("+autopickup", false); - - if (config->FriendlyFire) - w->addElement("+friendlyfire", "+", videoManager->RegularText, l, - 8 * h, TextManager::LEFT, TextManager::MIDDLE); - else - w->removeElement("+friendlyfire", false); - - if (config->Screen.Full) - w->addElement("+fullscreen", "+", videoManager->RegularText, r, 6 * h, - TextManager::LEFT, TextManager::MIDDLE); - else - w->removeElement("+fullscreen", false); - - ostringstream oss; - oss << tempConfig->Screen.Width << 'x' << tempConfig->Screen.Height; - w->addElement("+resolution", oss.str(), videoManager->RegularText, - r + 8 * h, 7 * h, TextManager::LEFT, TextManager::MIDDLE); - - oss.str(""); - oss << config->SoundVolume * 10 << '%'; - w->addElement("+soundvolume", oss.str(), videoManager->RegularText, l, - 12 * h, TextManager::LEFT, TextManager::MIDDLE); - - oss.str(""); - oss << config->MusicVolume * 10 << '%'; - w->addElement("+musicvolume", oss.str(), videoManager->RegularText, l, - 13 * h, TextManager::LEFT, TextManager::MIDDLE); -} - -void switchGameOption(std::string elementName) { - map m; - m["autoreload"] = &config->AutoReload; - m["autopickup"] = &config->AutoWeaponPickup; - m["friendlyfire"] = &config->FriendlyFire; - m["fullscreen"] = &config->Screen.Full; - - map::iterator it = m.find(elementName); - if (it != m.end()) { - *it->second = !*it->second; - refreshOptionsWindow(); - } -} - -void switchVolumeDown(std::string elementName) { - if (elementName == "musicvolume") { - if (config->MusicVolume > 0) { - config->MusicVolume--; - Mix_VolumeMusic(config->MusicVolume * 12); - } else { - config->MusicVolume = 10; - Mix_VolumeMusic(config->MusicVolume * 12); - } - } else if (elementName == "soundvolume") { - if (config->SoundVolume > 0) { - config->SoundVolume--; - for (unsigned int a = 1; a <= 8; a++) { - Mix_Volume(a, config->SoundVolume * 12); - } - } else { - config->SoundVolume = 10; - for (unsigned int a = 1; a <= 8; a++) { - Mix_Volume(a, config->SoundVolume * 12); - } - } - } else - return; - - refreshOptionsWindow(); -} - -void switchVolumeUp(std::string elementName) { - if (elementName == "musicvolume") { - if (config->MusicVolume <= 9) { - config->MusicVolume++; - Mix_VolumeMusic(config->MusicVolume * 12); - } else { - config->MusicVolume = 0; - Mix_VolumeMusic(0); - } - } else if (elementName == "soundvolume") { - if (config->SoundVolume <= 9) { - config->SoundVolume++; - for (unsigned int a = 1; a <= 8; a++) { - Mix_Volume(a, config->SoundVolume * 12); - } - } else { - config->SoundVolume = 0; - for (unsigned int a = 1; a <= 8; a++) { - Mix_Volume(a, 0); - } - } - } else - return; - - refreshOptionsWindow(); -} - -void switchResolutionDown(std::string elementName) { - vector modes = videoManager->GetAvailableModes(); - - bool set = false; - for (int i = modes.size() - 1; i > 0; i--) { - if (tempConfig->Screen.Width == modes[i].w && tempConfig->Screen.Height - == modes[i].h) { - tempConfig->Screen.Width = modes[i - 1].w; - tempConfig->Screen.Height = modes[i - 1].h; - set = true; - break; - } - } - if (!set) { - tempConfig->Screen.Width = modes[modes.size() - 1].w; - tempConfig->Screen.Height = modes[modes.size() - 1].h; - } - - refreshOptionsWindow(); -} - -void switchResolutionUp(std::string elementName) { - vector modes = videoManager->GetAvailableModes(); - - bool set = false; - for (unsigned int i = 0; i < modes.size() - 1; i++) { - if (tempConfig->Screen.Width == modes[i].w && tempConfig->Screen.Height - == modes[i].h) { - tempConfig->Screen.Width = modes[i + 1].w; - tempConfig->Screen.Height = modes[i + 1].h; - set = true; - break; - } - } - if (!set) { - tempConfig->Screen.Width = modes[0].w; - tempConfig->Screen.Height = modes[0].h; - } - - refreshOptionsWindow(); -} - -void refreshControlsMenuWindow(); - -void changeControlStyle(std::string elementName) { - enum ControlStyle style = GetNextControlStyle(config->Control); - config->Control = style; - - std::cout << (boost::format(_("Changed control style to %s.")) % ControlStyleToString(style)) << std::endl; - config->write(); - - refreshControlsMenuWindow(); -} - -void controlsMenuWindowController(std::string elementName); - -inline void addControlElement(Window* w, unsigned i, unsigned strN, - unsigned lx, unsigned rx) { - unsigned y = videoManager->RegularText->getHeight() * strN; - string eventId = InputHandler::getEventIdentifier(i); - string eventName = InputHandler::getEventName(i); - string keyName = InputHandler::getKeyName(config->PlayerInputBinding[i]); - - w->addElement(eventId, eventName, videoManager->RegularText, lx, y, - TextManager::LEFT, TextManager::MIDDLE); - - w->addElement(eventId + "key", keyName, videoManager->RegularText, rx, y, - TextManager::RIGHT, TextManager::MIDDLE); - - w->addHandler(Window::hdl_lclick, eventId, boost::bind(&controlsMenuWindowController, _1)); -} - -void refreshControlsMenuWindow() { - Window* w = windows.find("controls")->second; - - const int col1_l = videoManager->getVideoMode().Width * 0.1f; - const int col1_r = videoManager->getVideoMode().Width * 0.45f; - - w->addElement("controls", _("Controls"), videoManager->RegularText, - col1_l, videoManager->RegularText->getHeight() * 2.0f, - TextManager::LEFT, TextManager::MIDDLE - ); - const int col2_l = videoManager->getVideoMode().Width * 0.55f; - const int col2_r = videoManager->getVideoMode().Width * 0.9f; - - - /* Change the control style - */ - w->addElement("control-style", _("Control style"), - videoManager->RegularText, - col1_l, (videoManager->RegularText->getHeight() + 35) * 2.0f, - TextManager::LEFT, TextManager::MIDDLE - ); - w->addElement("control-style-value", ControlStyleToString(config->Control), - videoManager->RegularText, - col1_r, (videoManager->RegularText->getHeight() + 35) * 2.0f, - TextManager::RIGHT, TextManager::MIDDLE - ); - w->addHandler(Window::hdl_lclick, "control-style", boost::bind(changeControlStyle, _1)); - - - unsigned col1_items = (InputHandler::GameInputEventsCount + 1) / 2; - - for (unsigned i = 0; i < col1_items; i++) - addControlElement(w, i, i + 6, col1_l, col1_r); - - for (unsigned i = col1_items; i < InputHandler::GameInputEventsCount; i++) - addControlElement(w, i, i - col1_items + 6, col2_l, col2_r); -} - -void drawWindows() { - if (!windows.empty()) { - std::map::iterator win, victim; - for (win = windows.begin(); win != windows.end(); ++win) { - Window* w = win->second; - w->draw(); - w->process(input); - } - win = windows.begin(); - while (win != windows.end()) { - if (win->second->CloseFlag) { - victim = win++; - windows.erase(victim); - } else { - win++; - } - } - } -} - -void controlsMenuWindowController(std::string elementName) { - Window *w = new Window(0.0f, 0.0f, config->Screen.Width, - config->Screen.Height, 0.0f, 0.0f, 0.0f, 0.5f); - - w->addElement("pressakey", _("Press a key, please..."), - videoManager->RegularText, config->Screen.Width / 2, - config->Screen.Height / 2, TextManager::CENTER, TextManager::MIDDLE); - - windows["pressakey"] = w; - - drawWindows(); - SDL_GL_SwapBuffers(); - - int key = InputHandler::getEventNumber(elementName); - - input->resetMouseButtons(); - - SDL_Event sdlEvent; - - bool ok = false; - while (!ok) { - SDL_WaitEvent(&sdlEvent); - - switch (sdlEvent.type) { - case SDL_KEYDOWN: - config->PlayerInputBinding[key].Type = InputHandler::Keyboard; - config->PlayerInputBinding[key].Value = sdlEvent.key.keysym.sym; - ok = true; - break; - case SDL_MOUSEBUTTONDOWN: - config->PlayerInputBinding[key].Type = InputHandler::Mouse; - config->PlayerInputBinding[key].Value = sdlEvent.button.button; - ok = true; - break; - case SDL_QUIT: - ok = true; - gameState->end(); - break; - } - } - - cout << (boost::format(_("Bind action %s to key %s.")) % elementName - % InputHandler::getKeyName(config->PlayerInputBinding[key])) - << endl; - - config->write(); - - windows["pressakey"]->CloseFlag = true; - - refreshControlsMenuWindow(); -} - -void drawWindows(); -void showHighScores(std::string); - -void createControlsMenuWindow(std::string elementName) { - Window *w = new Window(0.0f, 0.0f, config->Screen.Width, - config->Screen.Height, 0.0f, 0.0f, 0.0f, 0.5f); - - windows["controls"] = w; - - refreshControlsMenuWindow(); - - windows["options"]->CloseFlag = true; -} - -void resetControls(std::string elementName) { - Configuration* config_default = new Configuration(fileUtility); - for (int i = 0; i < InputHandler::GameInputEventsCount; i++) - config->PlayerInputBinding[i] = config_default->PlayerInputBinding[i]; -} - -void createOptionsWindow() { - tempConfig = new Configuration(*config); - - Window *w = new Window(0.0f, 0.0f, config->Screen.Width, - config->Screen.Height, 0.0f, 0.0f, 0.0f, 0.5f); - - const int l = videoManager->getVideoMode().Width * 0.1f; - const int r = videoManager->getVideoMode().Width * 0.6f; - const int h = videoManager->RegularText->getHeight(); - - w->addElement("options", _("Options"), videoManager->RegularText, l, 2 * h, - TextManager::LEFT, TextManager::MIDDLE); - - vector