PBR Textures

Well, the game for May is certainly not very much a game.

It was going to be an 'escape room' game, where you have to hunt around for things and then escape from the rooms you're in.

Since I only had two weeks to do this one in and I wasted a whole lot of that learning to do texturing (and actually doing texturing), I don't feel too bad about it.

It came out quite pretty:

Screenshot 1

Screenshot 2

You can't actually win, all you can do it move around and interact with things by jumping on them, but there's certainly a lot of learning from this to apply to future games:

All in all, not really very much game to see here, but it's playable! Play it here!

Technical notes

Honestly, there was nothing particularly amazing here to see on the technical front; a whole lot of work went into integrating the new Input.Next input streams into a FPS controller, which I've added to the scaffolds in the input module.

There is now clean separation between polling and binding input in the controller:

public void Start()
        // Devices
        var mouse = Devices.Mouse;

        // Inputs: Mouse
        binding = new Binding<FPSAction>(Inputs.Default);
        binding.Bind(new Cursor2Binding<FPSAction>(new Vector2(0f, 0f), new Vector2(1f, 1f), null, null, new FPSLookAtEvent()));

        // Inputs: Keyboard
        binding.Bind(new KeyBinding<FPSAction>(keyBindings.forwards, new FPSMoveEvent(FPSMotion.FORWARDS, true), new FPSMoveEvent(FPSMotion.FORWARDS, false)));
        binding.Bind(new KeyBinding<FPSAction>(keyBindings.backwards, new FPSMoveEvent(FPSMotion.BACKWARDS, true), new FPSMoveEvent(FPSMotion.BACKWARDS, false)));
        binding.Bind(new KeyBinding<FPSAction>(keyBindings.left, new FPSMoveEvent(FPSMotion.LEFT, true), new FPSMoveEvent(FPSMotion.LEFT, false)));
        binding.Bind(new KeyBinding<FPSAction>(keyBindings.right, new FPSMoveEvent(FPSMotion.RIGHT, true), new FPSMoveEvent(FPSMotion.RIGHT, false)));
        binding.Bind(new KeyBinding<FPSAction>(keyBindings.turnLeft, new FPSMoveEvent(FPSMotion.TURN_LEFT, true), new FPSMoveEvent(FPSMotion.TURN_LEFT, false)));
        binding.Bind(new KeyBinding<FPSAction>(keyBindings.turnRight, new FPSMoveEvent(FPSMotion.TURN_RIGHT, true), new FPSMoveEvent(FPSMotion.TURN_RIGHT, false)));
        binding.Bind(new KeyBinding<FPSAction>(keyBindings.jump, new FPSMoveEvent(FPSMotion.JUMP, true), new FPSMoveEvent(FPSMotion.JUMP, false)));


public override IEnumerable<TAction> Actions<TAction>()
        if (typeof(TAction) == typeof(FPSAction))
                foreach (var action in binding.Actions())
                        InvertLook(action as FPSLookAtEvent);
                        yield return (TAction)(object)action;

...and the code that actually handles complex input types on an Actor:

public void Update()

public override void Trigger<TAction>(TAction action)
        LookAt(action as FPSLookAtEvent);
        Move(action as FPSMoveEvent);

public void LookAt(FPSLookAtEvent data)
        if (data != null)
                var y = Mathf.Clamp(data.point.y * -90f, -maxLookUpDown, maxLookUpDown);
                var x = Mathf.Clamp(data.point.x * 90f, -maxLookLeftRight, maxLookLeftRight);
                head.SetRotation(new Vector3(y, x, 0f));
                body.SetRotation(new Vector3(0f, x, 0f));
                motion.SyncMotionToLook(head, rbody);

In many ways this is actually the biggest technical achievement here; the FPSLookAtEvent is streamed into the Actor every update with a new mouse position.

However, it's not a new instance of the event, it's the same instance with updated internal data representing the mouse pointer.

This will be highly significant later when I have to deal with VR move controllers and a 3D point input that streams over time.

Other than that... not much. Everything was pretty focused on generating content this time round, which resulted in not much code in there.

Oh well, next time should be more interesting with some VR stuff and some interactive agent work.