Привет Хабр!

Под предыдущей статьей собралось много вопросов и рассуждений относительно microStudio, в частности языка microScript, которому я не уделил внимания в предыдущей статье. Да я и не ставил цель затронуть все вопросы в одной статье.

Напомню:

- microStudio это бесплатная интегрированная среда разработки видеоигр.

- microStudio - проект с открытым исходным кодом, распространяемый по лицензии MIT. Вот ссылка на GitHub.

- создателя microStudio и ЯП microScript зовут Жиль Померей (фр. Gilles Pommereuil)

- microScript задумывался автором, в первую очередь, как язык для обучения программированию для новичков. Порог вхождения низкий - этот язык можно изучать с нуля, не зная до него о программировании вообще. microScript имеет простой синтаксис и набор правил, но при этом он достаточно функционален. На этом языке можно писать игры и приложения в среде microStudio, которые затем можно экспортировать в отдельное приложение HTML5.

Язык программирования microScript

Итак, для начала, microScript - это локальный язык. В настоящее время он используется только в пределах microStudio. По синтаксису microScript схож с языком Lua. Программа написанная на языке microScript транспилируется в javascript.

Вот некоторые общие принципы языка microScript о которых поговорим подробнее в этой статье:

  • По умолчанию переменные являются глобальными. Чтобы определить локальную переменную, нужно использовать ключевое слово "local".

  • Разрывы строк не имеют особого значения, они рассматриваются как пробелы.

  • Нет значения nullnil или undefined. Любая неопределенная или нулевая переменная по умолчанию равна 0.

  • Нет логического типа. 0 - это ложь, а все что не 0 - истина.

  • Нет ошибки выполнения или исключения. Любая переменная, которая не определена, возвращает значение 0.

  • Вызов значения в качестве функции, которое не является функцией, возвращает само значение.

"Hello, world!" на языке microScript:

print("Hello, world!")

Написание однострочных комментариев с помощью //:

print("Hello, world!") //здесь можно написать комментарий

Все, что следует до следующего разрыва строки, игнорируется при работе программы. Многострочные комментарии в microScript не предусмотрены.

Переменные

Переменные в microScript объявлять не нужно. Любая переменная, которая еще не использовалась, может считаться существующей и иметь значение 0. Чтобы начать использовать переменную, ей нужно присвоить значение со знаком равенства:

x = 1

Все переменные в microScript считаются глобальными, если они явно не объявлены как локальные.

Локальную переменную можно определить используя ключевое слово "local":

myFunction = function()
	local i = 0
end

Когда тип указан как локальный для переменной, тогда ее область действия ограничена функциями внутри их области.

Имя переменной должно начинаться либо с латинской буквы, либо с символа нижнего подчеркивания _, после которых могут следовать латинские буквы, цифры или символы подчеркивания:

_x1 = 2
var_a = 3

Прописные и строчные буквы различны, потому что microScript, как и Lua, чувствителен к регистру - X1 не то же самое что и x1.

microScript - язык с динамической типизацией. Типы определяются во время выполнения программы. Таким образом, у одной и той же переменной могут быть разные типы в разных частях программы:

n = 5 //число
n = "name" //строка

Есть список зарезервированных слов, которые нельзя использовать в качестве идентификатора переменной: and, break, by, class, continue, else, elsif, end, extends, for, function, if, in, local, new, not, object, or, return, then, to, while.

Типы значений

microScript распознает пять типов значений:

  • числа,

  • строки (массив символов),

  • списки,

  • объекты

  • функции.

Числа

Значения типа "число" в микроскрипте могут быть целыми или десятичными числами. Например:

pi = 3.1415
x = 1
half = 1/2

Строки

Строки это тексты или фрагменты текстов. Они должны быть определены в кавычках, в двойных или одинарных. Пример:

name = "Вася"
print('Привет ' + name) //конкатенация сток с помощью оператора сложения "+"              

В консоли: Привет Вася

Списки

В список можно поместить сколько угодно необходимых значений любого из пяти типов:

empty_list = [] //пустой список
prime_numbers =[2,3,5,5,7,11,13,17,19] //список чисел
mixed_list =[1,"кот",[1,2,3],drawObject()] //смешанный список

Можно получить доступ к элементам списка по их индексу, т. е. их положению в списке, начиная с индекса 0:

