вторник, 24 января 2012 г.

Layers.script v.1.1 RC + видео его работы

Автор: Серёжа


Спешу сообщить, что моя работа тоже не стоит на месте =) Вот, кстати, видео по работе слоёв:


Помните, я говорил, сколько ещё надо сделать в скрипте по перемещению слоёв? Вот этим я и занимался несколько дней. Для нашей игры это действительно важно, контроль над "камерой"  нужен полный, плюс ещё головоломки классные получатся.
Напоминаю, остановился я на том, что у меня начали нормально ездить спрайты (Entity). Решил, что этого мало и неудобно, надо туда ещё регионы прикрутить.
Регионы (Regions), в отличие от Entity, состоят из n-го количества точек, не имеют своего однозначного .X и .Y, не умеют просто так перемещаться. Ловятся при помощи "Scene.GetNode()". Это то, что можно почерпнуть из манов.
Однако есть то, что в манах не описано (да и нигде на форумах). Существует, отказывается 3 типа Node:
  • Entity. Самый простой, просто картинка и не более. В Scene Edit обозначется жёлтым пакманом. С ним проблем нет.
  • Region. Простой пример есть на каждой сцене - это floor. Представляет собой набор точек, ограничивает движение actor. Может быть создать только на Main layer.
  • Entity, который region. Обозначается зелёным пакманом. Очень интересная штука. Представляет из себя пустой Entity (this.Type == entity), который ссылается на регион (this.Region)
Что нам это даёт? Кучу проблем и не более. Радует одно, все они отзываются на Scene.GetNode().
Дам сразу готовое решение: надо сделать так, чтобы каждый их этих типов узлов нормально поддерживал 3 вещи: this.X, this.Y, this.SkipTo(). Для каждого эти вещи будут вычисляться немного по-разному.
Так, например, у Region нужно писать this.SetPoint(...), а у  Entity, который region нужно сначала выцепить регион (this.Region), а только потом делать ему SetPoint.
Да и цеплять скрипты к каждому объекту стало неудобно.
Короче, решился я править scene.script. Этот скрипт выполняется на каждой сцене при её загрузке, "цепляется" к ней. Теперь в неё происходит аттач всех необходимых скриптов к нужным объектам.
Скрипт "region.script" - перемещает регионы.
Скрипт "region_entity.script" транслирует методы из предыдущего скрипта на  Entity, который region
Так же появился скрипт "node.script". Он очень короткий, но выполняет очень важную задачу -- распараллеливает перемещение. Т.е. Entity не ждёт, пока закончит ехать 5 узел региона, а начинает ехать сам вместе с первым узлом. Производительность over 9000 ^.^
 Так же был переписан основной скрипт, выкинута половина (я не шучу) кода, остальная часть прошла жёсткую оптимизацию и испытания в боевых условиях.
Установка проста, достаточно скопировать эти скрипты в папочку scripts и можно пользоваться!
Встречаем (упорядочены по размеру по возрастанию):

node.script:


#include "scripts\base.inc"

on "DoSkip"
{
this.SkipTo(this.GOX,this.GOY);
}



region_entity.script:



#include "scripts\base.inc"
method UpdateCord()
{
var Obj=this.Region;
Obj.UpdateCord();
this.X=Obj.X;
this.Y=Obj.Y;
}

method SkipTo (x,y)
{
var Obj=this.Region;
Obj.SkipTo(x,y);
}


region.script:



#include "scripts\base.inc"
method UpdateCord()
{
var P=this.GetPoint(0);
this.X=P.X;
this.Y=P.Y;
}

method SkipTo (x,y)
{
this.dx=x-this.X;
this.dy=y-this.Y;
this.ApplyEvent("GO");
}

on "GO"
{
for (var i=0; i<this.NumPoints; i=i+1)
{
var P=this.GetPoint(i);
this.SetPoint(i,P.X+this.dx,P.Y+this.dy);
}
this.UpdateCord();
this.dx=0;
this.dy=0;
}



