جیامال
جیامال(gml) (زبان گیم میکر یا Game Maker Language) یک زبان برنامهنویسی مفسری است که برای استفاده به همراه برنامههای کاربردی ساخت بازی که Game Maker (گیم میکر) نامیده میشود ساخته شدهاست.
اصل این زبان در ابتدا به وسیلهMark Overmars ساخته شد تا سیستم عمل کشیدن و انداختن (بگیر و بکش) "drag-and-drop action" را که در Game Maker استفاده میشود تکمیل نماید. هرچند که در آخرین نسخه اعمال کشیدن و انداختن به GML ترجمه شدند تا بخواهند ازآن به صورت مجزا باشند. GML به سختی با محیط و فضای Game Maker مجتمع شده. اغلب عناصر مانند بلوک پیکسلها و صداها در داخل Game Maker IDE استفاده شدند (در حالی که میتوانستند ازفایلهای خارجی استفاده کنند) معماری Game Maker طراحی شده تا اعمالی مانند کشف رویدادها، طراحی سطح و پیکر بندی شیها را اجرا کند بدون آنکه نیاز باشد تا کد آن را به صورت دستی پیادهسازی کرد.(اضافات کد را به وسیله محیط تعاملی پیشرفته خود کم کردهاست.) یک تصور غلط وجود دارد که میگوید زبانهایی مانندPascal وC++ به صورت مستقیم در GML به کار رفتهاست. این تصور اشتباه است و از آنجا ناشی میشود که GML این توانایی را دارد که شکلبندی Pascal وC++ را به کار ببرد. (مثلاً"&&" قابل تعویض با "and" میباشد.)
کتابخانهها Libraries
در مجموعه دستورالعملهای کشیدن و انداختنی کتابخانه نامیده میشود. در محیط تعاملی کتابخانهها به عنوان تبهایی شامل شکلکها نمایش داده میشوند که دستورلعمل نامیده میشود. هر دستورالعمل یک مجموعه متن gml یا یک تابع میباشد که کاربر میتواند برای بازی به کار برد. با یک سری کتابخانهها ی پیشساخته آماده شدهاست که دستور العملهای معمولی است که در اغلب بازیها به کار میرود. نحو و مفاهیم در GML ساختار GML بسیار شبیه به زبان C است. این شباهت در کاربرد بلوکها و فراخوانی توابع، تخصیص متغیرها، نحو عملگرها و غیره مشهود است. GML بین متون و عبارات منطقی تفاوت میگذارد. برای مثال g<1 یک متن صحیح نیست و GML خطا می هد. با این وجود تخصیص متغیرها معمولاً متن هستند و نمیتوانند در یک عبارت منطقی به کار روند. GML عملگرهی افزایشی و کاهشی را اجازه میدهد. مانند:
g+=1;
مساوی است با
g = g+1;
این تابع شامل *= و -= و=/ هم میشود. GML نحو ?: را اجازه نمیدهد.عبارت با؛ جدا میشود . اما GML ما را مجبور به این کار نمیکند.
توابع
GML یک کتابخانه بزرگ از توابع پیشساخته دارد که برای کارهایی مبتنی بر توابع مهیا شدهاست.برنامه نویس میتواند scriptهایی بسازد. که مانند توابع فراخوانی میشود. رسم توابع با استفاده Direct3d API ممکن است. همچنین GML توابع پیش ساختهای برای استفاده از DLLهای خارجی دارد. هر ویژگی که در این برنامه فراهم نشده را میتوان با استفاده از DLLها اضافه کرد.
متغیرها
در حالت معمول GML احتیاج ندارد که متغیرها مانند زبانهای دیگر اعلان کند. هر متغیر بعد از آن که برنامه نویس اولین بار آن را مقدار دهی کرد ساخته میشود. مثلاً : for = “bar”. GML متغیرها و ثابتهای پیش ساخته زیادی دارد هر نمونه در بازی دارای متغیرهای محلی مانند X،Y میباشد و همچنین متغیرها عمومی که برنامهنویس میسازد متغیرهای عمومی پیشساخته پیشوند global را ندارد. آرایهها در GML شناسایی میشدند که میتوانند یک یا دو بعد باشند. آرایهها میتوانند مخلوطی از مقادیر طبیعی و رشتهها باشند اما نمیتوانند خودشان را مرتب کنند. آرایهها در GML نمیتوانند به تابع داده شوند یا مقدار بازگشتی تابع باشند.اندیس آرایهها محدود آرایهها محدود است. اندیسها نمیتوانند از 32000 بیشتر باشند و یک آرایه تنها نیز نمیتواند بیش از 1000000 مقدار دانسته باشند GML در نسخههای جدید خود 6 نوع ساختار دادهای را فراهم میکند.
- پشته
- صف
- لیست
- نقشه
- صف اولویت
- توری(شبکه)
TYPE(نوع)
برای سادگی GML فقط دو نوع تایپ دارد: STRING(رشته) : مجموعهای از کاراکترهای ASCI است. که میتواند هر طولی داشته باشد. تنها محدودیت برای رشته محدویت حافظه است. مقادیر طبیعی (real value) اعداد ممیز شناور هستند. از نسخه 6.1 به بعد اعداد هگزادسیمال نیز اضافه شده چون GML مقدار منطقی ندارد. بیانهایی که احتیاج به مقدار منطقی دارند مانند if هر مقداری بالاتر از 0.5 را صحیح ارزیابی میکنند و مقادیر کوچکتر را غلط ثابتهای "true"و”false” میتوانند به جای 1و0 در GML استفاده شوند.
حوزه( scope)
در GML دو نوع محل متغیر وجود دارد: محل "نمونه ها" و محل "script"(یا هر تکه کد دیگر که محتویات خود را دارد) محلی بودن یک نمونه به این معنا است که متغیر به یک نمونه مشخص متصل شده و به وسیله یک نمونه پیشوند مشخصکننده فراخوانی میشود . محلی بودن یک script به این معنی است که متغیر میتواند ارجاع داده شود فقط در داخل همان script (وقتی که پردازش script تمام میشود، منقضی میشود)چون بعد از آن معرفیکننده script دسترسی به آن برای کار فراهم نکردهاست. وقتی کلمه "local" بدون بیشتر خصوصیات آن به کار میرود معمولاً به نمونه محلی اشاره دارد. بهطور پیش فرض متغیرها برای یک نمونه به صورت محلی هستند اما نه برای script ی که به کار میرود. برای آن که متغیری بسازیم که تمام نمونهها به توانند با آن کار کنند باید از فضای اسم عمومی استفاده کنیم(global.foo = bar)صریحاً به فرام (globalvarfoo،bar) اعلان شود. در نوع اول متغیر باید همیشه با پیشوند global استفاده شود. اما اعلان با globalvar اجازه میدهد تا متغیر را بدون استفاده از پیشوند به کار بریم. برای آنکه یک متغیر را در یک script بهطور محلی به کار بریم. کلمه کلیدی VAR به کار میرود. متغیرهایی که به صورت محلی در یک نمونه به کار میروند میتوانند در خارج از نمونه با استفاده از معینکننده به کار روند(instance refrence.varname)اگر چندین script در یک زمان در پشته پردازش باشند هیچ راهی وجود ندارد که به متغیرهای محلی یک script از دیگری دسترسی داشته باشیم. مگر اینکه در script دیگر به عنوان آرگومان آمده باشد. فضای نام معمول نمونه میتواند به وسیله سازه with عوض شود. برای مثال کدهایی که در ادامه میآید، بهطور تلاقی جا داده شده میتواند از بین بردن نمونههای دیگر استفاده شود. در ساخت وقایع متلاقی GML بهطور خودکار یک متغیر "other" برای ارجاع به اشیا درگیر دیگر میسازد.
with (other) { instance_destroy (); }
دقت کنید که وقتی متغیری به عنوان یک متغیر محلی برای script خاصی معرفی میشود، اجماع خود را با نمونهای که script نامیده میشد از دست میدهد، و به یک نمونه مستقل تبدیل میشود برای مثال کدی که در ادامه میآید صحیح کار میکند با وجود اینکه متغیر foo برای some other instance معرفی نشدهاست:
var foo; foo = "bar"; with (someOtherInstance) { show_message(foo); }
اخذ حافظه
GML به صورت خودکار برای متغیرها حافظه اخذ میکند و برای این کار از انواع پویا استفاده میکند و به این وسیله به وجود آوردن متغیرهای گوناگون ممکن است. به عنوان مثال میتوان یک متغیر صحیح را تعریف کرد ونوع آن را به رشته تبدیل کرد.
intNumber = 1 ; intNumber = "This variable now contains a string";
متأسفانه برای آزاد کردن حافظه اخذ شده هیچ دستوری وجود ندارد. اگر یک نمونه از بین برود یا یک script تمام شود، در هر حالت هر گونه متغیری به آن نمونه یا script آزاد میشود. از این رو برای نگهداری حافظه این امرکه برای نگهداری متغیرها برای نمونه و script متغیر محلی بهتر از عمومی است. برای ذخیره و دستکاری مقادیر بزرگتری از اطلاعات بهطور مؤثر تر،GML یک سری ساختار درون ساختاری دارد، مانند stack،queues،lists،mapspriority queues، grids دارد. این ساختارهای به وجود میآیند، پرداخته میشوند و از بین میروند در درون توابع درون ساخت. همچنین توابعی برای مرتب سازی این ساختارها که مربوط به هر کدام از این ساختارهای هستند وجود دارد. این باعث میشود که به خصوص سرعت بهینه سازی بالا رود.
نمونهها و منابع
GML اشاره گر به محلهای مرجع در حافظه را پشتیبانی نمیکند. بدین ترتیب هر منبع و نمونهای در GML یک شماره ID منحصربهفرد دارد، که برای رجوع به منبع یا نمونه خاص به کار میرود. این شماره ID میتواند توسط script و توابع برای رجوع به منبع یا نمونه به کار میرود. به مجرد اینکه یک منبع GML ساخته شود نام آن را به عنوان ثابتی در نظر گرفته میشود که میتواند مورد رجوع قرار گیرد.(برای اشیا اولین نمونه مرجع میباشد) ID نمونههای خاص هر شی میتوانند با متغیر ID یافت شوند. در زبان ساخته شدن منابع و نمونهها در زمان اجرا ID منحصربهفرد آنها باز گردانده میشود یا به متغیرها وتوابع داده میشود.
3D در GML
هر چند GML در اصل برای برنامهنویسی دوبعدی به وجود آمدهاست، نسخه حرفهای آن توابع سهبعدی نیز دارد. کتابخانه فعال استاندارد برنامه نویسی سه بعدی را پوشش نمیدهد که در این صورت کاربران باید توابع اضافی را دانلود کنند.GML از توابع Direct 3D و Direct2D استفاده میکنند.
نمونه کد
در این قسمت یک نمونه کد آمدهاست که متن HELLO WORLD را در یک جعبه پیام نشان میدهد. show_message("Hello World!"); مثال دیگر همان متن را در پنجره بازی نشان میدهد . توجه کنید که GML خود بهطور پیش فرض پس زمینه را مداوما رسم میکند. بنابراین شاید لازم باشد که تنظیمات پیشفرض به این کد ضمیمه شود با به درستی کار کند: draw_text(0، 0، "Hello World!"); در این قسمت کدی از یک بازی که از GML استفاده کردهاست:
// This is a comment
/* this is a C-Style comment. */
/* temporary variable declaration.
A temporary variable will be released at the end of a script.
Note that this doesn't declare it to be of a specific type! */
var xx, yy, nn;
// A conditional. It can also be shortened to "if (can_shoot)".
if (can_shoot = true) // "=" and "==" can be used interchangeably in conditionals
{ // This begins a block of code. You can also use "begin" as with Pascal.
/* Here we are setting the variable to false. This could also be written as "can_shoot = 0;"
since Game Maker doesn't distinguish between integer and boolean types. */
can_shoot = false;
/* Here you are setting the 0th alarm to five steps. The alarm
variable will automatically count down to 0, and when it hits 0,
the alarm0 event will be triggered. */
alarm[0] = 5;
/* Here the temporary variable xx is defined implicitly as an integer,
and the lengthdir_x function is used. */
xx = x + lengthdir_x(14, direction);
yy = y + lengthdir_y(14, direction);
//This function creates a obj_bullet and then returns its instance id to nn.
nn = instance_create(xx, yy, obj_bullet);
/* The with statement allows you to access the fields of an object directly,
without having to write statements like nn.speed or nn.direction. */
with (nn)
{
speed = obj_tank.speed + 3;
direction = obj_tank.direction;
}
}
GML از تغییرات زیاد در نحو پشتیبانی میکند. برای دلیل مثال قبلی میتواند به این صورت نیز نوشته شود:
var xx, yy, nn;
if can_shoot = true then begin
can_shoot := false
alarm[0] := 5
xx := x + lengthdir_x(14, direction)
yy := y + lengthdir_y(14, direction)
nn := instance_create(xx, yy, obj_bullet)
with nn begin
speed := obj_tank.speed + 3
direction := obj_tank.direction
end
end
در اینجا مثالی از حرکت کلیدهای کنترلی آمدهاست. دستگاه حرکتی دو آرگومان میگیرد. مسیر و سرعت. فراخوانی این تابع دو متغیر محلی speed&direction را میسازد. که در هر مرحله GML خود نمونهها را به روز رسانی میکند:
if (keyboard_check(vk_left)) motion_set(180,4);
if (keyboard_check(vk_up)) motion_set(90,4);
if (keyboard_check(vk_right)) motion_set(0,4);
if (keyboard_check(vk_down)) motion_set(270,4);
if (keyboard_check(vk_nokey)) motion_set(0,0);
در اینجا نمونه از یک اسکریپت پیچیده تر یک سطح بازی آمدهاست. بااستفاده از این بازیکن میتواند روی تپه و عوارض طبیعی زمین قدم بزند:
if (!place_free(x-4,y))
{
if (place_free(x-4,y-4))
{
x-=4;
y-=4;
}
else if (place_free(x-3,y-5))
{
x-=3;
y-=5;
}
else if (place_free(x-2,y-6))
{
x-=2;
y-=6;
}
}
else
x-=4;
در این جام هم یک کد آمده که سقفی سه بعدی میسازد. تابع d3d_start() باید قبلاً فراخوانی شده باشد:
d3d_draw_floor(0,0,0,500,600,1,background1,.01,.01);