This repository has been archived on 2023-06-24. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
2022FuncProg-project3-RPGEn.../README.md

294 lines
No EOL
10 KiB
Markdown

<!--
## Functional requirements
- [ ] Parsing of engine configuration file to game object
- [ ] Rendering of all game objects (Levels, objects, entities, ...)
- [ ] A start menu with the possibility of selecting a level
- [ ] An end screen that shows wether or not a player won
- [ ] Support for built-in engine functions
- [x] Player can move around in grid-world.
- [ ] Player can pick up objects.
- [ ] Player can use objects.
- [ ] Player can loose and gain health points.
- [ ] Player can interact with other entities (fight enemies, open doors, ...).
- [ ] Player can go to the next level.
## Not-functional requirements
- [x] Use Parsing.
- [ ] Use at least one (1) monad transformer.
- [ ] Write good and plenty of documentation.:w
- [x] Write tests (for example, using HSpec).
---
Nuttige links:
- https://jakewheat.github.io/intro_to_parsing/
```
Jarne — Today at 22:44
Da kan hoor en had da eerst, me gloss eeft geen goede text dus...
ListDirectory, en er was ook een fuctie takeBaseName
```
---
<div style="page-break-after: always;"></div>
-->
# RPG-Engine
RPG-Engine is a game engine for playing and creating your own RPG games.
If you are interested in the development side of things, [development notes can be found here](#Development-notes).
This README serves as both documentation and project report, so excuse the details that might not be important for the average user.
## Playing the game
These are the keybinds *in* the game. All other keybinds in the menus should be straightforward.
| Action | Primary | Secondary |
| ---------- | ------------- | ----------- |
| Move up | `Arrow Up` | `w` |
| Move left | `Arrow Left` | `a` |
| Move down | `Arrow Down` | `s` |
| Move right | `Arrow Right` | `d` |
### Example playthrough
TODO
- An example playthrough, with pictures and explanations
\pagebreak
## Writing your own stages
A stage description file, conventionally named `<stage_name>.txt` is a file with a JSON-like format. It is used to describe
everything inside a single stage of your game, including anything related to the player, the levels your game contains
and what happens in that level. It is essentially the raw representation of the initial state of a single game.
> Note: At the moment, every game has a single stage description file. Chaining several files together is not possible yet.
A stage description file consists of several elements.
| Element | Short description |
| --------------- | --------------------------------------------------------------------------------------------------------- |
| `Block` | optionally surrounded by `{ ... }`, consists of several `Entry`'s, optionally separated by commas `,` |
| `Entry` | is a `Key` - `Value` pair, optionally separated by a colon `:` |
| `Key` | is a unique, predefined `String` describing `Value` |
| `Value` | is either a `Block` or a `BlockList` or a traditional value, such as `String` or `Int` |
| `BlockList` | is a number of `Block`'s, surrounded by `[ ... ]`, separated by commas, can be empty |
<details>
<summary>We'll look at the following example to explain these concepts.</summary>
```javascript
player: {
hp: 50,
inventory: [
{
id: "dagger",
x: 0,
y: 0,
name: "Dagger",
description: "Basic dagger you found somewhere",
useTimes: infinite,
value: 10,
actions: {}
}
]
}
levels: [
{
layout: {
| * * * * * *
| * s . . e *
| * * * * * *
},
items: [],
entities: []
},
{
layout: {
| * * * * * * * *
| * s . . . . e *
| * * * * * * * *
},
items: [
{
id: "key",
x: 3,
y: 1,
name: "Door key",
description: "Unlocks a secret door",
useTimes: 1,
value: 0,
actions: {
[not(inventoryFull())] retrieveItem(key),
[] leave()
}
}
],
entities: [
{
id: "door",
x: 4,
y: 1,
name: "Secret door",
description: "This secret door can only be opened with a key",
direction: left,
actions: {
[inventoryContains(key)] useItem(key),
[] leave()
}
}
]
}
]
```
</details>
This stage description file consists of a single `Block`. A stage description file always does. This top level `Block`
contains two `Value`s `player` and `levels`, not separated by commas.
`player` describes a `Block` that represents the player of the game. Its `Entry`s are `hp` (a traditional value) and
`inventory` (a `BlockList` of several other `Block`s). They are both separated by commas this time. It is possible for
the inventory to be an empty list `[]`.
`levels` is a `BlockList` that contains all the information to construct your game.
### `layout` syntax
If `Key` has the value `layout`, `Value` is none of the types discussed so far. Instead `Layout` is specifically made
to describe the layout of a level. This object is surrounded by `{ ... }` and consists of multiple lines, starting with
a vertical line `|` and several characters of the following:
- `x` is an empty tile a.k.a. void.
- `.` is a tile walkable by the player.
- `*` is a tile not walkable by the player.
- `s` is the starting position of the player.
- `e` is the exit.
All characters are interspersed with spaces.
### `actions` syntax
If `Key` has the value `actions`, the following changes are important for its `Value`, which in this case is a `Block`
with zero or more `Entry`s like so:
- `Key` has type `ConditionList`.
A `ConditionList` consists of several `Condition`s, surrounded by `[ ... ]`, separated by commas. A `ConditionList`
can be empty. If so, the conditional is always fulfilled.
A `Condition` is one of the following:
- `inventoryFull()`: the players inventory is full.
- `inventoryContains(objectId)`: the players inventory contains an object with id `objectId`.
- `not(condition)`: logical negation of `condition`.
- `Value` is an `Action`.
An `Action` is one of the following:
- `leave()`
- `retrieveItem(objectId)`
- `useItem(objectId)`
- `decreaseHp(entityId, objectId)`
- `increasePlayerHp(objectId)`
### Back to the example
If we look at the example, all the objects are
```
>Block<
Entry = Key ('player') + >Block<
Entry = Key ('hp') + Value (50)
Entry = Key ('inventory') + >BlockList<
length = 1
Block
Entry = Key ('id') + Value ("dagger")
... <several traditional entries like this>
Entry = Key ('actions') + empty Block
Entry = Key ('levels') + >BlockList<
length = 2
>Block<
Entry = Key ('layout') + Layout
<multiple lines that describe the layout>
Entry = Key ('items') + empty BlockList
Entry = Key ('entities') + empty BlockList
>Block<
Entry = Key ('layout') + Layout
<multiple lines that describe the layout>
Entry = Key ('items') + >BlockList<
length = 1
>Block<
Entry = Key ('id') + Value ("key")
... <several traditional entries like this>
Entry = Key ('actions') + >Block<
Entry = >ConditionList< + Action ('retrieveItem(key)')
length = 1
Condition ('not(inventoryFull())'))
Entry = empty ConditionList + Action ('leave()')
Entry = Key ('entities') + >BlockList<
length = 1
>Block<
Entry = Key ('id') + Value ("door")
... <several traditional entries like this>
Entry = Key ('actions') + >Block<
Entry = >ConditionList< + Action ('useItem(key)')
length = 1
Condition ('inventoryContains(key)')
Entry = empty ConditionList + Action ('leave()')
```
\pagebreak
## Development notes
### Assets & dependencies
The following assets were used (and modified if specified):
- Kyrise's Free 16x16 RPG Icon Pack<sup>[[1]](#1)</sup>
Every needed asset was taken and put into its own `.png`, instead of in the overview.
- 2D Pixel Dungeon Asset Pack by Pixel_Poem<sup>[[2]](#2)</sup>
Every needed asset was taken and put into its own `.png`, instead of in the overview.
RPG-Engine makes use of the following libraries:
- [gloss](https://hackage.haskell.org/package/gloss) for game rendering
- [gloss-juicy](https://hackage.haskell.org/package/gloss-juicy) for rendering images
- [hspec](https://hackage.haskell.org/package/hspec) for testing
- [hspec-discover](https://hackage.haskell.org/package/hspec-discover) for allowing to split test files in multiple files
- [parsec](https://hackage.haskell.org/package/parsec) for parsing configuration files
### Future development ideas
The following ideas could (or should) be implemented in the future of this project.
- [ ] Entity system: With en ES, you can implement moving entities and repeated input. It also resembles the typical
game loop more closely which can make it easier to implement other ideas in the future.
- [ ] Game music: Ambient game music and sound effects can improve the gaming experience I think.
\pagebreak
## References
<a id="1">[1]</a> [Kyrise's Free 16x16 RPG Icon Pack](https://kyrise.itch.io/kyrises-free-16x16-rpg-icon-pack) © 2018
by [Kyrise](https://kyrise.itch.io/) is licensed under [CC BY 4.0](http://creativecommons.org/licenses/by/4.0/?ref=chooser-v1)
<a id="2">[2]</a> [2D Pixel Dungeon Asset Pack](https://pixel-poem.itch.io/dungeon-assetpuck) by [Pixel_Poem](https://pixel-poem.itch.io/)
is not licensed