-
-
Notifications
You must be signed in to change notification settings - Fork 105
pl Programming
microScript is a simple language inspired by Lua. Here are some general principles used by microScript:
- the variables are global by default. To define a local variable, use the keyword "local".
- line breaks have no particular meaning, they are considered as spaces.
- in microScript there is no value
null
,nil
orundefined
. Any undefined or null variable is equal to0
. - In microScript, there is no Boolean type.
0
is false and everything that is not0
is true. - there is no execution error or exception in microScript. Any variable that is not defined returns
0
. Invoking a value that is not a function as a function returns the value itself.
A variable is a name (or "identifier") to which it is decided to assign a value. It therefore makes it possible to store this value
Variables in microScript do not need to be declared. Any variable that has not yet been used can be considered existing and has the value 0
.
To start using a variable, simply assign it a value with the equal sign:
x = 1
The value of x is now 1.
microScript recognizes five types of values: numbers, strings (text), lists, objects and functions.
The values of type Number in microScript can be integer or decimal numbers.
pi = 3.1415
x = 1
half = 1/2
Strings are texts or pieces of texts. They must be defined in quotation marks.
animal = "cat"
print("Hello "+animal)
Lists can contain a number of values:
empty_list = []
prime_numbers =[2,3,5,5,7,11,13,17,19]
mixed_list =[1,"cat",[1,2,3]]
You can access the elements of a list by their index, i.e. their position in the list from 0 :
list = ["cat", "dog", "mouse"]
print(list[0])
print(list[1])
print(list[2])
It is also easy to browse a list with a for loop
:
for element in list
print(element)
end
An object in microScript is a form of associative list. The object has one or more "fields" that have a key and a value. The key is a string of characters, the value can be any value microScript. The definition of an object begins with the keyword "object" and ends with the keyword "end". Between the two can be defined several fields. Example :
my_object = object
x = 0
y = 0
name = "object 1"
end
You can access the fields of an object with the operator .
. The above definition can therefore also be written:
my_object.x = 0
my_object.y = 0
my_object.name = "object 1"
It can also be accessed with brackets []
. The above definition can therefore also be written:
my_object["x"] = 0
my_object["y"] = 0
my_object["name"] = "object 1"
You can browse the list of fields of an object with a for loop
:
for field in my_object
print(field +" = " + " + my_object[field])
end
See "Classes" for a more in-depth coverage of object
A value can be of the function type. When writing draw = function() ... end
, a function value is created and assigned to the variable draw
(see section on functions below).
By default, the variables declared by assigning them are global. It is possible to define a local variable, as part of a function, by using the keyword "local":
maFunction = function()
local i = 0
end
A function is a sub-sequence of operations, which performs a job, a calculation and sometimes returns a result.
A function is defined with the keyword "function" and ends with the keyword "end".
nextNumber = function(s)
x+1
end
print(nextNumber(10))
When you invoke a value that is not a function as a function, it simply returns its value. Example :
x = 1
x(0)
The code above returns the value 1, without generating an error. So you can even invoke a function that is not yet defined (it is then worth 0
), without triggering an error. This allows you to start structuring your program very early on with sub-functions, which you will work on later. For example:
draw = function()
drawSky()
drawClouds()
drawTrees()
drawEnemies()
drawHero()
end
// I can implement the above functions at my own pace.
A conditional statement allows the program to test a hypothesis and perform different operations depending on the test result. In microScript, the conditions are written as follows:
if age<18 then
print("child")
else
print("adult")
end
"if" means "if"; "then" means "then"; "else" means "otherwise"; "end" means "end"
In the example above, if the value of the age variable is less than 18, then the instruction print("child")
will be executed, else the instruction print("adult")
will be executed.
Here are the binary operators that can be used for comparisons:
Operator | Description |
---|---|
== |
a == b is true only if a is equal to b |
!= |
a != b is true only if it is different from b |
< |
a < b is true only if a is strictly less than b |
> |
a > b is true only if a is strictly greater than b |
<= |
a <= b is true only if a is less than or equal to b |
>= |
a >= b is true only if a is greater than or equal to b |
Operator | Description |
---|---|
and | logical AND: a and b is true only if a and b are true |
or | logical OR: "a or b" is true only if a is true or b is true |
not | logical NOT: not a is true if a is false and false if a is true. |
In microScript, there is no boolean type. 0
is considered false and any other value is true. Comparison operators return 1
for true or 0
for false. For convenience, microScript also allows you to use these two predefined variables:
Variable | Value |
---|---|
true | 1 |
false | 0 |
It is possible to test multiple hypotheses using the keyword "elsif" (contraction of "else if")
if age<10 then
print("child")
elsif age<18 then
print("teenager")
elsif age<30 then
print("young adult")
else
print("very respectable age")
end
The loops allow repeated treatments to be performed.
The for
loop is widely used in programming. It allows the same treatment to be carried out on all the elements of a list or series of values.
for i=1 to 10
print(i)
end
The above example shows in the console each number from 1 to 10.
for i=0 to 10 by 2
print(i)
end
The above example shows the numbers from 0 to 10 in the console in steps of 2.
list =[2,3,5,5,7,11]
for number in list
print(number)
end
The example above defines a list and then displays each item in the list.
The while
loop allows operations to be performed repeatedly until a satisfactory result is obtained.
x = 1
while x*x<100
print(x*x)
x = x+1
end
The example above prints the square of x, then increments x (i. e. adds 1 to x), as long as the square of x is less than 100.
You can exit a for
or while
loop prematurely with the statement break
. Example:
while true
x = x+1
if x>= 100 then break end
end
You can skip the remaining operations of a loop and continue to the next iteration of the loop with the statement continue
. Example:
for i=0 to 10000
if i%10 == 0 then continue end // this will skip processing of multiples of 10
doSomeProcessing(i)
end
Here is the list of binary operators in microScript (excluding comparisons, already mentioned above)
Description | Description |
---|---|
+ | Addition |
- | Subtraction |
* | Multiplication |
/ | Division |
% | Modulo : x % y is equal to the rest of the division of x by y |
^ | Power: x ^ y is equal to x high at power y is pow(x,y)
|
Function | Description |
---|---|
max(a,b) | Returns the largest number of a or b |
min(a,b) | Returns the smallest number of a or b |
round(a) | Returns the value a rounded to the nearest integer value |
floor(a) | Returns the value a rounded down to the lower integer |
ceil(a) | Returns the value a rounded upwards |
abs(a) | Returns the absolute value of a |
sqrt(a) | Returns the square root from a |
pow(a,b) | Returns a to the power of b (other possible notation: a ^ b ) |
PI | Constant equals to the number Pi |
log(a) | Returns the natural logarithm of a |
exp(a) | Returns the Euler number raised to the power of a |
Function | Description |
---|---|
sin(a) | Returns the sine from a (a in radians) |
cos(a) | Returns the cosine from a (a in radians) |
tan(a) | Returns the tangent from a (a in radians) |
acos(a) | Returns the arc cosine of a (result in radians) |
asin(a) | Returns the arc sine of a (result in radians) |
atan(a) | Returns the arc tangent of a (result in radians) |
atan2(y,x) | Returns the arc tangent of y/x (result in radians) |
Function | Description |
---|---|
sind(a) | Returns the sine from a (a in degrees) |
cosd(a) | Returns the cosine from a (a in degrees) |
tand(a) | Returns the tangent from a (a in degrees) |
acosd(a) | Returns the arc cosine of a (result in degrees) |
asind(a) | Returns the arc sine of a (result in degrees) |
atand(a) | Returns the arc tangent of a (result in degrees) |
atan2d(y,x) | Returns the arc tangent of y/x (result in degrees) |
The random object is used to generate pseudo-random numbers. It is possible to initialize the generator with the seed
function to obtain the same sequence of numbers at each execution, or on the contrary a different sequence each time.
Description | Description |
---|---|
random.next() |
Removes a new random number between 0 and 1 |
random.nextInt(a) |
Returns a new integer random number between 0 and a-1 |
random.seed(a) |
reset the random number sequence using the value a ; if you use the same initialization value twice, you will get the same random number sequence. If a == 0, the random number generator is initialized... randomly and therefore not reproducible |
Operation | Description |
---|---|
string1 + string2 |
The + operator can be used to concatenate strings. |
string.length |
Field retains the length of the string. |
string.substring(i1,i2) |
Returns a substring of the character string, starting at index i1 and ending at index i2 |
string.startsWith(s) |
Returns whether string starts exactly with s
|
string.endsWith(s) |
Returns whether string ends exactly with s
|
string.indexOf(s) |
Returns the index of the first occurrence of s in string , or -1 if string doesn't contain any such occurrence |
string.lastIndexOf(s) |
Returns the index of the last occurrence of s in string , or -1 if string doesn't contain any such occurrence |
string.replace(s1,s2) |
Returns a new string in which the first occurrence of s1 (if any) is replaced with s2
|
string.toUpperCase() |
Returns the string converted to upper case |
string.toLowerCase() |
Returns the string converted to lower case |
string.split(s) |
The split function divides the string into a list of substrings, by searching for the separator substring given as argument and returns that list |
Operation | Description |
---|---|
list.length |
Retains the length of the list (number of elements in the list). |
list.push(element) |
Adds the element to the end of the list |
list.insert(element) |
Inserts an element at the beginning of the list |
list.insertAt(element,index) |
Inserts an element at the given index in the list |
list.indexOf(element) |
Returns the position of the element in the list (0 for the first element, 1 for the second element ...). Returns -1 when the element is not found in the list. |
list.contains(element) |
Returns 1 (true) when element is in the list, or 0 (false) when the element cannot be found in the list |
list.removeAt(index) |
Removes from the list the element at position index
|
list.removeElement(element) |
Removes from the list element , if it can be found in the list |
list1.concat(list2) |
Returns a new list obtained by appending list2 to list1 |
Comments in microScript can be added after a double-slash: //
; everything that follows until the next line break is ignored when analyzing the program.
myFunction = ()
// my notes on the role of the myFunction function
end
A class in a programming language refers to a kind of blueprint or template for creating objects. A class defines default properties and functions which constitute the default state and behavior of all objects that will be created from it. You can create object instances derived from a class, which will all inherit from the properties of the class. Using classes and their derived objects in a program is called object-oriented programming (OOP).
To illustrate these concepts, we will see how you can use classes to manage enemies in your game:
We will start by creating a class Enemy
that will be shared by all our enemies objects. Each enemy will have a position (on screen). It will have health points hp
, move at a certain velocity
:
Enemy = class
constructor = function(position)
this.position = position
end
hp = 10
velocity = 1
move = function()
position += velocity
end
hit = function(damage)
hp -= damage
end
end
In microScript, classes and objects are very similar concepts and can almost be used interchangeably. The class definition thus ends with keyword end
. The first property we defined in the class above is the function "constructor". This function is called when a object instance of the class is created. It will set the property position of the object. this
refers to the object instance on which the function will be called, thus setting this.position
means the object sets the property position on itself.
Let's create two enemies objects derived from our class:
enemy_1 = new Enemy(50)
enemy_2 = new Enemy(100)
The operator new
is used to create a new object instance derived from a class. The argument we pass here will is aimed at the constructor function of our class. We thus have created an enemy instance at position 50 and another enemy instance at position 100.
Both enemies share the same velocity or health points (hp). However, we may choose to set a different velocity to the second enemy:
enemy_2.velocity = 2
We can now make our enemies move by calling:
enemy_1.move()
enemy_2.move()
The second enemy will move twice faster because we altered its property velocity before calling function move.
We can make a class inherit from another class. For example, if we want to create a variation of our Enemy, we could do as follows:
Boss = class extends Enemy
constructor = function(position)
super(position)
hp = 50
end
move = function()
super()
hp += 1
end
end
We have created a new class Boss
by extending the class Enemy
. Our new class shares all properties from Enemy, except that it replaces some of these properties by its own values. Calling super(position)
in the constructor of our new class ensures that the constructor of our parent class Enemy is also called.
We created a new behavior move
for our Boss, which overrides the default behavior of Enemy. In this new function, we call super()
in order to keep the default behavior that was defined in the class Enemy ; we then increment the value of hp
, which implies that our Bosses will regain health points when moving.
We can now create an instance of our Boss at position 120:
the_final_boss = new Boss(120)
-
variables space: when a function is called on an object (like
enemy_1.move()
), the variables referred to in the body of the called functions are the properties of the object. For example, in the body of the move function,position += 1
will increment the propertyposition
of the object itself. -
It is sometimes necessary to use
this
to ensure we are correctly referring to a property of our object. This is why, in the constructor of our class Enemy, we usethis.position = position
, becauseposition
also refers to the argument of the function and thus "hides" the property of our object. -
super()
can be used in a function attached to an object or a class, to invoke the equally named function of the parent class.