skip to content
heny.quest

SFAS Feedback and Learnings

/ 10 min read

If you haven’t read the original project post for Escape Ghoul Prison, you can do so here!

I received an awesome amount of feedback for my SFAS 2024 submission and thought it would be a great learning opportunity to write them up, as well as discuss what I learned from them. Below, I have split them by Technical Feedback and Gameplay Feedback.

Note: Some of the write-ups are based off the shared feedback document as well as the individual feedback document. So some points won’t apply to my project, but I figured would be great to write up for future reference.

Technical Feedback

I learned a lot from this section — especially about how memory is managed in C++. This was identified as a gap in my knowledge, especially when coming from a garbage collected language like C#.

Feedback
I like your BT implementation and the use of modern c++ features
This is an interesting project and a good showcase of your behaviour tree code, and the game is simplistic but interesting, I think it would be an interesting minigame in a wider game’s scope. Your implementation is pretty clean in general, however most of your game code lives in the game.cpp. I think this is a good Portfolio project.
I would suggest a class based GameState upproach and to move hard coded levels to files.
I had an easy time navigating the project and appreciated the comments to mark sections. Particular impressive is managing to implement a behavior tree using coroutines in the limited time frame of the project. The two majors issues I found are: non of the head allocated memory is freed (after creating a pointer object with new one must call delete to clean up the memory later) and std::list is a poor choice for collections as it’s C++ implementation of linked lists which may lead to cache misses and are usually much slower than inplace collection like std::vector. The combination of the issues with the otherwise overall great code quality suggest, that the participant is quite experienced with another programming language like C# (include advanced features like coroutines), but is not familiary with memory management in C/C++. I recommend reading up on memory allocation and memory patterns of various data structures in C++. Aside from this knowledge gap, the code structure, features and workflow definetly on the level I like to see in a code sample of an application.
Function parameters should be const whenever possible. Recommend commenting parameters where the unit expected is unclear, e.g. rotation - radians or degrees. Good to consider different naming conventions for parameters and locals versus member variables, e.g. use camelCase for the former and PascalCase for the latter. Ideally should tidyup before a commit and remove any commented out code unless you have good reason to keep it around. If it’s an experimental idea, create a separate branch and store it there. Recommend using enum class now that it’s widely supported by compilers. Take care with operator precedence, nothing wrong with using extra brackets to make it clear what you mean in case the precedence isn’t quite what you think. Don’t make members public without good reason, use accessors by preference. Share assets if you can, use refcounted objects and/or track assets.

Input

  1. Windows messages was not advised to be used as an input handler.
    • More preferable to use games related APIs such as DirectInput.
    • This can be helpful for more specific inputs, e.g., Released and Pressed states for key presses.
  2. Action-based inputs.
    • So instead of directly assigning key presses different actions, assign them to a function.
    • Ensures actions are not directly tied to the key presses themselves, keeping implementation modular.
    • I recently read about the Command pattern 1, and saw an implementation of an InputManager which looks like it would have fit well in this project.

Coding Best Practises

  1. Pass non-POD (Plain Old Data) Types as a const reference — unless you have a good reason.
    • Ensures you are not mutating objects unexpectedly.
    • Generally can pass POD types by value.
    • I made a nifty table below based off this article 2 I read on passing parameters.
Pass byWhen
ValueNot modified by func, easy to copy.
const PointerNot modified by function, expensive to copy, NULL is possible
Non-const PointerModified by func, expensive to copy, NULL
const ReferenceNot modified by func, expensive to copy, NULL not accepted
Non-const ReferenceModified by func, expensive to copy, NULL not accepted
  1. Don’t make members public without good reason.
    • This is a bad habit of mine.
  2. Sharing assets.
    • Use reference-counted objects or an asset database.
    • It would have been good to use smart pointers here, which I learned about here 3
  1. Avoid hardcoding arrays and screen positions
    • Use data files.
    • Or use relative positioning for different screen sizes — especially for HUD or UI.
  2. Remember to use assertions or if() statements to avoid possible exceptions.

Submission-Specific

This has personally been my favourite section to go through. Specifically, I spent quite some time ensuring I understood the memory layout of C as this was identified by one of the assessors as a gap in my knowledge. This is true, especially when coming from a memory managed language like C#.

  1. Most of my game code lived in the Game.cpp, it would have been worth splitting it out more into separate files. e.g.,
    • Class-based GameState
    • Class-based Levels
  2. None of the heap allocated memory was freed.
    • For each new, a corresponding delete must be called.
    • You can also use smart pointers which will do this automatically. 3
    • I have read up on Dynamic Memory Allocation 4 and the C Memory Layout5, as this specific feedback highlighted a gap in my knowledge coming to C++ from C#.
  1. Don’t use std::list if you can avoid it.
    • Will lead to cache misses.
    • Slower than collections like std::vector.
  2. Use the enum class instead.
    • Using scoped enumerations has multiple advantages over the enum type used in my game.
    • Here is a good article I found comparing the two6.
  1. Comments to clarify units used.
  2. Recommended to use camelCase for local variables and PascalCase for member variables. (Sorry Unreal)

