2016年2月24日 星期三

[RPG] 對話字幕 talk animate with setTimeout

身為 RPG...最重要的就是對話啦~~
然而,對話的表現方式是 一字一字的跑...(拖台錢真好用)
但是~ HTML 主要的用途是 閱讀,一開始的理念就不一樣~

所以想了有點久~就以基本的方式組合 jquery.append 跟 setTimeout 來模擬~

來貼一下當初最早早開發的原型(在 404 page 裡)
http://www.realmofprogrammersgamble.website/404.html
http://www.realmofprogrammersgamble.website/js/anit.js
 很粗糙的手法,直接一個字一個setTimeout append 出來,但因為字數不多且又單純,好像就感覺還好~
function captionEffect(tid, str, isfadeout, dely) {
    anitid = tid;
    anitword = str;
    anitidx = 0;
    if (dely && parseInt(dely) > 10) {
        anitdelay = dely;
    }
    $('#'+anitid).html('');
    if (anitword && anitword.length > 0) {
        for (var i = 0 ; i < anitword.length ; i++) {
            setTimeout(anitappend, anitdelay*i );
        }
        if (isfadeout) {
            setTimeout("anitfadeOut('"+tid+"')", parseInt(anitdelay*anitword.length+1000) );
        }
    }
}
  
function anitappend() {
    $('#'+anitid).append(anitword[anitidx]);
    anitidx++;
}

但是~等到要做完整對話時,問題就開始頭大了Orz...
而且上面的作法其實是有問題的,一是 html 的 setTimeout 很....有問題!~有時候他自己本身執行會lag(網路load圖,或開很多網頁,跑到一半開別的網頁又回來點)...二是同時開 N 個 setTimeout 在那邊等,根本不安心Orz...
只能說 JS 本身沒有 Thread 的概念,很難處理Q_Q...

所以後來又做了一個改良版~ 基礎還是 jquery append 跟 setTimeout...
但只是 在 setTimeout 裡 才跑下一個 setTimeout (有點像遞迴自己call自己到完)... --> 同時間只有一個 setTimeout 在跑~
其一開始的原型大概是 像這樣子@@a (為了做一堆例外和設定,opt 加到整隻都快不認識了XDXD)

function tanittalk(did, w, tw, ms, opt) {
  if (ms && parseInt(ms) > 0) {
    ms = parseInt(ms);
  }  else  {
    ms = 60;
  }
 
  if (tw && tw.length > w.length) {
    var add = tw.substring(w.length, w.length+1);
    var nms = ms;
    if (opt && opt[w.length]) {
     
    }  else  {
      w += add; 
    }
    $('#'+did).append(add);
   
    if (tw.length > w.length) {
      setTimeout("tanittalk('"+did+"', '"+w+"', '"+tw+"', "+ms+")" ,nms);
    }
  }
}

不過就是用 append 時要注意的是~ 當要換行 <br> 時,是要一次 append('<br>'),如果呆呆的一個字一個字的就會 GG...當然同理,有要用到 tag,內碼 等各種 html 格式內容都是這樣~
還有一些跳脫字元,或是 「'」、「"」都是要再例外處理的部份QQ~

補充一下, setTimeout 這東西阿,在正常看的時後是不會出事的,
會出事的情況大多是,當 page  lose focus 時(另開視窗,或是看其他page)
browser 會自動暫停運作,但是 delay的時間並沒有被暫停。
所以~當去別地方看完回來後,會突然發現原本頁面的 setTimeout 一次全跑出來了XD...
因為去別的地方逛完回來,那些delay全都結束了,就不會照心中所想的順序跑出來...

所以若是很要求順序的顯示,就要注意了~

沒有留言: