Login
Community
DARK THEME

microScript 2.0 is coming!

Actually, it is already available, still in 'alpha' status because not 100% feature-complete yet. But progress is being made everyday and we should reach 'beta' soon. To try it out, just go in the advanced project settings and pick "microScript v2 - alpha" as project language.

You already know microScript 2.0!

Fear not: everything you have learnt to do in microScript 1.0 still works in microScript 2.0. You can easily switch to microScript 2.0 already and make no change to your programming habits. You might even activate microScript 2.0 on a project you have started in 1.0. In most cases, it will work flawlessly.

In some edge cases, you could encounter one of the following problems though:

  • maybe your project uses a variable name which is now a keyword (do, every, after, sleep, type) ; if it does, you will have to rename such variables
  • The scoping of local variables in microScript v1 was a bit too fuzzy and too permissive. A local variable could still be visible after the end of the block where it was defined. This is no longer the case and depending on how you were using local variables, could necessitate a slight rework of your code to make it work with microScript 2.0
  • microScript 2.0 still may have bugs. If you encounter some strange situation, please contact me and let me have a look!

Design goals

The design goals of microScript haven't changed: a language which is simple to learn, forgiving, that cannot break at runtime and can be edited live. microScript 2.0 is still very much that and some of the new features it brings make it even simpler to use ("threads" may sound scary but just ignore that and think that you can now use sleep 1 second!).

Implementation

microScript 2.0 is a full reimplementation of the microScript engine. The new engine is based on a stack machine which reads and interprets a bytecode representation of your code, generated by a compiler. This design alone makes it much more efficient compared to the v1 interpreter (about 3x performance boost). But this is not enough and the new engine is also capable of transpiling whole chunks of code to JavaScript, allowing it to match or even outperform the v1 transpiler in some cases!

Note that currently, the transpiler is turned off, time to get a first stable version of microScript 2.0. Then I will start activating transpilation incrementally (each bytecode instruction is set to be transpilable or not and transpilation is only triggered when a sequence of such instructions is encountered).

This new microScript engine opens many more possibilities: the most obvious one is the introduction of preemptive threads / coroutines, providing much easier ways to control the timing of events in your game (see below). It also makes it possible to create a full step-by-step debugger or to implement some advanced performance profiling. Do not take this as a promise though, it will take a lot of time to get there! Another possibility I am thinking of is to make a port of the language engine to C or Nim or maybe C# ; the new engine design would make that much easier.

What is new and how to use it

But enough of blah blah and let's see what you can already do with microScript 2.0 today ;-)

Non-ASCII identifiers are now allowed

This has been discussed on Discord and I finally decided to go for it. What convinced me was to read the reasons why Python went for it too: https://peps.python.org/pep-3131/

Easily handle time in your game

Simple things like waiting 2 seconds before returning to the main menu or taking damage every second were not so easy to do in microScript 1. Many beginners had to struggle with the idea of creating an incremental counter and checking its value until it reaches value x. It is much easier now:

Sleep

You can pause execution of your code for a specified amount of time. Example:

if gameover() then
  sleep 2 seconds
  backToMainMenu()
end

The sleeping time can be given just as a number in milliseconds, or you can append a time unit. Accepted units are: millisecond, milliseconds, second, seconds, minute, minutes, hour, hours, day and days.

Note: doing this (sleeping in the "main thread") implies that the screen will stop being refreshed during that time. If you just want to delay the execution by 2 seconds without stopping your screen animations, check other methods below.

Schedule something for the future

Here is another way to return to the main menu after 2 seconds:

if gameover() then
  after 2 seconds do
    backToMainMenu()
  end
end

You can put any number of instructions between do and end, consider it a function body - that is exactly what it is!

Do something periodically

As someone once suggested, you can now do:

every 500 milliseconds do
  if player.isInLava() then
    player.takeDamage()
  end
end

Do some heavy work in background

If you want to do heavy computations without affecting the main rendering loop, you can start it in a new "thread" like this:

do
  while not world_ready
    generateMoreChunksOfMyProceduralWorld()
  end
  worldIsReady()
