diff --git a/content/souleng/_index.md b/content/souleng/_index.md new file mode 100644 index 0000000..1714e18 --- /dev/null +++ b/content/souleng/_index.md @@ -0,0 +1,4 @@ ++++ +title = "souleng" +template = "souleng.html" ++++ diff --git a/sass/souleng.scss b/sass/souleng.scss new file mode 100644 index 0000000..e69de29 diff --git a/static/images/souleng.png b/static/images/souleng.png new file mode 100644 index 0000000..0fb21c7 Binary files /dev/null and b/static/images/souleng.png differ diff --git a/static/images/ss1.png b/static/images/ss1.png new file mode 100644 index 0000000..d17f7b1 Binary files /dev/null and b/static/images/ss1.png differ diff --git a/static/images/ss2.png b/static/images/ss2.png new file mode 100644 index 0000000..1b26baa Binary files /dev/null and b/static/images/ss2.png differ diff --git a/static/images/ss3.png b/static/images/ss3.png new file mode 100644 index 0000000..6cc3d55 Binary files /dev/null and b/static/images/ss3.png differ diff --git a/static/scripts/souleng.js b/static/scripts/souleng.js new file mode 100644 index 0000000..e69de29 diff --git a/static/videos/finalvid.mp4 b/static/videos/finalvid.mp4 new file mode 100644 index 0000000..31e66df Binary files /dev/null and b/static/videos/finalvid.mp4 differ diff --git a/templates/souleng.html b/templates/souleng.html new file mode 100644 index 0000000..707ad22 --- /dev/null +++ b/templates/souleng.html @@ -0,0 +1,256 @@ + + + + + + + + +

Souleng

+ +
+
+ +

+ Souleng is a component-based game engine which allows for the creation of games + entirely in Python, utilizing the modern pybind11 fork + pybind11k + to allow users to derive their own custom Components in Python and effortlessly interface with + the C++ side of things. +

+
+ {% set ss1 = resize_image(path='static/images/ss1.png', width=376, height=213) %} + + {% set ss2 = resize_image(path='static/images/ss2.png', width=381, height=213) %} + + {% set ss3 = resize_image(path='static/images/ss3.png', width=588, height=333) %} + +
+ +

Running the engine

+ +

+ You can build the engine on Linux with build.sh, provided in the + engine directory. +

+

+ You can run the engine with run.sh, which will automatically set the + LD_LIBRARY_PATH to be the lib/ directory. You can also set this + variable yourself and run the binary directly. The expected format is +

+ +
+    $ ./run.sh <scene>
+  
+ + where the scene is either + + +

Python scripting

+ +

+ To create a scene in Python, at minimum the following functions must be present in the script: +

+ + +

Custom components can be created as follows:

+ +

+    import souleng as sw
+    class Foo(sw.ScriptComponent):
+      def __init__():
+        super().__init__()
+        ...
+
+      def input():
+        ... # handle input here
+
+      def update(dt: float):
+        ...
+
+      def render():
+        ...
+  
+ +

+ Custom functions can be written as well, but these functions must be overridden for the + component to run code every frame, as the C++ engine will only call these functions. +

+ +

+ Three additional submodules exist, to allow the user to interface with different systems in the + game engine: +

+ + + +

+ The full list of available Python methods can be found in engine/src/bindings.cpp. +

+ +

Process and Postmortem

+ +

+ My main inspiration for making Souleng was the video for the Eternal engine, linked as a good + sample game engine in the final project repository. In their video demonstration, they showed + games using Python components such that most of the game could just be scripted in Python. + However, these components were a bit ad-hoc: they required the module and class name of the + Python module to link properly. I wanted to improve on this idea, to create a seamless + integration between the scripting side of the game engine and the actual components. +

+ +

+ In order to do this, I looked more closely at how Pybind worked, and tried to understand exactly + why it was not possible to inherit from components in Python, and then use them in C++. I ran + into the issue of this not being possible when adapting Space Invaders for this new engine, but + researching it shows that this would only happen if Python no longer held any references to the + object being passed to C++. It would "slice" components, so that any Python specific logic was + lost. A more modern fork of pybind11 addressed this issue, so I opted to use that + library and included it in my game engine. +

+ +

+ Ultimately, my game engine accomplished what it set out to do, and I'm happy with that component + of it. The game development process in Python has as much power as it did in C++, but all of the + parts of the engine which require high performance can still run in C++, including the game loop + itself. This engine also adds some smaller features onto the previous iteration, including + support for spritesheets (swapping textures), loading multiple scenes, and much more + comprehensive input handling (handling all keys, and mouse clicks/motion). +

+ +

+ There was still a lot I wish I could've accomplished for this project, as much of it was spent + understanding the internals of pybind rather than focusing on more user-friendly features. + Scenes in the game engine can be layed out in scene_startup in Python, but there is + no GUI editor to accomplish this. Additionally, I would've liked to had this GUI editor parse + the AST for any Python scenes, to detect any custom components and allow users to add them + through the editor, as with a game engine like Unity. I would also add some more builtin + components, for things like sound and animation- sound would be something that C++ is needed + for, but even something like animation could be implemented from Python, which would be a good + showcase of the potential of this scripting feature. I would give more thought to the memory + model used for the game engine, possibly using a memory arena to manage lifetimes rather than + shared pointers, to allow for more granular control over the lifetimes of game objects. Finally, + I would like to evaluate the way I was using singleton data structures- they felt necessary at + times, but there might've been room for some other construct (maybe even just static classes, + since they need to live for the lifetime of the program). +

+ + +