Сделал набор функций, с которыми можно быстро и удобно реализовать "карусель", типа такой.
https://youtu.be/ynnC-GM9GtEПосле кода будет инструкция как пользоваться.
Код:
func atan2f(x,y)
{
if((float)x>0.0)
{
return gs_atan(y/x);
}
if((float)x<0.0 && (float)y>=0.0)
{
return (gs_atan(y/x)+PI);
}
if((float)x<0.0 && (float)y<0.0)
{
return (gs_atan(y/x)-PI);
}
if((float)x==0.0)
{
if((float)y>0.0)return PI/2.0;
if((float)y<0.0)return -PI/2.0;
if((float)y==0.0)return 0.0;
}
}
Код:
func do_karusel(id,ccx,ccy,ang)
{
idx=ObjFind(id);
x=(float)ObjGet(idx,O_X);
y=(float)ObjGet(idx,O_Y);
w=(float)ObjGet(idx,O_W);
h=(float)ObjGet(idx,O_H);
ox=(float)x+w/2.0;
oy=(float)y+h/2.0;
delta=ObjGet(idx,O_USER);
if(delta==0)
{
delta=(int)gs_sqrt(((ox-ccx)*(ox-ccx))+((oy-ccy)*(oy-ccy)));
ObjSet(idx,O_USER,(int)delta);
}
afloor=(float)ObjGet(idx,O_USER+1);
aceil=(float)ObjGet(idx,O_USER+2);
ang2=afloor+aceil/10.0;
if(ang2==0.0)
{
ang2=atan2f(ccx-ox,ccy-oy);
ang2=180.0/PI*(float)ang2;
ang2+=180.0;
afloor=gs_floor((float)ang2);
aceil=(float)ang2-afloor;
ObjSet(idx,O_USER+1,(int)afloor);
ObjSet(idx,O_USER+2,(int)(aceil*10.0));
}
rad=((float)ang+ang2)/180.0*PI;
acx=gs_cos(rad);
acy=gs_sin(rad);
xx=ccx+acx*(float)delta;
yy=acy*(float)delta+ccy;
xx-=w/2.0;
yy-=h/2.0;
ObjSet(idx,O_X,(int)xx);
ObjSet(idx,O_Y,(int)yy);
if(ObjGet(idx,O_COLLIDER)==2)
{
plx=PlayerGet(P_X);
ply=PlayerGet(P_Y);
plw=PlayerGet(P_W);
plh=PlayerGet(P_H);
if(plx>=(int)x && plx<=(int)x+(int)w && ply<=(int)y&& ply>=(int)y-plh-5)
{
dx=(float)plx-x;
PlayerSet(P_X,(int)((float)dx+xx));
println(((float)dx+xx));
}
}
id=ObjGet(idx,O_TARGET);
if(id!=0)do_karusel(id,ccx,ccy,ang);
}
func karusel(id,corner_speed)
{
odc=ObjFind(id);
afloor=(float)ObjGet(odc,O_USER);
aceil=(float)ObjGet(odc,O_USER+1);
ang=afloor+aceil/10.0;
ang+=corner_speed;
if(ang>=360.0)ang=0.0;
if(ang<0.0)ang=360.0;
afloor=gs_floor((float)ang);
aceil=(float)ang-afloor;
ObjSet(odc,O_USER,(int)afloor);
ObjSet(odc,O_USER+1,(int)(aceil*10.0));
cnt=ObjGet(odc,O_USER+2);
cx=(float)ObjGet(odc,O_X);
cy=(float)ObjGet(odc,O_Y);
cw=(float)ObjGet(odc,O_W);
ch=(float)ObjGet(odc,O_H);
ccx=(float)cx+cw/2.0;
ccy=(float)cy+ch/2.0;
for(a=0;a<cnt;a++)
{
do_karusel(ObjGet(odc,O_USER+a+3),ccx,ccy,ang);
}
}
Настройка:
Рисуем на карте объект - центр типа dynamic.
Рисуем вокруг него динамические объекты, которые будем вертеть.
В центральном объекте User+0 и User+1 оставляем пустыми. В User+2 вбиваем количество вращаемых объектов.
Начиная с User+3 вбиваем id вращаемых объектов.
У вращаемых объектов O_USER +0 - O_USER +2 Должен быть = 0. Эти переменные используются в функциях.
т.к. объектов может крутиться реально много, то я сделал что-то типа цепочек.
К любому объекту можно прицепить ведомый. Для этого в O_TARGET вписываем id ведомого. У последнего объекта в цепочке O_TARGET должен быть = 0.
В видео-примере, к центру прицеплены только 4 внутренних шарика, а к ним ещё по одному шарику, а уже к ним - платформы.
После настройки в функциях обновления комнат (н.р. UpdateRoom_47_48()) вызываем karusel(ID,angle_speed);
Скорость вращения - дробная.
PS. Я не знаю насколько тормозной gscript, сколько он отъедает памяти и процессорного времени, и как оно будет работать на слабых компьютерах. У меня стабильно 64fps.