Browse Source

Make this repository a submodule of a superbuild repository. And countless changes and updates to the game, including converting gameplay code to ECS-based

master
C. J. Howard 5 years ago
parent
commit
7410a2ea85
Signed by: cjhoward GPG Key ID: 03E1FABA9C3EC195
180 changed files with 25375 additions and 10840 deletions
  1. +10
    -0
      .gitignore
  2. +0
    -12
      .gitmodules
  3. +46
    -0
      CMakeLists.txt
  4. +674
    -674
      COPYING
  5. +18
    -64
      README.md
  6. +0
    -3
      bin/.gitignore
  7. +0
    -3
      build/linux32/.gitignore
  8. +0
    -3
      build/linux64/.gitignore
  9. +0
    -3
      build/win32/.gitignore
  10. +0
    -3
      build/win64/.gitignore
  11. +1
    -0
      cmake/project.cmake
  12. +0
    -1
      data
  13. +0
    -3
      dist/.gitignore
  14. +0
    -1
      lib/SDL2
  15. +0
    -1
      lib/dirent
  16. +0
    -1
      lib/emergent
  17. +0
    -429
      src/application.hpp
  18. +9
    -65
      src/configuration.hpp.in
  19. +0
    -134
      src/controls.hpp
  20. +0
    -80
      src/debug.cpp
  21. +2
    -0
      src/dr_libs/dr_wav.cpp
  22. +4377
    -0
      src/dr_libs/dr_wav.h
  23. +81
    -0
      src/entity/component-manager.cpp
  24. +116
    -0
      src/entity/component-manager.hpp
  25. +9
    -10
      src/entity/component-observer.cpp
  26. +69
    -0
      src/entity/component-observer.hpp
  27. +77
    -0
      src/entity/component.hpp
  28. +13
    -19
      src/entity/components/animation-component.hpp
  29. +27
    -0
      src/entity/components/ant-hill-component.cpp
  30. +36
    -0
      src/entity/components/ant-hill-component.hpp
  31. +29
    -0
      src/entity/components/behavior-component.cpp
  32. +41
    -0
      src/entity/components/behavior-component.hpp
  33. +30
    -0
      src/entity/components/collision-component.cpp
  34. +13
    -17
      src/entity/components/collision-component.hpp
  35. +38
    -0
      src/entity/components/component-type.hpp
  36. +34
    -0
      src/entity/components/legged-locomotion-component.cpp
  37. +45
    -0
      src/entity/components/legged-locomotion-component.hpp
  38. +29
    -0
      src/entity/components/model-component.cpp
  39. +37
    -0
      src/entity/components/model-component.hpp
  40. +28
    -0
      src/entity/components/sound-source-component.cpp
  41. +39
    -0
      src/entity/components/sound-source-component.hpp
  42. +27
    -0
      src/entity/components/steering-component.cpp
  43. +56
    -0
      src/entity/components/steering-component.hpp
  44. +29
    -0
      src/entity/components/tool-component.cpp
  45. +10
    -14
      src/entity/components/tool-component.hpp
  46. +28
    -0
      src/entity/components/transform-component.cpp
  47. +38
    -0
      src/entity/components/transform-component.hpp
  48. +43
    -0
      src/entity/entity-group-member.hpp
  49. +52
    -0
      src/entity/entity-group-observer.hpp
  50. +59
    -0
      src/entity/entity-group.cpp
  51. +268
    -0
      src/entity/entity-group.hpp
  52. +68
    -0
      src/entity/entity-id-pool.cpp
  53. +87
    -0
      src/entity/entity-id-pool.hpp
  54. +28
    -0
      src/entity/entity-id.hpp
  55. +69
    -0
      src/entity/entity-manager.cpp
  56. +97
    -0
      src/entity/entity-manager.hpp
  57. +54
    -0
      src/entity/entity-template.cpp
  58. +60
    -0
      src/entity/entity-template.hpp
  59. +45
    -0
      src/entity/system-manager.cpp
  60. +68
    -0
      src/entity/system-manager.hpp
  61. +4
    -6
      src/entity/system.cpp
  62. +28
    -20
      src/entity/system.hpp
  63. +48
    -0
      src/entity/systems/animation-system.cpp
  64. +46
    -0
      src/entity/systems/animation-system.hpp
  65. +181
    -0
      src/entity/systems/behavior-system.cpp
  66. +61
    -0
      src/entity/systems/behavior-system.hpp
  67. +65
    -0
      src/entity/systems/collision-system.cpp
  68. +46
    -0
      src/entity/systems/collision-system.hpp
  69. +107
    -0
      src/entity/systems/locomotion-system.cpp
  70. +52
    -0
      src/entity/systems/locomotion-system.hpp
  71. +161
    -0
      src/entity/systems/particle-system.cpp
  72. +86
    -0
      src/entity/systems/particle-system.hpp
  73. +56
    -0
      src/entity/systems/render-system.cpp
  74. +55
    -0
      src/entity/systems/render-system.hpp
  75. +119
    -0
      src/entity/systems/sound-system.cpp
  76. +56
    -0
      src/entity/systems/sound-system.hpp
  77. +96
    -0
      src/entity/systems/steering-system.cpp
  78. +53
    -0
      src/entity/systems/steering-system.hpp
  79. +96
    -0
      src/entity/systems/tool-system.cpp
  80. +66
    -0
      src/entity/systems/tool-system.hpp
  81. +1719
    -0
      src/game.cpp
  82. +404
    -0
      src/game.hpp
  83. +0
    -222
      src/game/agent.cpp
  84. +0
    -216
      src/game/agent.hpp
  85. +0
    -293
      src/game/ant.cpp
  86. +0
    -155
      src/game/ant.hpp
  87. +0
    -42
      src/game/biome.hpp
  88. +168
    -0
      src/game/brush.cpp
  89. +67
    -0
      src/game/brush.hpp
  90. +2
    -2
      src/game/camera-rig.cpp
  91. +2
    -2
      src/game/camera-rig.hpp
  92. +0
    -106
      src/game/colony.cpp
  93. +0
    -146
      src/game/colony.hpp
  94. +40
    -0
      src/game/curl-noise.cpp
  95. +28
    -0
      src/game/curl-noise.hpp
  96. +396
    -0
      src/game/forceps.cpp
  97. +95
    -0
      src/game/forceps.hpp
  98. +176
    -0
      src/game/lens.cpp
  99. +96
    -0
      src/game/lens.hpp
  100. +0
    -149
      src/game/level.cpp

+ 10
- 0
.gitignore View File

@ -1,3 +1,12 @@
<<<<<<< HEAD
CMakeFiles
cmake_install.cmake
CMakeCache.txt
Makefile
bin
dist
tags
=======
CMakeFiles
CMakeCache.txt
cmake_install.cmake
@ -6,3 +15,4 @@ src/configuration.hpp
.DS_Store
*.swo
*.swp
>>>>>>> df8405f4e83febb81a5ce8f772bd7f5b9e9b6036

+ 0
- 12
.gitmodules View File

@ -1,12 +0,0 @@
[submodule "emergent"]
path = lib/emergent
url = https://github.com/cjhoward/emergent.git
[submodule "lib/SDL2"]
path = lib/SDL2
url = https://github.com/cjhoward/SDL2.git
[submodule "data"]
path = data
url = https://gitlab.com/cjhoward/antkeeper-data.git
[submodule "lib/dirent"]
path = lib/dirent
url = https://github.com/cjhoward/dirent.git

+ 46
- 0
CMakeLists.txt View File

@ -1,3 +1,48 @@
<<<<<<< HEAD
cmake_minimum_required(VERSION 3.7)
# Set compiler flags
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g -O3 -DDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
# Include project macro
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/project.cmake)
# Find dependency packages
find_package(emergent REQUIRED CONFIG)
find_package(OpenAL REQUIRED CONFIG)
# Determine dependencies
set(STATIC_LIBS
emergent
OpenAL::OpenAL)
# Generate configuration header file
configure_file(${PROJECT_SOURCE_DIR}/src/configuration.hpp.in
${PROJECT_BINARY_DIR}/src/configuration.hpp)
# Collect source files
file(GLOB_RECURSE SOURCE_FILES
${PROJECT_SOURCE_DIR}/src/*.cpp)
# Add executable target
set(EXECUTABLE_TARGET ${PROJECT_NAME}-executable)
add_executable(${EXECUTABLE_TARGET} ${SOURCE_FILES})
set_target_properties(${EXECUTABLE_TARGET} PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
# Set include directories
target_include_directories(${EXECUTABLE_TARGET}
PUBLIC
${PROJECT_SOURCE_DIR}/src
${PROJECT_BINARY_DIR}/src)
# Link to dependencies
target_link_libraries(${EXECUTABLE_TARGET} ${STATIC_LIBS})
# Install executable
install(TARGETS ${EXECUTABLE_TARGET} DESTINATION bin)
=======
cmake_minimum_required(VERSION 3.7)
project(antkeeper
VERSION "0.0.0"
@ -372,3 +417,4 @@ elseif(${PLATFORM} STREQUAL "linux32" OR ${PLATFORM} STREQUAL "linux64")
endif()
include(CPack)
>>>>>>> df8405f4e83febb81a5ce8f772bd7f5b9e9b6036

+ 674
- 674
COPYING
File diff suppressed because it is too large
View File


+ 18
- 64
README.md View File

@ -1,64 +1,18 @@
# Antkeeper
Antkeeper is an ant colony simulation game. This repository contains all of the source code to Antkeeper. The game data, however, is proprietary and resides in a closed-source Git submodule.
## Download
Use Git to download the `antkeeper` repository and its submodules:
git clone --recursive https://github.com/cjhoward/antkeeper.git antkeeper
## Configuration & Building
CMake is required to configure and build the application. Depending on the target build platform, CMake should be invoked from one of the following directories:
build/linux32 // 32-bit GNU/Linux application
build/linux64 // 64-bit GNU/Linux application
build/win32 // 32-bit Windows application
build/win64 // 64-bit Windows application
The following arguments may be passed to CMake during configuration:
-DCMAKE_BUILD_TYPE // [Debug, Release]
-DLANGUAGE // [en-us, zh-cn]
-DSTANDALONE // [OFF, ON]
### GNU/Linux
Building on GNU/Linux requires CMake, GCC, G++, and GNU Make. Open a terminal in the project root directory and run the following commands:
cd build/linux64
cmake ../.. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=...
cmake --build .
### Windows
Building on Windows requires CMake and Visual Studio 2017. Additionally, [NSIS](http://nsis.sourceforge.net/) is required if you want to build a distributable installer program. In order to correctly build for your target architecture, you must use the `x86 Native Tools Command Prompt` or the `x64 Native Tools Command Prompt` for 32-bit and 64-bit applications, respectively. Then navigate to the project root directory and run the following commands:
cd build\win64
cmake ..\.. -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=...
cmake --build .
## Testing
After building, a standalone version of the application will be located somewhere in the `bin` directory according to the build type, build platform, and version string. This application can be executed with the following command:
cmake --build . --target run
## Distribution
The built application can be packaged into a distributable format with the following command:
cmake --build . --target package
The resulting package will be located in the `dist` directory.
## Contributing
If any changes have been made to the submodules, commit those first. Each submodule can then be updated to their latest commits with the following command:
git submodule update --recursive --remote
## License
The source code for Antkeeper is licensed under the GNU General Public License, version 3. See [COPYING](./COPYING) for details.
# Antkeeper Source &middot; [![GitHub license](https://img.shields.io/github/license/cjhoward/antkeeper.svg)](https://github.com/cjhoward/antkeeper/blob/master/COPYING) [![GitHub release](https://img.shields.io/github/release/cjhoward/antkeeper.svg)](https://github.com/cjhoward/antkeeper/releases/)
Antkeeper is an ant colony simulation game for Windows, Mac OS X, and GNU/Linux. This repository contains all of the source code to Antkeeper. The game data, however, is proprietary. You can access the game data by purchasing a copy of Antkeeper at [https://antkeeper.com/]().
## License
The source code for Antkeeper is licensed under the GNU General Public License, version 3. See [`COPYING`](./COPYING) for details.
### 3rd-Party Software
| Name | Author(s) | License | Files |
| :--------------- | :----------- | :-------------------------- | :---- |
| dr_wav | David Reid | Public Domain | [`dr_wav.h`](./src/dr_libs/dr_wav.h) |
| Emergent | C. J. Howard | GNU GPL v3.0 | |
| OpenAL soft | | GNU GPL v2.0 | |
| stb_image | Sean Barrett | Public Domain / MIT License | [`stb_image.h`](./src/stb/stb_image.h) |
| stb_image_writer | Sean Barrett | Public Domain / MIT License | [`stb_image_writer.h`](./src/stb/stb_image_writer.h) |

+ 0
- 3
bin/.gitignore View File

@ -1,3 +0,0 @@
*
*/*
!.gitignore

+ 0
- 3
build/linux32/.gitignore View File

@ -1,3 +0,0 @@
*
*/*
!.gitignore

+ 0
- 3
build/linux64/.gitignore View File

@ -1,3 +0,0 @@
*
*/*
!.gitignore

+ 0
- 3
build/win32/.gitignore View File

@ -1,3 +0,0 @@
*
*/*
!.gitignore

+ 0
- 3
build/win64/.gitignore View File

@ -1,3 +0,0 @@
*
*/*
!.gitignore

+ 1
- 0
cmake/project.cmake View File

@ -0,0 +1 @@
project(antkeeper VERSION "0.0.0")

+ 0
- 1
data

@ -1 +0,0 @@
Subproject commit 0ed0baf703fdc72c524d8c779c3ae2d92402d041

+ 0
- 3
dist/.gitignore View File

@ -1,3 +0,0 @@
*
*/*
!.gitignore

+ 0
- 1
lib/SDL2

@ -1 +0,0 @@
Subproject commit 6f6d0abad18a8a1bb8131d2676a4ed6e606b1ccf

+ 0
- 1
lib/dirent

@ -1 +0,0 @@
Subproject commit c652395f771a76796d2308a938cf6ce371c10d4a

+ 0
- 1
lib/emergent

@ -1 +0,0 @@
Subproject commit 16405a4181a39cff79b57b4c9c2389c31a136794

+ 0
- 429
src/application.hpp View File

@ -1,429 +0,0 @@
/*
* Copyright (C) 2017 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef APPLICATION_HPP
#define APPLICATION_HPP
#include <emergent/emergent.hpp>
using namespace Emergent;
#include "mesh.hpp"
#include "game/terrain.hpp"
#include "game/level.hpp"
#include "game/biome.hpp"
#include "game/terrain.hpp"
#include "input.hpp"
#include "controls.hpp"
#include "settings.hpp"
#include "render-passes.hpp"
#include "ui/ui.hpp"
#include "ui/tween.hpp"
class Menu;
class MenuItem;
class ApplicationState;
class Colony;
class LoadingState;
class SplashState;
class TitleState;
class GameState;
class CameraRig;
class OrbitCam;
class FreeCam;
class LineBatcher;
class ModelLoader;
class MaterialLoader;
class Toolbar;
class PieMenu;
class Tool;
class Forceps;
class Lens;
class Brush;
/**
* Encapsulates the state of the application.
*/
class Application
{
public:
Application(int argc, char* argv[]);
~Application();
// Executes the application and returns a status code
int execute();
// Changes the application state
void changeState(ApplicationState* state);
// Sets the termination code to be returned when the application finishes
void setTerminationCode(int code);
// Closes the application
void close(int terminationCode);
void changeFullscreen();
void changeVerticalSync();
void saveUserSettings();
bool loadScene();
bool loadUI();
bool loadModels();
bool loadControls();
bool loadGame();
void resizeUI();
void restringUI();
void openMenu(Menu* menu);
void closeMenu();
void selectMenuItem(std::size_t index);
void activateMenuItem();
void incrementMenuItem();
void decrementMenuItem();
void loadWorld(std::size_t index);
void loadLevel(std::size_t index);
void continueGame();
void newGame();
void deselectTool(Tool* tool);
void selectTool(Tool* tool);
void pauseSimulation();
void unpauseSimulation();
void openPauseMenu();
void closePauseMenu();
void setDisplayDebugInfo(bool display);
std::u32string getLevelName(std::size_t world, std::size_t level) const;
// Options menu functions
void selectWindowedResolution(std::size_t index);
void selectFullscreenResolution(std::size_t index);
void selectFullscreenMode(std::size_t index);
void selectVSyncMode(std::size_t index);
void selectLanguage(std::size_t index);
void bindControl(Control* control);
private:
ApplicationState* state;
ApplicationState* nextState;
int terminationCode;
public:
// SDL
SDL_Window* window;
SDL_GLContext context;
// Paths
std::string appDataPath;
std::string userDataPath;
std::string defaultSettingsFilename;
std::string userSettingsFilename;
// Settings
ParameterDict settings;
// State machine
LoadingState* loadingState;
SplashState* splashState;
TitleState* titleState;
GameState* gameState;
// Scene
Scene scene;
SceneLayer* defaultLayer;
SceneLayer* uiLayer;
Camera camera;
Camera sunlightCamera;
Camera uiCamera;
DirectionalLight sunlight;
ModelInstance forcepsModelInstance;
ModelInstance navigatorObject;
ModelInstance antModelInstance;
ModelInstance antHillModelInstance;
ModelInstance nestModelInstance;
ModelInstance sidewalkPanelInstance;
ModelInstance sidewalkPanelInstance1;
ModelInstance sidewalkPanelInstance2;
ModelInstance sidewalkPanelInstance3;
ModelInstance sidewalkPanelInstance4;
ModelInstance soilInstance;
// Graphics
Renderer renderer;
RenderTarget defaultRenderTarget;
int shadowMapResolution;
GLuint shadowMapDepthTextureID;
GLuint shadowMapFramebuffer;
RenderTarget shadowMapRenderTarget;
ShadowMapRenderPass shadowMapPass;
Compositor shadowMapCompositor;
Texture2D shadowMapDepthTexture;
GLuint framebufferAColorTextureID;
GLuint framebufferADepthTextureID;
GLuint framebufferA;
RenderTarget framebufferARenderTarget;
Texture2D framebufferAColorTexture;
GLuint framebufferBColorTextureID;
GLuint framebufferBDepthTextureID;
GLuint framebufferB;
RenderTarget framebufferBRenderTarget;
Texture2D framebufferBColorTexture;
GLuint pheromonePBO;
GLuint pheromoneTextureID;
Texture2D pheromoneTexture;
ClearRenderPass clearDepthPass;
LightingRenderPass lightingPass;
DebugRenderPass debugPass;
Compositor defaultCompositor;
BillboardBatch* uiBatch;
UIBatcher* uiBatcher;
UIRenderPass uiPass;
Compositor uiCompositor;
SkyboxRenderPass skyboxPass;
TextureLoader* textureLoader;
MaterialLoader* materialLoader;
ModelLoader* modelLoader;
BlurRenderPass horizontalBlurPass;
BlurRenderPass verticalBlurPass;
BlurRenderPass horizontalBlurPass2;
BlurRenderPass verticalBlurPass2;
// Controls
Control* bindingControl;
InputManager* inputManager;
Keyboard* keyboard;
Mouse* mouse;
ControlProfile* menuControlProfile;
Control menuLeft;
Control menuRight;
Control menuUp;
Control menuDown;
Control menuSelect;
Control menuCancel;
Control toggleFullscreen;
Control toggleDebugDisplay;
Control escape;
ControlProfile* gameControlProfile;
Control cameraMoveForward;
Control cameraMoveBack;
Control cameraMoveLeft;
Control cameraMoveRight;
Control cameraRotateCW;
Control cameraRotateCCW;
Control cameraZoomIn;
Control cameraZoomOut;
Control cameraToggleOverheadView;
Control cameraToggleNestView;
Control walkForward;
Control walkBack;
Control turnLeft;
Control turnRight;
Control togglePause;
Control togglePauseMenu;
Control fastForward;
Control switchRig;
Arcball arcball;
// Misc
Timer frameTimer;
float t;
float dt;
// UI text
ParameterDict strings;
float dpi;
float fontSizePT;
float fontSizePX;
Font* menuFont;
Font* copyrightFont;
Font* levelNameFont;
// UI textures
Texture2D* splashTexture;
Texture2D* titleTexture;
Texture2D* rectangularPaletteTexture;
Texture2D* foodIndicatorTexture;
Texture2D* toolBrushTexture;
Texture2D* toolLensTexture;
Texture2D* toolForcepsTexture;
Texture2D* toolTrowelTexture;
Texture2D* toolbarTopTexture;
Texture2D* toolbarBottomTexture;
Texture2D* toolbarMiddleTexture;
Texture2D* toolbarButtonRaisedTexture;
Texture2D* toolbarButtonDepressedTexture;
Texture2D* arcNorthTexture;
Texture2D* arcEastTexture;
Texture2D* arcSouthTexture;
Texture2D* arcWestTexture;
Texture2D* mouseLeftTexture;
Texture2D* mouseRightTexture;
Texture2D* depthTexture;
// UI elements
Vector4 selectedColor;
Vector4 deselectedColor;
UIContainer* uiRootElement;
UIImage* blackoutImage;
UIImage* splashBackgroundImage;
UIImage* splashImage;
UIImage* titleImage;
UIImage* darkenImage;
UILabel* frameTimeLabel;
UILabel* anyKeyLabel;
UILabel* copyrightLabel;
UIImage* rectangularPaletteImage;
UIImage* foodIndicatorImage;
UIImage* contextButtonImage0;
UIImage* contextButtonImage1;
UIImage* depthTextureImage;
UILabel* levelNameLabel;
Toolbar* toolbar;
PieMenu* pieMenu;
// Animation
Tweener* tweener;
Tween<Vector4>* fadeInTween;
Tween<Vector4>* fadeOutTween;
Tween<Vector4>* darkenFadeInTween;
Tween<Vector4>* darkenFadeOutTween;
Tween<float>* blurFadeInTween;
Tween<float>* blurFadeOutTween;
Tween<Vector4>* splashFadeInTween;
Tween<Vector4>* splashFadeOutTween;
Tween<float>* splashHangTween;
Tween<Vector4>* titleFadeInTween;
Tween<Vector4>* titleFadeOutTween;
Tween<Vector4>* anyKeyFadeInTween;
Tween<Vector4>* anyKeyFadeOutTween;
Tween<Vector4>* menuFadeInTween;
Tween<Vector4>* menuFadeOutTween;
Tween<float>* menuActivateTween;
Tween<Vector3>* cameraTranslationTween;
Tween<float>* forcepsSwoopTween;
// Menus
Menu* activeMenu;
Menu* previousActiveMenu;
Menu* mainMenu;
MenuItem* mainMenuContinueItem;
MenuItem* mainMenuLevelsItem;
MenuItem* mainMenuNewGameItem;
MenuItem* mainMenuSandboxItem;
MenuItem* mainMenuOptionsItem;
MenuItem* mainMenuExitItem;
Menu* levelsMenu;
MenuItem* levelsMenuBackItem;
Menu* optionsMenu;
MenuItem* optionsMenuWindowedResolutionItem;
MenuItem* optionsMenuFullscreenResolutionItem;
MenuItem* optionsMenuFullscreenItem;
MenuItem* optionsMenuVSyncItem;
MenuItem* optionsMenuLanguageItem;
MenuItem* optionsMenuControlsItem;
MenuItem* optionsMenuBackItem;
Menu* controlsMenu;
MenuItem* controlsMenuResetToDefaultItem;
MenuItem* controlsMenuMoveForwardItem;
MenuItem* controlsMenuMoveBackItem;
MenuItem* controlsMenuMoveLeftItem;
MenuItem* controlsMenuMoveRightItem;
MenuItem* controlsMenuBackItem;
Menu* graphicsMenu;
Menu* audioMenu;
Menu* gameplayMenu;
Menu* pauseMenu;
MenuItem* pauseMenuResumeItem;
MenuItem* pauseMenuLevelsItem;
MenuItem* pauseMenuOptionsItem;
MenuItem* pauseMenuMainMenuItem;
MenuItem* pauseMenuExitItem;
// Models
Model* antModel;
Model* antHillModel;
Model* nestModel;
Model* forcepsModel;
Model* lensModel;
Model* brushModel;
Model* sidewalkPanelModel;
Model* soilModel;
// Game variables
Biosphere biosphere;
Campaign campaign;
int currentWorldIndex;
int currentLevelIndex;
Level* currentLevel;
Colony* colony;
OrbitCam* orbitCam;
FreeCam* freeCam;
CameraRig* activeRig;
bool cameraOverheadView;
bool cameraNestView;
int toolIndex;
Tool* currentTool;
Forceps* forceps;
Lens* lens;
Brush* brush;
bool simulationPaused;
// Debug
LineBatcher* lineBatcher;
bool displayDebugInfo;
// Options menu values
bool fullscreen;
int swapInterval;
Vector2 resolution;
std::vector<Vector2> resolutions;
std::size_t windowedResolutionIndex;
std::size_t fullscreenResolutionIndex;
int* fullscreenModes;
int* vsyncModes;
std::vector<std::string> languages;
std::size_t languageIndex;
};
#endif // APPLICATION_HPP

+ 9
- 65
src/configuration.hpp.in View File

@ -1,65 +1,9 @@
/*
* Copyright (C) 2017 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONFIGURATION_HPP
#define CONFIGURATION_HPP
#include <emergent/emergent.hpp>
using namespace Emergent;
#define ANTKEEPER_VERSION_MAJOR @ANTKEEPER_VERSION_MAJOR@
#define ANTKEEPER_VERSION_MINOR @ANTKEEPER_VERSION_MINOR@
#define ANTKEEPER_VERSION_PATCH @ANTKEEPER_VERSION_PATCH@
#define ANTKEEPER_VERSION_STRING "@ANTKEEPER_VERSION@"
#cmakedefine ANTKEEPER_DEBUG
// Terrain dimensions
const float ANTKEEPER_TERRAIN_WIDTH = 100.0f;
const float ANTKEEPER_TERRAIN_BASE_HEIGHT = 35.7f;
const float ANTKEEPER_TERRAIN_DEPTH = ANTKEEPER_TERRAIN_WIDTH;
const float ANTKEEPER_OCTREE_PADDING = 5.0f;
// UI
const int ANTKEEPER_UI_LAYER_LOADING = 40;
const int ANTKEEPER_UI_LAYER_BLACKOUT = 30;
const int ANTKEEPER_UI_LAYER_MENU = 20;
const int ANTKEEPER_UI_LAYER_DARKEN = 10;
const int ANTKEEPER_UI_LAYER_HUD = 0;
const float WORLD_WIDTH = 100.0f; // cm
const float WORLD_HEIGHT = 100.0f; // cm
const float FRAMES_PER_SECOND = 60.0f;
const float TIMESTEP = 1.0f / FRAMES_PER_SECOND;
const float PHEROMONE_MATRIX_RESOLUTION = 5.12f; // pheromone cells per cm
const int PHEROMONE_MATRIX_COLUMNS = (int)(WORLD_WIDTH * PHEROMONE_MATRIX_RESOLUTION);
const int PHEROMONE_MATRIX_ROWS = (int)(WORLD_HEIGHT * PHEROMONE_MATRIX_RESOLUTION);
const Vector2 WORLD_BOUNDS_MIN = Vector2(-WORLD_WIDTH * 0.5f, -WORLD_HEIGHT * 0.5f);
const Vector2 WORLD_BOUNDS_MAX = Vector2(WORLD_WIDTH * 0.5f, WORLD_HEIGHT * 0.5f);
const float BRUSH_RADIUS = 0.5f;
const float EVAPORATION_FACTOR = 0.99925f;
const float DIFFUSIONS_PER_SECOND = 4.0f;
const int DIFFUSION_FRAME = static_cast<int>(FRAMES_PER_SECOND / DIFFUSIONS_PER_SECOND);
const float HOMING_PHEROMONE_COLOR[] = {0.55f, 0.55f, 0.00f, 0.0f}; // CMYK
const float RECRUITMENT_PHEROMONE_COLOR[] = {0.00f, 0.55f, 0.55f, 0.0f}; // CMYK
const float ALARM_PHEROMONE_COLOR[] = {0.00f, 0.00f, 1.00f, 0.0f}; // CMYK
const std::uint64_t MATERIAL_FLAG_TRANSLUCENT = 0x0000000001;
const std::uint64_t MATERIAL_FLAG_DISABLE_SHADOW_CASTING = 0x0000000002;
#endif // CONFIGURATION_HPP
#ifndef CONFIGURATION_HPP
#define CONFIGURATION_HPP
#define VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define VERSION_MINOR @PROJECT_VERSION_MINOR@
#define VERSION_PATCH @PROJECT_VERSION_PATCH@
#define VERSION_STRING "@PROJECT_VERSION@"
#endif // CONFIGURATION_HPP

+ 0
- 134
src/controls.hpp View File

@ -1,134 +0,0 @@
/*
* Copyright (C) 2017 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONTROLS_HPP
#define CONTROLS_HPP
#include "input.hpp"
#include <list>
#include <utility>
#include <tuple>
#include <map>
enum class MouseWheelAxis
{
POSITIVE_X,
NEGATIVE_X,
POSITIVE_Y,
NEGATIVE_Y
};
class Control:
public KeyObserver,
public MouseButtonObserver,
public MouseWheelObserver,
public GamepadButtonObserver,
public GamepadAxisObserver
{
public:
Control();
virtual ~Control();
void setDeadzone(float value);
void update();
float getDeadzone() const;
float getCurrentValue() const;
float getPreviousValue() const;
bool isTriggered() const;
bool wasTriggered() const;
bool isUnbound() const;
void bindKey(Keyboard* keyboard, int scancode);
void bindMouseButton(Mouse* mouse, int button);
void bindMouseWheelAxis(Mouse* mouse, MouseWheelAxis axis);
void bindGamepadButton(Gamepad* gamepad, int button);
void bindGamepadAxis(Gamepad* gamepad, int axis, bool negative);
void bind(const InputEvent& event);
void unbind();
virtual void keyPressed(int scancode);
virtual void keyReleased(int scancode);
virtual void mouseButtonPressed(int button, int x, int y);
virtual void mouseButtonReleased(int button, int x, int y);
virtual void mouseWheelScrolled(int x, int y);
virtual void gamepadButtonPressed(int button);
virtual void gamepadButtonReleased(int button);
virtual void gamepadAxisMoved(int axis, bool negative, float value);
const std::list<std::pair<Keyboard*, int>>* getBoundKeys() const;
const std::list<std::pair<Mouse*, int>>* getBoundMouseButtons() const;
const std::list<std::pair<Mouse*, MouseWheelAxis>>* getBoundMouseWheelAxes() const;
const std::list<std::pair<Gamepad*, int>>* getBoundGamepadButtons() const;
const std::list<std::tuple<Gamepad*, int, bool>>* getBoundGamepadAxes() const;
private:
float deadzone;
float currentValue;
float previousValue;
std::list<std::pair<Keyboard*, int>> boundKeys;
std::list<std::pair<Mouse*, int>> boundMouseButtons;
std::list<std::pair<Mouse*, MouseWheelAxis>> boundMouseWheelAxes;
std::list<std::pair<Gamepad*, int>> boundGamepadButtons;
std::list<std::tuple<Gamepad*, int, bool>> boundGamepadAxes;
};
inline float Control::getDeadzone() const
{
return deadzone;
}
inline float Control::getCurrentValue() const
{
return currentValue;
}
inline float Control::getPreviousValue() const
{
return previousValue;
}
class ControlProfile
{
public:
ControlProfile(InputManager* inputManager);
void registerControl(const std::string& name, Control* control);
bool save(const std::string& filename);
bool load(const std::string& filename);
// Calls Control::update() on each control registered with this profile
void update();
const std::map<std::string, Control*>* getControlMap() const;
private:
InputManager* inputManager;
std::map<std::string, Control*> controls;
};
inline const std::map<std::string, Control*>* ControlProfile::getControlMap() const
{
return &controls;
}
#endif

+ 0
- 80
src/debug.cpp View File

@ -1,80 +0,0 @@
/*
* Copyright (C) 2017 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "debug.hpp"
#include <iostream>
LineBatcher::LineBatcher(std::size_t lineCount):
lineCount(lineCount),
currentLine(0),
width(1.0f),
color(1.0f)
{
batch.resize(lineCount);
range = batch.addRange();
range->material = nullptr;//&material;
//material.albedo = Vector3(1.0f);
}
void LineBatcher::begin()
{
currentLine = 0;
range->start = 0;
range->length = 0;
}
void LineBatcher::end()
{
range->length = currentLine;
batch.update();
}
void LineBatcher::draw(const Vector3& start, const Vector3& end)
{
if (currentLine >= batch.getBillboardCount())
{
std::cout << "LineBatcher::draw(): maximum line count exceeded" << std::endl;
return;
}
Vector3 center = (start + end) * 0.5f;
float length = glm::length(end - start);
Vector3 forward = glm::normalize(end - start);
glm::quat rotation = glm::normalize(glm::rotation(Vector3(1, 0, 0), forward));
Billboard* billboard = batch.getBillboard(currentLine);
billboard->setTranslation(center);
billboard->setDimensions(Vector2(length, width));
billboard->setRotation(rotation);
billboard->setTintColor(color);
++currentLine;
}
void LineBatcher::setWidth(float width)
{
this->width = width;
}
void LineBatcher::setColor(const Vector4& color)
{
this->color = color;
}

+ 2
- 0
src/dr_libs/dr_wav.cpp View File

@ -0,0 +1,2 @@
#define DR_WAV_IMPLEMENTATION
#include "dr_wav.h"

+ 4377
- 0
src/dr_libs/dr_wav.h
File diff suppressed because it is too large
View File


+ 81
- 0
src/entity/component-manager.cpp View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "component-manager.hpp"
#include "component-observer.hpp"
void ComponentManager::addComponentObserver(ComponentObserver* observer)
{
componentObservers.push_back(observer);
}
void ComponentManager::removeComponentObserver(ComponentObserver* observer)
{
componentObservers.remove(observer);
}
void ComponentManager::addComponent(EntityID entity, ComponentBase* component)
{
ComponentType componentType = component->getComponentType();
entityMap[entity][componentType] = component;
// Notify observers
for (auto observer: componentObservers)
{
observer->componentAdded(entity, component);
}
}
ComponentBase* ComponentManager::removeComponent(EntityID entity, ComponentType type)
{
ComponentMap& componentMap = entityMap[entity];
auto it = componentMap.find(type);
if (it == componentMap.end())
{
return nullptr;
}
ComponentBase* component = it->second;
// Notify observers
for (auto observer: componentObservers)
{
observer->componentRemoved(entity, component);
}
componentMap.erase(it);
return component;
}
ComponentBase* ComponentManager::getComponent(EntityID entity, ComponentType type)
{
ComponentMap& componentMap = entityMap[entity];
auto it = componentMap.find(type);
if (it == componentMap.end())
{
return nullptr;
}
return it->second;
}

+ 116
- 0
src/entity/component-manager.hpp View File

@ -0,0 +1,116 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COMPONENT_MANAGER_HPP
#define COMPONENT_MANAGER_HPP
#include "entity-id.hpp"
#include "component.hpp"
#include <list>
#include <map>
class ComponentObserver;
/// Maps component types to components.
typedef std::map<ComponentType, ComponentBase*> ComponentMap;
/// Maps entity IDs to a component map.
typedef std::map<EntityID, ComponentMap> EntityComponentMap;
/**
* Manages the aggregation of components which make up entities.
*/
class ComponentManager
{
public:
/**
* Creates an instance of ComponentManager.
*/
ComponentManager() = default;
/**
* Destroys an instance of ComponentManager.
*/
~ComponentManager() = default;
/**
* Adds a ComponentObserver.
*
* @param observer Pointer to the observer to add.
*/
void addComponentObserver(ComponentObserver* observer);
/**
* Removes a ComponentObserver.
*
* @param observer Pointer to the observer to remove.
*/
void removeComponentObserver(ComponentObserver* observer);
/**
* Adds a component to the specified entity.
*
* @param entity Specifies an entity.
* @param component Specifies the component to add.
*/
void addComponent(EntityID entity, ComponentBase* component);
/**
* Removes a component from the specified entity.
*
* @param entity Specifies an entity.
* @param type Specifies the type of component.
*
* @return Pointer to the removed component.
*/
ComponentBase* removeComponent(EntityID entity, ComponentType type);
/**
* Returns the specified component of an entity.
*
* @param entity Specifies an entity.
* @param type Specifies the type of component.
*
* @return Pointer to the component, or `nullptr` if the specified component was not found.
*/
ComponentBase* getComponent(EntityID entity, ComponentType type);
/**
* Returns the component map of the specified entity.
*
* @param entity Specifies an entity.
*
* @return Pointer to the component map.
*/
ComponentMap* getComponents(EntityID entity);
private:
ComponentManager(const ComponentManager&) = delete;
ComponentManager& operator=(const ComponentManager&) = delete;
EntityComponentMap entityMap;
std::list<ComponentObserver*> componentObservers;
};
inline ComponentMap* ComponentManager::getComponents(EntityID entity)
{
return &entityMap[entity];
}
#endif // COMPONENT_MANAGER_HPP

src/game/habitat.cpp → src/entity/component-observer.cpp View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Christopher J. Howard
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
@ -17,18 +17,17 @@
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "habitat.hpp"
#include "component-observer.hpp"
#include "component-manager.hpp"
Habitat::Habitat(const AABB& bounds, int maxOctreeDepth)
ComponentObserver::ComponentObserver(ComponentManager* componentManager):
componentManager(componentManager)
{
obstacleOctree = new Octree<Navmesh*>(maxOctreeDepth, bounds);
pheromoneOctree = new Octree<Pheromone*>(maxOctreeDepth, bounds);
agentOctree = new Octree<Agent*>(maxOctreeDepth, bounds);
componentManager->addComponentObserver(this);
}
Habitat::~Habitat()
ComponentObserver::~ComponentObserver()
{
delete obstacleOctree;
delete pheromoneOctree;
delete agentOctree;
componentManager->removeComponentObserver(this);
}

+ 69
- 0
src/entity/component-observer.hpp View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COMPONENT_OBSERVER_HPP
#define COMPONENT_OBSERVER_HPP
#include "entity-id.hpp"
class ComponentBase;
class ComponentManager;
/**
* Abstract base class for component observers.
*/
class ComponentObserver
{
public:
/**
* Creates a component observer.
*
* @param componentManager Specifies the component manager with which to associate this component observer.
*/
ComponentObserver(ComponentManager* componentManager);
/**
* Destroys a component observer.
*/
virtual ~ComponentObserver();
protected:
ComponentManager* componentManager;
private:
friend class ComponentManager;
/**
* Called after a component is added to an entity.
*
* @param entity Specifies the entity with which the component is associated.
* @param component Specifies the component added.
*/
virtual void componentAdded(EntityID entity, ComponentBase* component) = 0;
/**
* Called after a component is removed from an entity.
*
* @param entity Specifies the entity with which the component is associated.
* @param component Specifies the component removed.
*/
virtual void componentRemoved(EntityID entity, ComponentBase* component) = 0;
};
#endif // COMPONENT_OBSERVER_HPP

+ 77
- 0
src/entity/component.hpp View File

@ -0,0 +1,77 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COMPONENT_HPP
#define COMPONENT_HPP
enum class ComponentType;
/**
* Abstract base class for entity components.
*/
class ComponentBase
{
public:
/**
* Destroys a component.
*/
virtual ~ComponentBase() = default;
/**
* Clones the component.
*/
virtual ComponentBase* clone() const = 0;
/**
* Returns the component type.
*/
virtual ComponentType getComponentType() const = 0;
};
/**
* Abstract templated class for entity components.
*/
template <ComponentType type>
class Component: public ComponentBase
{
public:
static const ComponentType TYPE;
/**
* Destroys a component.
*/
virtual ~Component() = default;
/**
* Returns the component type.
*/
virtual ComponentType getComponentType() const final;
};
template <ComponentType type>
const ComponentType Component<type>::TYPE = type;
template <ComponentType type>
inline ComponentType Component<type>::getComponentType() const
{
return type;
}
#endif // COMPONENT_HPP

src/game/habitat.hpp → src/entity/components/animation-component.hpp View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Christopher J. Howard
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
@ -17,32 +17,26 @@
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HABITAT_HPP
#define HABITAT_HPP
#ifndef ANIMATION_COMPONENT_HPP
#define ANIMATION_COMPONENT_HPP
#include <vector>
#include "../component.hpp"
#include "component-type.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
class Navmesh;
class Pheromone;
class Agent;
#include <list>
#include <utility>
class Habitat
class AnimationComponent: public Component<ComponentType::ANIMATION>
{
public:
Habitat(const AABB& bounds, int maxOctreeDepth);
~Habitat();
virtual ComponentBase* clone() const;
const Octree<Navmesh*>* getObstacleOctree() const;
const Octree<Pheromone*>* getPheromoneOctree() const;
const Octree<Agent*>* getAgentOctree() const;
private:
Octree<Navmesh*>* obstacleOctree;
Octree<Pheromone*>* pheromoneOctree;
Octree<Agent*>* agentOctree;
// List of animation-blend weight pairs
std::list<std::pair<AnimationClip<Transform>, float>> animations;
};
#endif // HABITAT_HPP
#endif // ANIMATION_COMPONENT_HPP

+ 27
- 0
src/entity/components/ant-hill-component.cpp View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ant-hill-component.hpp"
ComponentBase* AntHillComponent::clone() const
{
AntHillComponent* component = new AntHillComponent();
return component;
}

+ 36
- 0
src/entity/components/ant-hill-component.hpp View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANT_HILL_COMPONENT_HPP
#define ANT_HILL_COMPONENT_HPP
#include "../component.hpp"
#include "component-type.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
class AntHillComponent: public Component<ComponentType::ANT_HILL>
{
public:
virtual ComponentBase* clone() const;
};
#endif // ANT_HILL_COMPONENT_HPP

+ 29
- 0
src/entity/components/behavior-component.cpp View File

@ -0,0 +1,29 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "behavior-component.hpp"
ComponentBase* BehaviorComponent::clone() const
{
BehaviorComponent* component = new BehaviorComponent();
component->wanderDirection = wanderDirection;
component->wanderTriangle = wanderTriangle;
return component;
}

+ 41
- 0
src/entity/components/behavior-component.hpp View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BEHAVIOR_COMPONENT_HPP
#define BEHAVIOR_COMPONENT_HPP
#include "../component.hpp"
#include "component-type.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
class BehaviorComponent: public Component<ComponentType::BEHAVIOR>
{
public:
virtual ComponentBase* clone() const;
float wanderCircleDistance; // cm
float wanderCircleRadius; // cm
float wanderRate; // radians/s
Vector3 wanderDirection;
TriangleMesh::Triangle* wanderTriangle;
};
#endif // BEHAVIOR_COMPONENT_HPP

+ 30
- 0
src/entity/components/collision-component.cpp View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "collision-component.hpp"
ComponentBase* CollisionComponent::clone() const
{
CollisionComponent* component = new CollisionComponent();
component->radius = radius;
component->collisions = collisions;
component->mesh = mesh;
return component;
}

src/states/title-state.hpp → src/entity/components/collision-component.hpp View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Christopher J. Howard
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
@ -17,30 +17,26 @@
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TITLE_STATE_HPP
#define TITLE_STATE_HPP
#ifndef COLLISION_COMPONENT_HPP
#define COLLISION_COMPONENT_HPP
#include "../application-state.hpp"
#include "../ui/ui.hpp"
#include "../component.hpp"
#include "../entity-id.hpp"
#include "component-type.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
/**
* Displays the title screen.
*/
class TitleState: public ApplicationState, public WindowObserver
class CollisionComponent: public Component<ComponentType::COLLISION>
{
public:
TitleState(Application* application);
virtual ~TitleState();
virtual ComponentBase* clone() const;
virtual void enter();
virtual void execute();
virtual void exit();
float radius;
std::list<EntityID> collisions;
virtual void windowClosed();
virtual void windowResized(int width, int height);
TriangleMesh* mesh;
};
#endif // TITLE_STATE_HPP
#endif // COLLISION_COMPONENT_HPP

+ 38
- 0
src/entity/components/component-type.hpp View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COMPONENT__TYPE_HPP
#define COMPONENT__TYPE_HPP
enum class ComponentType
{
ANIMATION,
ANT_HILL,
BEHAVIOR,
COLLISION,
LEGGED_LOCOMOTION,
MODEL,
STEERING,
SOUND_SOURCE,
TOOL,
TRANSFORM
};
#endif // COMPONENT_TYPE_HPP

+ 34
- 0
src/entity/components/legged-locomotion-component.cpp View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "legged-locomotion-component.hpp"
ComponentBase* LeggedLocomotionComponent::clone() const
{
LeggedLocomotionComponent* component = new LeggedLocomotionComponent();
component->legCount = legCount;
component->crawlingSpeed = crawlingSpeed;
component->walkingSpeed = walkingSpeed;
component->runningSpeed = runningSpeed;
component->turningSpeed = turningSpeed;
component->speed = walkingSpeed;
component->surface = nullptr;
return component;
}

+ 45
- 0
src/entity/components/legged-locomotion-component.hpp View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LEGGED_LOCOMOTION_COMPONENT_HPP
#define LEGGED_LOCOMOTION_COMPONENT_HPP
#include "../component.hpp"
#include "component-type.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
class LeggedLocomotionComponent: public Component<ComponentType::LEGGED_LOCOMOTION>
{
public:
virtual ComponentBase* clone() const;
unsigned char legCount;
float crawlingSpeed; // cm/s
float walkingSpeed; // cm/s
float runningSpeed; // cm/s
float turningSpeed; // radians/s
float speed;
TriangleMesh::Triangle* surface;
Vector3 barycentricPosition;
};
#endif // LEGGED_LOCOMOTION_COMPONENT_HPP

+ 29
- 0
src/entity/components/model-component.cpp View File

@ -0,0 +1,29 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "model-component.hpp"
ComponentBase* ModelComponent::clone() const
{
ModelComponent* component = new ModelComponent();
component->model.setModel(model.getModel());
component->model.setPose(nullptr);
return component;
}

+ 37
- 0
src/entity/components/model-component.hpp View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MODEL_COMPONENT_HPP
#define MODEL_COMPONENT_HPP
#include "../component.hpp"
#include "component-type.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
class ModelComponent: public Component<ComponentType::MODEL>
{
public:
virtual ComponentBase* clone() const;
ModelInstance model;
};
#endif // MODEL_COMPONENT_HPP

+ 28
- 0
src/entity/components/sound-source-component.cpp View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sound-source-component.hpp"
ComponentBase* SoundSourceComponent::clone() const
{
SoundSourceComponent* component = new SoundSourceComponent();
component->playing = playing;
return component;
}

+ 39
- 0
src/entity/components/sound-source-component.hpp View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SOUND_SOURCE_COMPONENT_HPP
#define SOUND_SOURCE_COMPONENT_HPP
#include "../component.hpp"
#include "../entity-id.hpp"
#include "component-type.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
class SoundSourceComponent: public Component<ComponentType::SOUND_SOURCE>
{
public:
virtual ComponentBase* clone() const;
bool playing;
};
#endif // SOUND_SOURCE_COMPONENT_HPP

+ 27
- 0
src/entity/components/steering-component.cpp View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "steering-component.hpp"
ComponentBase* SteeringComponent::clone() const
{
SteeringComponent* component = new SteeringComponent();
return component;
}

+ 56
- 0
src/entity/components/steering-component.hpp View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef STEERING_COMPONENT_HPP
#define STEERING_COMPONENT_HPP
#include "../component.hpp"
#include "component-type.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
#define MAX_STEERING_BEHAVIORS 8
struct SteeringBehavior
{
/// Function object which calculates steering force
std::function<Vector3()> function;
/// Priority value which determines in what order the behaviors will be evaluated
float priority;
/// Weight factor by which the calculated steering force should be multiplied
float weight;
};
class SteeringComponent: public Component<ComponentType::STEERING>
{
public:
virtual ComponentBase* clone() const;
SteeringBehavior behaviors[MAX_STEERING_BEHAVIORS];
std::size_t behaviorCount;
Vector3 force;
float speed;
float maxSpeed;
};
#endif // STEERING_COMPONENT_HPP

+ 29
- 0
src/entity/components/tool-component.cpp View File

@ -0,0 +1,29 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tool-component.hpp"
ComponentBase* ToolComponent::clone() const
{
ToolComponent* component = new ToolComponent();
component->active = active;
return component;
}

src/states/loading-state.hpp → src/entity/components/tool-component.hpp View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Christopher J. Howard
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
@ -17,23 +17,19 @@
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LOADING_STATE_HPP
#define LOADING_STATE_HPP
#ifndef TOOL_COMPONENT_HPP
#define TOOL_COMPONENT_HPP
#include "../application-state.hpp"
#include "../component.hpp"
#include "component-type.hpp"
/**
* Loads the application
*/
class LoadingState: public ApplicationState
class ToolComponent: public Component<ComponentType::TOOL>
{
public:
LoadingState(Application* application);
virtual ~LoadingState();
virtual ComponentBase* clone() const;
virtual void enter();
virtual void execute();
virtual void exit();
bool active;
};
#endif // LOADING_STATE_HPP
#endif // TOOL_COMPONENT_HPP

+ 28
- 0
src/entity/components/transform-component.cpp View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "transform-component.hpp"
ComponentBase* TransformComponent::clone() const
{
TransformComponent* component = new TransformComponent();
component->transform = transform;
return component;
}

+ 38
- 0
src/entity/components/transform-component.hpp View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRANSFORM_COMPONENT_HPP
#define TRANSFORM_COMPONENT_HPP
#include "../component.hpp"
#include "component-type.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
class TransformComponent: public Component<ComponentType::TRANSFORM>
{
public:
virtual ComponentBase* clone() const;
Transform transform;
};
#endif // TRANSFORM_COMPONENT_HPP

+ 43
- 0
src/entity/entity-group-member.hpp View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ENTITY_GROUP_MEMBER_HPP
#define ENTITY_GROUP_MEMBER_HPP
#include "entity-id.hpp"
#include <tuple>
#include <type_traits>
/**
* A group of entities which share a set of specified component types.
*
* @tparam T Set of components which are required for group membership.
*/
template <typename... T>
struct EntityGroupMember
{
/// Entity ID of the group member.
EntityID entity;
/// A tuple containing pointers to the member's group-related components, in the order specified by the order of the template parameters.
std::tuple<T*...> components;
};
#endif // ENTITY_GROUP_MEMBER_HPP

+ 52
- 0
src/entity/entity-group-observer.hpp View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ENTITY_GROUP_OBSERVER_HPP
#define ENTITY_GROUP_OBSERVER_HPP
#include "entity-group-member.hpp"
/**
* Abstract base class for entity group observers, which are notified each time a member is registered or unregistered from the group.
*
* @tparam T Set of components which are required for group membership.
*/
template <typename... T>
class EntityGroupObserver
{
public:
typedef EntityGroupMember<T...> Member;
/**
* Called each time an entity joins the entity group by obtaining the necessary component types.
*
* @param entity Entity ID of the new member.
*/
virtual void memberRegistered(const Member* member) = 0;
/**
* Called each time an entity leaves an the entity group by no longer possessing the necessary component types.
*
* @param entity Entity ID of the former member.
*/
virtual void memberUnregistered(const Member* member) = 0;
};
#endif // ENTITY_GROUP_OBSERVER_HPP

+ 59
- 0
src/entity/entity-group.cpp View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "component.hpp"
#include "component-manager.hpp"
#include "entity-group.hpp"
EntityGroupBase::EntityGroupBase(ComponentManager* componentManager, const ComponentFilter& componentFilter):
ComponentObserver(componentManager),
componentFilter(componentFilter)
{}
void EntityGroupBase::componentAdded(EntityID entity, ComponentBase* component)
{
if (componentFilter.find(component->getComponentType()) != componentFilter.end())
{
for (auto it = componentFilter.begin(); it != componentFilter.end(); ++it)
{
if (*it == component->getComponentType())
{
continue;
}
else if (!componentManager->getComponent(entity, *it))
{
return;
}
}
registerMember(entity);
}
}
void EntityGroupBase::componentRemoved(EntityID entity, ComponentBase* component)
{
if (componentFilter.find(component->getComponentType()) != componentFilter.end())
{
if (isRegistered(entity))
{
unregisterMember(entity);
}
}
}

+ 268
- 0
src/entity/entity-group.hpp View File

@ -0,0 +1,268 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ENTITY_GROUP_HPP
#define ENTITY_GROUP_HPP
#include "component-observer.hpp"
#include "component-manager.hpp"
#include "entity-group-member.hpp"
#include "entity-group-observer.hpp"
#include <list>
#include <map>
#include <set>
#include <tuple>
#include <utility>
enum class ComponentType;
/// A set of component types used to filter entities
typedef std::set<ComponentType> ComponentFilter;
/**
* Abstract base class for entity groups.
*/
class EntityGroupBase: protected ComponentObserver
{
public:
/**
* Creates a entity group base.
*
* @param componentManager The component manager with which to associate this entity group.
* @param componentFilter Set of component types which an entity must possess in order to join this entity group.
*/
EntityGroupBase(ComponentManager* componentManager, const ComponentFilter& componentFilter);
/// Returns the set of components which an entity must possess in order to join this entity group.
const ComponentFilter& getComponentFilter() const;
/**
* Returns true if the specified entity is registered with this entity group.
*
* @param entity ID of the entity to check.
*/
virtual bool isRegistered(EntityID entity) const = 0;
private:
virtual void componentAdded(EntityID entity, ComponentBase* component);
virtual void componentRemoved(EntityID entity, ComponentBase* component);
/**
* Called each time an entity joins the entity group by obtaining the necessary component types.
*
* @param entity Entity ID of the new member.
*/
virtual void registerMember(EntityID entity) = 0;
/**
* Called each time an entity leaves an the entity group by no longer possessing the necessary component types.
*
* @param entity Entity ID of the former member.
*/
virtual void unregisterMember(EntityID entity) = 0;
ComponentFilter componentFilter;
};
inline const ComponentFilter& EntityGroupBase::getComponentFilter() const
{
return componentFilter;
}
/**
* A group of entities which share a set of specified component types.
*
* @tparam T Set of components which are required for group membership.
*/
template <typename... T>
class EntityGroup: public EntityGroupBase
{
public:
typedef EntityGroupMember<T...> Member;
typedef EntityGroupObserver<T...> Observer;
/**
* Creates a entity group.
*
* @param componentManager Component manager with which to associate this entity group.
*/
EntityGroup(ComponentManager* componentManager);
/// Destroys a entity group.
~EntityGroup();
/**
* Adds a group observer.
*
* @param observer Observer to add.
*/
void addGroupObserver(Observer* observer);
/**
* Removes a group observer.
*
* @param observer Observer to remove.
*/
void removeGroupObserver(Observer* observer);
/// Removes all group observers.
void removeGroupObservers();
/// @copydoc EntityGroupBase::isRegistered(EntityID) const
virtual bool isRegistered(EntityID entity) const;
/**
* Returns the member list.
*
* @return List of members.
*/
const std::list<Member*>* getMembers() const;
/**
* Returns the member with the specified ID.
*
* @param entity Entity ID of a group member.
* @return Member with the specified ID, or nullptr if an entity with that ID is not registered.
*/
const Member* getMemberByEntity(EntityID entity) const;
private:
template <std::size_t index, typename U, typename... V>
typename std::enable_if<(sizeof...(V) == 0), void>::type attachComponents(Member* member)
{
std::get<index>(member->components) = static_cast<U*>(componentManager->getComponent(member->entity, U::TYPE));
}
template <std::size_t index, typename U, typename... V>
typename std::enable_if<(sizeof...(V) > 0), void>::type attachComponents(Member* member)
{
std::get<index>(member->components) = static_cast<U*>(componentManager->getComponent(member->entity, U::TYPE));
attachComponents<index + 1, V...>(member);
}
virtual void registerMember(EntityID entity);
virtual void unregisterMember(EntityID entity);
std::list<Member*> members;
std::map<EntityID, Member*> memberMap;
std::list<Observer*> observers;
};
template <typename... T>
EntityGroup<T...>::EntityGroup(ComponentManager* componentManager):
EntityGroupBase(componentManager, ComponentFilter({(T::TYPE)...}))
{}
template <typename... T>
EntityGroup<T...>::~EntityGroup()
{
while (!members.empty())
{
Member* member = members.back();
members.pop_back();
memberMap.erase(memberMap.find(member->entity));
for (Observer* observer: observers)
{
observer->memberUnregistered(member);
}
delete member;
}
}
template <typename... T>
void EntityGroup<T...>::addGroupObserver(Observer* observer)
{
observers.push_back(observer);
}
template <typename... T>
void EntityGroup<T...>::removeGroupObserver(Observer* observer)
{
observers.remove(observer);
}
template <typename... T>
void EntityGroup<T...>::removeGroupObservers()
{
observers.clear();
}
template <typename... T>
inline bool EntityGroup<T...>::isRegistered(EntityID entity) const
{
return (memberMap.find(entity) != memberMap.end());
}
template <typename... T>
inline const std::list<typename EntityGroup<T...>::Member*>* EntityGroup<T...>::getMembers() const
{
return &members;
}
template <typename... T>
inline const typename EntityGroup<T...>::Member* EntityGroup<T...>::getMemberByEntity(EntityID entity) const
{
auto it = memberMap.find(entity);
if (it != memberMap.end())
{
return it->second;
}
return nullptr;
}
template <typename... T>
void EntityGroup<T...>::registerMember(EntityID entity)
{
Member* member = new Member();
member->entity = entity;
attachComponents<0, T...>(member);
members.push_back(member);
memberMap[entity] = member;
for (Observer* observer: observers)
{
observer->memberRegistered(member);
}
}
template <typename... T>
void EntityGroup<T...>::unregisterMember(EntityID entity)
{
auto it = memberMap.find(entity);
Member* member = it->second;
memberMap.erase(it);
members.remove(member);
for (Observer* observer: observers)
{
observer->memberUnregistered(member);
}
delete member;
}
#endif // ENTITY_GROUP_HPP

+ 68
- 0
src/entity/entity-id-pool.cpp View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "entity-id-pool.hpp"
EntityIDPool::EntityIDPool():
nextID(0)
{}
EntityIDPool::~EntityIDPool()
{}
EntityID EntityIDPool::reserveNextID()
{
EntityID id;
if (!availableIDs.empty())
{
id = *availableIDs.begin();
availableIDs.erase(availableIDs.begin());
reservedIDs.insert(id);
}
else
{
id = nextID;
reservedIDs.insert(id);
findNextID();
}
return id;
}
void EntityIDPool::reserveID(EntityID id)
{
availableIDs.erase(id);
reservedIDs.insert(id);
if (nextID == id)
{
findNextID();
}
}
inline void EntityIDPool::findNextID()
{
do
{
++nextID;
}
while (reservedIDs.find(nextID) != reservedIDs.end());
}

+ 87
- 0
src/entity/entity-id-pool.hpp View File

@ -0,0 +1,87 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ENTITY_ID_POOL_HPP
#define ENTITY_ID_POOL_HPP
#include "entity-id.hpp"
#include <set>
/**
* Manages the creation and destruction of entities.
*/
class EntityIDPool
{
public:
/**
* Creates an instance of EntityIDPool.
*/
EntityIDPool();
/**
* Destroys an instance of EntityIDPool.
*/
~EntityIDPool();
/**
* Reserves the next available ID.
*
* @return Reserved ID.
*/
EntityID reserveNextID();
/**
* Reserves the specified ID.
*
* @param id Specifies an ID to reserve.
*/
void reserveID(EntityID id);
/**
* Frees the specified ID.
*
* @param id Specifies an ID to free.
*/
void freeID(EntityID id);
/**
* Returns `true` if the specified ID is reserved.
*/
bool isReserved(EntityID id) const;
private:
void findNextID();
EntityID nextID;
std::set<EntityID> reservedIDs;
std::set<EntityID> availableIDs;
};
inline void EntityIDPool::freeID(EntityID id)
{
reservedIDs.erase(id);
availableIDs.insert(id);
}
inline bool EntityIDPool::isReserved(EntityID id) const
{
return (reservedIDs.find(id) != reservedIDs.end());
}
#endif // ENTITY_ID_POOL_HPP

+ 28
- 0
src/entity/entity-id.hpp View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ENTITY_ID_HPP
#define ENTITY_ID_HPP
#include <cstdint>
typedef std::uint32_t EntityID;
#endif // ENTITY_ID_HPP

+ 69
- 0
src/entity/entity-manager.cpp View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2015 Christopher J. Howard
*
* This file is part of Ecosys.
*
* Ecosys is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Ecosys is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Ecosys. If not, see <http://www.gnu.org/licenses/>.
*/
#include "entity-manager.hpp"
#include "component-manager.hpp"
EntityManager::EntityManager(ComponentManager* componentManager):
componentManager(componentManager)
{}
EntityManager::~EntityManager()
{}
EntityID EntityManager::createEntity()
{
return idPool.reserveNextID();
}
bool EntityManager::createEntity(EntityID id)
{
if (idPool.isReserved(id))
{
return false;
}
idPool.reserveID(id);
return true;
}
bool EntityManager::destroyEntity(EntityID id)
{
if (!idPool.isReserved(id))
{
return false;
}
// Delete components
ComponentMap* components = componentManager->getComponents(id);
for (auto it = components->begin(); it != components->end(); it = components->begin())
{
ComponentBase* component = it->second;
componentManager->removeComponent(id, component->getComponentType());
delete component;
}
// Free ID
idPool.freeID(id);
return true;
}

+ 97
- 0
src/entity/entity-manager.hpp View File

@ -0,0 +1,97 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ENTITY_MANAGER_HPP
#define ENTITY_MANAGER_HPP
#include "entity-id.hpp"
#include "entity-id-pool.hpp"
class ComponentManager;
/**
* Manages the creation and destruction of entities.
*/
class EntityManager
{
public:
/**
* Creates an entity manager.
*
* @param componentManager Component manager with which to associate this entity manag.er
*/
EntityManager(ComponentManager* componentManager);
/**
* Destroys an entity manager.
*/
~EntityManager();
/**
* Creates an entity with the next available ID.
*
* @return ID of the created entity.
*/
EntityID createEntity();
/**
* Creates an entity with the specified ID.
*
* @param id ID of the entity to be created.
* @return `true` if the entity was created, and `false` if an entity with the specified ID already exists.
*/
bool createEntity(EntityID id);
/**
* Destroys an entity with the specified ID.
*
* @param id ID of the entity to be destroyed.
*
* @return `true` if the entity was destroyed, and `false` if an invalid ID was supplied.
*/
bool destroyEntity(EntityID id);
/**
* Returns the component manager associated with this entity manager.
*/
const ComponentManager* getComponentManager() const;
/// @copydoc EntityManager::getComponentManager() const
ComponentManager* getComponentManager();
private:
EntityManager(const EntityManager&) = delete;
EntityManager& operator=(const EntityManager&) = delete;
EntityIDPool idPool;
ComponentManager* componentManager;
};
inline const ComponentManager* EntityManager::getComponentManager() const
{
return componentManager;
}
inline ComponentManager* EntityManager::getComponentManager()
{
return componentManager;
}
#endif // ENTITY_MANAGER_HPP

+ 54
- 0
src/entity/entity-template.cpp View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "component.hpp"
#include "component-manager.hpp"
#include "entity-template.hpp"
EntityTemplate::EntityTemplate(const std::list<ComponentBase*>& components)
{
for (ComponentBase* component: components)
{
this->components.push_back(component->clone());
}
}
EntityTemplate::~EntityTemplate()
{
for (ComponentBase* component: components)
{
delete component;
}
}
void EntityTemplate::apply(EntityID entity, ComponentManager* componentManager)
{
for (ComponentBase* component: components)
{
ComponentBase* oldComponent = componentManager->getComponent(entity, component->getComponentType());
if (oldComponent != nullptr)
{
componentManager->removeComponent(entity, component->getComponentType());
delete oldComponent;
}
componentManager->addComponent(entity, component->clone());
}
}

+ 60
- 0
src/entity/entity-template.hpp View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ENTITY_TEMPLATE_HPP
#define ENTITY_TEMPLATE_HPP
#include <list>
#include "entity-id.hpp"
class ComponentBase;
class ComponentManager;
/**
* A template which can be applied to entities.
*/
class EntityTemplate
{
public:
/**
* Creates an entity template.
*
* @param components List of components which make up the template. The components in the list will be cloned and the cloned data managed by this template.
*/
EntityTemplate(const std::list<ComponentBase*>& components);
/**
* Destroys an entity template.
*/
~EntityTemplate();
/**
* Applies the template to an entity.
*
* @param entity ID of an entity to which the template should be applied.
* @param componentManager Component manager with which the entity is associated.
*/
void apply(EntityID entity, ComponentManager* componentManager);
private:
std::list<ComponentBase*> components;
};
#endif // ENTITY_TEMPLATE_HPP

+ 45
- 0
src/entity/system-manager.cpp View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "system-manager.hpp"
#include "system.hpp"
SystemManager::SystemManager()
{}
SystemManager::~SystemManager()
{}
void SystemManager::update(float t, float dt)
{
for (System* system: systems)
{
system->update(t, dt);
}
}
void SystemManager::addSystem(System* system)
{
systems.push_back(system);
}
void SystemManager::removeSystem(System* system)
{
systems.remove(system);
}

+ 68
- 0
src/entity/system-manager.hpp View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SYSTEM_MANAGER_HPP
#define SYSTEM_MANAGER_HPP
#include <list>
class System;
/**
* Manages a series of systems.
*/
class SystemManager
{
public:
/**
* Creates a system manager.
*/
SystemManager();
/**
* Destroys a system manager.
*/
~SystemManager();
/**
* Updates all systems. Systems will be updated in the order that they were added to the system manager.
*
* @param t Total elapsed time, in seconds.
* @param dt Time elapsed since last update, in seconds.
*/
void update(float t, float dt);
/**
* Adds a system to the system manager.
*
* @param system System to add.
*/
void addSystem(System* system);
/**
* Removes a system from the system manager.
*/
void removeSystem(System* system);
private:
std::list<System*> systems;
};
#endif // SYSTEM_MANAGER_HPP

src/application-state.cpp → src/entity/system.cpp View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Christopher J. Howard
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
@ -17,11 +17,9 @@
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "application-state.hpp"
#include "system.hpp"
ApplicationState::ApplicationState(Application* application):
application(application)
System::System(ComponentManager* componentManager):
componentManager(componentManager)
{}
ApplicationState::~ApplicationState()
{}

src/application-state.hpp → src/entity/system.hpp View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Christopher J. Howard
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
@ -17,32 +17,40 @@
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef APPLICATION_STATE_HPP
#define APPLICATION_STATE_HPP
#ifndef SYSTEM_HPP
#define SYSTEM_HPP
class Application;
class ComponentManager;
/**
* Abstract base class for application states.
* Abstract base class for entity systems.
*/
class ApplicationState
class System
{
public:
ApplicationState(Application* application);
virtual ~ApplicationState();
// Run once when the state is initially entered
virtual void enter() = 0;
// Run continually while the state is valid
virtual void execute() = 0;
// Run once when the state is exited
virtual void exit() = 0;
/**
* Creates a system.
*
* @param componentManager Component manager with which to associate the system.
*/
System(ComponentManager* componentManager);
/**
* Destroys a system.
*/
virtual ~System() = default;
/**
* Updates the system.
*
* @param t Total elapsed time, in seconds.
* @param dt Time elapsed since last update, in seconds.
*/
virtual void update(float t, float dt) = 0;
protected:
Application* application;
ComponentManager* componentManager;
};
#endif // APPLICATION_STATE_HPP
#endif // SYSTEM_HPP

+ 48
- 0
src/entity/systems/animation-system.cpp View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "animation-system.hpp"
AnimationSystem::AnimationSystem(ComponentManager* componentManager):
System(componentManager),
animationGroup(componentManager)
{}
AnimationSystem::~AnimationSystem()
{}
void AnimationSystem::update(float t, float dt)
{
auto members = animationGroup.getMembers();
for (const AnimationEntityGroup::Member* member: *members)
{
AnimationComponent* animationComponent = std::get<0>(member->components);
ModelComponent* modelComponent = std::get<1>(member->components);
Pose* pose = modelComponent->model.getPose();
for (const std::pair<AnimationClip<Transform>, float>& clipWeightPair: animationComponent->animations)
{
const AnimationClip<Transform>& clip = clipWeightPair.first;
float weight = clipWeightPair.second;
}
}
}

+ 46
- 0
src/entity/systems/animation-system.hpp View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANIMATION_SYSTEM_HPP
#define ANIMATION_SYSTEM_HPP
#include "../entity-group.hpp"
#include "../components/animation-component.hpp"
#include "../components/model-component.hpp"
#include "../system.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
typedef EntityGroup<AnimationComponent, ModelComponent> AnimationEntityGroup;
class AnimationSystem: public System
{
public:
AnimationSystem(ComponentManager* componentManager);
virtual ~AnimationSystem();
virtual void update(float t, float dt);
private:
AnimationEntityGroup animationGroup;
};
#endif // ANIMATION_SYSTEM_HPP

+ 181
- 0
src/entity/systems/behavior-system.cpp View File

@ -0,0 +1,181 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "behavior-system.hpp"
#include <set>
BehaviorSystem::BehaviorSystem(ComponentManager* componentManager):
System(componentManager),
behaviorGroup(componentManager),
antHillGroup(componentManager)
{
behaviorGroup.addGroupObserver(this);
}
BehaviorSystem::~BehaviorSystem()
{}
void BehaviorSystem::update(float t, float dt)
{
auto members = behaviorGroup.getMembers();
for (const BehaviorGroup::Member* member: *members)
{
BehaviorComponent* behavior = std::get<0>(member->components);
LeggedLocomotionComponent* leggedLocomotion = std::get<1>(member->components);
SteeringComponent* steering = std::get<2>(member->components);
TransformComponent* transform = std::get<3>(member->components);
steering->maxSpeed = leggedLocomotion->speed;
steering->behaviorCount = 2;
steering->behaviors[0].priority = 2.0f;
steering->behaviors[0].weight = 1.0f;
steering->behaviors[0].function = std::bind(&BehaviorSystem::containment, this, member);
steering->behaviors[1].priority = 1.0f;
steering->behaviors[1].weight = 0.5f;
steering->behaviors[1].function = std::bind(&BehaviorSystem::wander, this, dt, member);
}
}
void BehaviorSystem::memberRegistered(const BehaviorGroup::Member* member)
{
BehaviorComponent* behavior = std::get<0>(member->components);
LeggedLocomotionComponent* leggedLocomotion = std::get<1>(member->components);
behavior->wanderDirection = Vector3(0.0f);
while (glm::length2(behavior->wanderDirection) == 0.0f)
{
behavior->wanderDirection = Vector3(frand(-1, 1), frand(-1, 1), frand(-1, 1));
}
behavior->wanderTriangle = leggedLocomotion->surface;
behavior->wanderDirection = glm::normalize(behavior->wanderDirection);
behavior->wanderCircleDistance = 3.0f;
behavior->wanderCircleRadius = 2.0f;
behavior->wanderRate = glm::radians(180.0f) * 5.0f;
leggedLocomotion->speed = 2.0f;
}
void BehaviorSystem::memberUnregistered(const BehaviorGroup::Member* member)
{}
Vector3 BehaviorSystem::containment(const BehaviorGroup::Member* agent)
{
LeggedLocomotionComponent* leggedLocomotion = std::get<1>(agent->components);
TransformComponent* transform = std::get<3>(agent->components);
float probeAngle = glm::radians(30.0f);
float probeDistance = 5.0f;
Vector3 direction = transform->transform.rotation * Vector3(0, 0, 1);
TriangleMesh::Triangle* surface = leggedLocomotion->surface;
Vector3 forward = transform->transform.rotation * Vector3(0, 0, 1);
Vector3 up = surface->normal;
Vector3 right = glm::normalize(glm::cross(forward, up));
Vector3 force(0.0f);
return force;
}
Vector3 BehaviorSystem::wander(float dt, const BehaviorGroup::Member* agent)
{
BehaviorComponent* behavior = std::get<0>(agent->components);
LeggedLocomotionComponent* leggedLocomotion = std::get<1>(agent->components);
SteeringComponent* steering = std::get<2>(agent->components);
TransformComponent* transform = std::get<3>(agent->components);
// Reorientate wander direction
if (behavior->wanderTriangle != leggedLocomotion->surface)
{
if (behavior->wanderTriangle)
{
behavior->wanderDirection = glm::normalize(glm::rotation(behavior->wanderTriangle->normal, leggedLocomotion->surface->normal) * behavior->wanderDirection);
}
behavior->wanderTriangle = leggedLocomotion->surface;
}
// Make wander direction coplanar with surface triangle
TriangleMesh::Triangle* triangle = leggedLocomotion->surface;
Vector3 triangleCenter = (triangle->edge->vertex->position + triangle->edge->next->vertex->position + triangle->edge->previous->vertex->position) * (1.0f / 3.0f);
behavior->wanderDirection = glm::normalize(projectOnPlane(transform->transform.translation + behavior->wanderDirection, triangleCenter, triangle->normal) - transform->transform.translation);
Vector3 forward = transform->transform.rotation * Vector3(0, 0, 1);
Vector3 up = triangle->normal;
// Calculate center of wander circle
Vector3 wanderCircleCenter = forward * behavior->wanderCircleDistance;
// Calculate wander force
Vector3 wanderForce = wanderCircleCenter + behavior->wanderDirection * behavior->wanderCircleRadius;
// Displace wander direction
float displacementAngle = frand(-behavior->wanderRate, behavior->wanderRate) * 0.5f * dt;
behavior->wanderDirection = glm::normalize(glm::angleAxis(displacementAngle, up) * behavior->wanderDirection);
return wanderForce;
}
Vector3 BehaviorSystem::forage(const BehaviorGroup::Member* agent)
{
return Vector3(0.0f);
}
Vector3 BehaviorSystem::homing(const BehaviorGroup::Member* agent)
{
// Get ant position
const Vector3& antPosition = std::get<3>(agent->components)->transform.translation;
// Find nearest ant-hill
bool found = false;
float minDistanceSquared = 0.0f;
Vector3 homingDirection(0.0f);
auto antHills = antHillGroup.getMembers();
for (const AntHillGroup::Member* antHill: *antHills)
{
// Get ant-hill position
const Vector3& antHillPosition = std::get<1>(antHill->components)->transform.translation;
// Determine distance to ant-hill
Vector3 difference = antHillPosition - antPosition;
float distanceSquared = glm::length2(difference);
if (!found || distanceSquared < minDistanceSquared)
{
minDistanceSquared = distanceSquared;
homingDirection = difference;
found = true;
}
}
if (found)
{
homingDirection = glm::normalize(homingDirection);
}
return homingDirection;
}

+ 61
- 0
src/entity/systems/behavior-system.hpp View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BEHAVIOR_SYSTEM_HPP
#define BEHAVIOR_SYSTEM_HPP
#include "../entity-group.hpp"
#include "../components/ant-hill-component.hpp"
#include "../components/behavior-component.hpp"
#include "../components/legged-locomotion-component.hpp"
#include "../components/steering-component.hpp"
#include "../components/transform-component.hpp"
#include "../system.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
typedef EntityGroup<BehaviorComponent, LeggedLocomotionComponent, SteeringComponent, TransformComponent> BehaviorGroup;
typedef EntityGroup<AntHillComponent, TransformComponent> AntHillGroup;
class BehaviorSystem: public
System,
BehaviorGroup::Observer
{
public:
BehaviorSystem(ComponentManager* componentManager);
virtual ~BehaviorSystem();
virtual void update(float t, float dt);
private:
BehaviorGroup behaviorGroup;
AntHillGroup antHillGroup;
virtual void memberRegistered(const BehaviorGroup::Member* member);
virtual void memberUnregistered(const BehaviorGroup::Member* member);
Vector3 containment(const BehaviorGroup::Member* agent);
Vector3 wander(float dt, const BehaviorGroup::Member* agent);
Vector3 forage(const BehaviorGroup::Member* agent);
Vector3 homing(const BehaviorGroup::Member* agent);
};
#endif // BEHAVIOR_SYSTEM_HPP

+ 65
- 0
src/entity/systems/collision-system.cpp View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "collision-system.hpp"
CollisionSystem::CollisionSystem(ComponentManager* componentManager):
System(componentManager),
entityGroup(componentManager)
{}
CollisionSystem::~CollisionSystem()
{}
void CollisionSystem::update(float t, float dt)
{
auto members = entityGroup.getMembers();
// INEFFICIENT! Currently done twice (A vs B, then B vs A)
// Also no octrees or other structure
for (const CollisionEntityGroup::Member* memberA: *members)
{
CollisionComponent* collisionA = std::get<0>(memberA->components);
TransformComponent* transformA = std::get<1>(memberA->components);
// Clear previous collisions
collisionA->collisions.clear();
for (const CollisionEntityGroup::Member* memberB: *members)
{
if (memberA == memberB)
{
continue;
}
CollisionComponent* collisionB = std::get<0>(memberB->components);
TransformComponent* transformB = std::get<1>(memberB->components);
Vector3 difference = transformA->transform.translation - transformB->transform.translation;
float distanceSquared = glm::length2(difference);
float collisionRadius = collisionA->radius + collisionB->radius;
if (distanceSquared <= collisionRadius * collisionRadius)
{
collisionA->collisions.push_back(memberB->entity);
}
}
}
}

+ 46
- 0
src/entity/systems/collision-system.hpp View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COLLISION_SYSTEM_HPP
#define COLLISION_SYSTEM_HPP
#include "../entity-group.hpp"
#include "../components/collision-component.hpp"
#include "../components/transform-component.hpp"
#include "../system.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
typedef EntityGroup<CollisionComponent, TransformComponent> CollisionEntityGroup;
class CollisionSystem: public System
{
public:
CollisionSystem(ComponentManager* componentManager);
virtual ~CollisionSystem();
virtual void update(float t, float dt);
private:
CollisionEntityGroup entityGroup;
};
#endif // COLLISION_SYSTEM_HPP

+ 107
- 0
src/entity/systems/locomotion-system.cpp View File

@ -0,0 +1,107 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "locomotion-system.hpp"
#include "../../triangle-mesh-operations.hpp"
LocomotionSystem::LocomotionSystem(ComponentManager* componentManager):
System(componentManager),
leggedLocomotionGroup(componentManager)
{
leggedLocomotionGroup.addGroupObserver(this);
}
LocomotionSystem::~LocomotionSystem()
{}
void LocomotionSystem::update(float t, float dt)
{
auto members = leggedLocomotionGroup.getMembers();
// Perform legged locomotion
for (const LeggedLocomotionGroup::Member* member: *members)
{
LeggedLocomotionComponent* leggedLocomotion = std::get<0>(member->components);
SteeringComponent* steering = std::get<1>(member->components);
TransformComponent* transform = std::get<2>(member->components);
// Skip entities which are not on a surface
if (!leggedLocomotion->surface)
{
continue;
}
// Determine target position
Vector3 force = steering->force * dt;
float speed = steering->speed * dt;
if (speed == 0.0f)
{
continue;
}
// Calculate direction vector
Vector3 direction = force * (1.0f / speed);
std::vector<WrapOperationSegment> segments;
float wrapDistance = wrap(leggedLocomotion->surface, transform->transform.translation, direction, speed, &segments);
WrapOperationSegment segment = segments.back();
Vector3 cartesianStart = cartesian(segment.startPosition,
segment.triangle->edge->vertex->position,
segment.triangle->edge->next->vertex->position,
segment.triangle->edge->previous->vertex->position);
Vector3 cartesianEnd = cartesian(segment.endPosition,
segment.triangle->edge->vertex->position,
segment.triangle->edge->next->vertex->position,
segment.triangle->edge->previous->vertex->position);
// Calculate wrap direction of final segment
Vector3 segmentDirection(0.0f);
if (cartesianStart != cartesianEnd)
{
segmentDirection = glm::normalize(cartesianEnd - cartesianStart);
}
// Determine angle between the triangles
float angle = std::acos(glm::dot(leggedLocomotion->surface->normal, segment.triangle->normal));
if (std::abs(angle) > glm::radians(35.0f))
{
// Transition
}
leggedLocomotion->surface = segment.triangle;
leggedLocomotion->barycentricPosition = segment.endPosition;
transform->transform.translation = cartesianEnd;
if (cartesianStart != cartesianEnd)
{
transform->transform.rotation = lookRotation(segmentDirection, segment.triangle->normal);
}
}
}
void LocomotionSystem::memberRegistered(const LeggedLocomotionGroup::Member* member)
{}
void LocomotionSystem::memberUnregistered(const LeggedLocomotionGroup::Member* member)
{}

+ 52
- 0
src/entity/systems/locomotion-system.hpp View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LOCOMOTION_SYSTEM_HPP
#define LOCOMOTION_SYSTEM_HPP
#include "../entity-group.hpp"
#include "../components/legged-locomotion-component.hpp"
#include "../components/steering-component.hpp"
#include "../components/transform-component.hpp"
#include "../system.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
typedef EntityGroup<LeggedLocomotionComponent, SteeringComponent, TransformComponent> LeggedLocomotionGroup;
class LocomotionSystem: public
System,
LeggedLocomotionGroup::Observer
{
public:
LocomotionSystem(ComponentManager* componentManager);
virtual ~LocomotionSystem();
virtual void update(float t, float dt);
private:
LeggedLocomotionGroup leggedLocomotionGroup;
virtual void memberRegistered(const LeggedLocomotionGroup::Member* member);
virtual void memberUnregistered(const LeggedLocomotionGroup::Member* member);
};
#endif // LOCOMOTION_SYSTEM_HPP

+ 161
- 0
src/entity/systems/particle-system.cpp View File

@ -0,0 +1,161 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "particle-system.hpp"
#include "../../game/curl-noise.hpp"
ParticleSystem::ParticleSystem(ComponentManager* componentManager):
System(componentManager),
range(nullptr),
material(nullptr)
{
batch.setTransform(Transform::getIdentity());
batch.setCullingEnabled(false);
}
ParticleSystem::~ParticleSystem()
{}
void ParticleSystem::resize(std::size_t count)
{
particles.resize(count);
batch.resize(count);
range = batch.addRange();
range->start = 0;
range->length = particles.size();
range->material = material;
while (!stack.empty())
stack.pop();
for (int i = 0; i < particles.size(); ++i)
{
Particle& particle = particles[i];
particle.life = 0.0f;
particle.size = 0.0f;
Billboard* billboard = batch.getBillboard(i);
billboard->setDimensions(Vector2(particle.size));
billboard->resetTweens();
stack.push(i);
}
}
void ParticleSystem::emit(const Vector3& position)
{
if (!stack.empty())
{
std::size_t index = stack.top();
stack.pop();
Particle& particle = particles[index];
particle.life = frand(1.0f, 5.0f);
particle.translation = position;
particle.size = frand(0.01f, 0.2f);
particle.speed = frand(2.0f, 3.0f);
particle.direction = direction + Vector3(frand(-1, 1), 0, frand(-1, 1)) * 0.1f;
particle.direction = glm::normalize(particle.direction);
Billboard* billboard = batch.getBillboard(index);
billboard->setTranslation(particle.translation);
billboard->setRotation(Quaternion(1, 0, 0, 0));
billboard->setDimensions(Vector2(particle.size));
billboard->setTintColor(Vector4(1.0f));
billboard->resetTweens();
}
}
void ParticleSystem::update(float t, float dt)
{
if (stack.size() == particles.size())
{
// Inactive
return;
}
batch.reset();
const Vector3 wind = glm::normalize(Vector3(1.0f, 0.0f, -1.0f)) * 1.5f * dt;
float frequency = 0.4f;
Vector3 noiseOffset = Vector3(77.7f, 33.3f, 11.1f) * t * 0.01f;
for (std::size_t i = 0; i < particles.size(); ++i)
{
Particle& particle = particles[i];
if (particle.life <= 0.0f)
{
continue;
}
Billboard* billboard = batch.getBillboard(i);
bool reset = false;
Vector3 smoke = curl(particle.translation, noiseOffset, frequency) * 8.0f;
particle.translation += particle.direction * particle.speed * dt + smoke * dt + wind;
particle.size += 0.1f * dt;
particle.life -= dt;
if (particle.life <= 0.0f)
{
particle.size = 0.0f;
reset = true;
stack.push(i);
}
billboard->setTranslation(particle.translation);
billboard->setRotation(Quaternion(1, 0, 0, 0));
billboard->setDimensions(Vector2(particle.size));
billboard->setTintColor(Vector4(0.5f));
if (reset)
{
billboard->resetTweens();
}
}
}
void ParticleSystem::setMaterial(Material* material)
{
this->material = material;
if (range)
{
range->material = material;
}
}
void ParticleSystem::setDirection(const Vector3& direction)
{
this->direction = direction;
}
void ParticleSystem::setLifeTime(float time)
{
this->lifeTime = time;
}
void ParticleSystem::setEmissionRate(float frequency)
{
this->emissionRate = frequency;
}

+ 86
- 0
src/entity/systems/particle-system.hpp View File

@ -0,0 +1,86 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PARTICLE_SYSTEM_HPP
#define PARTICLE_SYSTEM_HPP
#include "../components/model-component.hpp"
#include "../components/transform-component.hpp"
#include "../entity-group.hpp"
#include "../system.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
#include <stack>
class ParticleSystem:
public System
{
public:
ParticleSystem(ComponentManager* componentManager);
~ParticleSystem();
void setMaterial(Material* material);
void setParticleCount(std::size_t count);
void setDirection(const Vector3& direction);
void setLifeTime(float time);
void setEmissionRate(float frequency);
const BillboardBatch* getBillboardBatch() const;
BillboardBatch* getBillboardBatch();
void resize(std::size_t count);
virtual void update(float t, float dt);
void emit(const Vector3& position);
private:
struct Particle
{
Vector3 translation;
float size;
float life;
float speed;
Vector3 direction;
};
BillboardBatch batch;
BillboardBatch::Range* range;
Material* material;
std::vector<Particle> particles;
Vector3 direction;
float lifeTime;
float emissionRate;
std::stack<std::size_t> stack;
};
inline const BillboardBatch* ParticleSystem::getBillboardBatch() const
{
return &batch;
}
inline BillboardBatch* ParticleSystem::getBillboardBatch()
{
return &batch;
}
#endif // PARTICLE_SYSTEM_HPP

+ 56
- 0
src/entity/systems/render-system.cpp View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "render-system.hpp"
RenderSystem::RenderSystem(ComponentManager* componentManager, SceneLayer* scene):
System(componentManager),
modelEntityGroup(componentManager),
scene(scene)
{
modelEntityGroup.addGroupObserver(this);
}
RenderSystem::~RenderSystem()
{}
void RenderSystem::update(float t, float dt)
{
auto members = modelEntityGroup.getMembers();
for (const ModelEntityGroup::Member* member: *members)
{
ModelComponent* model = std::get<0>(member->components);
TransformComponent* transform = std::get<1>(member->components);
model->model.setTransform(transform->transform);
}
}
void RenderSystem::memberRegistered(const ModelEntityGroup::Member* member)
{
ModelComponent* model = std::get<0>(member->components);
scene->addObject(&model->model);
}
void RenderSystem::memberUnregistered(const ModelEntityGroup::Member* member)
{
ModelComponent* model = std::get<0>(member->components);
scene->removeObject(&model->model);
}

+ 55
- 0
src/entity/systems/render-system.hpp View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef RENDER_SYSTEM_HPP
#define RENDER_SYSTEM_HPP
#include "../components/model-component.hpp"
#include "../components/transform-component.hpp"
#include "../entity-group.hpp"
#include "../system.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
typedef EntityGroup<ModelComponent, TransformComponent> ModelEntityGroup;
/**
* Abstract base class for entity systems.
*/
class RenderSystem: public
System,
ModelEntityGroup::Observer
{
public:
RenderSystem(ComponentManager* componentManager, SceneLayer* scene);
virtual ~RenderSystem();
virtual void update(float t, float dt);
private:
ModelEntityGroup modelEntityGroup;
SceneLayer* scene;
virtual void memberRegistered(const ModelEntityGroup::Member* member);
virtual void memberUnregistered(const ModelEntityGroup::Member* member);
};
#endif // RENDER_SYSTEM_HPP

+ 119
- 0
src/entity/systems/sound-system.cpp View File

@ -0,0 +1,119 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sound-system.hpp"
#include <stdexcept>
#include "dr_libs/dr_wav.h"
SoundSystem::SoundSystem(ComponentManager* componentManager):
System(componentManager),
entityGroup(componentManager),
device(nullptr),
context(nullptr)
{
device = alcOpenDevice(nullptr);
if (!device)
{
throw std::runtime_error("SoundSystem::SoundSystem(): Failed to open audio device.");
}
context = alcCreateContext(device, nullptr);
if (!alcMakeContextCurrent(context))
{
throw std::runtime_error("SoundSystem::SoundSystem(): Failed to create audio context.");
}
ALfloat listenerOrientation[] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f };
alListener3f(AL_POSITION, 0.0f, 0.0f, 1.0f);
alListener3f(AL_VELOCITY, 0.0f, 0.0f, 0.0f);
alListenerfv(AL_ORIENTATION, listenerOrientation);
alGenSources((ALuint)1, &source);
alSourcef(source, AL_PITCH, 1);
alSourcef(source, AL_GAIN, 1);
alSource3f(source, AL_POSITION, 0, 0, 0);
alSource3f(source, AL_VELOCITY, 0, 0, 0);
alSourcei(source, AL_LOOPING, AL_FALSE);
alGenBuffers((ALuint)1, &buffer);
// Load wav file
{
const char* filename = "/home/cjhoward/projects/antkeeper/modules/antkeeper-data/sounds/shutter.wav";
unsigned int channels;
unsigned int sampleRate;
drwav_uint64 frameCount;
std::int16_t* sampleData = drwav_open_file_and_read_pcm_frames_s16(filename, &channels, &sampleRate, &frameCount);
if (sampleData == nullptr)
{
throw std::runtime_error("Couldn't load wav file");
drwav_free(sampleData);
}
bool stereo = (channels > 1);
ALenum format = (stereo) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;
std::size_t sampleCount = frameCount * channels;
std::size_t sampleDataSize = sampleCount * sizeof(drwav_int16);
alBufferData(buffer, format, sampleData, sampleDataSize, sampleRate);
}
alSourcei(source, AL_BUFFER, buffer);
//alSourcePlay(source);
}
SoundSystem::~SoundSystem()
{
alDeleteSources(1, &source);
alDeleteBuffers(1, &buffer);
alcMakeContextCurrent(nullptr);
alcDestroyContext(context);
alcCloseDevice(device);
}
void SoundSystem::scrot()
{
alSourcePlay(source);
}
void SoundSystem::update(float t, float dt)
{
auto members = entityGroup.getMembers();
for (const SoundSourceEntityGroup::Member* member: *members)
{
TransformComponent* transform = std::get<0>(member->components);
SoundSourceComponent* sound = std::get<1>(member->components);
}
}
void SoundSystem::memberRegistered(const SoundSourceEntityGroup::Member* member)
{
TransformComponent* transform = std::get<0>(member->components);
SoundSourceComponent* sound = std::get<1>(member->components);
}
void SoundSystem::memberUnregistered(const SoundSourceEntityGroup::Member* member)
{
TransformComponent* transform = std::get<0>(member->components);
SoundSourceComponent* sound = std::get<1>(member->components);
}

