Implement BGANIM?
This commit is contained in:
206
SMILEBASIC/bg.d
206
SMILEBASIC/bg.d
@@ -1,6 +1,7 @@
|
|||||||
module otya.smilebasic.bg;
|
module otya.smilebasic.bg;
|
||||||
import otya.smilebasic.petitcomputer;
|
import otya.smilebasic.petitcomputer;
|
||||||
import otya.smilebasic.error;
|
import otya.smilebasic.error;
|
||||||
|
import otya.smilebasic.sprite;
|
||||||
import derelict.sdl2.sdl;
|
import derelict.sdl2.sdl;
|
||||||
import derelict.opengl3.gl;
|
import derelict.opengl3.gl;
|
||||||
|
|
||||||
@@ -46,9 +47,11 @@ class BG
|
|||||||
r = 0;
|
r = 0;
|
||||||
show = true;
|
show = true;
|
||||||
bgcolor = 0xffffffff;
|
bgcolor = 0xffffffff;
|
||||||
|
initBGAnimationTable();
|
||||||
}
|
}
|
||||||
void render(int display, float disw, float dish)
|
void render(int display, float disw, float dish)
|
||||||
{
|
{
|
||||||
|
animation();
|
||||||
if (!show)
|
if (!show)
|
||||||
return;
|
return;
|
||||||
float aspect = disw / dish;
|
float aspect = disw / dish;
|
||||||
@@ -292,4 +295,207 @@ class BG
|
|||||||
{
|
{
|
||||||
return this.bgcolor;
|
return this.bgcolor;
|
||||||
}
|
}
|
||||||
|
bool isAnim;
|
||||||
|
SpriteAnimData[][SpriteAnimTarget.V + 1] anim;
|
||||||
|
int[SpriteAnimTarget.V + 1] animindex;
|
||||||
|
int[SpriteAnimTarget.V + 1] animloop;
|
||||||
|
int[SpriteAnimTarget.V + 1] animloopcnt;
|
||||||
|
void setAnimation(SpriteAnimData[] anim, SpriteAnimTarget sat, int loop)
|
||||||
|
{
|
||||||
|
this.anim[sat] = null;
|
||||||
|
if(loop < 0)
|
||||||
|
{
|
||||||
|
throw new IllegalFunctionCall("BGANIM");
|
||||||
|
}
|
||||||
|
animloop[sat] = loop;
|
||||||
|
animloopcnt[sat] = 0;
|
||||||
|
animindex[sat] = 0;
|
||||||
|
this.anim[sat] = anim;
|
||||||
|
isAnim = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void bganim(wstring target, double[] data)
|
||||||
|
{
|
||||||
|
static import std.uni;
|
||||||
|
bool relative = false;
|
||||||
|
if(target[$ - 1..$] == "+")
|
||||||
|
{
|
||||||
|
target = target[0..$-1];
|
||||||
|
relative = true;
|
||||||
|
}
|
||||||
|
target = std.uni.toUpper(target);
|
||||||
|
if (!(target in bgAnimTarget))
|
||||||
|
throw new IllegalFunctionCall("BGANIM");
|
||||||
|
auto tgete = bgAnimTarget[target];
|
||||||
|
bganim(tgete | (relative ? SpriteAnimTarget.relative : cast(SpriteAnimTarget)0), data);
|
||||||
|
|
||||||
|
}
|
||||||
|
SpriteAnimTarget[wstring] bgAnimTarget;
|
||||||
|
void initBGAnimationTable()
|
||||||
|
{
|
||||||
|
bgAnimTarget = [
|
||||||
|
"XY": SpriteAnimTarget.XY,
|
||||||
|
"Z": SpriteAnimTarget.Z,
|
||||||
|
"R": SpriteAnimTarget.R,
|
||||||
|
"S": SpriteAnimTarget.S,
|
||||||
|
"C": SpriteAnimTarget.C,
|
||||||
|
"V": SpriteAnimTarget.V,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
SpriteAnimTarget getBGAnimTarget(wstring target)
|
||||||
|
{
|
||||||
|
bool relative = false;
|
||||||
|
if(target[$ - 1..$] == "+")
|
||||||
|
{
|
||||||
|
target = target[0..$-1];
|
||||||
|
relative = true;
|
||||||
|
}
|
||||||
|
return bgAnimTarget[target] | (relative ? SpriteAnimTarget.relative : cast(SpriteAnimTarget)0);
|
||||||
|
}
|
||||||
|
void animation(SpriteAnimData* data, SpriteAnimTarget target)
|
||||||
|
{
|
||||||
|
if (!animationEnabled)
|
||||||
|
return;
|
||||||
|
auto frame = data.elapse;
|
||||||
|
if(frame == 1)
|
||||||
|
{
|
||||||
|
if(!data.interpolation)
|
||||||
|
{
|
||||||
|
switch(target)
|
||||||
|
{
|
||||||
|
case SpriteAnimTarget.XY:
|
||||||
|
offsetx = cast(int)data.data.x;
|
||||||
|
offsety = cast(int)data.data.y;
|
||||||
|
break;
|
||||||
|
case SpriteAnimTarget.Z:
|
||||||
|
offsetz = cast(int)data.data.z;
|
||||||
|
break;
|
||||||
|
case SpriteAnimTarget.R:
|
||||||
|
r = data.data.r;
|
||||||
|
break;
|
||||||
|
case SpriteAnimTarget.S:
|
||||||
|
scalex = data.data.scalex;
|
||||||
|
scaley = data.data.scaley;
|
||||||
|
break;
|
||||||
|
case SpriteAnimTarget.C:
|
||||||
|
break;
|
||||||
|
case SpriteAnimTarget.V:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(data.interpolation)
|
||||||
|
{
|
||||||
|
//線形補完する奴
|
||||||
|
switch(target)
|
||||||
|
{
|
||||||
|
case SpriteAnimTarget.XY:
|
||||||
|
offsetx = cast(int)(data.old.x + ((data.data.x - data.old.x) / data.frame) * frame);
|
||||||
|
offsety = cast(int)(data.old.y + ((data.data.y - data.old.y) / data.frame) * frame);
|
||||||
|
break;
|
||||||
|
case SpriteAnimTarget.Z:
|
||||||
|
offsetz = cast(int)(data.old.z + ((data.data.z - data.old.z) / data.frame) * frame);
|
||||||
|
break;
|
||||||
|
case SpriteAnimTarget.R:
|
||||||
|
r = data.old.r + ((data.data.r - data.old.r) / data.frame) * frame;
|
||||||
|
break;
|
||||||
|
case SpriteAnimTarget.S:
|
||||||
|
scalex = data.old.scalex + ((data.data.scalex - data.old.scalex) / data.frame) * frame;
|
||||||
|
scaley = data.old.scaley + ((data.data.scaley - data.old.scaley) / data.frame) * frame;
|
||||||
|
break;
|
||||||
|
case SpriteAnimTarget.C:
|
||||||
|
break;
|
||||||
|
case SpriteAnimTarget.V:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void animation()
|
||||||
|
{
|
||||||
|
if (!animationEnabled)
|
||||||
|
return;
|
||||||
|
foreach(i, ref d; anim)
|
||||||
|
{
|
||||||
|
if(!d) continue;//未定義
|
||||||
|
SpriteAnimTarget target = cast(SpriteAnimTarget)i;
|
||||||
|
int index = animindex[i];
|
||||||
|
SpriteAnimData* data = &d[index];
|
||||||
|
data.elapse = data.elapse + 1;
|
||||||
|
auto frame = data.elapse;
|
||||||
|
animation(data, target);
|
||||||
|
if(frame >= data.frame)
|
||||||
|
{
|
||||||
|
animindex[i] = (animindex[i] + 1) % cast(int)d.length;
|
||||||
|
data.elapse = 0;
|
||||||
|
if(animloop[i] == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(!animindex[i])
|
||||||
|
{
|
||||||
|
animloop[i]++;
|
||||||
|
if(animloop[i] >= animloopcnt[i])
|
||||||
|
{
|
||||||
|
anim[i] = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool animationEnabled = true;
|
||||||
|
void bganim(SpriteAnimTarget target, double[] data)
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
bool relative;
|
||||||
|
if(SpriteAnimTarget.relative & target)
|
||||||
|
{
|
||||||
|
relative = true;
|
||||||
|
target ^= SpriteAnimTarget.relative;
|
||||||
|
}
|
||||||
|
int animcount = cast(int)data.length / ((target == SpriteAnimTarget.XY || target == SpriteAnimTarget.UV) ? 3 : 2);
|
||||||
|
SpriteAnimData[] animdata = new SpriteAnimData[animcount];
|
||||||
|
int j;
|
||||||
|
int loop = 1;
|
||||||
|
SpriteAnimData* old;
|
||||||
|
for(int i = 0; i < data.length;)
|
||||||
|
{
|
||||||
|
i = animdata[j].load(i, this, target, data, old, relative);
|
||||||
|
old = &animdata[j++];
|
||||||
|
if(data.length - i == 1)
|
||||||
|
{
|
||||||
|
//loop
|
||||||
|
loop = cast(int)data[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setAnimation(animdata, target, loop);
|
||||||
|
if(animdata[0].frame == 1)
|
||||||
|
{
|
||||||
|
animindex[target]++;
|
||||||
|
animation(&animdata[0], target);
|
||||||
|
if(animcount == 1)
|
||||||
|
{
|
||||||
|
if(loop > 1 || loop == 0)
|
||||||
|
{
|
||||||
|
animindex[target] = 0;
|
||||||
|
animloopcnt[target]++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
anim[target] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1790,6 +1790,54 @@ class BuiltinFunction
|
|||||||
if(args[1].isNumber)
|
if(args[1].isNumber)
|
||||||
p.sprite.spanim(no, cast(SpriteAnimTarget)(args[1].castInteger), animdata);
|
p.sprite.spanim(no, cast(SpriteAnimTarget)(args[1].castInteger), animdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void BGANIM(PetitComputer p, Value[] va_args)
|
||||||
|
{
|
||||||
|
//TODO:配列
|
||||||
|
auto args = retro(va_args);
|
||||||
|
int no = args[0].castInteger;
|
||||||
|
if (!p.isValidLayer(no))
|
||||||
|
{
|
||||||
|
throw new OutOfRange(smilebasicFunctionName, 1);
|
||||||
|
}
|
||||||
|
double[] animdata;
|
||||||
|
if(args[2].isString)
|
||||||
|
{
|
||||||
|
VM vm = p.vm;
|
||||||
|
vm.restoreData(args[2].castDString);
|
||||||
|
int keyframe = vm.readData.castInteger;
|
||||||
|
auto target = p.getBG(no).getBGAnimTarget(args[1].castDString);
|
||||||
|
int item = 2;
|
||||||
|
if((target & 7) == SpriteAnimTarget.XY || (target & 7) == SpriteAnimTarget.UV) item++;
|
||||||
|
animdata = new double[item * keyframe + 1];
|
||||||
|
int j;
|
||||||
|
for(int i = 0; i < keyframe; i++)
|
||||||
|
{
|
||||||
|
animdata[j] = vm.readData.castDouble;
|
||||||
|
animdata[j + 1] = vm.readData.castDouble;
|
||||||
|
if(item == 3)
|
||||||
|
animdata[j + 2] = vm.readData.castDouble;
|
||||||
|
j += item;
|
||||||
|
}
|
||||||
|
if(args.length > 3)
|
||||||
|
animdata[j] = args[3].castInteger;
|
||||||
|
else
|
||||||
|
animdata[j] = 1;//loop count
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
animdata = new double[args.length - 2];
|
||||||
|
foreach(a; args[2..$])
|
||||||
|
{
|
||||||
|
animdata[i++] = a.castDouble;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(args[1].isString)
|
||||||
|
p.getBG(no).bganim(args[1].castDString, animdata);
|
||||||
|
if(args[1].isNumber)
|
||||||
|
p.getBG(no).bganim(cast(SpriteAnimTarget)(args[1].castInteger), animdata);
|
||||||
|
}
|
||||||
static void SPDEF(PetitComputer p, int id, out int U, out int V)
|
static void SPDEF(PetitComputer p, int id, out int U, out int V)
|
||||||
{
|
{
|
||||||
if (!p.sprite.isValidDef(id))
|
if (!p.sprite.isValidDef(id))
|
||||||
|
|||||||
@@ -160,6 +160,73 @@ struct SpriteAnimData
|
|||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import otya.smilebasic.bg;
|
||||||
|
int load(int i, BG bg, SpriteAnimTarget target, double[] data, SpriteAnimData* old, bool r)
|
||||||
|
{
|
||||||
|
relative = r;
|
||||||
|
this.frame = cast(int)data[i];
|
||||||
|
if(this.frame < 0)
|
||||||
|
{
|
||||||
|
this.frame = -this.frame;
|
||||||
|
interpolation = true;
|
||||||
|
}
|
||||||
|
if(this.frame == 0)
|
||||||
|
{
|
||||||
|
throw new IllegalFunctionCall("BGANIM");
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
switch(target)
|
||||||
|
{
|
||||||
|
case SpriteAnimTarget.XY:
|
||||||
|
this.data.x = cast(int)data[i++];
|
||||||
|
this.data.y = cast(int)data[i++];
|
||||||
|
if (relative)
|
||||||
|
{
|
||||||
|
this.data.x += bg.offsetx;
|
||||||
|
this.data.y += bg.offsety;
|
||||||
|
}
|
||||||
|
this.old.x = old ? old.data.x : bg.offsetx;
|
||||||
|
this.old.y = old ? old.data.y : bg.offsety;
|
||||||
|
break;
|
||||||
|
case SpriteAnimTarget.Z:
|
||||||
|
this.data.z = cast(int)data[i++];
|
||||||
|
if (relative)
|
||||||
|
{
|
||||||
|
this.data.z += bg.offsetz;
|
||||||
|
}
|
||||||
|
this.old.z = old ? old.data.z : bg.offsetz;
|
||||||
|
break;
|
||||||
|
case SpriteAnimTarget.R:
|
||||||
|
this.data.r = data[i++];
|
||||||
|
if (relative)
|
||||||
|
{
|
||||||
|
this.data.r += bg.r;
|
||||||
|
}
|
||||||
|
this.old.r = old ? old.data.r : bg.r;
|
||||||
|
break;
|
||||||
|
case SpriteAnimTarget.S:
|
||||||
|
this.data.scalex = data[i++];
|
||||||
|
this.data.scaley = data[i++];
|
||||||
|
if (relative)
|
||||||
|
{
|
||||||
|
this.data.scalex += bg.scalex;
|
||||||
|
this.data.scaley += bg.scaley;
|
||||||
|
}
|
||||||
|
this.old.scalex = old ? old.data.scalex : bg.scalex;
|
||||||
|
this.old.scaley = old ? old.data.scaley : bg.scaley;
|
||||||
|
break;
|
||||||
|
case SpriteAnimTarget.C:
|
||||||
|
this.data.c = cast(uint)data[i++];
|
||||||
|
break;
|
||||||
|
case SpriteAnimTarget.V:
|
||||||
|
this.data.var = data[i++];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalFunctionCall("BGANIM");
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
struct SpriteDef
|
struct SpriteDef
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user