diff --git a/assignment2/README.md b/assignment2/README.md new file mode 100644 index 0000000..89e68b6 --- /dev/null +++ b/assignment2/README.md @@ -0,0 +1,39 @@ +# Assignment 2 + +*due on 19 February 2021* + +For the second assignment you can either pick one of the two provided specifications or come up with your own. +Yes, you are free to come up with a topic for the second assignment. +However, doing so requires you to put together a specification similar to the ones provided and get my approval. +The specification doesn't have to be bulletproof. +But it must contain a bullet list of goals (with points to score) at the bottom which can be checked / evaluated. +You can also adjust one of the provided specifications. + +You are allowed to work in teams, yet the team size has to correspond to the amount of work (features) of the topic. +For the provided specifications the recommended team size is 3. + +You are allowed to use: +- C++ standard library (C++17 standard) +- C standard library (as fallback) +- [Boost](https://www.boost.org/) +- [SDL](https://www.libsdl.org/) +- [GLFW](https://www.glfw.org/) +- [GLM](https://glm.g-truc.net/) +- [Vulkan](https://www.khronos.org/vulkan/) / [Vulkan-Hpp](https://github.com/KhronosGroup/Vulkan-Hpp) +- [Qt](https://www.qt.io/) +- [ImGui](https://github.com/ocornut/imgui) +- [OpenAL](https://openal.org/) +- [RapidJSON](https://rapidjson.org/) +- [Tiled](https://www.mapeditor.org/) + +Feel free to ask me about other libraries / tools. + +Your application should work on Linux and Windows unless there is a specific reason why it cannot be cross-platform. +For Linux, assume a recent version of Ubuntu Desktop and that the required dependencies are installed via the system's package manager. +Use the corresponding CMake `find_package` mechanism to find them, it is recommended to leverage [`pkgconf`](https://cmake.org/cmake/help/latest/module/FindPkgConfig.html). +For Windows you can simply ship pre-built libraries that are picked up by CMake automatically. + +You must use [CMake](https://cmake.org/) as build system. + +Use [ClangFormat](https://clang.llvm.org/docs/ClangFormat.html) to automatically format your code using the provided [`.clang-format`](../.clang-format) configuration. + diff --git a/assignment2/images/behaviour_tree_example.png b/assignment2/images/behaviour_tree_example.png new file mode 100644 index 0000000..8d4586f Binary files /dev/null and b/assignment2/images/behaviour_tree_example.png differ diff --git a/assignment2/images/ccotm_hud_bars.png b/assignment2/images/ccotm_hud_bars.png new file mode 100644 index 0000000..43ba7f6 Binary files /dev/null and b/assignment2/images/ccotm_hud_bars.png differ diff --git a/assignment2/images/ccotm_items.png b/assignment2/images/ccotm_items.png new file mode 100644 index 0000000..4c6e548 Binary files /dev/null and b/assignment2/images/ccotm_items.png differ diff --git a/assignment2/images/ccotm_kickboots_banner.png b/assignment2/images/ccotm_kickboots_banner.png new file mode 100644 index 0000000..029f382 Binary files /dev/null and b/assignment2/images/ccotm_kickboots_banner.png differ diff --git a/assignment2/images/ccotm_map.jpg b/assignment2/images/ccotm_map.jpg new file mode 100644 index 0000000..e8dc42e Binary files /dev/null and b/assignment2/images/ccotm_map.jpg differ diff --git a/assignment2/images/ccotm_nathen_sprite_map.png b/assignment2/images/ccotm_nathen_sprite_map.png new file mode 100644 index 0000000..83c3b0e Binary files /dev/null and b/assignment2/images/ccotm_nathen_sprite_map.png differ diff --git a/assignment2/images/ccotm_pause_menu.png b/assignment2/images/ccotm_pause_menu.png new file mode 100644 index 0000000..0b34447 Binary files /dev/null and b/assignment2/images/ccotm_pause_menu.png differ diff --git a/assignment2/images/game_loop.png b/assignment2/images/game_loop.png new file mode 100644 index 0000000..f041ab5 Binary files /dev/null and b/assignment2/images/game_loop.png differ diff --git a/assignment2/images/pokemon_map.png b/assignment2/images/pokemon_map.png new file mode 100644 index 0000000..bfdadd9 Binary files /dev/null and b/assignment2/images/pokemon_map.png differ diff --git a/assignment2/images/sprite_map.png b/assignment2/images/sprite_map.png new file mode 100644 index 0000000..544e105 Binary files /dev/null and b/assignment2/images/sprite_map.png differ diff --git a/assignment2/images/unity_inspector.png b/assignment2/images/unity_inspector.png new file mode 100644 index 0000000..f6e451d Binary files /dev/null and b/assignment2/images/unity_inspector.png differ diff --git a/assignment2/metroidvania_specification.md b/assignment2/metroidvania_specification.md new file mode 100644 index 0000000..b34c4e8 --- /dev/null +++ b/assignment2/metroidvania_specification.md @@ -0,0 +1,436 @@ +# Metroidvania Specification + +As the title already suggests, the ultimate goal is to create a small, *[Metroidvania](https://en.wikipedia.org/wiki/Metroidvania)-like* side-scroller. +If you are not familiar with games falling into the Metroidvania genre – or side-scrollers in general – I recommend having a look at these titles: + +- [Castlevania: Symphony of the Night](https://en.wikipedia.org/wiki/Castlevania:_Symphony_of_the_Night) +- [Castlevania: Circle of the Moon](https://en.wikipedia.org/wiki/Castlevania:_Circle_of_the_Moon) +- [Super Metroid](https://en.wikipedia.org/wiki/Super_Metroid) +- [Ori and the Blind Forest](https://www.gog.com/game/ori_and_the_blind_forest_definitive_edition) +- [Dust: An Elysian Tail](https://www.gog.com/game/dust_an_elysian_tail) +- [Salt and Sanctuary](https://store.steampowered.com/app/283640/Salt_and_Sanctuary/) +- [Owlboy](https://www.gog.com/game/owlboy) +- [Guacamelee](https://www.gog.com/game/guacamelee_gold_edition) +- [Hollow Knight](https://www.gog.com/game/hollow_knight) +- [Iconoclasts](https://www.gog.com/game/iconoclasts) +- [Dead Cells](https://www.gog.com/game/dead_cells) +- [**Timespinner**](https://store.steampowered.com/app/368620/Timespinner/) + +After playing some gam-… ehh… doing some research, you should be familiar with the core game concepts and mechanics of the genre. + +Before moving on, I want you to make up your minds about the setting your game takes place in. +While a medieval fantasy world with demons and vampires sounds straight forward, don't overlook other possibilities like cyberpunk, steampunk, post apocalypse and so on. +Determine upfront whether you are going for a more serious or a more humorous tone – whether things should be realistic or over the top with crazy anime effects everywhere. + +Now that a certain setting has been established, continue the read and imagine what the equivalences to my examples would be in your game. +These equivalences can often be derived directly from the chosen setting. +However, you might want to throw in a twist here and there to surprise the player and keep her engaged. + +Most of the examples presented in the following sections are taken from *Castlevania: Circle of the Moon*. +This way I can stick to a common setting throughout. + +### Assets + +That's nice and stuff, but what about all the assets (eg sprites, music, sound effects) that are required for such a game? + +Well, you don't have to look far. +As this is still about learning C++, I don't expect you to spend your precious time on creating all of them by hand. +There are megatons of assets for free- / non-commercial- / educational-use available online. +I am pretty sure you'll find something among them which suits your setting. +Maybe some slight modifications are needed here and there, but nothing that should distract you from learning C++. + +For various types of assets – sound effects especially – there are also generators available which can be tweaked for unique results. +Pick your poison! + +## Building the World + +Metroidvania style games are typically semi-open world. +While the player can explore the game world freely, certain areas are gated off at the start. + +Let's take a look at this map. + +![Castlevania: Circle of the Moon Map](images/ccotm_map.jpg) + +*source: http://castlevania.wikia.com/* + +It displays the whole layout of the castle – each wing (aka section or area) coloured differently. +Each of the polygons represents a room, which in turn is connected to other rooms, and is associated with one of the wings – here indicated by its colour. +The small, red rooms are save points; while the small, white rooms are teleporters. + +Each wing is unique in the architecture of the rooms, the enemies encountered, the background music, the items obtained, and so on and so forth. + +The player needs to face off the vicious boss of a wing in order to progress. +After defeating such a boss, a new item or ability is acquired which grants her passage to other, previously inaccessible, wings of the castle. + +Here is an example: + +![Castlevania: Circle of the Moon Kickboots Banner](images/ccotm_kickboots_banner.png) + +*source: http://castlevania.wikia.com/* + +The final boss of the *Machine Tower* is the *Iron Golem* (left). +From it, the player obtains the *Kick Boots* (centre) which enables jumping off walls to gain more height (right). +With them, the *Chapel Tower* can now be accessed. + +### Implementation + +A room essentially consists of a 2D array of tiles. +Together, the tiles build the floor, ceiling, and walls of the room. +Platforms are added to enable vertical traversal. +For additional depth, an image is rendered behind the layer of tiles, which is sometimes panned as the camera moves – similar to a skybox in 3D games. + +Game entities (eg items, enemies, doors) can be placed via XY coordinates. +The doors are particularly important as they are responsible for interconnecting rooms. + +The layout of each room in your game should be fully determined by a single file – preferably human-readable. +It *could* look like this: + +``` +MAP Room01 +BACKGROUND assets/images/background/library.png +MUSIC assets/music/ancient_tomb.ogg +TILES + . = none + w = Wall01 + c = Ceiling01 + f = Floor01 + p = Platform01 +LAYOUT + wcccccccccccccccccw + w.................w + w.................w + w..........ppp....w + w.................w + w.................w + fffffffffffffffffff +ENTITIES + ( 2, 5) Player() + ( 8, 5) Enemy_BookTossingRedneck() + (12, 2) SmallHealthPotion() + (18, 5) Door01_right(Room01_exit, Room02_entry) +``` + +Tiles and game entities are defined elsewhere, yet some of them require arguments for their instantiation. +In this example, the door gets a designation (`Room01_exit`) and is connected to some other door (`Room02_entry`). + +## Hearing the World + +Commonly, the music playing is either determined by the room or wing. +The selected tune is repeated until a room / wing with different background music is entered. + +A more advanced technique is to use different variations of the same background music and blend them together depending on the situation. + +For instance: +the player enters a room, no enemy in sight; +a *softer* version of the tune is playing. +As the player progresses through the room, enemies awake and engage the player; +the tune becomes more dramatic. +One of the enemies lands a devastating blow, depleting the player's health bar almost entirely; +a *high tension* version fades in – additionally the player's low health causes an annoying alarm to be played. + +### Implementation + +SDL_mixer is probably all you need for this. +It provides separate sound channels, each with its own volume setting. + +One simple way to blend variations of the same track is by playing all of them on separate channels and adjusting the volume accordingly. + +Obviously, sound effects are played on different channels than background music so they do not interfere. + +## Entities of the Game + +Having rooms and wings would be a bit pointless without anything that interacts with it, wouldn't it? + +All of the objects in your game are referred to as entities. +Entities interact with the game world as well as with each other. +Their complexity varies greatly, from a simple key that can be picked up to unlock doors, to AI controlled enemies. + +Most of them are visible (rendered) and have collision so they can be interacted with. +Others may be almost unnoticeable by the player – like a point in 2D space which just emits a screeching noise. + +Typically, entities have a position, rotation, scale, and a type; the latter may come with additional state and ways of interaction. +A more complex alternative for typing entities is by using an entity component system (see below). + +### Rendering + +Displaying (static) entities is straight forward. + +![Castlevania: Circle of the Moon Items](images/ccotm_items.png) + +*source: https://strategywiki.org/wiki/Castlevania:_Circle_of_the_Moon* + +[Sprites](https://en.wikipedia.org/wiki/Sprite_(computer_graphics)) are essentially bitmap images with transparent background. +The position, rotation, and scale for rendering the sprite is determined by the position, rotation, and scale of the entity respectively. +Offsets may be added, but apart from that, that's it. + +### Animation + +More dynamic entities, like the player character (PC) or enemies, often feature animations. +These start with simple idle and walking animations, but can also turn into breathtaking combat and dodging choreographies. + +![Castlevania: Circle of the Moon Nathen Sprite Map](images/ccotm_nathen_sprite_map.png) + +*modified: removed middle part for brevity* + +The key idea is to use multiple sprites instead of just one. +Each animation frame is a new sprite. +When an animation is played, the related sprites are displayed one after another to simulate motion. + +Multiple sprites are combined and put into the same image, which is then called a *sprite map*. +The rendering API allows us to select which part of the image to use for rendering. +A simple rectangle selection is used to pick the sprite for the current frame. + +#### Implementation + +Composing a sprite map is trivial, yet we are still missing some information. +Namely, where exactly the sprites are located in the sprite map, which animation they belong to, and how long each sprite should be displayed before it is swapped out. + +This can be solved via a simple text file. +Like with the room layout, determine the format yourself, preferably human-readable. +A hypothetical example is provided: + +``` +ANIMATION Enemy_BookTossingRedneck +SPRITES assets/images/sprites/enemies/book_tossing_redneck.png +ITEMS + idle 0ms ( 0, 0) (16, 16) + drinking 0ms (16, 0) (32, 16) + walking 500ms ( 0, 16) (16, 32) + (16, 16) (32, 32) + (32, 16) (48, 32) + (48, 16) (64, 32) +``` + +First we state to which entity the animation file belongs and where the corresponding sprite map can be found. +It consists of 6 sprites, the first two are displayed when the entity is idling or drinking respectively. +As both only consist of a single sprite, the timing is irrelevant and therefore set to zero. +For the walking animation, we use 4 sprites and state that one period takes 500 ms, hence each sprite is displayed 125 ms before getting swapped out. +After the forth sprite has been displayed, the animation loops, starting over with the first sprite. + +### Collision + +So far we can display the game world and entities – even with animations – yet we still lack basic interaction. +This is where collision comes in. +Whenever one entity collides with the room layout (walls, floors, platforms etc) or another entity, this needs to be recognised so the associated logic can be triggered. + +If the player runs into a wall, the wall should of course stop the player and prevent her from running out of bounds. +Similarly, an enemy projectile hitting the player should cause a hit animation to be played along with a sound effect and decreasing the player's health. + +#### Implementation + +There are various different ways one can implement collision for 2D side-scrollers. +All of them come with their own benefits and drawbacks. +I'll leave things for you to decide. + +## Stats + +Sometimes Metroidvania-like games implement mechanics originating from role-playing games (RPGs). + +A prime example is the introduction of stats. +Rather than having fixed values for weapon damage, health, damage resistance etc; the actual values are computed by taking a base-value and scaling it. +This scale factor is determined by the entity's stats (aka attributes). + +These stats change over the course of the game. +Typically, the player character's stats are improved by earning experience points (XP) and levelling up. +Experience is often earned by slaying enemies, completing quests, and alike. + +Even further, entity stats can be influenced by items (eg *speed boost elixir*), gear (eg *boots of strength*), spells (eg *improved fire resistance*), conditions (eg *cursed*), and the list goes on and on and on. + +## AI + +Enemies just standing around, doin' nothing ain't particularly interesting. + +Even very simple and deterministic AI can be sufficient. +Like: + +```cpp +void do_something() +{ + static bool moved_forward = true; + + if (player_in_range()) { + attack_player(); + return; + } + + if (moved_forward) { + move_backward(); + } else { + move_forward(); + } + + moved_forward = !moved_forward; +} +``` + +Additionally, one can add randomness to make enemies less predictable. +For instance: one out of ten times, use a different attack which is faster and does more damage. + +Leverage randomness and other factors to create interesting boss AIs. +The distance to the player could determine which kind of attack the boss uses. +The player's health could dictate how aggressive the boss becomes. +The number of possibilities is endless. + +### Implementation + +For simplicity, the AI can be hardcoded in the logic of an enemy. + +Alternatively, you may want to look into [behaviour trees](https://en.wikipedia.org/wiki/Behavior_tree_(artificial_intelligence,_robotics_and_control)). + +![Behaviour Tree Example](images/behaviour_tree_example.png) + +## HUD and Menus + +The head-up display (HUD) is a crucial component as it conveys important information to the player. +In Castlevania, the health- and mana-bar can be found in the top-left corner of the screen, along with the secondary weapon, and ammo. + +![Castlevania Circle of the Moon Hud Bars](images/ccotm_hud_bars.png) + +*source: http://castlevania.wikia.com* + +Not all aspects of the game can be done (reasonably) by moving the player character around. +Certain tasks require a menu system. +This starts at the main menu of the game, along with the pause and option menus. + +![Castlevania Circle of the Moon Pause Menu](images/ccotm_pause_menu.png) + +*source: https://strategywiki.org/wiki/Castlevania:_Circle_of_the_Moon* + +The pause menu displays the players stats (health, attributes, experience etc) and provides access to various submenus – inventory management among them. + +### Implementation + +SDL provides basic shape drawing functionality. +With it, you can easily build an abstraction layer for creating rudimentary user interface (UI) components. +Alternatively, you can simply use images. + +SDL_ttf allows you to use fonts for printing text. +Please supply used fonts along with all assets. + +## Entity Component System + +Many modern game engines use an architecture known as [entity component system (ECS)](https://en.wikipedia.org/wiki/Entity%E2%80%93component%E2%80%93system). +While this paradigm is probably overkill for a small project like this, you may scavenge some of its ideas. + +In ECS, entities are just containers for components. +Components, however, determine how the associated entity behaves, how it can be interacted with, and so on. + +Take the player entity for a moment, in terms of the ECS architecture, it would have: + +- a component for rendering sprites +- a component which deals with animations +- a component which emits sound +- a physics collider or bounding box +- a component which models health +- … + +You basically create a huge toolbox of little things (components) that can be mixed and matched to compose a full-blown entity. + +![Unity Inspector](images/unity_inspector.png) + +The figure above shows the inspector window of the [Unity](https://unity3d.com/) editor. +The inspector displays the components attached to the selected entity. +Here, the entity named *Cube* consists of a *Mesh Filter*, *Box Collider*, and *Mash Renderer* component. +The *Transform* is part of the entity itself and gives it its position, rotation, and scale. +As can be seen from the screen-shot, each component possesses properties that can be tweaked, like, the material used for mesh rendering. + +This leaves us with the *system* part. +Each system (audio system, physics system, rendering, *whatever you can think of*) interacts with the associated components possessed by entities. + +## Main Game Loop + +Often, in addition to ECS, games use the *main game loop* paradigm. +In combination with ECS this is commonly presented as a straightforward sequence: + +1. Take the current game state. +2. Invoke all systems. + Each system generates events based on the game state. + For instance, one event indicates that the jump button is pressed, another that two entities collide, and so on. +3. Gather emitted events in a queue. +4. Process each event one after another, mutating the game state. + Upon exhausting the queue, the next game state is reached. +5. Move on to rendering. +6. `goto 1` + +See also this figure, taken from *[How to Think Like a Computer Scientist](http://openbookproject.net/thinkcs/python/english3e/index.html)*: + +![Main Game Loop Example](images/game_loop.png) + +However, what looks easy on paper can be rather challenging in reality. +First, certain events may stay in conflict with each other. +Like, while the player character should move upwards because of the jump button being pressed, a projectile may hit her in the exact same frame which causes knock-back. +Now, do you move the player up, or away from the projectile due to knock-back? +Or both? +And what if a wall is there preventing the player character from being pushed in this specific direction. + +Even in this tiny example, the order in which events are processed matters. +They may even build circular dependencies with each other. + +As it turns out, such an *invoke everything first, ask questions later* approach comes with a lot of problems. +One way to improve upon this is by doing stuff in phases, plus ensuring that the modified game state is always valid. + +The whole topic of game engine architecture is huge and most decisions are trade-offs. +I recommend that you try not to over-think this. +Keep your cool and experiment until you find something that kinda works. + +## Debugging + +Develop debugging utilities as early as possible. +Consider the following: + +- log output +- show bounding boxes, game entity positions, damage numbers etc; on screen +- *noclip* (disable collision + player can fly) +- *god mode* (player doesn't take any damage) +- infinite ammo / mana / resources +- spawning entities in front of the player +- directly load a specific map +- goto x y +- … + +Another helpful technique is the use of fallback assets. +Let's say, a certain sprite cannot be loaded for whatever reason. +Instead of crashing the application with a cryptic error code, log a warning and use an *error sprite* instead. + +- - - + +## Goals (11 Points) + +- (2) two consecutive areas, each: + - with its own tone (architecture, sprites, music, enemies etc) + - with a handful of rooms each + - a boss guarding an item / ability +- (2) basic movement + - running left / right + - jumping + - interacting with game entities (doors, chests etc) +- (1) save / load with dedicated save points (rooms) +- (1) one or more advanced movement mechanics + - eg double jump, wall jump, sliding + - needs to be unlocked +- (1) main combat + - melee and/or ranged + - hitting enemies + - getting hit by enemies +- (2) enemies + - attack the player character as it gets in range + - variants with melee attacks + - variants with ranged attacks + - bosses are capable of using different attacks +- (1) map + - shows discovered rooms and their doorways + - shows discovered save points + - shows where the player is currently located +- (1) menus + - main menu + - new game + - load game + - exit + - pause menu + - shows player stats + - inventory management + - continue + - go to main menu + - game over + - player dies + - player defeats final boss diff --git a/assignment2/rpg_specification.md b/assignment2/rpg_specification.md new file mode 100644 index 0000000..84f1e81 --- /dev/null +++ b/assignment2/rpg_specification.md @@ -0,0 +1,166 @@ +# RPG Specification + +We describe a simple 2D RPG with two layers. + +The first layer is an interactive *overworld* which is explored by the player. +There, the player can talk to other characters and manage their resources (items, equipment, …). + +The second layer is a turn-based combat system as typically found in JRPGs. + +For references, have a look at these titles / series: + +- Octopath Traveler +- Final Fantasy +- Chrono Trigger +- Pokémon +- Persona +- Trails of Cold Steel + +After playing some gam-… ehh… doing some research, you should be familiar with the core game concepts and mechanics of the genre. + +Before moving on, I want you to make up your mind about the setting your game takes place in. +While a fantasy world with magic and monsters sounds straight forward, don't overlook other possibilities like cyberpunk, steampunk, post apocalypse and so on. +Determine upfront whether you are going for a more serious or a more humorous tone — whether things should be realistic or over the top with crazy anime effects everywhere. + +### Assets + +But, what about all the assets (sprites, music, sound effects, …) that are required for such a game? + +Well, you don't have to look far. +As this is still about learning C++, I don't expect you to spend your precious time on creating all of them by hand. +There are megatons of assets for free- / non-commercial- / educational-use available online. +I am pretty sure you'll find something among them which suits your setting. +Maybe some slight modifications are needed here and there, but nothing that should distract you from learning C++. + +For various types of assets — sound effects especially — there are also generators available which can be tweaked for unique results. +Pick your poison! + +## Building the World + +As already mentioned, the first layer of your game is an overworld where the player interacts with other characters and so on. +This overworld is typically composed of safe-zones (like villages or small settlements) and wilderness where enemies are encountered. +Often, certain sections of the overworld remain gated off until the player has advanced far enough into the story. + +Here is the overworld of Pokémon Red and Blue (1996) + +![Pokémon Red and Blue Map](images/pokemon_map.png) + +### Overworld Implementation + +A 2D array of tiles can be used to describe the map itself. +Entities (characters, chests, enemies, …) can be added by simply stating their coordinates. + +I recommend to put the world definition into a dedicated file, following a human-readable, easy-to-parse file-format. +Alternatively, just put the definition in your code. + +## Viewing the World + +[Sprites](https://en.wikipedia.org/wiki/Sprite_(computer_graphics)) are essentially bitmap images with transparent background. +They are used for everything that needs to be displayed. + +The *transform* (position, rotation, scale) of an entity determines where and how the corresponding sprite is rendered. + +### Animations + +Dynamic entities, like the player character (PC) or enemies, often feature animations. +These start with simple idle and walking animations, but can also turn into breath-taking combat and dodging choreographies. + +![Sprite Map](images/sprite_map.png) + +The key idea is to use multiple sprites instead of just one. +Each animation frame is a new sprite. +When an animation is played, the related sprites are displayed one after another to simulate motion. + +Multiple sprites are combined and put into the same image, which is then called a *sprite map*. +The rendering API allows us to select which part of the image to use for rendering. +A simple rectangle selection is used to pick the sprite for the current frame. + +## Hearing the World + +Commonly, the background music is either determined by the section of the overworld or enemy encounter (regular battle theme, boss battle theme, …). +The selected tune is repeated until the player moves to a new section or finishes the encounter. + +A more advanced technique would be to use different variations of the same background music and blend them together depending on the situation. Say, switch to a more tense version of your regular battle theme as soon as the player's combatants are low on health. + +### Audio Implementation + +SDL_mixer is probably all you need for this. +It provides separate sound channels, each with its own volume setting. +Sound effects are played on different channels than background music so they do not interfere. + +If you wanna go for something fancy, with more features, have a look at [OpenAL]. + +## Interacting with the World + +Most interaction between the player and the game world is done through message boxes and menu systems. +For this, you need to implement some basic UI system. +You already know how to render sprites, font support is available via [SDL_ttf]. + +### Interaction Implementation + +Often, a scripting engine is added to the game engine for scripting the interactions between characters, combat, and so on. +However, this goes beyond the scope of this project. + +My recommendation is to simply hard-code the logic and script of your game in C++. +Think about creating your own little embedded domain-specific language (EDSL) on top of C++. +Consider trying [Boost Coroutine](https://theboostcpplibraries.com/boost.coroutine) for adding asynchronous programming paradigms. + +## Story + +Again, the focus of the side project lies on learning C++. +Your RPG should feature a short story with a twist near the end. +Nothing fancy, just something to keep the player interested while exploring the overworld. + +## Combat AI + +Similar to your other game logic components, the combat AI may be hard-coded in C++. +[Behaviour trees](https://en.wikipedia.org/wiki/Behavior_tree_(artificial_intelligence,_robotics_and_control)) are often utilised for creating game AI. +Maybe give them a try. +Consider adding randomness to your decision making progress to make enemies less predictable. + +## Debugging + +Develop debugging utilities as early as possible. +Consider the following: + +- Log output +- Show details (positions, damage numbers, decision making process, …) on screen +- *God mode* (player's combatants can't die) +- Infinite resources (items, spells, …) +- … + +Another helpful technique is the use of fall-back assets. +Let's say, a certain sprite cannot be loaded for whatever reason. +Instead of crashing the application with a cryptic error code, log a warning and use an *error sprite* instead. + +--- + +## Goals (11 Points) + +- (2) Overworld with 2 different sections: + - Each with its own tone (architecture, sprites, music, enemies, …) + - The second is only accessible after some story progress + - Player can roam the world and interact with other entities +- (1) Characters + - Player can talk to other characters +- (1) Resources + - Player can manage acquired resources through dedicated menus +- (1) Stats + - Player's combatants have stats that influence the combat + - Player's combatants get experience from combat, increasing their stats + - Stats are influenced by equipment +- (3) Combat + - Turn-based + - Player selects which attacks, spells, items, etc. to use on which target + - Enemies use attacks, spells, items, etc. to combat the player + - *Game Over* when all of player's combatants are dead +- (1) Save points + - Player can save her progress at specific points in the game + - Saved progress is persistent across play sessions (application termination) +- (1) Audio + - Background music + - Sound effects +- (1) Main menu + - New game + - Load game + - Exit