+ 56
- 0
src/entity/systems/sound-system.hpp View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SOUND_SYSTEM_HPP
#define SOUND_SYSTEM_HPP
#include "../entity-group.hpp"
#include "../system.hpp"
#include "../components/sound-source-component.hpp"
#include "../components/transform-component.hpp"
#include <AL/al.h>
#include <AL/alc.h>
typedef EntityGroup<TransformComponent, SoundSourceComponent> SoundSourceEntityGroup;
class SoundSystem:
public System,
public SoundSourceEntityGroup::Observer
{
public:
SoundSystem(ComponentManager* componentManager);
virtual ~SoundSystem();
virtual void update(float t, float dt);
void scrot();
private:
virtual void memberRegistered(const SoundSourceEntityGroup::Member* member);
virtual void memberUnregistered(const SoundSourceEntityGroup::Member* member);
SoundSourceEntityGroup entityGroup;
ALCdevice* device;
ALCcontext* context;
ALuint source;
ALuint buffer;
};
#endif // SOUND_SYSTEM_HPP

+ 96
- 0
src/entity/systems/steering-system.cpp View File

@ -0,0 +1,96 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "steering-system.hpp"
SteeringSystem::SteeringSystem(ComponentManager* componentManager):
System(componentManager),
boids(componentManager)
{
boids.addGroupObserver(this);
}
SteeringSystem::~SteeringSystem()
{}
void SteeringSystem::update(float t, float dt)
{
auto members = boids.getMembers();
for (const SteeringGroup::Member* member: *members)
{
SteeringComponent* steering = std::get<0>(member->components);
// Initialize summed steering force
steering->force = Vector3(0.0f);
steering->speed = 0.0f;
float speedSquared = 0.0f;
float maxSpeedSquared = steering->maxSpeed * steering->maxSpeed;
bool truncated = false;
if (steering->behaviorCount > 0)
{
// Sort steering beaviors by priority
std::sort(steering->behaviors, steering->behaviors + steering->behaviorCount,
[](const SteeringBehavior& a, const SteeringBehavior& b) -> bool
{
return (a.priority >= b.priority);
}
);
}
// Evaluate steering forces in order
for (std::size_t i = 0; i < steering->behaviorCount; ++i)
{
const SteeringBehavior& behavior = steering->behaviors[i];
// Skip zero-weighted steering behaviors
if (behavior.weight == 0.0f)
{
continue;
}
// Add weighted steering behavior force
steering->force += behavior.function() * behavior.weight;
// Limit speed
speedSquared = glm::length2(steering->force);
if (speedSquared >= maxSpeedSquared)
{
steering->force *= (1.0f / std::sqrt(speedSquared)) * steering->maxSpeed;
steering->speed = steering->maxSpeed;
truncated = true;
break;
}
}
if (!truncated)
{
steering->speed = std::sqrt(speedSquared);
}
}
}
void SteeringSystem::memberRegistered(const SteeringGroup::Member* member)
{}
void SteeringSystem::memberUnregistered(const SteeringGroup::Member* member)
{}

