diff --git a/SMILEBASIC/builtinfunctions.d b/SMILEBASIC/builtinfunctions.d index 56a249d..4dcfc69 100644 --- a/SMILEBASIC/builtinfunctions.d +++ b/SMILEBASIC/builtinfunctions.d @@ -10,6 +10,7 @@ import std.range; import otya.smilebasic.error; import otya.smilebasic.type; import otya.smilebasic.petitcomputer; +import otya.smilebasic.sprite; //プチコンの引数省略は特殊なので //LOCATE ,,0のように省略できる struct DefaultValue(T, bool skippable = true) @@ -241,6 +242,18 @@ class BuiltinFunction static void SPANIM(PetitComputer p, Value[] va_args) { 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) { diff --git a/SMILEBASIC/petitcomputer.d b/SMILEBASIC/petitcomputer.d index f3125d9..2cfa8c7 100644 --- a/SMILEBASIC/petitcomputer.d +++ b/SMILEBASIC/petitcomputer.d @@ -512,7 +512,7 @@ class PetitComputer buttonTable[SDL_SCANCODE_LEFT] = Button.LEFT; buttonTable[SDL_SCANCODE_RIGHT] = Button.RIGHT; buttonTable[SDL_SCANCODE_SPACE] = Button.A; - bool renderprofile;// = true; + bool renderprofile = true; try { version(Windows) @@ -555,8 +555,8 @@ class PetitComputer glAlphaFunc(GL_GEQUAL, 0.5); glEnable(GL_ALPHA_TEST); draw = new otya.smilebasic.draw.Draw(this); - sprite.spset(0, 0); - sprite.spofs(0, 9, 8); + // sprite.spset(0, 0); + // sprite.spofs(0, 9, 8); while(true) { auto profile = SDL_GetTicks(); @@ -575,6 +575,16 @@ class PetitComputer renderGraphicPage(); renderConsoleGL(); 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); auto renderticks = (SDL_GetTicks() - profile); if(renderprofile) writeln(renderticks); @@ -658,9 +668,9 @@ class PetitComputer consolem = new Mutex(); keybuffermutex = new Mutex(); grpmutex = new Mutex(); - sprite = new Sprite(this); core.thread.Thread thread = new core.thread.Thread(&render); thread.start(); + sprite = new Sprite(this); auto startTicks = SDL_GetTicks(); //とりあえず auto parser = new Parser( @@ -750,6 +760,15 @@ class PetitComputer } } 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); vsyncCount++; if(vsyncFrame <= vsyncCount) vsyncFrame = 0; diff --git a/SMILEBASIC/sprite.d b/SMILEBASIC/sprite.d index 8f90d71..2c6357d 100644 --- a/SMILEBASIC/sprite.d +++ b/SMILEBASIC/sprite.d @@ -1,5 +1,6 @@ module otya.smilebasic.sprite; import otya.smilebasic.petitcomputer; +import otya.smilebasic.error; import derelict.sdl2.sdl; import derelict.opengl3.gl; enum SpriteAttr @@ -9,17 +10,129 @@ enum SpriteAttr rotate180 = 4, 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 { + bool isAnim; int id; int defno; double x, y; + int homex, homey; double z;/*!*/ int u, v, w, h;//個々で保持してるみたい,SPSETをして後でSPDEFをしても変化しない uint color; double[8] var; SpriteAttr attr; bool define;//定義されてればtrue + this(bool flag) + { + define = false; + } this(int id, int defno) { x = 0; @@ -28,6 +141,7 @@ struct SpriteData this.defno = defno; this.color = -1; this.attr = SpriteAttr.show; + this.define = true; } this(int id, int u, int v, int w, int h) { @@ -40,25 +154,103 @@ struct SpriteData this.h = h; this.color = -1; 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 { - SDL_Rect[2048] UVTable; - SpriteData[512] sprites; + SpriteDef[] SPDEFTable; + SpriteData[] sprites; PetitComputer petitcom; 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) { + sprites = new SpriteData[512]; + sprites[] = SpriteData(false); initUVTable; 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() { auto texture = petitcom.GRP[petitcom.sppage].glTexture; @@ -66,21 +258,28 @@ class Sprite glBindTexture(GL_TEXTURE_2D, texture); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); - foreach(sprite; sprites) + foreach(ref sprite; sprites) { + //定義されてたら動かす + if(sprite.define) + { + animation(sprite); + } if(sprite.attr & SpriteAttr.show) { glColor3f(1.0, 1.0, 1.0); - int x2 = cast(int)sprite.x + sprite.w;//-1 - int y2 = cast(int)sprite.y + sprite.h; + int x = cast(int)sprite.x - sprite.homex; + 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 v2 = cast(int)sprite.v + sprite.h; 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); - 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); - glVertex3f(x2 / 200f - 1, 1 - sprite.y / 120f, z); + glVertex3f(x2 / 200f - 1, 1 - y / 120f, z); glTexCoord2f(u2 / 512f - 1, v2 / 512f - 1); glVertex3f(x2 / 200f - 1, 1 - y2 / 120f, z); } @@ -89,11 +288,7 @@ class Sprite } void spset(int id, int defno) { - if(defno >= 2048 && defno < 4096) - { - defno -= 2048; - } - sprites[id] = SpriteData(id, UVTable[defno].x, UVTable[defno].y, UVTable[defno].w, UVTable[defno].h); + sprites[id] = SpriteData(id, SPDEFTable[defno]); } void spofs(int id, int x, int y) { @@ -108,4 +303,44 @@ class Sprite { 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); + } } diff --git a/SMILEBASIC/type.d b/SMILEBASIC/type.d index 25c1e1c..2e50372 100644 --- a/SMILEBASIC/type.d +++ b/SMILEBASIC/type.d @@ -82,6 +82,10 @@ struct Value { return this.type == ValueType.Integer || this.type == ValueType.Double; } + bool isString() + { + return this.type == ValueType.String; + } int castInteger() { return this.type == ValueType.Integer ? this.integerValue : (this.type == ValueType.Double ? cast(int)this.doubleValue : 0);