Arrays Completed 75%

Arrays can now be declared separately from it’s definition. So

will now work.

I’ve also added two new operators; “array push front”, which looks like
-> , and “array push back” which looks like <- . The idea is that it’s pointing from the left to the left-most element, meaning push front and the alternative pointing from the right to the right-most element.

Next; because arrays are now effectively dynamically sized, I need some inherent way to find the size of an array. Like a .size  member or something…

Arrays Completed 50%

I’ve now finished implementing arrays in my scripting language. For now, they’re not dynamically sized, and they need all their arguments when first created.

I.e. you need to write:

You can’t write

You can otherwise access array elements and update them as necessary. All regular automatic type conversion is handled. So:

Will work. However, it does it a bit of a round-about way. The first element in an array value, everything between the {  and }  is used to determine the type of the array. In the above case it’s a string array.

Then, each subsequent element is type-converted to this type. So this becomes an array of strings.

Then the assignment of a string array value to an int array variable will cause a conversion from a string array to an int array.

If the first element was an int and not a string, only the first conversion takes place.

But, this allows me to keep the any-type to any-type conversion I wanted.

Interpreter Works

The first go at writing an interpreter for my compiled opcodes is working.

Great result. Now I basically have a working scripting engine, I just need to polish up the code and a few little bugs here and there (“-1” is read as “negative one” or “minus one”).

Scripting Language Updates

I’ve managed to put together a scripting language compiler that has the following features:

  • Native data types: bool, string, char, int + float (I need to add vector types)
  • C-like syntax
  • Functions
  • Automatic POD casting. I.e., every data type can be casted to another. This will be true even when I add classes or structs, not sure how…
  • Ability to call “Engine” functions. I.e., you seed the Compiler with possible function calls that can be made of the platform

The compiler converts something like:

Into:

Which should be very simple for a Virtual Machine to run through and execute. You can see that no optimization has taken place; I’ll probably think about doing that after getting it to actually run.

Lexer

I’ve just completed a Lexer in order to produce a stream of tokens for the Parser.

There’s some parts of the Dragon Book which I don’t really understand the reasoning. Such as the Lexer adding info to the Symbol Table… why would it do that? It’s the Parsers job to build a syntax-tree, that seems like the correct place to add symbols. The Lexer is complicated enough just producing a stream of tokens.

Updates

I’ve now managed to implement a SpaceEngine Format file to use as a UI layout file. In it you basically use the JSON like data format to create the individual top-level UI elements for the game.

Next is to give the UI layout files some ability to implement actions. At the moment you can design everything, but you can’t actually say what “button x” will do.

I’m thinking of separating out a “scripting” language which you can create a function in. Then in the layout file you reference that function.

This would give the UI three separate files, the Class Definitions, Layout, and Scripting. Which I think is sort of akin to CSS, HTML and Javascript.

So scripting… I’ve thought about implementing Lua or something, but like everything else, I’d rather roll my own to learn how it’s done.

My initial thoughts are to use the regular lexical parser deal as per the Dragon Book. I don’t think I need to do compiled, but just interpreted. Something like Java.

How to actually make it all function together is something of a mystery to me. I imagine the scripting processor will have set functions mapped to identifiers to be used in the script. So the script could call Game.CreatePlanet()  or something like that. The parser will see this and invoke my engines random planet spawning function or whatever.

But at what level do I abstract out these? Maybe I should abstract out the planet creation, so that the method of creation can be modded, expanded etc.?

I imagine that in future I’d want random events and AI to be scripted as well. So it seems like the lower level would allow for more flexibility.

But it also seems like it’s going to mean I need to do a lot of coding to make a full-fledged scripting language.

Multithreading

I’ve now completed some additional engine work and implemented some architectural changes. The “Engine” is now decoupled quite a bit from the other components. So at the moment I have:

  1. SDLGLHandler  which manages the creation and management of the SDL_Window*  and the SDL_GLContext* . Essentially this does the buffer swapping, it also applies a spaceengine::PostProcessingEffectChain to the buffer before being swapped to the window.
  2. PostProcessingEffectChain  which is made up of a series of PostProcessingEffect s. This applies things like bloom and the real-time lens flare and bokeh. This is currently handled by external SpaceFormatFiles.
  3. SpaceEngine  and a GameObject  class which are closely linked. Basically, the SpaceEngine  object holds an SDLGLHandler  and a GameObject*  . When the SpaceEngine  instance is started, it throws the GameObject s Start  method into a new thread and then drops into a standard SDL message pump.

    The only message explicitly handled is SDL_WINDOWEVENT_CLOSE , everything that’s input related is thrown to the InputManager .

    After processing the messages in the queue the draw method of the GameObject  is called followed by the swapping method of SDLGLHandler .

    For it’s part, the GameObject  is an abstract class. When using my engine, you need to derive your own game class from GameObject  and implement the drawing method and update method. You also need to register your own callbacks via the InputManager . This GameObject  features a single std::mutex  as all methods need to be thread-safe.

  4. A static InputManager  class. This class features methods to push events onto a queue and to register callback functors that will be called if a specific SDL_EventType  is processed.

    The InputManager  finally has a Start  method which creates a new thread to process the internal queue, looking at each SDL_Event.type  and calling the correlated functors from the registered callbacks.

I’ve gone with a multi-threaded approach for a couple of reasons. Firstly I wanted to learn how to do it. Secondly, I anticipate needing the decoupled processing to handle the various aspects of the simulation.

I’m pretty happy, aside from any exception handling, the main function looks like this:

SpecificGame is derived from GameObject . You can see how both the SpaceEngine and the GameObject hold a pointer to each other. This allows the Engine to ask the game to quit as well as allow the game to ask the engine to quit.

My reasoning for this is that the game window could be closed, which I consider an engine responsibility, vs game specific menu options which would also need to close the game. I believe I could manually push the window close event onto the queue from the game if I needed to; but I think this method works well enough as it doesn’t require the game to suddenly need to be cognisant of SDL2.