end

Embedding any code like this into a do .. end has the effect of creating a separate, new execution thread, just like after and every do.

Threads

Each use of after, every or just do .. end creates a new execution thread and returns a thread object. Threads can be paused, resumed or stopped.

score_counter = every 100 milliseconds do
  score += 1
end

// when you want to stop scoring
score_counter.pause()
// when you want to restart counting score
score_counter.resume()
Function Description
thread.pause() Pauses the execution of the thread until resume() is called
thread.resume() Resumes execution of the thread
thread.stop() Stops and discards the thread definitely

system.threads retains a list of currently active secondary threads (running or paused).

Note about threads

  • The default thread, or "main thread" is dedicated to loading your source code files and to executing update() and draw(). This thread has a higher priority than secondary threads, to prevent your code from being interrupted in the middle of a screen refresh.
  • microScript "Threads" are not matched with system-level threads. They all share time slices of a single real thread (the browser's JavaScript execution loop).
  • Periodic threads created with every will follow their pace with great accuracy, down to the millisecond.
  • Interrupting a thread with sleep is not as accurate, expect variations up to 16 milliseconds.

Preemptiveness (is that even a word?)

The threading system in microScript is preemptive by default. It means that if you have some level of concurrency (several different tasks running at the same time and consuming CPU time), the system will take care of sharing the computing time, giving each task a chance to run at any moment, by interrupting other tasks whenever necessary. This is the best and recommended setting for everyone.

You can switch to a non-preemptive scheduling if you wish to, by setting system.preemptive = 0. If you do this, the system will never interrupt a running task before it is complete, unless the task explicitly calls sleep 0 (or any other value), from time to time, to give a chance to other tasks to use their share of the CPU.

Dynamic type checking

You can now check if a variable exists, if an object property exists and which type they have. my_variable.type will return:

  • 0 (no type) if my_variable is not defined
  • "number" if my_variable is a number
  • "string" if my_variable is a string
  • "function" if my_variable is a function
  • "list" if my_variable is a list
  • "object" if my_variable is an object

Numbers

  • You can now write numbers with exponential notation, e.g. 5.0e+10
  • You can write hexadecimal numbers e.g. 0xFF

Binary ops

They were requested a long time ago, so here they are:

  • Binary and: &
  • Binary or: |
  • Binary shift left: <<
  • Binary shift right: >>

More string escapes

Strings can span on multiple lines in microScript, the syntax highlighter in microScript 2.0 was fixed to correctly reflect this. Also there is a number of new escape characters you can include in your strings:

  • \n is a newline character
  • \' single quote
  • \" double quote
  • \\ backslash
  • "" within a double-quoted string value, a pair of double quotes is parsed as one double-quote
  • '' within a single-quoted string value, a pair of single quotes is parsed as one single-quote

Multi-line comments

/* You can now
   insert
   multiple-lines comments */

Upcoming features

This is what remains to be done for microScript 2.0:

  • capture outer local as const values in function def, including function itself when assigned as local
  • capture this in function def as well
  • more complete String functions and Array functions
  • parse number / convert string from and to number
  • operator overloading

Possible upcoming features

Also remaining on my list:

  • add functions to List prototype, allowing to augment the functionality of the lists
  • prototypes for String, List, Object?, Function?

Wonderful! The timing features will be especially useful for my students, who are always asking how to do things like this. As you mentioned, it can already be done with incrementing a variable, but this is much cleaner conceptually and will allow students to make more interesting games with less difficulty.

Great! Thanks for all the work you put in Gilles and keep it up! :=)

That time delay function is going to be especially helpful, it took me some effort to code delay functions in the latest projects I've been working on. I know this will make it a LOT easier :D

The control over periodic sensing functions is also going to be useful when trying to make games that give some safety margins for the players, e.g when you want hitboxes to be accurate yet you want to give the player some time to get out after hitting the spikes. It also makes controlling update times easier.

Post a reply

Progress

Status

Preview
Cancel
Post
Validate your e-mail address to participate in the community