1
0

SPANIMを実装.

This commit is contained in:
otya128
2015-08-20 22:58:35 +09:00
parent 8e0a4e0ae4
commit 8c38a2306d
4 changed files with 290 additions and 19 deletions

View File

@@ -10,6 +10,7 @@ import std.range;
import otya.smilebasic.error; import otya.smilebasic.error;
import otya.smilebasic.type; import otya.smilebasic.type;
import otya.smilebasic.petitcomputer; import otya.smilebasic.petitcomputer;
import otya.smilebasic.sprite;
//プチコンの引数省略は特殊なので //プチコンの引数省略は特殊なので
//LOCATE ,,0のように省略できる //LOCATE ,,0のように省略できる
struct DefaultValue(T, bool skippable = true) struct DefaultValue(T, bool skippable = true)
@@ -241,6 +242,18 @@ class BuiltinFunction
static void SPANIM(PetitComputer p, Value[] va_args) static void SPANIM(PetitComputer p, Value[] va_args)
{ {
writeln("NOTIMPL:SPANIM"); writeln("NOTIMPL:SPANIM");
auto args = retro(va_args);
int no = args[0].castInteger;
double[] animdata = new double[args.length - 2];
int i;
foreach(a; args[2..$])
{
animdata[i++] = a.castDouble;
}
if(args[1].isString)
p.sprite.spanim(no, args[1].castString, animdata);
if(args[1].isNumber)
p.sprite.spanim(no, cast(SpriteAnimTarget)(args[1].castInteger), animdata);
} }
static void BGMSTOP(PetitComputer p) static void BGMSTOP(PetitComputer p)
{ {

View File

@@ -512,7 +512,7 @@ class PetitComputer
buttonTable[SDL_SCANCODE_LEFT] = Button.LEFT; buttonTable[SDL_SCANCODE_LEFT] = Button.LEFT;
buttonTable[SDL_SCANCODE_RIGHT] = Button.RIGHT; buttonTable[SDL_SCANCODE_RIGHT] = Button.RIGHT;
buttonTable[SDL_SCANCODE_SPACE] = Button.A; buttonTable[SDL_SCANCODE_SPACE] = Button.A;
bool renderprofile;// = true; bool renderprofile = true;
try try
{ {
version(Windows) version(Windows)
@@ -555,8 +555,8 @@ class PetitComputer
glAlphaFunc(GL_GEQUAL, 0.5); glAlphaFunc(GL_GEQUAL, 0.5);
glEnable(GL_ALPHA_TEST); glEnable(GL_ALPHA_TEST);
draw = new otya.smilebasic.draw.Draw(this); draw = new otya.smilebasic.draw.Draw(this);
sprite.spset(0, 0); // sprite.spset(0, 0);
sprite.spofs(0, 9, 8); // sprite.spofs(0, 9, 8);
while(true) while(true)
{ {
auto profile = SDL_GetTicks(); auto profile = SDL_GetTicks();
@@ -575,6 +575,16 @@ class PetitComputer
renderGraphicPage(); renderGraphicPage();
renderConsoleGL(); renderConsoleGL();
sprite.render(); sprite.render();
/* if(this.sprite.sprites[0].define)
if(this.sprite.sprites[0].u == 0)
{
writeln("WHATW");
}
else
{
writeln(this.sprite.sprites[0].u);
}*/
SDL_GL_SwapWindow(window); SDL_GL_SwapWindow(window);
auto renderticks = (SDL_GetTicks() - profile); auto renderticks = (SDL_GetTicks() - profile);
if(renderprofile) writeln(renderticks); if(renderprofile) writeln(renderticks);
@@ -658,9 +668,9 @@ class PetitComputer
consolem = new Mutex(); consolem = new Mutex();
keybuffermutex = new Mutex(); keybuffermutex = new Mutex();
grpmutex = new Mutex(); grpmutex = new Mutex();
sprite = new Sprite(this);
core.thread.Thread thread = new core.thread.Thread(&render); core.thread.Thread thread = new core.thread.Thread(&render);
thread.start(); thread.start();
sprite = new Sprite(this);
auto startTicks = SDL_GetTicks(); auto startTicks = SDL_GetTicks();
//とりあえず //とりあえず
auto parser = new Parser( auto parser = new Parser(
@@ -750,6 +760,15 @@ class PetitComputer
} }
} }
elapse = SDL_GetTicks() - startTicks; elapse = SDL_GetTicks() - startTicks;
/*if(this.sprite.sprites[0].define)
if(this.sprite.sprites[0].u == 0)
{
writeln("WHATW");
}
else
{
writeln(this.sprite.sprites[0].u);
}*/
} while(elapse <= 1000 / 60); } while(elapse <= 1000 / 60);
vsyncCount++; vsyncCount++;
if(vsyncFrame <= vsyncCount) vsyncFrame = 0; if(vsyncFrame <= vsyncCount) vsyncFrame = 0;

View File

@@ -1,5 +1,6 @@
module otya.smilebasic.sprite; module otya.smilebasic.sprite;
import otya.smilebasic.petitcomputer; import otya.smilebasic.petitcomputer;
import otya.smilebasic.error;
import derelict.sdl2.sdl; import derelict.sdl2.sdl;
import derelict.opengl3.gl; import derelict.opengl3.gl;
enum SpriteAttr enum SpriteAttr
@@ -9,17 +10,129 @@ enum SpriteAttr
rotate180 = 4, rotate180 = 4,
rotate270 = 8, rotate270 = 8,
} }
enum SpriteAnimTarget
{
XY = 0,
Z,
UV,
I,
R,
S,
C,
V,
relative = 8,
}
struct SpriteAnimState
{
union
{
struct
{
double x, y;
}
struct
{
double z;
}
struct
{
int u, v;
}
struct
{
int i;
}
struct
{
double r;
}
struct
{
double s;
}
struct
{
uint c;
}
struct
{
double var;
}
}
}
struct SpriteAnimData
{
bool relative;//相対座標として扱うか
int frame;//何フレームごとに動かすか
int elapse;//何フレーム目か
//int repeatcount;//何回目のループか
//int loop;//何回ループするか(0で無限ループ)
bool interpolation;//線形補完するかどうか
SpriteAnimState data;
SpriteAnimState old;
int load(ref SpriteData sprite, SpriteAnimTarget target, double[] data)
{
int i = 0;
this.frame = -cast(int)data[i];
i++;
switch(target)
{
case SpriteAnimTarget.XY:
this.data.x = cast(int)data[i++];
this.data.y = cast(int)data[i++];
this.old.x = sprite.x;
this.old.y = sprite.y;
break;
case SpriteAnimTarget.Z:
this.data.z = cast(int)data[i++];
this.old.z = sprite.z;
break;
case SpriteAnimTarget.UV:
this.data.u = cast(int)data[i++];
this.data.v = cast(int)data[i++];
this.old.u = sprite.u;
this.old.v = sprite.v;
break;
case SpriteAnimTarget.I:
this.data.i = cast(int)data[i++];
this.old.i = sprite.defno;
break;
case SpriteAnimTarget.R:
this.data.r = data[i++];
break;
case SpriteAnimTarget.S:
this.data.s = data[i++];
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();
}
return i;
}
}
struct SpriteData struct SpriteData
{ {
bool isAnim;
int id; int id;
int defno; int defno;
double x, y; double x, y;
int homex, homey;
double z;/*!*/ double z;/*!*/
int u, v, w, h;//個々で保持してるみたい,SPSETをして後でSPDEFをしても変化しない int u, v, w, h;//個々で保持してるみたい,SPSETをして後でSPDEFをしても変化しない
uint color; uint color;
double[8] var; double[8] var;
SpriteAttr attr; SpriteAttr attr;
bool define;//定義されてればtrue bool define;//定義されてればtrue
this(bool flag)
{
define = false;
}
this(int id, int defno) this(int id, int defno)
{ {
x = 0; x = 0;
@@ -28,6 +141,7 @@ struct SpriteData
this.defno = defno; this.defno = defno;
this.color = -1; this.color = -1;
this.attr = SpriteAttr.show; this.attr = SpriteAttr.show;
this.define = true;
} }
this(int id, int u, int v, int w, int h) this(int id, int u, int v, int w, int h)
{ {
@@ -40,25 +154,103 @@ struct SpriteData
this.h = h; this.h = h;
this.color = -1; this.color = -1;
this.attr = SpriteAttr.show; this.attr = SpriteAttr.show;
this.define = true;
} }
this(int id, ref SpriteDef spdef)
{
x = 0;
y = 0;
this.id = id;
this.u = spdef.u;
this.v = spdef.v;
this.w = spdef.w;
this.h = spdef.h;
this.color = -1;
this.attr = spdef.a;
this.homex = spdef.hx;
this.homey = spdef.hy;
this.define = true;
}
SpriteAnimData[][SpriteAnimTarget.V] anim;
void setAnimation(SpriteAnimData[] anim, SpriteAnimTarget sat)
{
this.anim[sat] = anim;
isAnim = true;
}
}
struct SpriteDef
{
int u, v, w, h, hx, hy;
SpriteAttr a;
} }
class Sprite class Sprite
{ {
SDL_Rect[2048] UVTable; SpriteDef[] SPDEFTable;
SpriteData[512] sprites; SpriteData[] sprites;
PetitComputer petitcom; PetitComputer petitcom;
void initUVTable() void initUVTable()
{ {
UVTable[] = SDL_Rect(0, 0, 16, 16);//Ichigo SPDEFTable = new SpriteDef[4096];
//UVTable[] = SDL_Rect(0, 0, 16, 16);//Ichigo
for(int i = 0; i < 4096; i++)
{
SPDEFTable[i] = SpriteDef(0, 0, 16, 16, 0, 0, SpriteAttr.show);
}
SPDEFTable[4095] = SpriteDef(192, 480, 96, 32, 48, 16, SpriteAttr.show);
//UVTable[] = SDL_Rect(192, 480, 96, 32);
} }
this(PetitComputer petitcom) this(PetitComputer petitcom)
{ {
sprites = new SpriteData[512];
sprites[] = SpriteData(false);
initUVTable; initUVTable;
this.petitcom = petitcom; this.petitcom = petitcom;
} }
void animation() void animation(ref SpriteData sprite)
{ {
foreach(i, ref d; sprite.anim)
{
if(!d) continue;//未定義
SpriteAnimTarget target = cast(SpriteAnimTarget)i;
int index = 0;
SpriteAnimData* data = &d[index];
data.elapse = data.elapse + 1;
auto frame = data.elapse;
switch(target)
{
case SpriteAnimTarget.XY:
sprite.x = data.old.x + ((data.data.x - data.old.x) / data.frame) * frame;
sprite.y = data.old.y + ((data.data.y - data.old.y) / data.frame) * frame;
break;
case SpriteAnimTarget.Z:
sprite.z = data.old.z + ((data.data.z - data.old.z) / data.frame) * frame;
break;
case SpriteAnimTarget.UV:
sprite.u = data.old.u + ((data.data.u - data.old.u) / data.frame) * frame;
sprite.v = data.old.v + ((data.data.v - data.old.v) / data.frame) * frame;
break;
case SpriteAnimTarget.I:
sprite.id = data.old.i + ((data.data.i - data.old.i) / data.frame) * frame;
break;
case SpriteAnimTarget.R:
break;
case SpriteAnimTarget.S:
break;
case SpriteAnimTarget.C:
break;
case SpriteAnimTarget.V:
break;
default:
break;
}
if(frame >= data.frame)
{
sprite.anim[i] = null;
continue;
}
}
} }
bool lll;
void render() void render()
{ {
auto texture = petitcom.GRP[petitcom.sppage].glTexture; auto texture = petitcom.GRP[petitcom.sppage].glTexture;
@@ -66,21 +258,28 @@ class Sprite
glBindTexture(GL_TEXTURE_2D, texture); glBindTexture(GL_TEXTURE_2D, texture);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS); glBegin(GL_QUADS);
foreach(sprite; sprites) foreach(ref sprite; sprites)
{ {
//定義されてたら動かす
if(sprite.define)
{
animation(sprite);
}
if(sprite.attr & SpriteAttr.show) if(sprite.attr & SpriteAttr.show)
{ {
glColor3f(1.0, 1.0, 1.0); glColor3f(1.0, 1.0, 1.0);
int x2 = cast(int)sprite.x + sprite.w;//-1 int x = cast(int)sprite.x - sprite.homex;
int y2 = cast(int)sprite.y + sprite.h; int y = cast(int)sprite.y - sprite.homey;
int x2 = cast(int)x + sprite.w;//-1
int y2 = cast(int)y + sprite.h;
int u2 = cast(int)sprite.u + sprite.w;//-1 int u2 = cast(int)sprite.u + sprite.w;//-1
int v2 = cast(int)sprite.v + sprite.h; int v2 = cast(int)sprite.v + sprite.h;
glTexCoord2f(sprite.u / 512f - 1 , v2 / 512f - 1); glTexCoord2f(sprite.u / 512f - 1 , v2 / 512f - 1);
glVertex3f(sprite.x / 200f - 1, 1 - y2 / 120f, z); glVertex3f(x / 200f - 1, 1 - y2 / 120f, z);
glTexCoord2f(sprite.u / 512f - 1, sprite.v / 512f - 1); glTexCoord2f(sprite.u / 512f - 1, sprite.v / 512f - 1);
glVertex3f(sprite.x / 200f - 1, 1 - sprite.y / 120f, z); glVertex3f(x / 200f - 1, 1 - y / 120f, z);
glTexCoord2f(u2 / 512f - 1, sprite.v / 512f - 1); glTexCoord2f(u2 / 512f - 1, sprite.v / 512f - 1);
glVertex3f(x2 / 200f - 1, 1 - sprite.y / 120f, z); glVertex3f(x2 / 200f - 1, 1 - y / 120f, z);
glTexCoord2f(u2 / 512f - 1, v2 / 512f - 1); glTexCoord2f(u2 / 512f - 1, v2 / 512f - 1);
glVertex3f(x2 / 200f - 1, 1 - y2 / 120f, z); glVertex3f(x2 / 200f - 1, 1 - y2 / 120f, z);
} }
@@ -89,11 +288,7 @@ class Sprite
} }
void spset(int id, int defno) void spset(int id, int defno)
{ {
if(defno >= 2048 && defno < 4096) sprites[id] = SpriteData(id, SPDEFTable[defno]);
{
defno -= 2048;
}
sprites[id] = SpriteData(id, UVTable[defno].x, UVTable[defno].y, UVTable[defno].w, UVTable[defno].h);
} }
void spofs(int id, int x, int y) void spofs(int id, int x, int y)
{ {
@@ -108,4 +303,44 @@ class Sprite
{ {
sprites[id].attr |= SpriteAttr.show; sprites[id].attr |= SpriteAttr.show;
} }
void spanim(int id, wstring target, double[] data)
{
bool relative = false;
if(target[$..$] == "+")
{
target = target[0..$-1];
relative = true;
}
spanim(id, spriteAnimTarget[target] | SpriteAnimTarget.relative, data);
}
static SpriteAnimTarget[wstring] spriteAnimTarget;
static this()
{
spriteAnimTarget = [
"XY": SpriteAnimTarget.XY,
"Z": SpriteAnimTarget.Z,
"UV": SpriteAnimTarget.UV,
"I": SpriteAnimTarget.I,
"R": SpriteAnimTarget.R,
"S": SpriteAnimTarget.S,
"C": SpriteAnimTarget.C,
"V": SpriteAnimTarget.V,
];
}
void spanim(int id, SpriteAnimTarget target, double[] data)
{
bool relative;
if(SpriteAnimTarget.relative & target)
{
relative = true;
target ^= SpriteAnimTarget.relative;
}
int animcount = data.length / ((target == SpriteAnimTarget.XY || target == SpriteAnimTarget.UV) ? 3 : 2);
SpriteAnimData[] animdata = new SpriteAnimData[animcount];
for(int i = 0; i < data.length;)
{
i = animdata[i].load(sprites[id], target, data);
}
sprites[id].setAnimation(animdata, target);
}
} }

View File

@@ -82,6 +82,10 @@ struct Value
{ {
return this.type == ValueType.Integer || this.type == ValueType.Double; return this.type == ValueType.Integer || this.type == ValueType.Double;
} }
bool isString()
{
return this.type == ValueType.String;
}
int castInteger() int castInteger()
{ {
return this.type == ValueType.Integer ? this.integerValue : (this.type == ValueType.Double ? cast(int)this.doubleValue : 0); return this.type == ValueType.Integer ? this.integerValue : (this.type == ValueType.Double ? cast(int)this.doubleValue : 0);