Nov 11, 2020

Q

Team of 5
September 2020 - December 2020
Skills Utilized: C++, OpenGL, Python

Introduction

During this semester's GAM class, my group decided to create a 2D action platformer game. I was responsible for constructing the graphics layer of the custom game engine using OpenGL and establishing a Python scripting system.

Showcase

↑ Prototype Demo

↑ Graphics showcase




↑ Scripting system showcase







↑ Scripting system showcase (integrated with the engine)




GitHubFunction Property Inspector (Part of the Python Embedder)

Responsibilites

  • Technical Director
  • Graphics Programming
  • Scripting System
  • Part of the Engine Programming
  • Other Gameplay Programming

Technical Highlights

Graphics layer of the engine

One of the challenges when working with OpenGL in an object-oriented language is that it functions as a giant state machine. While efforts have been made to encapsulate some aspects in version 4.5 and above, the core inconvenience remains. Consequently, during the design phase of the engine's graphics layer, I prioritized an object-oriented approach. I encapsulated each distinct concept, such as mesh, texture, and shader, in its own class to maximize encapsulation.


Python scripting system

Last semester, an assignment required the application of template programming. I decided to develop a Python embedder for personal exploration. And in this semester, for the game project, I decided to upgrade and use this embedder instead of relying on existing solutions, well, just for fun.
It automates the cumbersome process of registering C++ functions for using them in Python. All you have to do is one macro or a function call, depending on your preference. It heavily uses template metaprogramming for that automation.
One biggest challenge was iterating over the variadic template parameters. To expose a function to Python, you need to make another function that takes in the PyObjects, parses them then calls the original function with the parsed objects.
I was making that part of the automation and I needed to parse an arbitrary amount of arguments, so I was taking the list of the parameter types as a std::tuple. I needed to iterate over them to parse them. I couldn't use a for loop since the index of the std::tuple_element_t should be complie-time constant.
What should I do? The only thing I know in extra is the count of the parameters. After many trials and errors, I managed to figure out a solution. Make an index sequence with that count, take them with std::index_sequence<ArgumentIndices...>, and call a function for each of them with { parse<Tuple, Indices>(args)... }.




With this, I was able to register all different kinds of functions with various parameter lists with a single function call.

Conclusion

It was fun to design and build a graphics layer of the engine and implement a scripting system, which allowed us to iterate faster on the gameplay programming. Throughout the project, I gained valuable insights into OpenGL and template metaprogramming, as well as the integration of a scripting language into a game engine. These experiences collectively contributed to a significant enhancement of my skillset.

No comments:

Post a Comment