+ 53
- 0
src/entity/systems/steering-system.hpp View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef STEERING_SYSTEM_HPP
#define STEERING_SYSTEM_HPP
#include "../entity-group.hpp"
#include "../components/steering-component.hpp"
#include "../system.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
typedef EntityGroup<SteeringComponent> SteeringGroup;
class SteeringSystem: public
System,
SteeringGroup::Observer
{
public:
SteeringSystem(ComponentManager* componentManager);
virtual ~SteeringSystem();
/**
* Calculates the steering force for each steering component using weighted truncated running sums with prioritization.
*/
virtual void update(float t, float dt);
private:
SteeringGroup boids;
virtual void memberRegistered(const SteeringGroup::Member* member);
virtual void memberUnregistered(const SteeringGroup::Member* member);
};
#endif // STEERING_SYSTEM_HPP

+ 96
- 0
src/entity/systems/tool-system.cpp View File

@ -0,0 +1,96 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tool-system.hpp"
ToolSystem::ToolSystem(ComponentManager* componentManager):
System(componentManager),
tools(componentManager),
picked(false)
{
tools.addGroupObserver(this);
}
ToolSystem::~ToolSystem()
{}
void ToolSystem::update(float t, float dt)
{
pick();
auto members = tools.getMembers();
for (const ToolGroup::Member* member: *members)
{
ModelComponent* model = std::get<0>(member->components);
ToolComponent* tool = std::get<1>(member->components);
TransformComponent* transform = std::get<2>(member->components);
model->model.setActive(tool->active);
if (picked)
{
transform->transform.translation = mouseWorldPosition;
}
}
picked = false;
}
void ToolSystem::setPickingCamera(const Camera* camera)
{
pickingCamera = camera;
}
void ToolSystem::setPickingViewport(const Vector4& viewport)
{
pickingViewport = viewport;
}
void ToolSystem::pick()
{
Vector3 mouseNear = pickingCamera->unproject(Vector3(mouseScreenPosition, 0.0f), pickingViewport);
Vector3 mouseFar = pickingCamera->unproject(Vector3(mouseScreenPosition, 1.0f), pickingViewport);
Ray pickingRay;
pickingRay.origin = mouseNear;
pickingRay.direction = glm::normalize(mouseFar - mouseNear);
Plane pickingPlane(Vector3(0.0f, 1.0f, 0.0f), Vector3(0.0f));
auto pickingIntersection = pickingRay.intersects(pickingPlane);
picked = std::get<0>(pickingIntersection);
if (picked)
{
mouseWorldPosition = pickingRay.extrapolate(std::get<1>(pickingIntersection));
}
}
void ToolSystem::memberRegistered(const ToolGroup::Member* member)
{
ToolComponent* tool = std::get<1>(member->components);
tool->active = false;
}
void ToolSystem::memberUnregistered(const ToolGroup::Member* member)
{}
void ToolSystem::handleEvent(const MouseMovedEvent& event)
{
mouseScreenPosition = Vector2(event.x, pickingViewport[3] - event.y);
}

