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 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.
+
+ 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
+ $ ./run.sh games/mario
would load and run the scene in the file
+ games/mario.py
+ .scenes
extension. This file should contain the
+ relative path from itself to any number of Python files, specified as in the above bullet
+ points. For example, the file mario.scenes
with content
+
+
+ ui/mario_menu
+ mario
+ ui/game_over
+
+
+ would load the scenes in ui/mario_menu.py
, mario
, and
+ ui/game_over
, and would start running the scene in ui/mario_menu.py
+ + To create a scene in Python, at minimum the following functions must be present in the script: +
+scene_startup
scene_shutdown
scene_input
scene_update
scene_render
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: +
+ +input
- allows the user to query the input manager for keys pressed and mouse
+ clicks
+ get_key(key: str)
- returns an object for the key
showing if
+ it's been pressed
, held
, or released
this frame
+ get_mouse_click()
- returns an object with mouse click data from the current
+ frame
+ pressed
- True
if the mouse button was
+ first pressed this frame
+ held
- True
if the mouse button was held
+ down this frame
+ released
- True
if the mouse button was
+ released this frame
+ clicks
- number of times the mouse was clicked this
+ frame
+ pos
- vector with x and y for the current mouse position
+ button
- the mouse button pressed this frame
+ get_mouse_motion()
- returns an object with mouse motion data from the
+ current frame
+ motion
- vector with x and y for the amount the mouse
+ moved in each direction since the last time it was polled
+ pos
- vector with x and y for the current mouse position
+ render
- allows the user to call rendering methods necessary to run a scene,
+ interfacing with SDL
+ set_render_draw_color(r: int, g: int, b: int, a: int)
- sets the background
+ color. equivalent to SDL_SetRenderDrawColor
+ render_clear()
- clears the rendering target. equivalent to
+ SDL_RenderClear
+ render_present()
- presents rendered data to the screen. equivalent to
+ SDL_RenderPresent
+ director
- allows the user to change scenes
+ change_scene(name: str)
- changes the current scene to the one specified by
+ name
+
+ The full list of available Python methods can be found in engine/src/bindings.cpp
.
+
+ 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).
+