list = ["кот", "собака", "мышь"]
list[0] //"кот"
list[1] //"собака"
list[2] //"мышь"

Еще варианты доступа к элементу списка, не описанные в документации:

list["0"]
list['0']
list."0"
list.'0'
list.0

Можно просмотреть список с помощью цикла for:

for element in list
	print(element) //на консоль выведутся все элементы списка начиная с первого
end

Доступ к полям объекта через списки

Рассмотрим на таком примере, допустим, у нас есть три списка и три объекта:

list1 = []
list2 = []
list3 = []
object1 = object
	x = 1
	y = 3
end

object2 = object
	x = 24
	y = 0
end

object3 = object
	x = 100
	y = 62
end

Поместим объекты в первый список: list1 = [object1,object2,object3].

Получаем доступ к x объекта object2:

list1[1].x //object2 доступен по индексу 1
print(list1[1].x)

В консоли: 24

А теперь поместим первый список во второй, а второй в третий:

  list1=[object1,object2,object3] //этот список содержит объекты
  list2=[list1] //теперь этот список содержит первый список
  list3=[list2] //теперь этот список содержит второй список, 
								//кторой в свою очередь содержит первый список

Получить доступ к y объекта object3можно таким образом:

list3[0][0][2].y

Это можно сделать также и при помощи оператора.:

list3.0.0.2.y
print(list3.0.0.2.y)

В консоли: 62

Объекты

Объект в микроскрипте это форма ассоциативного списка. Объект имеет одно или несколько "полей", которые имеют ключ и значение. Ключ представляет собой строку символов, значением может быть любое значение microScript. Определение объекта начинается с ключевого слова "object" и заканчивается ключевым словом "end". Между ними можно определить несколько полей. Пример:

my_object = object
  x = 10
  y = 20
  name = "object 1"
end

Можно получить доступ к полям объекта с помощью оператора .:

print(my_object.x)

В консоли: 10

Таким образом, приведенный выше пример можно записать и так:

my_object.x = 0
my_object.y = 0
my_object.name = "object 1"

Можно добавить новое поле для объекта my_object:

my_object.vx = 5

Также, к полям объекта можно получить доступ с помощью скобок []:

my_object["x"] = 0
my_object["y"] = 0
my_object["name"] = "object 1"

Еще варианты доступа к полям объекта, не описанные в документации:

my_object['x']
my_object."y"
my_object.'name'

Функции

Функция определяется ключевым словом "function" и заканчивается ключевым словом "end":

nextNumber = function(x)
	x+1
end

Вызов функции:

nextNumber(10)
print(nextNumber(10))

В консоли:11
Когда вызывается значение в качестве функции, которое при этом не является функцией, оно просто возвращает свое значение. Пример:

x = 1
print(x())

В консоли:1
Приведенный выше код возвращает значение "1" без возникновения ошибки. Таким образом, можно даже вызвать функцию, которая еще не определена (тогда она возвращает 0), не вызывая ошибки. Это позволяет очень рано начать структурировать свою программу с помощью подфункций, над которыми вы будете работать позже. Например:

draw = function()
  drawSky()
  drawClouds()
  drawTrees()
  drawEnemies()
  drawHero()
end

Классы

Это краткое отступление, для тех кто только собирается изучать программирование и не имеет представление о том, что такое класс:

Класс на языке программирования относится к своего рода схеме или шаблону для создания объектов. Класс определяет свойства и функции по умолчанию, которые определяют состояние и поведение по умолчанию всех объектов, которые будут созданы на его основе. Вы можете создавать экземпляры объектов, производные от класса, которые будут наследовать все свойства этого класса. Использование классов и их производных объектов в программе называется объектно-ориентированным программированием (ООП).

В микроскрипте классы и объекты являются очень похожими понятиями и могут почти взаимозаменяемо использоваться.

Чтобы проиллюстрировать эти концепции, создадим класс, и разберем, как можно использовать классы для управления, например врагами в игре:

Начнем с создания класса Enemy, который будет использоваться всеми нашими объектами-врагами. У каждого врага будет своя позиция. У них будут очки здоровья hp, они будут двигайться с определенной скоростью velocity.

Создание класса начинается с ключевого слова "class" и заканчивается ключевым словом "end":

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 

Примечание: иногда необходимо использовать this, чтобы убедиться, что мы правильно ссылаемся на свойство нашего объекта. Вот почему в конструкторе класса Enemy мы используем this.position = position, потому что position также ссылается на аргумент функции и таким образом, "скрывает" свойство объекта.

Первое свойство, которое мы определили в приведенном выше классе - это функция "constructor". Эта функция вызывается при создании экземпляра объекта класса. Она установит свойство положения(position) объекта. this относится к экземпляру объекта, на котором будет вызвана функция, таким образом, установка this.position означает, что объект устанавливает свойство position для себя.

Создадим два объекта врагов, производных от нашего класса:

enemy_1 = new Enemy(50)
enemy_2 = new Enemy(100)

Оператор new используется для создания нового экземпляра объекта, производного от класса. Аргумент, который мы передаем здесь, будет направлен на функцию constructor класса Enemy. Таким образом, мы создали два экземпляра противника, один на позиции 50, другой на позиции 100.

Оба врага имеют одинаковую скорость velosityи очки здоровья hp. Однако, можно выбрать другую скорость для второго врага:

enemy_2.veloсity = 4

Теперь можно заставить врагов двигаться, вызвав функции:

enemy_1.move()
enemy_2.move()

Второй враг будет двигаться в четыре раза быстрее, потому как мы изменили значение его velosityперед вызовом функции move().

Примечание: когда функция вызывается для объекта (например enemy_1.move()), переменные, на которые ссылаются в теле вызываемых функций, являются свойствами объекта. Например, в теле функции move() position += 1 будет увеличивать свойство position самого объекта а не класса.

Переменные hp и velocity также доступны нам сразу из класса:

Enemy.hp
Enemy.velosity

Таким образом мы можем менять их значение по ходу выполнения программы. И все объекты созданные из этого класса будут наследовать новые значения hp и velocity (если мы до этого не меняли эти значения для конкретного объекта).

Наследование

Можно сделать класс наследуемым от другого класса. Например, если мы хотим создать вариацию нашего врага в игре, мы можем сделать следующее:

Boss = class extends Enemy
	constructor = function(position)
 		super(position)
 		hp = 50
 	end
 	move = function()
 		super()
 		hp += 1
 	end
end

Здесь ключевое слово extends, используется для обозначения наследования свойств класса.

Мы создали новый класс Boss, путем расширения класса Enemy. Наш новый класс разделяет все свойства класса Enemy, за исключением того, что он заменяет некоторые из этих свойств своими собственными значениями. Вызов функцииsuper(position) в теле функции constructor() нашего нового класса гарантирует, что constructor() нашего родительского класса Enemy также будет вызван.

Мы создали новую функцию move() для нашего босса, которая переопределяет поведение Enemy по умолчанию. В этой новой функции мы вызываем функцию super(), чтобы сохранить поведение по умолчанию, которое было определено в классе Enemy; затем мы увеличиваем значение hp, что означает, что наши боссы будут восстанавливать очки здоровья при перемещении.

Примечание: функция super() может использоваться в функции, прикрепленной к объекту или классу, для вызова функции родительского класса с одинаковым именем.

Теперь мы можем создать экземпляр босса на позиции 120:

the_final_boss = new Boss(120)

Условный оператор

В микроскрипте условия записываются следующим образом:

if age<18 then
	print("ребенок")
else
	print("взрослый")
end

"if" означает "если"; "then" означает "тогда"; "else" означает "иначе"; "end" означает "конец".
В приведенном выше примере, если значение переменной возраста меньше 18, то инструкция print("ребенок") будет выполнена, иначе будет выполнена инструкция print("взрослый").

Можно проверить несколько гипотез, используя ключевое слово "elsif" (сокращение от "еще, если").

if age<10 then
	print("ребенок")
elsif age<18 then
	print("подросток")
elsif age<30 then
	print("молодой человек")
else
	print("очень взрослый")
end 

Цикл for

Цикл for широко известен в программировании, также как и условный оператор if, тем не менее я опишу кратко его применение в микроскрипте.

Этот цикл позволяет проводить одинаковую обработку всех элементов списка или ряда значений:

for i=1 to 10
	print(i)
end

В приведенном выше примере мы выведем на консоль каждое число от 1 до 10.

Мы можем сделать тоже самое, только с шагом равным 2:

for i=0 to 10 by 2
	print(i)
end

В приведенном примере мы выведем на консоль числа от 0 до 10 с шагом 2(by 2).