+ 66
- 0
src/entity/systems/tool-system.hpp View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TOOL_SYSTEM_HPP
#define TOOL_SYSTEM_HPP
#include "../entity-group.hpp"
#include "../components/model-component.hpp"
#include "../components/tool-component.hpp"
#include "../components/transform-component.hpp"
#include "../system.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
typedef EntityGroup<ModelComponent, ToolComponent, TransformComponent> ToolGroup;
/**
* Abstract base class for entity systems.
*/
class ToolSystem:
public System,
public ToolGroup::Observer,
public EventHandler<MouseMovedEvent>
{
public:
ToolSystem(ComponentManager* componentManager);
virtual ~ToolSystem();
virtual void update(float t, float dt);
void setPickingCamera(const Camera* camera);
void setPickingViewport(const Vector4& viewport);
private:
void pick();
virtual void memberRegistered(const ToolGroup::Member* member);
virtual void memberUnregistered(const ToolGroup::Member* member);
virtual void handleEvent(const MouseMovedEvent& event);
Vector2 mouseScreenPosition;
Vector3 mouseWorldPosition;
const Camera* pickingCamera;
Vector4 pickingViewport;
bool picked;
ToolGroup tools;
};
#endif // TOOL_SYSTEM_HPP

+ 1719
- 0
src/game.cpp
File diff suppressed because it is too large
View File


+ 404
- 0
src/game.hpp View File