scene.script:



#include "scripts\base.inc"

for (var i=0; i<this.NumLayers; i=i+1)
{
var l=this.GetLayer(i);
l.AttachScript("scripts\layer.script");
for (var j=0; j<l.NumNodes; j=j+1)
{
var Node=l.GetNode(j);
Node.AttachScript("scripts\node.script");
if (Node.Type=="ad region")
{
Node.AttachScript("scripts\region.script");
Node.UpdateCord();
}
if (Node.Region!=null)
{
var Reg=Node.Region;
Reg.AttachScript("scripts\region.script");
Node.AttachScript("scripts\region_entity.script");
Node.UpdateCord();
}

}
}

on "LeftClick"
{
actor.GoTo(Scene.MouseX, Scene.MouseY);
}



layer.script:



#include "scripts\base.inc"
var pers=actor;

method Scroll (x, y, v)
{
var h=10;
if (this.NumNodes!=0)
{
this.dx=(x*h)/v;
this.dy=(y*h)/v;

//~ var Act; //для выключения регионов

var curNode;
var X3, Y3;
var X0, Y0;
var X0Free, Y0Free, X1Free, Y1Free; //для pers
for (var j=0; j<this.NumNodes ;j=j+1)
{
if (this.Main)
{
X0Free=pers.X;
Y0Free=pers.Y;
X1Free=X0Free+x;
Y1Free=Y0Free+y;
}
curNode=this.GetNode(j);
if (curNode.CanHandleMethod("UpdateCord"))
curNode.UpdateCord();
X3[j]=curNode.X;
Y3[j]=curNode.Y;
X0[j]=curNode.X+x;
Y0[j]=curNode.Y+y;
//~ if (curNode.Region!=null && curNode.Active==true) //Выключаем активные регионы на время движения
//~ {
//~ Act[j]=true;
//~ curNode.Active=false;
//~ }
}
var t1;
var c=true;
while (c)
{
t1=Game.CurrentTime;
for (var k=0; k<this.NumNodes;k=k+1)
{
curNode=this.GetNode(k);
X3[k]=X3[k]+this.dx;
Y3[k]=Y3[k]+this.dy;
curNode.GOX=X3[k];
curNode.GOY=Y3[k];
curNode.ApplyEvent ("DoSkip"); //Включить для параллельного перемещения
//curNode.SkipTo(X3[k],Y3[k]); //Включить для последовательного
}
if (this.Main)
{
X0Free=X0Free+this.dx;
Y0Free=Y0Free+this.dy;
pers.X=X0Free;
pers.Y=Y0Free;
}
if (x>0 && ((X3[0]+this.dx-X0[0])>0)) //проверяем, доедет ли слой за следующий шаг
c=false;
if (x<0 && ((X3[0]+this.dx-X0[0])<0))
c=false;
if (y>0 && ((Y3[0]+this.dy-Y0[0])>0))
c=false;
if (y<0 && ((Y3[0]+this.dy-Y0[0])<0))
c=false;
Sleep (t1+h-Game.CurrentTime);
}
for (var i=0 ; i<this.NumNodes ; i=i+1)
{
curNode=this.GetNode(i);
curNode.SkipTo(X0[i],Y0[i]);
//~ if (Act[i] == true)
//~ curNode.Active=true;
if (this.Main)
pers.SkipTo(X1Free,Y1Free);
}
}
}

method ScrollAsync(x,y,v)
{
this.x=x;
this.y=y;
this.v=v;
this.ApplyEvent ("move");
}

on "move"
{
this.Scroll(this.x,this.y,this.v);
}


____________________________________
P.S. Вот теперь думаю, как лучше управлять активацией/деактивацией регионов при движении. Либо через глобальную переменную слоя, либо ещё одну переменную на вход метода добавить... увы, перегрузки в WME нет =(

Комментариев нет:

Отправить комментарий