Цикл while

Этот цикл позволяет выполнять операции повторно, пока не будет получен удовлетворительный результат:

x = 1
while x*x<100
   print(x*x)
   x = x+1
end

В приведенном выше примере выводится квадрат x, затем увеличивается значение x (прибавляется единица к x), если квадрат x меньше 100.

Прервать или продолжить цикл

Мы можем прервать цикл досрочно используя оператор break:

while true
   x = x+1
   if x>= 100 then break end //если x больше либо равен 100, цикл будет прерван
end

Можно пропустить оставшиеся операции цикла и перейти к следующей итерации цикла с помощью оператора continue. Пример:

for i=0 to 10000
	if i%10 == 0 then continue end //это позволит пропустить обработку чисел,
                                 //кратных 10
	doSomeProcessing(i)
end

Арифметические Операторы

Оператор

Описание

+

Сложение

-

Вычитание

*

Умножение

/

Деление

%

Деление по модулю (остаток от деления)

^

Возведение в степень

Бинарные операторы сравнения

Оператор

Описание

==

a == b верно только в том случае, если a равно b

!=

a != b верно только в том случае, если a отличается от b

<

a < b верно только в том случае, если a строго меньше b

>

a > b верно только в том случае, если a строго больше b

<=

a <= b верно только в том случае, если a меньше или равно b

>=

a >= b верно только в том случае, если a больше или равно b

Булевы операторы

Оператор

Описание

and

логическое И: a and b истинно только в том случае, если a и b истинны

or

логическое ИЛИ: a or b истинно только в том случае, если a истинно или b истинно

not

логическое НЕ: логический оператор not меняет результат на противоположный начальному значению. То есть, если операндом является true (все, что не равно 0), то после применения логического not, результатом будет false (0). Если операнд до применения оператора not был false, то после его применения станет true. not- унарный оператор (применяется к одному операнду), он помещается перед операндом.

Пример с оператором not:

num_1 = 0
num_2 = 5
if not num_1 then print("not num_1 истина") end //not num_1 возвпащает true
if not num_2 then print("not num_2 ложь") end //not num_2 возвращает false

В консоли: not num_1 истина

Логические значения

В microScript нет логического типа. 0 считается ложным, а любое другое значение является истинным. Операторы сравнения возвращают значение 1 (true) или 0 (false). Для удобства microScript также позволяет использовать следующие предопределенные переменные:

Переменная

Значение

true

1

false

0

Три основные функции в языке microScript

Открыв окно проекта microStudio (в разделе "код") вы увидите три основные предопределенные функции:

init()
update()
draw()
Окно проекта microStudio
Окно проекта microStudio

Функция init()

Функция инициализации вызывается только один раз при запуске программы. Это полезно, в частности, для определения начального состояния глобальных переменных, которые могут использоваться в остальной части программы.

Функция update()

Функция обновления вызывается 60 раз в секунду. Тело этой функции - лучшее место для программирования логики и физики игры: изменения состояния, движения спрайтов, обнаружение столкновений, оценка входов с клавиатуры, оценка сенсорных или геймпадных входов и т.д.

Функция draw()

Функция рисования вызывается так часто, как только можно обновить экран. Здесь, например, можно нарисовать свою сцену на экране, заполнив большой цветной прямоугольник (чтобы стереть экран), а затем нарисовать поверх него несколько спрайтов.

Послесловие

Итак, считаю что я рассмотрел в этой статье основы данного языка. А если я упустил из виду какие-то базовые вещи, дайте мне знать об этом.

Уроки по изучению программирования на этом языке я буду публиковать у себя в группе ВК, как только наберется хотя бы небольшая заинтересованная в этом аудитория. Если вы новичок в программировании, и хотите изучить этот язык, создавать игры, то подписывайтесь, добавляйтесь в друзья, всем буду очень рад!

И как всегда, спасибо за внимание!