@ -0,0 +1,404 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GAME_HPP
#define GAME_HPP
#include <emergent/emergent.hpp>
using namespace Emergent;
#include "entity/entity-id.hpp"
#include <map>
#include <string>
#include <vector>
class GameState;
class SplashState;
class SandboxState;
class UIContainer;
class UIBatcher;
class UIImage;
class UILabel;
class UIRenderPass;
class ClearRenderPass;
class SkyRenderPass;
class ShadowMapRenderPass;
class LightingRenderPass;
class SilhouetteRenderPass;
class FinalRenderPass;
class ResourceManager;
typedef std::vector<std::vector<std::string>> CSVTable;
class CameraRig;
class OrbitCam;
class FreeCam;
class Tool;
class Lens;
class Forceps;
class Brush;
class ParticleSystem;
class EntityManager;
class ComponentManager;
class SystemManager;
class SoundSystem;
class CollisionSystem;
class RenderSystem;
class ToolSystem;
class BehaviorSystem;
class SteeringSystem;
class LocomotionSystem;
class TestEvent: public Event<TestEvent>
{
public:
inline EventBase* clone() const
{
TestEvent* event = new TestEvent();
event->id = id;
return event;
}
int id;
};
class Game:
public Application,
public EventHandler<TestEvent>
{
public:
/**
* Creates a game instance.
*
* @param argc Argument count
* @param argv Argument list
*/
Game(int argc, char* argv[]);
/// Destroys a game instance.
virtual ~Game();
/**
* Gets a string in the specified language.
*
* @param languageIndex Index of a language.
* @param name Name of the string.
* @return String in the specified language.
*/
std::string getString(std::size_t languageIndex, const std::string& name) const;
/**
* Changes the current language.
*
* @param languageIndex Index of the language to use.
*/
void changeLanguage(std::size_t languageIndex);
/// Returns the number of available languages.
std::size_t getLanguageCount() const;
/// Returns the index of the current language.
std::size_t getCurrentLanguage() const;
void toggleFullscreen();
void setUpdateRate(double frequency);
/**
* Changes the game state.
*
* @param state New game state.
*/
void changeState(GameState* state);
const EventDispatcher* getEventDispatcher() const;
EventDispatcher* getEventDispatcher();
const Animator* getAnimator() const;
Animator* getAnimator();
void fadeIn(float duration, const Vector3& color, std::function<void()> callback);
void fadeOut(float duration, const Vector3& color, std::function<void()> callback);
void selectTool(int toolIndex);
void pushNotification(const std::string& text);
void popNotification();
private:
virtual void setup();
virtual void input();
virtual void update(float t, float dt);
virtual void render();
virtual void exit();
virtual void handleEvent(const WindowResizedEvent& event);
virtual void handleEvent(const KeyPressedEvent& event);
virtual void handleEvent(const TestEvent& event);
void resizeUI(int w, int h);
void restringUI();
void resizeRenderTargets();
void setTimeOfDay(float time);
void toggleWireframe();
void screenshot();
void queueScreenshot();
public:
EntityID createInstanceOf(const std::string& templateName);
void destroyInstance(EntityID entity);
void setTranslation(EntityID entity, const Vector3& translation);
void setRotation(EntityID entity, const Quaternion& rotation);
void setScale(EntityID entity, const Vector3& scale);
void boxSelect(float x, float y, float w, float h);
public:
// States
GameState* currentState;
SplashState* splashState;
SandboxState* sandboxState;
// Paths
std::string dataPath;
std::string configPath;
// Localization
CSVTable* stringTable;
std::map<std::string, std::size_t> stringMap;
std::size_t languageCount;
std::size_t currentLanguage;
// Window management
Window* window;
bool fullscreen;
std::string title;
int w, h;
float dpi;
float fontSizePT;
float fontSizePX;
// Input
Mouse* mouse;
Keyboard* keyboard;
ControlProfile controlProfile;
Control fullscreenControl;
Control closeControl;
Control openRadialMenuControl;
Control moveForwardControl;
Control moveBackControl;
Control moveLeftControl;
Control moveRightControl;
Control rotateCCWControl;
Control rotateCWControl;
Control zoomInControl;
Control zoomOutControl;
Control adjustCameraControl;
Control dragCameraControl;
Control toggleNestViewControl;
Control toggleWireframeControl;
Control screenshotControl;
Control toggleEditModeControl;
// Logic
float time;
float timestep;
// UI
Typeface* labelTypeface;
Font* labelFont;
Typeface* debugTypeface;
Font* debugFont;
BillboardBatch* uiBatch;
UIBatcher* uiBatcher;
UIContainer* uiRootElement;
UIImage* splashBackgroundImage;
UIImage* splashImage;
UIContainer* hudContainer;
UIImage* toolIndicatorBGImage;
UIImage* toolIndicatorIconImage;
Rect* toolIndicatorsBounds;
UIImage* toolIconBrushImage;
UIImage* toolIconLensImage;
UIImage* toolIconForcepsImage;
UIImage* toolIconSpadeImage;
UIImage* toolIconCameraImage;
UIImage* toolIconTestTubeImage;
UIContainer* buttonContainer;
UIImage* playButtonBGImage;
UIImage* fastForwardButtonBGImage;
UIImage* pauseButtonBGImage;
UIImage* playButtonImage;
UIImage* fastForwardButtonImage;
UIImage* pauseButtonImage;
UIContainer* radialMenuContainer;
UIImage* radialMenuBackgroundImage;
UIImage* radialMenuImage;
UIImage* radialMenuSelectorImage;
UIImage* blackoutImage;
UIImage* cameraFlashImage;
UIImage* notificationBoxImage;
int notificationCount;
UIContainer* antTag;
UIContainer* antLabelContainer;
UILabel* fpsLabel;
UILabel* antLabel;
UIImage* antLabelTL; // Top-left
UIImage* antLabelTR; // Top-right
UIImage* antLabelBL; // Bottom-left
UIImage* antLabelBR; // Bottom-right
UIImage* antLabelCC; // Center-center
UIImage* antLabelCT; // Center-top
UIImage* antLabelCB; // Center-bottom
UIImage* antLabelCL; // Center-left
UIImage* antLabelCR; // Center-right
UIImage* antLabelPinHole;
UIImage* antPin;
UIImage* boxSelectionImageBackground;
UIImage* boxSelectionImageTop;
UIImage* boxSelectionImageBottom;
UIImage* boxSelectionImageLeft;
UIImage* boxSelectionImageRight;
UIContainer* boxSelectionContainer;
float boxSelectionBorderWidth;
UIImage* cameraGridY0Image;
UIImage* cameraGridY1Image;
UIImage* cameraGridX0Image;
UIImage* cameraGridX1Image;
UIContainer* cameraGridContainer;
Vector4 cameraGridColor;
// Rendering
Renderer renderer;
RenderTarget defaultRenderTarget;
ClearRenderPass* clearPass;
ClearRenderPass* clearSilhouettePass;
SkyRenderPass* skyPass;
UIRenderPass* uiPass;
Compositor uiCompositor;
Compositor defaultCompositor;
int shadowMapResolution;
GLuint shadowMapDepthTextureID;
GLuint shadowMapFramebuffer;
RenderTarget shadowMapRenderTarget;
ShadowMapRenderPass* shadowMapPass;
Compositor shadowMapCompositor;
Texture2D shadowMapDepthTexture;
LightingRenderPass* lightingPass;
SilhouetteRenderPass* silhouettePass;
FinalRenderPass* finalPass;
RenderTarget silhouetteRenderTarget;
// Scene
Scene* scene;
SceneLayer* defaultLayer;
SceneLayer* uiLayer;
DirectionalLight sunlight;
Camera camera;
Camera sunlightCamera;
Camera uiCamera;
// Animation
Animator animator;
Animation<float> fadeInAnimation;
Animation<float> fadeOutAnimation;
AnimationClip<float> fadeInClip;
AnimationClip<float> fadeOutClip;
std::function<void()> fadeInEndCallback;
std::function<void()> fadeOutEndCallback;
Animation<Vector2> showNotificationAnimation;
Animation<float> hideNotificationAnimation;
AnimationClip<Vector2> showNotificationClip;
AnimationClip<float> hideNotificationClip;
Animation<float> cameraFlashAnimation;
AnimationClip<float> cameraFlashClip;
// Assets
ResourceManager* resourceManager;
Texture2D* splashTexture;
Texture2D* hudSpriteSheetTexture;
TextureAtlas hudTextureAtlas;
Material* smokeMaterial;
Model* lensModel;
Model* forcepsModel;
Model* brushModel;
// Game
CameraRig* cameraRig;
OrbitCam* orbitCam;
FreeCam* freeCam;
Tool* currentTool;
Lens* lens;
Forceps* forceps;
Brush* brush;
ParticleSystem* particleSystem;
// ECS
EntityManager* entityManager;
ComponentManager* componentManager;
SystemManager* systemManager;
SoundSystem* soundSystem;
CollisionSystem* collisionSystem;
RenderSystem* renderSystem;
ToolSystem* toolSystem;
BehaviorSystem* behaviorSystem;
SteeringSystem* steeringSystem;
LocomotionSystem* locomotionSystem;
EntityID lollipop;
bool wireframe;
bool screenshotQueued;
private:
static void saveScreenshot(const std::string& filename, unsigned int width, unsigned int height, unsigned char* pixels);
};
inline const EventDispatcher* Game::getEventDispatcher() const
{
return &eventDispatcher;
}
inline EventDispatcher* Game::getEventDispatcher()
{
return &eventDispatcher;
}
inline const Animator* Game::getAnimator() const
{
return &animator;
}
inline Animator* Game::getAnimator()
{
return &animator;
}
inline std::size_t Game::getLanguageCount() const
{
return languageCount;
}
inline std::size_t Game::getCurrentLanguage() const
{
return currentLanguage;
}
#endif // GAME_HPP

+ 0
- 222
src/game/agent.cpp View File

@ -1,222 +0,0 @@
/*
* Copyright (C) 2017 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "agent.hpp"
Agent::Agent():
navmeshTriangle(nullptr),
barycentricPosition(0.0f),
position(0.0f),
forward(0, 0, -1),
up(0, 1, 0),
right(1, 0, 0),
rotation(1, 0, 0, 0)
//wanderDirection(0, 0, -1),
//velocity(0.0f)
{}
/*
void Agent::applyForce(const Vector3& force)
{
acceleration += force;
}
void Agent::updateVelocity()
{
// Limit acceleration
acceleration = limit(acceleration / mass, maxAcceleration);
// Add acceleration to velocity and limit
velocity = limit(velocity + acceleration, maxSpeed);
// Reset acceleration to zero
acceleration = Vector3(0.0f);
}
Vector3 Agent::wander(float dt)
{
// Calculate center of wander circle
Vector3 wanderCircleCenter = position + forward * wanderCircleDistance;
// Calculate wander force
Vector3 target = wanderCircleCenter + wanderDirection * wanderCircleRadius;
// Rotate wander direction by a random displacement angle
float displacement = frand(-wanderRate * 0.5f, wanderRate * 0.5f);
wanderDirection = glm::normalize(glm::angleAxis(displacement, up) * wanderDirection);
return seek(target);
}
Vector3 Agent::seek(const Vector3& target) const
{
Vector3 desiredVelocity = glm::normalize(target - position) * maxSpeed;
return desiredVelocity - velocity;
}
Vector3 Agent::flee(const Vector3& target) const
{
Vector3 desiredVelocity = glm::normalize(position - target) * maxSpeed;
return desiredVelocity - velocity;
}
Vector3 Agent::containment(const Vector3& probe) const
{
std::vector<Navmesh::Step> traversal;
Navmesh::traverse(navmeshTriangle, barycentricPosition, probe, &traversal);
if (traversal.empty())
{
return Vector3(0.0f);
}
const Navmesh::Step& step = traversal.back();
// If not on edge or on connected edge
if (step.edge == nullptr || step.edge->symmetric != nullptr)
{
return Vector3(0.0f);
}
// Calculate difference between probe position and position on edge
//Vector3 end = cartesian(step.end,
// step.triangle->edge->vertex->position,
// step.triangle->edge->next->vertex->position,
// step.triangle->edge->previous->vertex->position);
//Vector3 difference = probe - end;
//float depth = 0.0f;
//if (nonzero(difference))
//{
// depth = glm::length(difference);
//}
// Calculate edge normal
const Vector3& a = step.edge->vertex->position;
const Vector3& b = step.edge->next->vertex->position;
Vector3 ab = glm::normalize(b - a);
Vector3 edgeNormal = glm::cross(up, ab);
// Calculate reflection vector of forward vector and edge normal
//Vector3 reflection = glm::reflect(forward, edgeNormal);
//Vector3 target = cartesian(step.end,
// step.triangle->edge->vertex->position,
// step.triangle->edge->next->vertex->position,
// step.triangle->edge->previous->vertex->position) + reflection * 0.1f;
//std::cout << "reflection: " << reflection.x << ", " << reflection.y << ", " << reflection.z << std::endl;
return edgeNormal;
}
Vector3 Agent::separation(const std::list<Agent*>& neighbors) const
{
Vector3 force(0.0f);
for (Agent* neighbor: neighbors)
{
Vector3 difference = position - neighbor->position;
float distanceSquared = glm::dot(difference, difference);
if (distanceSquared > 0.0f && distanceSquared < separationRadiusSquared)
{
force += difference * (1.0f / distanceSquared);
}
}
if (nonzero(force))
{
force = glm::normalize(force);
}
return force;
}
*/
void Agent::setPosition(Navmesh::Triangle* triangle, const Vector3& position)
{
// Update navmesh triangle and position
navmeshTriangle = triangle;
barycentricPosition = position;
// Convert navmesh-space barycentric position to world-space cartesian position
const Vector3& a = triangle->edge->vertex->position;
const Vector3& b = triangle->edge->next->vertex->position;
const Vector3& c = triangle->edge->previous->vertex->position;
this->position = cartesian(position, a, b, c);
}
void Agent::setOrientation(const Vector3& newForward, const Vector3& newUp)
{
// Calculate alignment quaternion
Quaternion alignment = glm::rotation(up, newUp);
// Rebuild vector basis
forward = newForward;
right = glm::normalize(glm::cross(newUp, forward));
up = glm::cross(forward, right);
// Calculate rotation quaternion from vector basis
rotation = glm::normalize(glm::quat_cast(Matrix3(right, up, forward)));
// Align wander direction
//wanderDirection = glm::normalize(project_on_plane(alignment * wanderDirection, Vector3(0.0f), up));
}
/*
void Agent::setMaxSpeed(float speed)
{
maxSpeed = speed;
}
void Agent::setVelocity(const Vector3& velocity)
{
this->velocity = velocity;
}
void Agent::setWanderCircleDistance(float distance)
{
wanderCircleDistance = distance;
}
void Agent::setWanderCircleRadius(float radius)
{
wanderCircleRadius = radius;
}
void Agent::setWanderRate(float angle)
{
wanderRate = angle;
}
void Agent::setSeparationRadius(float radius)
{
separationRadius = radius;
separationRadiusSquared = separationRadius * separationRadius;
}
*/
/** EXAMPLE USAGE
Vector3 wanderForce = wander(dt) * wanderWeight;
Vector3 fleeForce = flee(mouse) * fleeWeight;
Vector3 steerForce = wanderForce + fleeForce;
steer(steerForce);
**/

+ 0
- 216
src/game/agent.hpp View File

@ -1,216 +0,0 @@
/*
* Copyright (C) 2017 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AGENT_HPP
#define AGENT_HPP
#include "navmesh.hpp"
#include <vector>
#include <emergent/emergent.hpp>
using namespace Emergent;
class Obstacle;
/*************88
Ant is an agent.
Ant combines steering behaviors with different weights.
I.E.
seek pheromones * 0.5
separation * 0.1
alignment * 0.1
cohesion * 0.1
followWall * 0.2
*/
/**
* An agent which navigates on a navmesh.
*/
class Agent
{
public:
Agent();
/**
* Adds a force to the agent's acceleration vector.
*
* @param force Acceleration force
*/
//void applyForce(const Vector3& force);
/**
* Calculates velocity based on current acceleration vector, then resets acceleration to zero.
*/
//void updateVelocity();
/**
* Calculates steering force for the wander behavior.
*/
//Vector3 wander(float dt);
/**
* Calculates steering force for the seek behavior.
*/
//Vector3 seek(const Vector3& target) const;
/**
* Calculates steering force for the flee behavior.
*/
//Vector3 flee(const Vector3& target) const;
//Vector3 containment(const Vector3& probe) const;
//Vector3 separation(const std::list<Agent*>& neighbors) const;
//Vector3 forage(const Vector3& leftProbe, const Vector3& rightProbe);
/*
void setMaxSpeed(float speed);
void setVelocity(const Vector3& velocity);
void setMaxAcceleration(float acceleration);
void setMass(float mass);
void setWanderCircleDistance(float distance);
void setWanderCircleRadius(float radius);
void setWanderRate(float angle);
void setSeparationRadius(float radius);
*/
/**
* Sets the position of the agent on a navmesh.
*
* @param triangle Navmesh triangle on which the agent resides
* @param position Barycentric position on the specified triangle
*/
void setPosition(Navmesh::Triangle* triangle, const Vector3& position);
/**
* Sets the orientation of the agent. This effectively updates the agent's vector basis and rotation quaternion.
*
* @param forward Normalized forward vector
* @param up Normalized up vector
*/
void setOrientation(const Vector3& newForward, const Vector3& newUp);
/*
Vector3 followWall();
// or
Vector3 followEdge();
Vector3 avoidObstacle(const Obstacle* obstacle);
Vector3 alignment(const std::vector<const Agent*>* neighbors);
Vector3 cohesion(const std::vector<const Agent*>* neighbors);
*/
const Navmesh::Triangle* getNavmeshTriangle() const;
Navmesh::Triangle* getNavmeshTriangle();
const Vector3& getBarycentricPosition() const;
const Vector3& getPosition() const;
const Vector3& getForward() const;
const Vector3& getUp() const;
const Vector3& getRight() const;
const Quaternion& getRotation() const;
//const Vector3& getVelocity() const;
private:
Navmesh::Triangle* navmeshTriangle;
Vector3 barycentricPosition;
Vector3 position;
Vector3 forward;
Vector3 up;
Vector3 right;
Quaternion rotation;
/*
// Limits
float maxSpeed;
float maxAcceleration;
// Steering forces
float mass;
Vector3 acceleration;
Vector3 velocity;
// Wander variables
float wanderCircleDistance;
float wanderCircleRadius;
float wanderRate;
Vector3 wanderDirection;
float separationRadius;
float separationRadiusSquared;
*/
};
inline const Navmesh::Triangle* Agent::getNavmeshTriangle() const
{
return navmeshTriangle;
}
inline Navmesh::Triangle* Agent::getNavmeshTriangle()
{
return navmeshTriangle;
}
inline const Vector3& Agent::getBarycentricPosition() const
{
return barycentricPosition;
}
inline const Vector3& Agent::getPosition() const
{
return position;
}
inline const Vector3& Agent::getForward() const
{
return forward;
}
inline const Vector3& Agent::getUp() const
{
return up;
}
inline const Vector3& Agent::getRight() const
{
return right;
}
inline const Quaternion& Agent::getRotation() const
{
return rotation;
}
/*
inline const Vector3& Agent::getVelocity() const
{
return velocity;
}
*/
#endif // AGENT_HPP

+ 0
- 293
src/game/ant.cpp View File

@ -1,293 +0,0 @@
/*
* Copyright (C) 2017 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ant.hpp"
#include "colony.hpp"
#include "pheromone-matrix.hpp"
#include <cmath>
float FRAMES_PER_SECOND = 60;
float TIMESTEP = 1.0f / FRAMES_PER_SECOND;
float ANT_LENGTH = 0.5f; // 0.5 cm, head to abdomen (not including legs / antennae)
float ANT_COLLISION_RADIUS = ANT_LENGTH * 1.25f;
float RECEPTOR_RADIUS = 0.4f;
float RECEPTOR_SEPARATION = 0.882f;
float RECEPTOR_DISTANCE = 0.588f;
float MOUTH_DISTANCE = 0.2646f;
float BITE_RADIUS = 0.0294f;
float FOOD_PARTICLE_RADIUS = 0.1176f;
float MAX_RECEPTOR_NOISE = 0.05f; // essentially an epsilon
float MAX_EXCITEMENT = 1.0f;
float MAX_PHEROMONE_TURNING_ANGLE = glm::radians(8.5f);
float MIN_WALK_TIME = 0.5f; // seconds
float MAX_WALK_TIME = 8.0f; // seconds
float MIN_REST_TIME = 0.15f;
float MAX_REST_TIME = 0.7f;
float MIN_CHEW_TIME = 0.25f;
float MAX_CHEW_TIME = 0.5f;
float DEEXCITEMENT_FACTOR = 0.999f; // This should probably always be less than the evaporation factor
float CALM_FACTOR = 0.995f;
float MAX_WALK_FORCE = 1.5;
float MAX_PANIC_FORCE = 0.1029f;
float MAX_WALK_SPEED = 3.0f; // cm/s
float MAX_PANIC_SPEED = 8.82f; // cm/s
float PANIC_RADIUS = 7.35f;
float WANDER_CIRCLE_DISTANCE = 0.441f;
float WANDER_CIRCLE_RADIUS = 0.0294f;
float MAX_WANDER_ANGLE = 0.15f;
inline float fwrap(float angle, float limit)
{
return angle - std::floor(angle / limit) * limit;
}
Ant::Ant(Colony* colony):
colony(colony),
state(Ant::State::IDLE),
transform(Transform::getIdentity()),
pose(nullptr)
{
pose = new Pose(colony->getAntModel()->getSkeleton());
pose->reset();
pose->concatenate();
modelInstance.setModel(colony->getAntModel());
modelInstance.setPose(pose);
animationTime = frand(0.0f, 60.0f);
velocity = Vector3(0);
acceleration = Vector3(0);
wanderDirection = getForward();
excitement = MAX_EXCITEMENT;
}
Ant::~Ant()
{
delete pose;
}
void Ant::animate()
{
colony->getTripodGaitAnimation()->animate(pose, animationTime);
pose->concatenate();
animationTime = fwrap(animationTime + 4.0f, colony->getTripodGaitAnimation()->getEndTime());
}
void Ant::suspend(const Vector3& suspensionPoint, const Quaternion& suspensionRotation)
{
transform.translation = suspensionPoint;
transform.rotation = suspensionRotation;
modelInstance.setTransform(transform);
}
void Ant::move(const Vector3& velocity)
{
std::vector<Navmesh::Step> traversal;
Navmesh::traverse(getNavmeshTriangle(), getBarycentricPosition(), velocity, &traversal);
if (!traversal.empty())
{
const Navmesh::Step& step = traversal.back();
if (step.start != step.end)
{
if (step.triangle != getNavmeshTriangle())
{
Quaternion alignment = glm::rotation(getNavmeshTriangle()->normal, step.triangle->normal);
Vector3 newForward = glm::normalize(project_on_plane(alignment * getForward(), Vector3(0.0f), step.triangle->normal));
setOrientation(newForward, step.triangle->normal);
}
}
setPosition(step.triangle, step.end);
}
}
void Ant::turn(float angle)
{
// Rotate forward vector
Vector3 newForward = glm::normalize(glm::angleAxis(angle, getUp()) * getForward());
setOrientation(newForward, getUp());
}
void Ant::update(float dt)
{
float probeLateralOffset = 0.1f;
float probeForwardOffset = 0.3f;
animate();
// Calculate positions of receptors
receptorL = getPosition() + getForward() * RECEPTOR_DISTANCE;
receptorR = receptorL;
receptorL -= getRight() * RECEPTOR_SEPARATION * 0.5f;
receptorR += getRight() * RECEPTOR_SEPARATION * 0.5f;
// Steering
if (state == Ant::State::WANDER)
{
//setWanderCircleDistance(4.0f);
//setWanderCircleRadius(0.3f);
//setWanderRate(glm::radians(90.0f));
//setSeparationRadius(0.5f);
//setMaxSpeed(0.025f);
// Calculate wander force
Vector3 wanderForce = wander() * 1.5f;
Vector3 followForce = follow() * 3.0f;
// Setup containment probes
//Vector3 leftProbe = getForward() * probeForwardOffset - getRight() * probeLateralOffset;
//Vector3 rightProbe = getForward() * probeForwardOffset + getRight() * probeLateralOffset;
// Calculate containment force
//Vector3 containmentForce = containment(leftProbe) + containment(rightProbe);
// Determine neighbors
//float neighborhoodSize = 2.0f;
//AABB neighborhoodAABB(getPosition() - Vector3(neighborhoodSize * 0.5f), getPosition() + Vector3(neighborhoodSize * 0.5f));
//std::list<Agent*> neighbors;
//colony->queryAnts(neighborhoodAABB, &neighbors);
// Calculate separation force
//Vector3 separationForce = separation(neighbors);
applyForce(wanderForce);
applyForce(followForce);
float maxSpeed = MAX_WALK_SPEED * TIMESTEP;
// Limit acceleration
float accelerationMagnitudeSquared = glm::dot(acceleration, acceleration);
if (accelerationMagnitudeSquared > MAX_WALK_FORCE * MAX_WALK_FORCE)
{
acceleration = glm::normalize(acceleration) * MAX_WALK_FORCE;
}
// Accelerate
velocity += acceleration;
// Limit speed
float speedSquared = glm::dot(velocity, velocity);
if (speedSquared > maxSpeed * maxSpeed)
{
velocity = glm::normalize(velocity) * maxSpeed;
}
Vector3 direction = glm::normalize(velocity);
setOrientation(direction, getUp());
// Deposit pheromones
Vector2 position2D = Vector2(getPosition().x, getPosition().z);
colony->getHomingMatrix()->deposit(position2D, excitement);
excitement *= DEEXCITEMENT_FACTOR;
// Move ant
move(velocity);
}
else if (state == Ant::State::IDLE)
{
velocity = Vector3(0.0f);
// Move ant
move(velocity);
}
// Update transform
if (state == Ant::State::WANDER || state == Ant::State::IDLE)
{
transform.translation = getPosition();
transform.rotation = getRotation();
// Update model instance
modelInstance.setTransform(transform);
}
}
void Ant::setState(Ant::State state)
{
this->state = state;
}
Vector3 Ant::seek(const Vector3& target)
{
Vector3 steer(0.0f);
Vector3 difference = target - getPosition();
float distanceSquared = glm::dot(difference, difference);
if (distanceSquared > 0.0f)
{
float maxForce = MAX_WALK_FORCE;
steer = glm::normalize(difference) * maxForce - velocity;
}
return steer;
}
Vector3 Ant::flee(const Vector3& target)
{
return -seek(target);
}
Vector3 Ant::wander()
{
// Determine center of wander circle
Vector3 center = getPosition() + getForward() * WANDER_CIRCLE_DISTANCE;
// Calculate wander target
Vector3 target = center + wanderDirection * WANDER_CIRCLE_RADIUS;
// Rotate wander direction by a random displacement angle
float displacement = frand(-MAX_WANDER_ANGLE, MAX_WANDER_ANGLE);
wanderDirection = glm::normalize(glm::angleAxis(displacement, getUp()) * wanderDirection);
return seek(target);
}
Vector3 Ant::follow()
{
const PheromoneMatrix* pheromoneMatrix = colony->getRecruitmentMatrix();
Vector2 receptorL2D = Vector2(receptorL.x, receptorL.z);
Vector2 receptorR2D = Vector2(receptorR.x, receptorR.z);
float signalL = pheromoneMatrix->query(receptorL2D, RECEPTOR_RADIUS);
signalL += frand(0.0f, MAX_RECEPTOR_NOISE);
float signalR = pheromoneMatrix->query(receptorR2D, RECEPTOR_RADIUS);
signalR += frand(0.0f, MAX_RECEPTOR_NOISE);
if (signalL + signalR > 0.0f)
{
float angle = -MAX_PHEROMONE_TURNING_ANGLE * ((signalL - signalR) / (signalL + signalR));
Vector3 steer = glm::normalize(glm::angleAxis(angle, getUp()) * getForward());
return steer;
}
return Vector3(0.0f);
}
void Ant::applyForce(const Vector3& force)
{
acceleration += force;
}

+ 0
- 155
src/game/ant.hpp View File

@ -1,155 +0,0 @@
/*
* Copyright (C) 2017 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANT_HPP
#define ANT_HPP
#include <vector>
#include "navmesh.hpp"
#include "agent.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
class Colony;
class Gait;
/**
* An individual ant which belongs to a colony.
*/
class Ant: public Agent
{
public:
/**
* Named constants corresponding to leg indices.
*
* \_/
* L1 --| |-- R1
* L2 --| |-- R2
* L3 --|_|-- R3
*/
enum class LegIndex
{
L1,
L2,
L3,
R1,
R2,
R3
};
enum class State
{
IDLE,
WANDER,
DEAD,
SUSPENDED
};
/**
* Creates an instance of Ant.
*/
Ant(Colony* colony);
~Ant();
void animate();
void suspend(const Vector3& suspensionPoint, const Quaternion& suspensionRotation);
void move(const Vector3& velocity);
void turn(float angle);
void update(float dt);
void setState(Ant::State state);
const Colony* getColony() const;
Colony* getColony();
const Transform& getTransform() const;
const ModelInstance* getModelInstance() const;
ModelInstance* getModelInstance();
// Boid functions
Vector3 seek(const Vector3& target);
Vector3 flee(const Vector3& target);
Vector3 wander();
Vector3 follow();
void applyForce(const Vector3& force);
private:
Vector3 forage(const Vector3& leftReceptor, const Vector3& rightReceptor);
/**
* Calculates the surface normal averaged between the surface normals at each of the ant's grounded feet.
*/
Vector3 calculateAverageSurfaceNormal() const;
void updateTransform();
Colony* colony;
Ant::State state;
float animationTime;
Transform transform;
ModelInstance modelInstance;
Pose* pose;
// Boid variables
//Vector3 position;
//Quaternion rotation;
//Vector3 forward;
Vector3 velocity;
Vector3 acceleration;
Vector3 wanderDirection;
float excitement;
Vector3 receptorL;
Vector3 receptorR;
};
inline const Colony* Ant::getColony() const
{
return colony;
}
inline Colony* Ant::getColony()
{
return colony;
}
inline const Transform& Ant::getTransform() const
{
return transform;
}
inline const ModelInstance* Ant::getModelInstance() const
{
return &modelInstance;
}
inline ModelInstance* Ant::getModelInstance()
{
return &modelInstance;
}
#endif // ANT_HPP

