1
0

Implement BGANIM?

This commit is contained in:
otya128
2017-07-22 14:34:07 +09:00
parent c3801f1477
commit c235687096
3 changed files with 321 additions and 0 deletions

View File

@@ -1,6 +1,7 @@
module otya.smilebasic.bg;
import otya.smilebasic.petitcomputer;
import otya.smilebasic.error;
import otya.smilebasic.sprite;
import derelict.sdl2.sdl;
import derelict.opengl3.gl;
@@ -46,9 +47,11 @@ class BG
r = 0;
show = true;
bgcolor = 0xffffffff;
initBGAnimationTable();
}
void render(int display, float disw, float dish)
{
animation();
if (!show)
return;
float aspect = disw / dish;
@@ -292,4 +295,207 @@ class BG
{
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;
}
}
}
}
}
}

View File

@@ -1790,6 +1790,54 @@ class BuiltinFunction
if(args[1].isNumber)
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)
{
if (!p.sprite.isValidDef(id))

View File

@@ -160,6 +160,73 @@ struct SpriteAnimData
}
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
{