1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
# Project Title
Team members:
- Freya Murphy <freya@freyacat.org>
- Audrey Fuller <alf9310@rit.edu>
- Yusif Elsharawy <yse2561@rit.edu>
- Ryan Symons <ras1178@rit.edu>
## Summary Description
Embark on a classic roguelike dungeon-crawling adventure. Players will explore
procedurally generated, tile-based dungeon floors crafted using Binary Space Partitioning.
Battle through waves of enemies with real-time combat, collect powerful items, and
push your limits to see how deep you can delve into the ever-changing depths.
## Checkpoint Progress Summary
Give a summary of the progress made and lessons learned thus far.
So far, our group has been able to achieve most of our MVP functionalities, including:
- Dunegon floor procedural dungeon generation
- Player movement and complex enemy movement (roaming and pathing to player).
- Collision Logic
We've even managed to achieve some stretch goals and additional features:
- Usage of pixel art sprite sheets
- Item/Inventory system
## Lessons Learned
With the work completed so far, we've gained a greater understanding of creating Rust
programs from the ground-up, however this came with some roadblocks.
### Goodbye Wave Function Collapse
The nixing of the Wave Function Collapse Algoritm for dungeon generation was an unfortunate
but nessesary step in the development of this project. After fully writing a generic
implementation of the algorithm and testing it, we learned that tragically WFC does not
guarantee it's constraints are imposed globally, only in small local patches. This means
that it doesn't guarantee every dunegon room will be accessable from the player's start location.
While there are workarounds for this, it usually involves pairing WFC as a post-processing step
on a complely different generation algorithm that does guarantee connectivity. So ultimately
after more thourough research, we switched to Binary Space Partitioning for generating the
map instead.
### Float vs u16 vs usize
Another issue during development was the standardizarion of our data types for dungeon structure,
traversal and generation. With several of us working on differnent but interconnected components,
there were some instances where we would define our type fields for storing location information.
This lead to refactoring later to standardize most of our dungeon-related types into u16, as placing
expect(clippy::cast_possible_truncation) every few lines isn't what I would call "good practice".
### Raylib Double Free
Working with C libraries are always fun, especially when it comes to memory management. When using
these libraries with Rust, the bindings must gurentee that it encapsulates all C-like memory
shenanigans such that any safe use of the rust bindings do not result in a panic/segfault/undefined
behavior. Sadly, `raylib-rs` seemd to miss this when it comes to deallocating its structures. The
`RenderTexture2D` (pretty much just a Frame Buffer Object or FBO), is created by using the raylib
handle, but is not lifetime bound to it. Thus it's possible for the raylib handle to be dropped first,
and then the render texture next. The issue is the raylib handle will deallocate all of raylib when
dropped, and thus cause a double free when the render texture is attempted to be dropped. The solution?
Re-order the fields on the `Window` struct. Very cool.
### Windows HATES Default Features
Well maybe not? To optimize a rust binary, it's normal to go through default features and disable
what is not used. For `raylib-rs`, there are a ton of default features, as all raylib modules
are enabled by default, along with support for all file formats. Most of this is not needed
and therefore can be disabled. Turns out, at least on windows, when these features are disabled,
the program fails to link. It attempts to link to symbols such as `LoadModelFromMesh`, even though
these were never called. Why, who knows? The work around was to enable default features for raylib
on windows builds.
## Structure
### **Game Crate**
Initializes the game state and handles the Model-View-Controller loop and player movement.
### **Dungeon Crate**
Contains the core functionality for interacting with a dungeon and it's components.
- **[astar](dungeon\src\astar.rs)** - Generic A* Pathfinding Algorithm Implemented for Player Movement.
- **[bsp](dungeon\src\bsp.rs)** - Binary-Space Partitioning Algorithm for Dungeon Tile Generation.
Recurively splits the dungeon into randomly sized rooms, then collapses the tree upwards connecting each root node.
- **[bsp_tests](dungeon\tests\bsp_tests.rs)** - Integration tests to verify all moveable tiles are connected.
- **[entity](dungeon\src\bsp.rs)** - Contains the structures for all entities, including the player, items and enemies.
Implemented features:
- Enemy movement
- Inventory
- **[map](dungeon\src\map.rs)** - Structures for the dungeon game map including the current `Floor`, and map `Tile`.
- **[player_input](dungeon\src\player_input.rs)** - Carries information about player inputs, including mpve direction.
- **[pos](dungeon\src\pos.rs)** - Representation of a position and direction inside the dungeon grid.
- **[wfc](dungeon\src\wfs.rs)** - **Not Used** Wave Function Collapse Algorithm for Dungeon Generation.
### **Graphics Crate**
Core functionality for
- **[audio](graphics\src\render.rs)** - Framework for loading audio assets during runtime.
- **[render](graphics\src\render.rs)** - Defines wrappers for calling the raylib library for sprite displaying.
Implemented Features:
- UI
- Text
- Texture loading
- Debug view
- Tilemap with foreground and background
- Minimap
- Stats
- Camera locked to player
## External Crates
- `argh` - Argument parser
- `rand` - Seeded random number generation
- `raylib` - Graphics and rendering
- `strum` - Making strings and enums easier to work with
## Work To Do For the Final
### **Dungeon Crate**
- Implement attacking for both enemies and player
- Picking up and using items
- Create new enemy types for a more interesting game experience, currently only a basic "Zombie" exists
- Make a balance system for number of enemies on each floor, scaling with floor number (e.g. higher floor, more enemies)
- Implement a heuristic algorithm for enemy and item spawns
### **Graphics Crate**
- Finalize game textures
(Currently many textures are placeholders, or straight up "error" textures)
- Sound effects/background music?
|