Gameplay Feedback

I had some great gameplay feedback and thought it would be good to save them here in case the itch.io page went down.

Feedback
Escape Ghoul Prison is fun to play, technically well executed and well scoped. While behaviour trees would be an overkill for this project if the primary purpose was to make a great game with these mechanics, it demonstrates technical expertise well as a portfolio project. The game builds creatively on the starter project with a sensible scope for the submission timeline. The participant delivered a quality result both in the game as well as in the documentation. The main feature I was missing was a tutorial and controls explanation in game. Overall a well thought through and polished submission.
This is super fun, I got so frustrated when I got caught and kept retrying! This is a great example of using the base mechanics in a creative way and building on the areas which you are passionate about - that’s the best way to learn! I’m very impressed with your development of the AI. Also, the UI and controls are intuitive and make it an easy to figure out how to play. Great stuff!
This is a neat game, with a nice set up of the two different screens. Holding space to see what the guard is doing is a nice mechanic, but you should disable input for the lockpick when doing this, otherwise you can just hold space and continue to blindly fumble with the lock. The timer could be brought down a lot to make the game more difficult. And some audio would elevate this game quite a lot. It’s quite basic graphically, and that’s ok for the style. But some music would really add to the tension that the game is trying to create.
I tried to play it without reading the game page (as I do with other games) and struggled to understand what was going on outside turning the key and unlocking. After reading the game page and grokking how all the elements are related to each other, it became much more interesting to play with the tension between swapping views and making progress with the lock as soon as possible. However, once I realised there was no real time limit, the tension was gone since there was no incentive to progress through the lock as quickly as possible. Having some sort of timer, scoring system and/or some in-theme narrative (e.g. all the other inmates are taken away one by one) would balance that. I’m not sure how the battery level applies to the game as it went down but wasn’t sure ‘why’. I ended up quickly tapping between D, Space and W to get through the lock stages rapidly. Not sure how the game would scale though for replayability or difficulty. Maybe different puzzle locks, different guard behaviours, etc. The UI/UX had good cohesiveness on the theme, it looked like it all tied together and the two tone aesthetic worked well. A couple of areas of polish would be: - making the three lock stages part of the lock instead of a separate UI so it’s immediately clear - showing the torch in some fashion to show where it’s being used that drains the battery - some hint in control that pressing space changes view with clear indication which one is your cell - maybe some indication of state changes with the guard (Metal Gear Solid style) The AI behaviour system looks like it is the focus of the coding as mentioned in your writeup and it’s great to see that you are using new C++ features with it. I would be interested to hear how you found debugging the system compared to a state machine as well as a comparison between working with the two.
Interesting, I can see the potential there!
Clean release ZIP Good minimalist art aesthetic Controls work well Took a while but was able to escape successfully Great player documentation Good job on design/development documentation

Changes

Here are some gameplay changes I would have liked to implement if I had time. Some of these are based off feedback received above.

  1. Stricter battery/timer
    • Battery was far too forgiving, and in some instances, unnoticeable.
    • It might have also been worth swapping out the indicator for something more clearly tied to time.
  2. Taking away prisoners
    • This is such a good idea for difficulty scaling. I wish I had thought of that.
  3. Clearly highlighting player cell
    • I should have made the indicator larger, or anything else.
  4. Audio
    • One of the assessors mentioned that sound would have increased the tension a lot.
    • It would have been cool to tie specific sounds to different guard behaviours.
  5. More clarity around indicator
    • I think the notice player indicator should be bigger to show its immediate threat.
    • Audio would also help in this regard.

Conclusions

This project has helped with my personal development an immense amount. I would like to thank Grads In Games and the Assessors who gave me feedback for the project. Overall, I am happy with the submission and am excited to implement my learnings in other C++ projects.

Thanks for reading!

Footnotes

  1. Command Pattern, Game Programming Patterns

  2. When to pass parameters by value, reference, and pointer, CPlusPlus

  3. Smart Pointers, GeeksForGeeks 2

  4. What is Dynamic Memory Allocation, GeeksForGeeks

  5. Memory Layout of C Program, GeeksForGeeks

  6. Enum Classes in C++ and Their Advantage over Enum Data Type, GeeksForGeeks