+ 0
- 42
src/game/biome.hpp View File

@ -1,42 +0,0 @@
#ifndef BIOME_HPP
#define BIOME_HPP
#include <map>
#include <string>
#include <emergent/emergent.hpp>
using namespace Emergent;
class Biome
{
public:
Biome();
~Biome();
bool load();
std::string filename;
std::string name;
std::string soilHorizonOFilename;
std::string soilHorizonAFilename;
std::string soilHorizonBFilename;
std::string soilHorizonCFilename;
std::string cubemapName;
Texture2D* soilHorizonO;
Texture2D* soilHorizonA;
Texture2D* soilHorizonB;
Texture2D* soilHorizonC;
TextureCube* diffuseCubemap;
TextureCube* specularCubemap;
};
class Biosphere
{
public:
bool load(const std::string& directory);
std::map<std::string, Biome> biomes;
};
#endif // BIOME_HPP

+ 168
- 0
src/game/brush.cpp View File

@ -0,0 +1,168 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "brush.hpp"
#include "camera-rig.hpp"
#include <stdexcept>
Brush::Brush(const Model* model, Animator* animator):
wasActive(false)
{
// Setup model instance
modelInstance.setModel(model);
pressedDistance = -0.25f;
releasedDistance = 0.5f;
pressDuration = 0.25f;
releaseDuration = 0.175f;
tipDistance = releasedDistance;
lastTipDistance = tipDistance;
painting = false;
speed = 0.0f;
mousePosition = Vector2(0.0f);
lastMousePosition = mousePosition;
screenDimensions = Vector2(1.0f);
// Construct press animation clip
AnimationChannel<float>* channel;
pressClip.setInterpolator(easeOutCubic<float>);
channel = pressClip.addChannel(0);
channel->insertKeyframe(0.0f, 0.0f);
channel->insertKeyframe(pressDuration, 1.0f);
// Construct release animation clip
releaseClip.setInterpolator(easeOutCubic<float>);
channel = releaseClip.addChannel(0);
channel->insertKeyframe(0.0f, 0.0f);
channel->insertKeyframe(releaseDuration, 1.0f);
// Setup press animation callbacks
pressAnimation.setTimeFrame(pressClip.getTimeFrame());
pressAnimation.setClip(&pressClip);
pressAnimation.setAnimateCallback
(
[this](std::size_t id, float t)
{
this->tipDistance = lerp(lastTipDistance, pressedDistance, t);
}
);
pressAnimation.setEndCallback
(
[this]()
{
this->painting = true;
}
);
// Setup release animation callbacks
releaseAnimation.setTimeFrame(releaseClip.getTimeFrame());
releaseAnimation.setClip(&releaseClip);
releaseAnimation.setAnimateCallback
(
[this](std::size_t id, float t)
{
this->tipDistance = lerp(lastTipDistance, releasedDistance, t);
}
);
// Add animations to animator
animator->addAnimation(&pressAnimation);
animator->addAnimation(&releaseAnimation);
}
Brush::~Brush()
{}
void Brush::update(float dt)
{
Vector2 screenCenter = Vector2(screenDimensions.x * 0.5f, screenDimensions.y * 0.5f);
// Calculate mouse movement speed
Vector2 mouseDifference = (mousePosition - lastMousePosition) / std::min<float>(screenDimensions.x, screenDimensions.y);
Vector2 mouseDirection(0.0f);
float mouseSpeed = glm::length2(mouseDifference);
if (mouseSpeed != 0.0f)
{
mouseSpeed = std::sqrt(mouseSpeed);
mouseDirection = mouseDifference * (1.0f / mouseSpeed);
}
this->lastMousePosition = this->mousePosition;
Vector3 tiltDirection = Vector3(mouseDirection.x, 0.0f, mouseDirection.y);
float tiltMagnitude = std::min<float>(0.5f, mouseSpeed * 10.0f);
if (!tiltMagnitude)
{
tiltDirection = Vector3(0, 1, 0);
}
Vector2 tiltForce = mouseDirection * mouseSpeed;
velocity += tiltForce;
Quaternion tilt = glm::normalize(glm::slerp(Quaternion(1, 0, 0, 0), glm::normalize(glm::rotation(Vector3(0, 1, 0), tiltDirection)), tiltMagnitude * 0.0f));
Quaternion alignment = glm::angleAxis(orbitCam->getAzimuth(), Vector3(0, 1, 0));
Quaternion rotation = glm::normalize(alignment * tilt);
Vector3 translation = pick + rotation * Vector3(0, tipDistance, 0);
// Set tool position
modelInstance.setTranslation(translation);
modelInstance.setRotation(rotation);
if (active && !wasActive)
{
modelInstance.resetTweens();
modelInstance.setActive(true);
}
else if (!active && wasActive)
{
modelInstance.setActive(false);
}
wasActive = active;
}
void Brush::press()
{
lastTipDistance = tipDistance;
releaseAnimation.stop();
pressAnimation.rewind();
pressAnimation.play();
}
void Brush::release()
{
lastTipDistance = tipDistance;
pressAnimation.stop();
releaseAnimation.rewind();
releaseAnimation.play();
painting = false;
}
void Brush::setTiltParams(const Vector2& mousePosition, const Vector2& screenDimensions)
{
this->mousePosition = mousePosition;
this->screenDimensions = screenDimensions;
}

+ 67
- 0
src/game/brush.hpp View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BRUSH_HPP
#define BRUSH_HPP
#include "tool.hpp"
class Brush: public Tool
{
public:
Brush(const Model* model, Animator* animator);
~Brush();
/**
* Updates the brush.
*
* @param dt Game timestep.
*/
virtual void update(float dt);
void press();
void release();
void setTiltParams(const Vector2& mousePosition, const Vector2& screenDimensions);
private:
float pressedDistance;
float releasedDistance;
float tipDistance;
float lastTipDistance;
bool painting;
float pressDuration;
float releaseDuration;
Animation<float> pressAnimation;
Animation<float> releaseAnimation;
AnimationClip<float> pressClip;
AnimationClip<float> releaseClip;
Vector2 mousePosition;
Vector2 lastMousePosition;
Vector2 screenDimensions;
float speed;
Vector2 velocity;
bool wasActive;
};
#endif // BRUSH_HPP

src/camera-rig.cpp → src/game/camera-rig.cpp View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Christopher J. Howard
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
@ -79,7 +79,7 @@ void FreeCam::update(float dt)
void FreeCam::move(const Vector2& velocity)
{
setTranslation(getTranslation() + getForward() * velocity.x + getRight() * velocity.y);
setTranslation(getTranslation() + getForward() * -velocity.y + getRight() * velocity.x);
}
float wrapAngle(float x)

src/camera-rig.hpp → src/game/camera-rig.hpp View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Christopher J. Howard
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
@ -271,4 +271,4 @@ private:
const PunctualLight* light;
};
#endif // CAMERA_RIG_HPP
#endif // CAMERA_RIG_HPP

+ 0
- 106
src/game/colony.cpp View File

@ -1,106 +0,0 @@
/*
* Copyright (C) 2017 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "colony.hpp"
#include "ant.hpp"
#include "pheromone-matrix.hpp"
#include "../configuration.hpp"
Colony::Colony():
antModel(nullptr),
tripodGaitAnimation(nullptr)
{
Vector3 octreeMin = Vector3(-ANTKEEPER_TERRAIN_WIDTH, -ANTKEEPER_TERRAIN_BASE_HEIGHT, -ANTKEEPER_TERRAIN_DEPTH) * 0.5f - Vector3(ANTKEEPER_OCTREE_PADDING);
Vector3 octreeMax = Vector3( ANTKEEPER_TERRAIN_WIDTH, ANTKEEPER_TERRAIN_BASE_HEIGHT, ANTKEEPER_TERRAIN_DEPTH) * 0.5f + Vector3(ANTKEEPER_OCTREE_PADDING);
AABB octreeBounds(octreeMin, octreeMax);
antOctree = new Octree<Agent*>(5, octreeBounds);
// Create pheromone matrices
homingMatrix = new PheromoneMatrix(PHEROMONE_MATRIX_COLUMNS, PHEROMONE_MATRIX_ROWS, WORLD_BOUNDS_MIN, WORLD_BOUNDS_MAX);
recruitmentMatrix = new PheromoneMatrix(PHEROMONE_MATRIX_COLUMNS, PHEROMONE_MATRIX_ROWS, WORLD_BOUNDS_MIN, WORLD_BOUNDS_MAX);
}
Colony::~Colony()
{
killAll();
delete antOctree;
delete homingMatrix;
delete recruitmentMatrix;
}
Ant* Colony::spawn(Navmesh* navmesh, Navmesh::Triangle* triangle, const Vector3& position)
{
// Allocate ant
Ant* ant = new Ant(this);
// Position it on the navmesh
ant->setPosition(triangle, position);
// Add ant to the colony
ants.push_back(ant);
return ant;
}
void Colony::update(float dt)
{
// Rebuild octree
antOctree->clear();
for (Ant* ant: ants)
{
antOctree->insert(ant->getModelInstance()->getBounds(), ant);
}
// Update ants
for (Ant* ant: ants)
{
ant->update(dt);
}
}
void Colony::setAntModel(Model* model)
{
this->antModel = model;
// Find tripod gait animation
tripodGaitAnimation = model->getSkeleton()->getAnimation("tripod-gait");
if (!tripodGaitAnimation)
{
std::cerr << "Ant tripod gait animation not found" << std::endl;
}
}
void Colony::queryAnts(const BoundingVolume& volume, std::list<Agent*>* results) const
{
antOctree->query(volume, results);
}
void Colony::killAll()
{
antOctree->clear();
homingMatrix->clear();
recruitmentMatrix->clear();
for (Ant* ant: ants)
{
delete ant;
}
ants.clear();
}

+ 0
- 146
src/game/colony.hpp View File

@ -1,146 +0,0 @@
/*
* Copyright (C) 2017 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COLONY_HPP
#define COLONY_HPP
#include <vector>
#include "navmesh.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
class Ant;
class Agent;
class Pheromone;
class Gait;
class PheromoneMatrix;
/**
* A colony of ants.
*/
class Colony
{
public:
Colony();
~Colony();
Ant* spawn(Navmesh* navmesh, Navmesh::Triangle* triangle, const Vector3& position);
void update(float dt);
void setAntModel(Model* model);
const Model* getAntModel() const;
Model* getAntModel();
const Animation* getTripodGaitAnimation() const;
void queryAnts(const BoundingVolume& volume, std::list<Agent*>* results) const;
std::size_t getAntCount() const;
const Ant* getAnt(std::size_t index) const;
Ant* getAnt(std::size_t index);
void killAll();
const Octree<Agent*>* getAntOctree() const;
const PheromoneMatrix* getHomingMatrix() const;
PheromoneMatrix* getHomingMatrix();
const PheromoneMatrix* getRecruitmentMatrix() const;
PheromoneMatrix* getRecruitmentMatrix();
private:
// Rendering
Model* antModel;
const Animation* tripodGaitAnimation;
// Locomotion
float walkSpeed;
float turnSpeed;
Gait* tripodGait;
Gait* rippleGait;
Gait* slowWaveGait;
std::vector<Ant*> ants;
Octree<Agent*>* antOctree;
PheromoneMatrix* homingMatrix;
PheromoneMatrix* recruitmentMatrix;
};
inline const Model* Colony::getAntModel() const
{
return antModel;
}
inline Model* Colony::getAntModel()
{
return antModel;
}
inline const Animation* Colony::getTripodGaitAnimation() const
{
return tripodGaitAnimation;
}
inline std::size_t Colony::getAntCount() const
{
return ants.size();
}
inline const Ant* Colony::getAnt(std::size_t index) const
{
return ants[index];
}
inline Ant* Colony::getAnt(std::size_t index)
{
return ants[index];
}
inline const Octree<Agent*>* Colony::getAntOctree() const
{
return antOctree;
}
inline const PheromoneMatrix* Colony::getHomingMatrix() const
{
return homingMatrix;
}
inline PheromoneMatrix* Colony::getHomingMatrix()
{
return homingMatrix;
}
inline const PheromoneMatrix* Colony::getRecruitmentMatrix() const
{
return recruitmentMatrix;
}
inline PheromoneMatrix* Colony::getRecruitmentMatrix()
{
return recruitmentMatrix;
}
#endif // COLONY_HPP

+ 40
- 0
src/game/curl-noise.cpp View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "curl-noise.hpp"
inline static Vector3 gradient(const Vector3& p, float frequency)
{
const float epsilon = 0.0001f;
float n0 = glm::perlin(p * frequency);
float nx = glm::perlin((p + Vector3(epsilon, 0, 0)) * frequency);
float ny = glm::perlin((p + Vector3(0, epsilon, 0)) * frequency);
float nz = glm::perlin((p + Vector3(0, 0, epsilon)) * frequency);
return Vector3(nx - n0, ny - n0, nz - n0) * (1.0f / epsilon);
}
Vector3 curl(const Vector3& p, const Vector3& offset, float frequency)
{
Vector3 g1 = gradient(p, frequency);
Vector3 g2 = gradient(p + offset, frequency);
return glm::cross(g1, g2);
}

+ 28
- 0
src/game/curl-noise.hpp View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CURL_NOISE_HPP
#define CURL_NOISE_HPP
#include <emergent/emergent.hpp>
using namespace Emergent;
Vector3 curl(const Vector3& p, const Vector3& offset, float frequency);
#endif // CURL_NOISE_HPP

+ 396
- 0
src/game/forceps.cpp View File

