2006-12-20 12:34
Miliardo
[原创]LRC歌词同步显示插件
嗯……使用方法待补完……
这个应该在ED和插曲的时候很有用处的……
[quote]
0.92更新:
通过tf.lyric_count可以得到现在执行的行数,通过tf.lyric_time可以得到现在执行到的时间,
此外,使用@waittrig name="lyric"可以等待下一句歌词被显示。
通过访问(Array) global.lyric_object.lrctimes和(Array) global.lyric_object.lrcwords可以得到每句歌词的时间和内容。
这些功能可以用于控制某些需要跟随歌曲节奏安排的场景,例如ED画面。[/quote]
下一次技术挑战的目标应该就是坦克大战了……Orz
[code]
;LRC Lyric Displaying Plugin/LRC歌词同步显示插件
;A Part of Project.FairyTale
;Version 0.92-beta(2006-12)
;Author:Miliardo (Whitefang Studio)
;Copyright 2001-2006 Whitefang Studio, All Right Reserved
@if exp="typeof(global.lyric_object) == 'undefined'"
@iscript
class LyricPlugin extends KAGPlugin
{
var fore, back;
var timer;
var window;
var dk,times;
var lrcwords,lrctimes;
var temp,stime;
var l,flg;
var t,mode;
var ctime,lc;
var width,height;
var align="left";
var delay=0;
function LyricPlugin(window)
{
super.KAGPlugin();
fore = new Layer(window, window.fore.base);
back = new Layer(window, window.back.base);
width=window.fore.base.width;
height=window.fore.base.height;
fore.setImagePos(0,0);
fore.setImageSize(width,height);
back.setImagePos(0,0);
fore.setImageSize(width,height);
fore.absolute = back.absolute = 2000000-2;
fore.hitType = back.hitType = htMask;
fore.hitThreshold = back.hitThreshold = 256;
fore.setSizeToImageSize();
fore.fillRect(0, 0, fore.imageWidth, fore.imageHeight, 0);
back.assignImages(fore);
back.setSizeToImageSize();
fore.visible = back.visible = fore.seen = back.seen = true;
fore.font.face = back.font.face = "Arial";
fore.font.bold = back.font.bold = true;
// back.font.mapPrerenderedFont("SH17.tft");
// fore.font.mapPrerenderedFont("SH17.tft");
fore.font.height = back.font.height = 20;
timer = new Timer(onTimer, '');
timer.enabled=false;
this.window = window;
}
function finalize()
{
invalidate fore;
invalidate back;
invalidate timer;
super.finalize(...);
}
function LoadLyric(elm)
{
temp = new Array();
lrctimes = new Array();
lrcwords = new Array();
var tm = new Array();
temp.load(elm.storage,'');
for(var i=0;i<temp.count;i++)
{
tm.split("\[*:*.*\]",temp[i],,true);
for(var j=0;j<3;j++)
{
if(tm[j]!=(void))
{
if(tm[j].charAt(0) == "0")
tm[j] = tm[j].charAt(1);
}
}
lrctimes[i]=((int)tm[0])*60*1000+((int)tm[1])*1000+((int)tm[2]);
lrcwords[i]=tm[3];
}
}
function Play(elm)
{
var tmp;
fore.stopTransition();
l=(int)elm.l;
t=(int)elm.t;
if(elm.face || elm.face!="")
{
fore.font.face = back.font.face = elm.face;
}
if(elm.height || elm.height!="")
{
fore.font.height = back.font.height=elm.height;
}
timer.interval=10;
times=(int)elm.time;
stime=System.getTickCount();
if (elm.align!=(void))
{
align=elm.align;
}
if (elm.delay!=(void))
{
delay=(int)elm.delay;
}
dk=0;
timer.enabled=true;
tmp = back;
back = fore;
fore = tmp;
}
function Stop(elm)
{
timer.enabled=false;
dk=0;
tmp = back;
back = fore;
fore = tmp;
back.fillRect(0,0,width,height,0x00000000);
fore.fillRect(0,0,width,height,0x00000000);
}
function onTimer()
{
ctime=kag.bgm.currentBuffer.position-delay;
var tmp;
var odk=dk;
if(dk>=lrctimes.count||kag.bgm.currentBuffer.paused==true)
{
timer.enabled=false;
dk=0;
tmp = back;
back = fore;
fore = tmp;
back.fillRect(0,0,width,height,0x00000000);
fore.fillRect(0,0,width,height,0x00000000);
}
else
{
while(dk<lrctimes.count&&ctime>lrctimes[dk])
dk++;
if (dk!=odk)
{
// if (mode=="half")
{
tmp = back;
back = fore;
fore = tmp;
back.fillRect(0,0,width,height,0x00000000);
switch(align)
{
case "left":
lc=l;
break;
case "center":
lc=(width-fore.font.getTextWidth(lrcwords[dk-1]))/2+l;
break;
case "right":
lc=(width-fore.font.getTextWidth(lrcwords[dk-1]))-l;
break;
}
back.drawText(lc,t,lrcwords[dk-1],0x00A0A0);
fore.stopTransition();
back.stopTransition();
fore.beginTransition("crossfade",false,back,%[time:times]);
kag.trigger("lyric");
tf.lyric_count=dk;
}
/*else
{
if(flg==0)
{
tmp = back;
back = fore;
fore = tmp;
back.fillRect(0,0,width,height,0x00000000);
fore.stopTransition();
back.stopTransition();
fore.beginTransition("crossfade",false,back,%[time:times/2]);
flg=lrctimes[dk-1];
}
else if (ctime>(flg+times/2))
{
tmp = back;
back = fore;
fore = tmp;
back.drawText(l,t,lrcwords[dk-1],0x00A0A0);
fore.stopTransition();
back.stopTransition();
fore.beginTransition("crossfade",false,back,%[time:times/2]);
flg=0;
}
}*/
}
}
}
function onStore(f, elm)
{
}
function onRestore(f, clear, elm)
{
}
function onStableStateChanged(stable)
{
}
function onMessageHiddenStateChanged(hidden)
{
}
function onCopyLayer(toback)
{
if(toback)
{
back.visible = fore.visible;
back.seen = fore.seen;
}
else
{
fore.visible = back.visible;
fore.seen = back.seen;
}
var tmp;
tmp = back;
back = fore;
fore = tmp;
}
function onExchangeForeBack()
{
var tmp;
tmp = back;
back = fore;
fore = tmp;
}
}
kag.addPlugin(global.lyric_object = new LyricPlugin(kag));
@endscript
@endif
@macro name="loadlrc"
@eval exp="lyric_object.LoadLyric(mp)"
@endmacro
@macro name="playlrc"
@eval exp="lyric_object.Play(mp)"
@endmacro
@macro name="stoplrc"
@eval exp="lyric_object.Stop(mp)"
@endmacro
@return
[/code]
使用例子给一个吧……(这个和MusicName同时使用的……)
样例工程我有时间另外发布……
[code]
@call storage=lyric.ks
@call storage=musicname.ks
*start
@loadlrc storage="Second Flight.lrc"
@bgm storage="Second Flight.mp3"
@musicname l=10 t=10 ch="Second Flight/KOTOKO & 佐藤裕美 ( Produced by I've Sound )" time=4000 align="right"
@playlrc time=500 l=0 t=550 align=center face="FA 丸ゴシックM"
欢迎来到Kirikiri/KAG的世界![l][r]
[/code]