Комментарии (23)


  1. sergeymolchanovsky
    07.01.2022 01:04

    Неочевидный момент

    Доступ к полю через точку

    my_object.x = 0

    через оператор [ ]

    my_object["x"] = 0

    Опа, откуда-то кавычки появились. То есть, у объекта каждому полю соответствует неявный ключ строкового типа, и обращаемся мы по этому ключу?


    1. horror_x
      07.01.2022 01:15
      +5

      Программа написанная на языке microScript транспилируется в javascript.


    1. pvvv
      07.01.2022 14:22
      +1

      x=5;
      my_object[x] без кавычек что вернуть должен?


      вопрос в другом, если собственно "по синтаксису схож с Lua" зачем было изобретать велосипед, а не просто скомпилировать ту же Lua в webassembly?
      или fengary — lua переписанная на яваскрипте.


      1. Constantine_RetroGamer Автор
        08.01.2022 00:13

        x=5;my_object[x] без кавычек что вернуть должен?

        Вернет 0

        вопрос в другом, если собственно "по синтаксису схож с Lua" зачем было изобретать велосипед, а не просто скомпилировать ту же Lua в webassembly?или fengary — lua переписанная на яваскрипте.

        microScript это простой ЯП, легкий в изучении, легче чем Lua. Он похож на Lua, но далеко не во всем. microScript был создан для начинающих программистов, как легкий для изучения язык с которого можно быстро стартануть. Он и с простым синтаксисом, и не сильно ругающейся консолью, без лишних кавычек и закорючек - говоря простыми словами:)


  1. mn3m0n1c_3n3m1
    07.01.2022 02:19
    +1

    Очень компактный и интересный язык. Не понятно только для чего по-умолчанию делать переменные глобальными, а локальность вводить оператором local.

    Ведь в JavaScript тоже так было.

    First, strict mode makes it impossible to accidentally create global variables. In normal JavaScript mistyping a variable in an assignment creates a new property on the global object and continues to "work" (although future failure is possible: likely, in modern JavaScript). Assignments, which would accidentally create global variables, instead throw an error in strict mode.

    (c) MDN

    Но с появлением strict modeпоявилась возможность сделать код надежнее благодаря конструкции 'use strict'.

    А теперь и эта конструкция не нужно: строгий режим включён по-умолчанию в EcmaScriptмодулях:

    ECMAScript 2015 introduced JavaScript modules and therefore a 3rd way to enter strict mode.  The entire contents of JavaScript modules are automatically in strict mode, with no statement needed to initiate it.

    По этому, мне кажется, имеет смысл использовать опыт предшественников, и сделать переменные локальными по-умолчанию, а для глобальных - кодовое слово.

    Глобальные переменные имеют неограниченный потенциал для создания взаимных зависимостей, что приводит к усложнению программы.

    (c) Википедия

    В этом плане мне нравится подход Rust: защитить и оградить разработчика от написания запутанного, хрупкого кода, который сложно поддерживать - это большое искусство, есть чему поучится.

    В плане эргономичности чего только стоят:

    loop {
        break;
    }

    Вместо:

    while(true) {
        break;
    }

    Все операторы - выражения, а последнее выражение в функции, если оно не содержит ";" - возвращается.

    Вишенка на торте: объявление переменных.

    • let - не меняет значение;

    • let mut - меняет;

    Ну и конечно borrowing очень мощная и полезная концепция, заставляет писать простой код, а что бы его запутать нужно хорошенько постараться.

    В общем, мне кажется, что язык программирования должен защищать разработчика от выстрела в ногу и учить хорошим практикам. От этого все будут в выигрыше.


  1. K_Chicago
    07.01.2022 04:14
    +2

    " если я упустил из виду какие-то базовые вещи, дайте мне знать об этом "

    Даю знать:

    Очень хотелось бы в первом параграфе материала увидеть ответ на вопрос: "а зачем?"

    Это игра ума, это дипломная работа, это позволяет лучше и быстрее решать задачи, чем <что?>, это "я дерусь просто потому, что дерусь" - ?


    1. Constantine_RetroGamer Автор
      07.01.2022 04:57
      +2

      Здравствуйте! Возможно, если Вы переформулируете вопрос, я смогу понять точнее. Зачем я написал статью? Или зачем существует этот язык и какие задачи можно эффективнее решить на нем?

      "Это игра ума, это дипломная работа" - нет, это не игра и не дипломная работа:)

      Эта статья по сути является дополнением к предыдущей статье.

      Возможно, если прочтете предыдущую стать, Вам станет более понятно о чем речь https://habr.com/ru/post/595213/


      1. m0tral
        08.01.2022 18:36
        +1

        Рискну предположить, зачем этот язык и какие задачи эффективнее на нем решать, я боюсь что все устали уже от JS-style языков, типа задач: phyton, js в процессорах - чтобы ниже порог вхождения, боюсь true языки таких образом будут нечто магии


  1. yellow79
    07.01.2022 14:14
    +2

    "Привет" + "Вася" = "Привет Вася". То есть язык за меня решает, что я хочу вставить между словами пробел?


    1. Constantine_RetroGamer Автор
      07.01.2022 15:43

      Спасибо за замечание, нет, не решает:) Пробел нужно ставить, отредактирую


  1. mSnus
    07.01.2022 14:50
    +3

    Очень интересно, напоминает ActionScript 2, но с классами. Так как старый Flash давно накрылся, было бы очень классно сделать ему простую замену! Вопрос в том, как у вас там дальше с работой со спрайтами, таймлайном, движением по траекториям и программной анимацией...

    Да, а переменные класса ведь не глобальные, их область видимости какая, внутри класса? А в методах класса?


    1. Constantine_RetroGamer Автор
      08.01.2022 00:24

      Да, а переменные класса ведь не глобальные, их область видимости какая, внутри класса? А в методах класса?

      Эти переменные не являются глобальными, они доступны только внутри класса. Переменные из методов также доступны только классу, которому пренадлежит метод. С объектами тоже самое.

      Вопрос в том, как у вас там дальше с работой со спрайтами, таймлайном, движением по траекториям и программной анимацией...

      Это уже тема для отдельной статьи:)


  1. dikey_0ficial
    07.01.2022 20:47

    логическое НЕТ: a не истинно, если a ложно, и ложно, если a истинно

    мо мозг немного закипел от этого :) может лучше написать что-то вроде "not a возвращает обратное значение от a", ну или поместить объяснение про bool как число (очень классная кстати концепция, показывает, что bool это, по факту, один бит) раньше и написать, что not возвращает 1-a


    1. slonopotamus
      07.01.2022 23:38
      +1

      Нельзя объяснять про bool, его же в языке нет.


      1. dikey_0ficial
        08.01.2022 08:17

        он как бы есть, но нет)


    1. Constantine_RetroGamer Автор
      08.01.2022 05:03
      +1

      Так сказано в официальной документации:

      not

      logical NOT: not a is true if a is false and false if a is true.


      1. dikey_0ficial
        08.01.2022 08:27
        +1

        Данный фрагмент документации переводится как "not a истинно, если a ложно, и ложно, если a истинно". У вас же "a не истинно, если a ложно, и ложно, если a истинно"


        1. Constantine_RetroGamer Автор
          08.01.2022 17:29
          +1

          Поскольку использование оператора отрицания может быть менее очевидной вещью, я препеписал эту формулировку полностью (написал более понятно, на мой взгляд). А так же добавил пример использования. Надеюсь теперь этот пункт будет более понятен, особенно тем, кто только знакомится с программированием.

          Спасибо за это замечание! Если Вы видите еще какие-то недочеты, дайте знать:)


  1. tetelevm
    07.01.2022 22:03

    Немного неочевидный для меня момент - чем это отличается от обрезанного питона кроме js-ных `smth.arg === smth["arg"]` и небольших изменений в синтаксисе?


    1. Carburn
      08.01.2022 02:18

      написано же, что это обрезанный lua.


    1. Constantine_RetroGamer Автор
      08.01.2022 04:52

      Привидите хотя бы пример ЯП который является "обрезанной версией" Python, который можно сравнить с microScript.

      microScript может напоминать чем то Python, но только на первый взгляд. Да и чего стоит только придирчивость Python к отступам.

      Скорее microScript напоминает чем то Lua. По словам автора, он вдохновлялся именно этим языком при создании microScript. А также, если брать во внимание синтаксис, то можно сравнить и с MiniScript.


  1. mSnus
    08.01.2022 02:48
    +2

    Мне кажется, стоит обозначить, что простой, но достаточно мощный язык нужен не программистам, а дизайнерам, аниматорам, гейм-девелоперам и прочим, чтобы создать простые игры и анимации, не закапываясь в код.


    1. Constantine_RetroGamer Автор
      08.01.2022 03:19
      +1

      В сущности оно так и есть, как я и сказал в статье: "...microScript - это локальный язык. В настоящее время он используется только в пределах microStudio." Ну а microStudio это среда разработки игр.

      Совершенно точно подмечено, да, думаю что можно добавить этот пункт в статью.