@ -0,0 +1,396 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "forceps.hpp"
#include "camera-rig.hpp"
#include <stdexcept>
Forceps::Forceps(const Model* model, Animator* animator):
wasActive(false)
{
// Allocate pose and initialize to bind pose
pose = new Pose(model->getSkeleton());
pose->reset();
// Setup model instance
modelInstance.setModel(model);
modelInstance.setPose(pose);
// Find pinch animation
pinchClip = model->getSkeleton()->getAnimationClip("pinch");
if (!pinchClip)
{
throw std::runtime_error("Forceps pinch animation clip not found.");
}
// Find release animation
releaseClip = model->getSkeleton()->getAnimationClip("release");
if (!releaseClip)
{
throw std::runtime_error("Forceps release animation clip not found.");
}
// Scale animation speed
float pinchDuration = 0.1f;
float releaseDuration = 0.05f;
float pinchSpeed = std::get<1>(pinchClip->getTimeFrame()) / pinchDuration;
float releaseSpeed = std::get<1>(releaseClip->getTimeFrame()) / releaseDuration;
std::cout << std::get<1>(pinchClip->getTimeFrame()) << std::endl;
std::cout << std::get<1>(releaseClip->getTimeFrame()) << std::endl;
// Setup pinch animation callbacks
pinchAnimation.setSpeed(pinchSpeed);
pinchAnimation.setTimeFrame(pinchClip->getTimeFrame());
pinchAnimation.setClip(pinchClip);
pinchAnimation.setAnimateCallback
(
[this](std::size_t id, const Transform& transform)
{
this->pose->setRelativeTransform(id, transform);
}
);
pinchAnimation.setEndCallback
(
[this]()
{
this->pinched = true;
}
);
// Setup release animation callbacks
releaseAnimation.setSpeed(releaseSpeed);
releaseAnimation.setTimeFrame(releaseClip->getTimeFrame());
releaseAnimation.setClip(releaseClip);
releaseAnimation.setAnimateCallback
(
[this](std::size_t id, const Transform& transform)
{
this->pose->setRelativeTransform(id, transform);
}
);
hoverDistance = 1.0f;
// Setup timing
float descentDuration = 0.125f;
float ascentDuration = 0.125f;
/*
// Allocate tweener and and setup tweens
tweener = new Tweener();
descentTween = new Tween<float>(EaseFunction::OUT_CUBIC, 0.0f, descentDuration, hoverDistance, -hoverDistance);
ascentTween = new Tween<float>(EaseFunction::IN_CUBIC, 0.0f, ascentDuration, 0.0f, hoverDistance);
descentTween->setEndCallback(std::bind(&TweenBase::start, ascentTween));
tweener->addTween(descentTween);
tweener->addTween(ascentTween);
*/
// Setup initial state
state = Forceps::State::RELEASED;
for (std::size_t i = 0; i < pinchClip->getChannelCount(); ++i)
{
const AnimationChannel<Transform>* channel = pinchClip->getChannelByIndex(i);
pose->setRelativeTransform(channel->getChannelID(), *std::get<1>(channel->getKeyframe(0)));
}
pose->concatenate();
animator->addAnimation(&pinchAnimation);
animator->addAnimation(&releaseAnimation);
}
Forceps::~Forceps()
{
delete pose;
}
void Forceps::update(float dt)
{
// Determine distance from pick point
float forcepsDistance = hoverDistance;
Quaternion alignment = glm::angleAxis(orbitCam->getAzimuth(), Vector3(0, 1, 0));
Quaternion tilt = glm::angleAxis(glm::radians(15.0f), Vector3(0, 0, -1));
tilt = tilt * glm::angleAxis(glm::radians(-70.0f), tilt * Vector3(0, 1, 0));
Quaternion rotation = glm::normalize(alignment * tilt);
Vector3 translation = pick + rotation * Vector3(0, forcepsDistance, 0);
// Set tool position
modelInstance.setTranslation(translation);
modelInstance.setRotation(rotation);
pose->concatenate();
if (active && !wasActive)
{
modelInstance.resetTweens();
modelInstance.setActive(true);
}
else if (!active && wasActive)
{
modelInstance.setActive(false);
}
wasActive = active;
/*
if (state == Forceps::State::RELEASED)
{
}
else if (state == Forceps::State::RELEASING)
{
// Perform release animation
releaseAnimation->animate(pose, animationTime);
pose->concatenate();
// If release animation is finished
if (animationTime >= releaseAnimation->getEndTime())
{
// Changed to released state
state = Forceps::State::RELEASED;
}
}
else if (state == Forceps::State::PINCHED)
{
if (!ascentTween->isStopped())
{
// Calculate interpolation factor
float interpolationFactor = (ascentTween->getTweenValue() - ascentTween->getStartValue()) / ascentTween->getDeltaValue();
// Form tilt quaternion
//Quaternion tilt = glm::angleAxis(glm::radians(15.0f), Vector3(0, 0, -1));
tilt = glm::angleAxis(glm::radians(15.0f), Vector3(0, 0, -1));
// Project camera forward onto XZ plane
Vector3 cameraForwardXZ = orbitCam->getCamera()->getForward();
cameraForwardXZ.y = 0.0f;
cameraForwardXZ = glm::normalize(cameraForwardXZ);
// Form alignment quaternion
//Quaternion alignment = glm::rotation(Vector3(0, 0, -1), cameraForwardXZ);
alignment = glm::angleAxis(orbitCam->getAzimuth(), Vector3(0, 1, 0));
// Calculate target rotation at the top of the ascentTween
rotationTop = glm::normalize(alignment * tilt);
// Interpolate between bottom and top rotations
Quaternion interpolatedRotation = glm::normalize(glm::slerp(rotationBottom, rotationTop, interpolationFactor));
// Set target translation at the top of the ascent
translationTop = pick + rotationTop * Vector3(0, hoverDistance, 0);
// Interpolate between bottom and top translations
Vector3 interpolatedTranslation = glm::lerp(translationBottom, translationTop, interpolationFactor);
// Update model instance transform
modelInstance.setTranslation(interpolatedTranslation);
modelInstance.setRotation(interpolatedRotation);
}
if (suspendedAnt != nullptr)
{
// Project forceps forward vector onto XZ plane
Vector3 forward = glm::normalize(modelInstance.getRotation() * Vector3(0, 0, -1));
forward.y = 0.0f;
forward = glm::normalize(forward);
// Calculate suspension quaternion
Quaternion suspensionRotation = glm::normalize(glm::rotation(Vector3(0, 0, -1), ((flipRotation) ? -forward : forward)));
// Suspend ant
suspendedAnt->suspend(modelInstance.getTranslation(), suspensionRotation);
}
}
else if (state == Forceps::State::PINCHING)
{
// Perform pinch animation
pinchAnimation->animate(pose, animationTime);
pose->concatenate();
// Rotate to align forceps with ant
if (targetedAnt != nullptr)
{
// Calculate interpolation factor
float interpolationFactor = (descentTween->getTweenValue() - descentTween->getStartValue()) / descentTween->getDeltaValue();
// Set target translation at the bottom of the descent
translationBottom = targetedAnt->getPosition();
// Interpolate between top and bottom translations
Vector3 interpolatedTranslation = glm::lerp(translationTop, translationBottom, interpolationFactor);
// Project camera forward onto XZ plane
Vector3 cameraForwardXZ = orbitCam->getCamera()->getForward();
cameraForwardXZ.y = 0.0f;
cameraForwardXZ = glm::normalize(cameraForwardXZ);
// Form tilt quaternion
tilt = glm::angleAxis(glm::radians(15.0f), -cameraForwardXZ);
// Project ant forward onto XZ plane
Vector3 antForwardXZ = targetedAnt->getForward();
antForwardXZ.y = 0.0f;
antForwardXZ = glm::normalize(antForwardXZ);
// Form alignment quaternion
alignment = glm::rotation(Vector3(0, 0, -1), (flipRotation) ? antForwardXZ : -antForwardXZ);
// Calculate target rotation at the bottom of the descent
rotationBottom = glm::normalize(tilt * alignment);
// Interpolate between top and bottom rotations
Quaternion interpolatedRotation = glm::normalize(glm::slerp(rotationTop, rotationBottom, interpolationFactor));
// Update model instance transform
modelInstance.setTranslation(interpolatedTranslation);
modelInstance.setRotation(interpolatedRotation);
}
// If pinch animation is finished
if (animationTime >= pinchAnimation->getEndTime() && descentTween->isStopped())
{
// If an ant was targeted
if (targetedAnt != nullptr)
{
// Suspend targeted ant
suspendedAnt = targetedAnt;
suspendedAnt->setState(Ant::State::SUSPENDED);
//suspendedAnt->suspend(modelInstance.getTranslation());
targetedAnt = nullptr;
}
// Change to pinched state
state = Forceps::State::PINCHED;
}
}
*/
}
void Forceps::pinch()
{
releaseAnimation.stop();
pinchAnimation.rewind();
pinchAnimation.play();
/*
// Change state to pinching
state = Forceps::State::PINCHING;
animationTime = 0.0f;
if (colony != nullptr)
{
// Target nearest ant in pinching radius
Sphere pinchingBounds = Sphere(pick, 0.35f);
// Build a list of ants which intersect the pinching bounds
std::list<Agent*> ants;
colony->queryAnts(pinchingBounds, &ants);
// Target ant closest to the center of the pinching bounds
float closestDistance = std::numeric_limits<float>::infinity();
for (Agent* agent: ants)
{
Ant* ant = static_cast<Ant*>(agent);
Vector3 difference = ant->getPosition() - pinchingBounds.getCenter();
float distanceSquared = glm::dot(difference, difference);
if (distanceSquared < closestDistance)
{
closestDistance = distanceSquared;
targetedAnt = ant;
}
}
if (targetedAnt != nullptr)
{
// Start descent tweener
descentTween->start();
// Save translation & rotation
translationTop = modelInstance.getTranslation();
rotationTop = modelInstance.getRotation();
// Project ant forward onto XZ plane
Vector3 antForwardXZ = targetedAnt->getForward();
antForwardXZ.y = 0.0f;
antForwardXZ = glm::normalize(antForwardXZ);
// Project camera forward onto XZ plane
Vector3 cameraForwardXZ = orbitCam->getCamera()->getForward();
cameraForwardXZ.y = 0.0f;
cameraForwardXZ = glm::normalize(cameraForwardXZ);
// Find angle between ant and camera on XZ plane
float angle = std::acos(glm::dot(cameraForwardXZ, antForwardXZ));
// Determine direction to rotate
flipRotation = (angle > glm::radians(90.0f));
}
}
*/
}
void Forceps::release()
{
pinchAnimation.stop();
releaseAnimation.rewind();
releaseAnimation.play();
/*
// Change state to releasing
state = Forceps::State::RELEASING;
animationTime = 0.0f;
targetedAnt = nullptr;
if (suspendedAnt != nullptr)
{
Ray pickingRay;
pickingRay.origin = pick + Vector3(0, 1, 0);
pickingRay.direction = Vector3(0, -1, 0);
const std::vector<Navmesh::Triangle*>* navmeshTriangles = navmesh->getTriangles();
for (Navmesh::Triangle* triangle: *navmeshTriangles)
{
auto result = intersects(pickingRay, triangle);
if (std::get<0>(result))
{
Vector3 barycentricPosition = Vector3(std::get<2>(result), std::get<3>(result), 1.0f - std::get<2>(result) - std::get<3>(result));
suspendedAnt->setPosition(triangle, barycentricPosition);
break;
}
}
// Release suspended ant
suspendedAnt->setState(Ant::State::WANDER);
suspendedAnt = nullptr;
}
// Reset tweens
descentTween->reset();
descentTween->stop();
ascentTween->reset();
ascentTween->stop();
*/
}

+ 95
- 0
src/game/forceps.hpp View File

@ -0,0 +1,95 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FORCEPS_HPP
#define FORCEPS_HPP
#include "tool.hpp"
/**
* The forceps tool can pick up ants and place them anywhere in the world.
*/
class Forceps: public Tool
{
public:
enum class State
{
RELEASED,
RELEASING,
PINCHED,
PINCHING
};
/**
* Creates an instance of Forceps.
*
* @param model Forceps model
*/
Forceps(const Model* model, Animator* animator);
/**
* Destroys an instance of Forceps.
*/
~Forceps();
/**
* Updates the forceps.
*
* @param dt Application timestep.
*/
virtual void update(float dt);
/**
* Pinches the forceps.
*/
void pinch();
/**
* Releases the forceps.
*/
void release();
/**
* Returns the current state of the forceps.
*/
Forceps::State getState() const;
private:
Forceps::State state;
Pose* pose;
const AnimationClip<Transform>* pinchClip;
const AnimationClip<Transform>* releaseClip;
Animation<Transform> pinchAnimation;
Animation<Transform> releaseAnimation;
float hoverDistance;
Vector3 translationBottom;
Vector3 translationTop;
Quaternion rotationTop;
Quaternion rotationBottom;
bool flipRotation;
bool pinched;
bool wasActive;
};
inline Forceps::State Forceps::getState() const
{
return state;
}
#endif // FORCEPS_HPP

+ 176
- 0
src/game/lens.cpp View File

@ -0,0 +1,176 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "lens.hpp"
#include "camera-rig.hpp"
#include "../entity/systems/particle-system.hpp"
Lens::Lens(const Model* model, Animator* animator):
wasActive(false),
particleSystem(nullptr)
{
// Setup model instance
modelInstance.setModel(model);
modelInstance.setCullingEnabled(false);
// Setup spotlight
spotlight.setColor(Vector3(1.0f));
spotlight.setIntensity(1000.0f);
spotlight.setAttenuation(Vector3(1, 0, 1));
spotlight.setCutoff(std::cos(glm::radians(45.0f)));
spotlight.setExponent(150.0f);
spotlight.setActive(false);
unfocusedDistance = 18.0f;
unfocusDuration = 0.25f;
focusedDistance = 12.0f;
focusDuration = 0.75f;
lensDistance = unfocusedDistance;
focused = false;
lastDistance = unfocusedDistance;
sunDirection = Vector3(0, -1, 0);
// Construct focus animation clip
AnimationChannel<float>* channel;
focusClip.setInterpolator(easeOutCubic<float>);
channel = focusClip.addChannel(0);
channel->insertKeyframe(0.0f, 0.0f);
channel->insertKeyframe(focusDuration, 1.0f);
// Construct unfocus animation clip
unfocusClip.setInterpolator(easeOutCubic<float>);
channel = unfocusClip.addChannel(0);
channel->insertKeyframe(0.0f, 0.0f);
channel->insertKeyframe(unfocusDuration, 1.0f);
// Setup focus animation callbacks
focusAnimation.setTimeFrame(focusClip.getTimeFrame());
focusAnimation.setClip(&focusClip);
focusAnimation.setAnimateCallback
(
[this](std::size_t id, float distance)
{
this->lensDistance = lerp(lastDistance, focusedDistance, distance);
}
);
focusAnimation.setEndCallback
(
[this]()
{
this->focused = true;
}
);
// Setup unfocus animation callbacks
unfocusAnimation.setTimeFrame(unfocusClip.getTimeFrame());
unfocusAnimation.setClip(&unfocusClip);
unfocusAnimation.setAnimateCallback
(
[this](std::size_t id, float distance)
{
this->lensDistance = lerp(lastDistance, unfocusedDistance, distance);
}
);
// Add animations to animator
animator->addAnimation(&focusAnimation);
animator->addAnimation(&unfocusAnimation);
}
Lens::~Lens()
{}
void Lens::update(float dt)
{
//Quaternion alignment = glm::rotation(Vector3(0, 1, 0), -sunDirection) * glm::angleAxis(glm::radians(90.0f), Vector3(0, 1, 0));
Quaternion alignment = glm::rotation(Vector3(0, 1, 0), -sunDirection) * glm::angleAxis(orbitCam->getAzimuth() + glm::radians(90.0f), Vector3(0, 1, 0));
Quaternion rotation = glm::normalize(alignment);
Vector3 translation = pick + sunDirection * -lensDistance;
modelInstance.setTranslation(translation);
modelInstance.setRotation(rotation);
float t = (1.0 - (lensDistance - focusedDistance) / (unfocusedDistance - focusedDistance));
float unfocusedIntensity = 250.0f * 2.0f;
float focusedIntensity = 1000.0f * 2.0f;
float intensity = easeInExpo(unfocusedIntensity, focusedIntensity, t);
float unfocusedExponent = 100.0f;
float focusedExponent = 5000.0f;
float exponent = easeInExpo(unfocusedExponent, focusedExponent, t);
spotlight.setIntensity(intensity);
spotlight.setExponent(exponent);
spotlight.setTranslation(pick + sunDirection * -lensDistance);
spotlight.setDirection(sunDirection);
if (active && !wasActive)
{
modelInstance.resetTweens();
spotlight.resetTweens();
modelInstance.setActive(true);
spotlight.setActive(true);
}
else if (!active && wasActive)
{
modelInstance.setActive(false);
spotlight.setActive(false);
}
if (active && focused)
{
int count = 10;
for (int i = 0; i < count; ++i)
particleSystem->emit(pick);
}
wasActive = active;
}
void Lens::focus()
{
lastDistance = lensDistance;
unfocusAnimation.stop();
focusAnimation.rewind();
focusAnimation.play();
}
void Lens::unfocus()
{
lastDistance = lensDistance;
focusAnimation.stop();
unfocusAnimation.rewind();
unfocusAnimation.play();
focused = false;
}
void Lens::setSunDirection(const Vector3& direction)
{
sunDirection = direction;
}
void Lens::setParticleSystem(ParticleSystem* particleSystem)
{
this->particleSystem = particleSystem;
}

+ 96
- 0
src/game/lens.hpp View File

@ -0,0 +1,96 @@
/*
* Copyright (C) 2017-2019 Christopher J. Howard
*
* This file is part of Antkeeper Source Code.
*
* Antkeeper Source Code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper Source Code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LENS_HPP
#define LENS_HPP
#include "tool.hpp"
class ParticleSystem;
/**
* The lens tool can be used to burn ants.
*
* @see https://taylorpetrick.com/blog/post/dispersion-opengl
* @see https://taylorpetrick.com/portfolio/webgl/lense
*/
class Lens: public Tool
{
public:
/**
* Creates an instance of Lens.
*
* @param model Lens model
*/
Lens(const Model* model, Animator* animator);
/**
* Destroys an instance of Lens.
*/
~Lens();
/**
* Updates the lens.
*
* @param dt Application timestep.
*/
virtual void update(float dt);
void focus();
void unfocus();
void setSunDirection(const Vector3& direction);
void setParticleSystem(ParticleSystem* particleSystem);
/**
* Returns the spotlight.
*/
const Spotlight* getSpotlight() const;
Spotlight* getSpotlight();
private:
Spotlight spotlight;
float focusedDistance;
float unfocusedDistance;
float focusDuration;
float unfocusDuration;
float lensDistance;
float lastDistance;
bool focused;
Vector3 sunDirection;
Animation<float> focusAnimation;
Animation<float> unfocusAnimation;
AnimationClip<float> focusClip;
AnimationClip<float> unfocusClip;
bool wasActive;
ParticleSystem* particleSystem;
};
inline const Spotlight* Lens::getSpotlight() const
{
return &spotlight;
}
inline Spotlight* Lens::getSpotlight()
{
return &spotlight;
}
#endif // LENS_HPP

+ 0
- 149
src/game/level.cpp View File

@ -1,149 +0,0 @@
#include "level.hpp"
#include "../settings.hpp"
#include "../configuration.hpp"
#include <dirent.h>
#include <iostream>
#include <sstream>
LevelParameterSet::LevelParameterSet()
{}
LevelParameterSet::~LevelParameterSet()
{}
bool LevelParameterSet::load(const std::string& filename)
{
this->filename = filename;
ParameterDict parameters;
if (!parameters.load(filename))
{
return false;
}
parameters.get("biome", &biome);
parameters.get("heightmap", &heightmap);
return true;
}
Level::Level()
{
terrain.create(255, 255, Vector3(ANTKEEPER_TERRAIN_WIDTH, ANTKEEPER_TERRAIN_BASE_HEIGHT, ANTKEEPER_TERRAIN_DEPTH));
}
Level::~Level()
{}
bool Level::load(const LevelParameterSet& params)
{
// Load terrain from heightmap
std::string heightmapFilename = std::string("data/textures/") + params.heightmap;
if (!terrain.load(heightmapFilename))
{
std::cerr << "Failed to load terrain from heightmap file \"" << heightmapFilename << "\" for level \"" << params.filename << "\"" << std::endl;
return false;
}
//application->currentLevelTerrain->getSurfaceModel()->getGroup(0)->material = application->materialLoader->load("data/materials/debug-terrain-surface.mtl");
// Setup terrain surface model instance
terrainSurface.setModel(terrain.getSurfaceModel());
terrainSurface.setTranslation(Vector3(0, 0, 0));
// Setup terrain subsurface model instance
terrainSubsurface.setModel(terrain.getSubsurfaceModel());
terrainSubsurface.setTranslation(Vector3(0, 0, 0));
return true;
}
Campaign::Campaign()
{}
Campaign::~Campaign()
{}
bool Campaign::load(const std::string& directory)
{
// Open levels directory
DIR* dir = opendir(directory.c_str());
if (dir == nullptr)
{
std::cout << "Failed to open levels directory \"" << directory << "\"" << std::endl;
return false;
}
// Scan directory for .lvl files
for (struct dirent* entry = readdir(dir); entry != nullptr; entry = readdir(dir))
{
if (entry->d_type == DT_DIR || *entry->d_name == '.')
{
continue;
}
std::string filename = entry->d_name;
std::string::size_type delimeter = filename.find_last_of('.');
if (delimeter == std::string::npos)
{
continue;
}
std::string extension = filename.substr(delimeter + 1);
if (extension != "lvl")
{
continue;
}
std::string worldIndexString = filename.substr(0, 2);
std::string levelIndexString = filename.substr(3, 2);
int worldIndex = -1;
int levelIndex = -1;
std::stringstream stream;
stream << worldIndexString;
stream >> worldIndex;
worldIndex -= 1;
stream.str(std::string());
stream.clear();
stream << levelIndexString;
stream >> levelIndex;
levelIndex -= 1;
if (worldIndex < 0 || levelIndex < 0)
{
std::cout << "Invalid level parameters file \"" << filename << "\"" << std::endl;
continue;
}
// Resize vector to accommodate maximum world index
if (worldIndex >= static_cast<int>(levelParameterSets.size()))
{
levelParameterSets.resize(worldIndex + 1);
}
// Resize vector to accommodate maximum level file index
if (levelIndex >= static_cast<int>(levelParameterSets[worldIndex].size()))
{
levelParameterSets[worldIndex].resize(levelIndex + 1);
}
// Load level parameters
LevelParameterSet* levelParams = &levelParameterSets[worldIndex][levelIndex];
if (!levelParams->load(directory + filename))
{
std::cout << "Failed to load parameters for level " << (worldIndex + 1) << "-" << (levelIndex + 1) << std::endl;
}
else
{
std::cout << "Loaded level parameters for level " << (worldIndex + 1) << "-" << (levelIndex + 1) << std::endl;
}
}
// Close levels directory
closedir(dir);
return true;
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save