Quick Start

How Loxoc Works

Before we get started, lets install the Loxoc engine. This is as easy as:

pip install Loxoc

Loxoc is a very straight forward and easy to use game engine. If you have used game engines like Pygame things should look somewhat familiar in terms of the structure of a basic game/render loop.

To start, first lets make a basic renderloop in Loxoc:

from Loxoc import Camera, Window, EVENT_FLAG
import math

dim = (1280, 720,)

camera = Camera(Vec3(0.0, 0.0, 0.0), Vec3(0.0,0.0,0.0), *dim, 10000,
    math.radians(60))
# Create the camera at x = 0, y = 0, z = 0 with no rotation 720p resolution,
# 10000 focal length, and 60 fov

window = Window("Loxoc Quick Start", camera, *dim, False,
    Vec3(0.2, 0.2, 0.2))
# Create a window titled "Loxoc Quick Start" with the same dimensions as the camera,
# in windowed mode, with an ambient light level of red = 0.2, blue = 0.2, and green = 0.2

window.add_object_list([
    # This is where we add 3D objects to be rendered to the scene...
])

window.add_object2d_list([
    # This is where we add 2D objects to be rendered on the screen surface infront of
    # everything...
])

window.add_point_light_list([
    # This is where we add point lights to be rendered to the scene...
])

while not window.event.check_flag(EVENT_FLAG.QUIT):
    # While the close button has not been clicked run the game loop:

    # game code goes here...

    window.update()
    # At the end of the game loop we update the window.

Great! Now that we have our basic game loop we can move onto the fun part. Lets try rendering something to the Window .

Before we can render anything to the Window , we need to learn how the 3D asset / Mesh importing system works. It is recommended to have a /models/ directory or equivalent in your project for storing your game assets. Other than that Its pretty flexible.

Here is an example of a possible project structure:

./
    assets/
        models/
        sprites/
        sounds/
    my_game.py
    setup.py

    ...other project files...

While this example organizes its asset files inside of an assets/ folder, you dont have to. Now lets first add a 3D asset to this project, then we’ll explain how it works:

./
    assets/
        models/
            model_name/
                textures/
                    model_texture.png
                model_name.bin
                model_name.gltf
        sprites/
        sounds/
    my_game.py
    setup.py

    ...other project files...

There are a few things that are important to keep in mind here:

  • The /textures/ directory:

    The /textures/ directory is required to be adjacent to the model files and must include all of the model’s textures.

  • Model file formats:

    The format of model should be flexible, but we cannot promise every format will work. While .gltf format is recommended we have also seen success with .obj format. .fbx is not and will never be supported unfortunately due to its proprietary nature.

  • The /model_name/ directory:

    Each model should have its own directory and texture folder to prevent name conflicts.

Now that we have our model sorted out, lets get to adding it to our game. We’ll need a few new imports namely Loxoc.Mesh and Loxoc.Object3D . We will also include Loxoc.MeshDict (we will explain the purpose of MeshDict in a minute) for type annotations. It should look something like this:

# my_game.py
from Loxoc import Camera, Window, EVENT_FLAG, Mesh, Object3D, MeshDict, Model
import math

dim = (1280, 720,)

camera = Camera(Vec3(0.0, 0.0, 0.0), Vec3(0.0,0.0,0.0), *dim, 10000,
    math.radians(60))

window = Window("Loxoc Quick Start", camera, *dim, False,
    Vec3(0.2, 0.2, 0.2))

my_model: Model = Model.from_file("./assets/models/model_name/model_name.gltf")
# We import the contents from the 3D asset file into a Model variable so we can use our
# Model in our game.

my_object = Object3D(my_model, Vec3(0.0, 0.0, 20.0), vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0))
# We create an object from the model that can be used in our game with a position of
# x = 0, y = 0, z = 20 infront of the camera, no rotation, and a scale in all directions
# times 1 or in other words no change in scale.

window.add_object_list([
    my_object # Now we add our object to the list of objects to be rendered.
])

window.add_object2d_list([])

window.add_point_light_list([])

while not window.event.check_flag(EVENT_FLAG.QUIT):

    window.update()

Tada! you should now see your model being rendered when you run your game. Now lets explain a few things:

  • Model :

    Loxoc.Model is a datastructure holding all of the visual data for an Object3D . It contains a MeshDict , animation api, and some render settings that can be tweaked to change the final appearance of a rendered model. For now just think of this as the “appearance” data for an Object3D .

  • MeshDict :

    Loxoc.MeshDict is a datastructure that acts like a statically typed dictionary storing each Mesh by name. This is nessicary because 3D asset files can have more than one Mesh in them. If you have a 3D asset file with more than one Mesh inside of it, you can extract them from their MeshDict to new individual MeshDict s and then to Model s to be used in Object3D s like so:

    my_assets: MeshDict = Model.from_file("./assets/models/model_name/model_name.gltf").mesh_dict
    # Import the 3D asset file.
    
    player_md = MeshDict("player_model_mesh", [my_assets["player_model"]])
    # Extract the Mesh into its own group/MeshDict
    
    player_object = Object3D(Model(player_md), Vec3(0.0, 0.0, 20.0), vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0))
    # Now our model is ready to be used.
    

    We can extract the Mesh s we need from the my_assets MeshDict by name. Hence we use my_assets["player_model"]. This is assuming your desired Mesh is at the top level of your imported 3D file/asset’s heirarchy. if it is in a group inside the 3D file/asset you imported you could do something like: my_assets["group_name"]["player_model"]

  • Object3D :

    Loxoc.Object3D is our game object. It holds the Model to be rendered, the Object3D ‘s Vec3 position, it’s Quaternion rotation, any object level uniforms to be used in it’s Loxoc.Material and much more.

  • Window.add_object_list() :

    Loxoc.Window.add_object_list() is used to add objects to the set of objects to render to the screen on Window.update() . You can think of this like creating an object in the game. You can also remove objects with Window.remove_object() .

As one final bonus of this Quick Start We are going to make our Object3D spin! To do this we are going to rotate our Object3D arround its up directional vector. It should look something like so:

# my_game.py
from Loxoc import Camera, Window, EVENT_FLAG, Mesh, Object3D, MeshDict, Model
import math

dim = (1280, 720,)

camera = Camera(Vec3(0.0, 0.0, 0.0), Vec3(0.0,0.0,0.0), *dim, 10000,
    math.radians(60))

window = Window("Loxoc Quick Start", camera, *dim, False,
    Vec3(0.2, 0.2, 0.2))

my_model: Model = Model.from_file("./assets/models/model_name/model_name.gltf")

my_object = Object3D(my_model, Vec3(0.0, 0.0, 20.0), vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0))

window.add_object_list([
    my_object
])

window.add_object2d_list([])

window.add_point_light_list([])

while not window.event.check_flag(EVENT_FLAG.QUIT):

    my_object.rotation.rotate(my_object.rotation.up, 10.0 * window.dt)

    window.update()

And thats all there is to it! You should now have a spinning 3D model rendering on your game window. Check out the Loxoc API Reference for more info.