2007年12月21日 星期五

啥SL—【Event—Sensor】

  Sensor指的就是偵測感應,這個Event我最常拿來應用自動門和機器人。

  Sensor有兩種Event:
  意思就是當有感應時會啟動sensor當沒有感應時會啟動no_sensor。
  
  這兩個Event須要利用以下兩種方法來啟動:

  
sensor和no_sensor兩個Event也可以利用llSensorRemove來移除,減少程式負擔。

  而
llSensor與llSensorRepeat的不同處就在於llSensorRepeat多傳一個參數,就是rate,意思就是幾秒Sensor一次。也就是說llSensor只會呼喊一次,llSensorRepeat則會一直按照頻率喊叫。

  現在來解釋一下每個參數的意義:
  • name:偵測感應到的物件或使用者名稱
  • id:偵測感應到的物件或使用者的key值
  • type:限定感應到的是哪種類型的東西,參數如下表格:
    Constant Value Searches for
    AGENT 1 agents (users)
    ACTIVE 2
    physical objects that are moving or objects containing an active[1] script
    PASSIVE 4
    non-scripted or script is inactive[2] AND non-physical or, if physical, not moving
    SCRIPTED 8 objects containing an active[3] scrip

    這裡翻譯一下,AGENT只會感應到使用者;ACTIVE是只會感應到會移動的物件(包括有使用者對一物件編輯時產生了移動也會感應到);PASSIVE是感應不會動的物件;SCRIPTED是只要該物件有程式碼且他又會動,就會被感應,也就是說該物件沒程式碼,就算你編輯時進行上下移動也沒反應。
  • range:是感應的距離,也就是半徑。
  • arc:感應的角度,你可以用PI來表示,PI等於180度,而在這裡就等於是全部範圍,也就是360度,因為他這數字的意思是兩邊180度做感應。
  • rate:剛提到過了,就是更新頻率,以秒為單位。
  而啟動的sensor這個Event內有個參數可以接收,就是上面的total,這和touch一樣,統記數量用的,不過比touch還好用,就是統記瞬間偵測感應到的物件數量(當然要先符合條件,比如是使用者或物件或在幾公尺以內之類的)。 

  現在來放一下Sensor的範例程式:

default
{
state_entry()
{
llSensorRepeat("shortlin Yue", NULL_KEY,AGENT, 10, PI,1);
}

sensor(integer total)
{
llSay(0,(string)total);
}

no_sensor()
{
llSay(0,"no_sensor");
}
}

 
  由於llSensor與llSensorRepeat用法類似,所以只用後者當範例。這個程式碼會每秒鐘感應10m範圍內的使用者(AGENT),而我限制一定要感測到一名叫"shortlin Yue"的使用者,如果有感應到,就會說他感應到的人數,一般來講應該是1,除非有兩個玩家都叫shortlin Yue,不過這應該不可能發生。而如果沒感應到的話,他會說"no_sensor"。

  如果,你想要知道你感應到的玩家是誰?你可以利用Detected相關程式……這之後會特別說明(記得放連結)。

  基本上,這個Seonsor有個缺點,就是他只會以X軸來當基準點,要是你特別想感應某個以Y軸或Z軸為主的角度,你得把物件轉個方向……有點像最近殺戮都市最新幾回有一個人一直拿著會發射死亡光線的人頭攻擊敵人那樣,如圖:
殺戮都市的故事挺特別的

  嗯……所以,你知道我又想到了什麼了嗎?沒錯!就是白眼!
  利用Sensor可以做出火影忍者中日向寧次的白眼效果!

白眼也是有死角的!所以arc的設定千不能設為PI呀!!

啥SL—【Event—Touch】

Touch
當你一直對著一物件點選時就會啟動Touch Event

  Tocuh的Event總共有三個:

  Touch的意思就是玩家用游標點選物件,而不是碰撞物件。然而,這三個Event有什麼差別呢?基本上,如果你習慣對一物件右鍵,利用PieMenu上的Touch點選物件,這三種Event是不會感覺有差的……但是,如果你習慣是像上圖那樣有出現一隻手時點選物件,那就有差了。


這就是所謂的PieMenu

  基本上Touch的動作分成三個步驟:
  1. 點選開始
  2. 點選中
  3. 點選結束
  這看起來很像廢話,但指的就是上面的三個Event。基本上,你只要將這三種Event寫入,當有人Touch時,每個Event都會被啟動,而且會依照touch_start、touch、touch_end這樣的順序來啟動。

  而什麼叫點選中呢?這裡解釋一下,當使用者用滑鼠左鍵點選(有小手圖示出現的狀態)不放,他就會一直啟動
touch,也就是上面提到的點選中的Event。而這個也就是前面第一段提到,如果你習慣用小手一直點和利用PieMenu上的Touch的差別。只要按著不放,就會先啟動touch_startEvent,再不斷地先啟動touchEvent,最後再啟動touch_endEvent。

  至於上面的參數num_detected指的又是什麼呢?

  那是統記目前Touch人數用的,如果同一時間有兩個人在Touch,那num_detected就會是2,不過這要2的機率其實不大……實用性應該也不是很高。

  雖然我是想過一個用法,就是假若遊戲開發者有怪叔叔特戰隊的加農砲需要五個人一起操作的設定,那我想可以利用Touch,只要有同時五個人Touch加農砲按住不放,就會把加濃砲發射出去……



這讓我想起這段很有趣的影片……
來利用Touch Event製作五人戰隊的武器吧!!


  在這邊寫了一個Touch的程式範例:
default
{
touch_start(integer num)
{
llSay(0,"touch_start");
}

touch(integer total_number)
{
llSay(0,"touch");
llSay(0,(string)total_number);
}

touch_end(integer num)
{
llSay(0,"touch_end");
}
}
  簡單來講,就是當有人Touch時,該物件會先說"touch_start",再說"touch"與目前有幾個人碰,而如果這時你是用滑鼠左鍵按住不放,那他就會一直喊著"touch"以及目前有幾個人碰的數字,這時有別的使用者觸碰,這數字就會加1,而當你不碰時,就會喊"touch_end"

啥SL—【製作投影片】

  我在Second Life裡有製作一個專門放圖片展示,類似於投影片的東西,畫面如下:


  這個投影片有以下功用:
  • Next Page(下一頁):當頁碼到了最後一頁,就不顯示(上方的字是用llSetText)。
  • Last Page(上一頁):當頁碼在第一頁時,就不顯示(上方的字是用llSetText)。
  • 使用者對他按Touch,會詢問使用者要看第幾頁,這時 使用者回答正確頁面就可以換頁(上方的圖片是用上傳的,並利用了llSetTexture切換頁面。
  • 顯示目前第幾頁與全部幾頁(Touch me and say a page字樣是用上傳圖片的與方塊上方的字是用llSetText)。
  • 只要使用者把圖片編碼後(1、2、3、4……)全部放入該投影片的inventory(content)以及設定好其程式碼內的all_page參數(全部頁面),reset後程式就可以跑了。如以下圖示:

  在介紹完功用後現在要介紹這個投影片需哪些物件:
  • 中間螢幕(該物件被稱為screen)

  • 箭頭朝左邊的三角形(代表上一頁)(該物件被稱為last page)

  • 箭頭朝右邊的三角形(代表下一頁)(該物件被稱為next page)

  • 顯示目前頁數的物件(該物件被稱為display page)
  

  共四樣,原理如下:

  所有物件都要知道目前到了第幾頁以及所有物件都要知道全部頁面總共有幾頁。因此,我利用了LinkMessage來互通資訊。主螢幕只要在程式reset時把所有頁數傳給其他物件知道就可以了,所以主程式在state_entry要利用LinkMessage傳給其它物件,而他還有三種功用,一就是傳給上一頁和下一頁物件知道目前是第幾頁;二是聽到要改變,就改變自己表面的Texture(材質);三是當使用者Touch,要把使用者有Touch的訊息傳給下面的display page,因為display page掌管當使用者想用說的到哪一頁就到哪一頁的功能。總之就是當主螢幕聽到"change"與要改變的頁面就會切換目前的表面Texture(材質)。

  OK,現在要貼上各程式碼:

  screen:
=====開始screen的程式碼=====



integer side=4;
integer all_page=15;

default
{
state_entry()
{
llMessageLinked(LINK_SET,0, "reset", NULL_KEY);
llSetTexture("1",side);
llMessageLinked(LINK_SET,all_page, "all_page", NULL_KEY);
}

touch_start(integer total_number)
{
//llSay(0,llKey2Name(llDetectedKey(0)));//for test

llMessageLinked(LINK_SET,0, "touch", NULL_KEY);

}//end state default touch_start


link_message(integer sender_num, integer page, string str, key id)
{

if(str=="next_want")
{
llMessageLinked(LINK_SET,(integer)llGetTexture(side), "re_next_want", NULL_KEY);
}

if(str=="last_want")
{
llMessageLinked(LINK_SET,(integer)llGetTexture(side), "re_last_want", NULL_KEY);
}

if(str=="change")
{
llSetTexture((string)page,side);
}

}//end state default link_message

}//end state default



=====結束screen的程式碼=====

  last page:
=====開始last page的程式碼=====

integer all_page;
integer this_page;

default
{
state_entry()
{
llSetText("",<0,1,1>,1.0);
}

touch_start(integer total_number)
{
if(this_page>1)
{
llMessageLinked(LINK_SET,0, "last_want", NULL_KEY);

}

}//end state default touch_start

link_message(integer sender_num, integer num, string str, key id)
{

if(str=="all_page")
{
all_page=num;
this_page=1;
}

if(str=="re_last_want")
{

this_page--;

if(this_page<=1) { llSetText("",<0,1,1>,1.0);
}

llMessageLinked(LINK_ALL_OTHERS,this_page, "change", NULL_KEY);

}

if(str=="change")
{
this_page=num;
if(this_page<=1) { llSetText("",<0,1,1>,1.0);
}

else
{

llSetText("Last Page",<0,1,1>,1.0);

}

}

if(str=="reset")
{
state temp;
}

}//end state default link_message

}//end state default

state temp
{
state_entry()
{
state default;
}
}

=====結束last page的程式碼=====

  next page:
=====開始next page的程式碼=====

integer all_page;
integer this_page;

default
{
state_entry()
{
llSetText("Next Page",<0,1,1>,1.0);
}

touch_start(integer total_number)
{
if(this_page < all_page)
{
llMessageLinked(LINK_SET,0, "next_want", NULL_KEY);
}

}//end state default touch_start

link_message(integer sender_num, integer num, string str, key id)
{
if(str=="all_page")
{
all_page=num;
this_page=1;
}

if(str=="re_next_want")
{

this_page++;

if(this_page>=all_page)
{
llSetText("",<0,1,1>,1.0);
}

llMessageLinked(LINK_ALL_OTHERS,this_page, "change", NULL_KEY);

}

if(str=="change")
{
this_page=num;

if(this_page>=all_page)
{
llSetText("",<0,1,1>,1.0);
}

else
{
llSetText("Next Page",<0,1,1>,1.0);

}

}

if(str=="reset")
{
state temp;
}

}//end state default link_message

}//end state default

state temp
{
state_entry()
{
state default;
}
}

=====結束next page的程式碼=====

  上一頁和下一頁的程式碼原理大致上是當有人按下了該按鈕,他會像主螢幕(screen)要求目前的頁數是第幾頁的,此時再依據目前頁數判斷可否到該頁並更改顯示的Text。

  display page:
=====開始display page的程式碼=====


integer all_page;
integer this_page;
integer handle;
key toucher;

default
{
state_entry()
{
llSetText("",<0,1,1>,1.0);

handle = llListen(0, "", NULL_KEY, "");

llListenControl(handle, FALSE);

}//end state default state_entry()

touch_start(integer total_number)
{
llListenControl(handle, TRUE);

llSay(0,"Say a page that you'd like to go");

}//end state default tiuch_start()

listen(integer ch, string name, key id, string message)
{
if((integer)message>=1 && (integer)message<=all_page) { this_page=(integer)message; llMessageLinked(LINK_ALL_OTHERS,this_page, "change", NULL_KEY); llSetText((string)this_page+"/"+(string)all_page,<0,1,1>,1.0);

llListenControl(handle, FALSE);
}

}//end state default listen()

link_message(integer sender_num, integer num, string str, key id)
{

if(str=="all_page")
{
all_page=num;

this_page=1;

llSetText((string)this_page+"/"+(string)all_page,<0,1,1>,1.0);
}

if(str=="touch")
{
//llSay(0,llKey2Name(id));//for test


llListenControl(handle, TRUE);

toucher=id;

llSay(0,"Say a page that you'd like to go.");
}

if(str=="change")
{
this_page=num;
llSetText((string)this_page+"/"+(string)all_page,<0,1,1>,1.0);
}

if(str=="reset")
{
state temp;
}

}//end state default link_message

}//end state default

state temp
{
state_entry()
{
state default;
}
}

=====結束display page的程式碼=====

  display page這個物件是啟動touch和顯示目前頁面與全部頁面的,所以當有玩家touch時,他要知道。而他這時會使用llListenControl來控制這時是否要聽取資訊,再從接收的資訊判斷該資訊是否為有效頁數。

  以上三個程式碼都有一個temp的state,由於LSL沒辦法直接state default來進行重回,所以只好用一個temp state重回,不過後來我突然想到,其實用llResetScript應該也可以。

啥SL—【訊息傳遞—HTTPRequest】

HTTPRequest
  老實說,個人認為會選擇梅興老師的大部分應該都有一定的網路知識基礎,所以我這個門外漢(哈,我應該是梅興老師底下小組成員裡擔任主力中的例外XD)要介紹這個還挺吃力的……所以個人認為這邊的講解可能會漏洞百出,請敬請指正。

  雖然圖中是用
php來介紹,但是不代表LSL只能用php……不過我也只會用php來和LSL做溝通= ="

  簡單來講,就是利用HTTP這個很普遍的通訊協定來和外部的伺服器做溝通。

  有一點要注意,根據這裡可以知道,在Second Life每一個土地擁有者所能做的Request有限制,雖然不清楚有多少限制就是了,這裡提一下的原因是,上次老師問如果要求學生做SL相關的project要做什麼,我提議可用HTTPRequest相關的應用,泰昇就用了以下的理由說,要是修老師課的有60人,那邊如果有60個物件同時Request的話,應該會被限制,這樣學生作業就交不成了……

  其實使用方法就是利用
llHTTPRequest向伺服器請求,這時伺服器會回傳訊息給Second Life裡一個被稱為http_response的event(如上面的圖解),而這訊息是傳送該頁面的html語法,也就是整個body,這裡指的body不是<body></body>內的東西而是整個html語法可以跑的頁面。

  而這裡有非常好的例子,內有整個php程式碼範例和LSL程式碼範例。
 
  由於不懂的東西太多,所以許多細部就不解釋了,等我哪天開竅了再說吧……那個範例已經說明了如果想要和外部的網站做溝通是如何實作的,只是有沒有其他方法我不清楚,而如果是這個範例程式碼不懂,就再問吧……

  只能說當初知道很多地方要快點趕工,所以就沒有心在這方面了,因為當時還想說還得摸熟php和mysql……沒想到昇哥一下子就包辦了,而且還做得很好……不過我是有一種知道工具怎用就直接上,而不清楚工具是怎做出來的感覺……雖然大多時候是要這樣啦……但他既然都提供出來了,也沒好好了解就的確有點糟糕了Orz……

2007年12月20日 星期四

啥SL—【訊息傳遞—Link Message】

物件被Link起來的模樣

  Link Message可以把訊息傳給本身自己其他的Script與其他Link物件的Script。而圖中黃色為parent藍色皆為child。Link Message的優點是傳的速度快,且不會被竊聽,但缺點就是要把兩物件Link起來,距離不能太遠,我算過大約只能4.346m的距離。不過這不代表所有被link的物件一定要這樣的距離,像以下圖中這樣,只要最近的兩塊物件沒有超過這個距離,就可以Link,雖然還是有限制,但在Second Life裡看到很多房子的製作其實都是被Link起來的。

如果要超過4.346m的距離得要有中間物件

  那Link Message到底是如何使用的?只要使用llMessageLinked,就會啟動指定物件的link_message這個event。

  
llMessageLinked的格式如下:
llMessageLinked(integer linknum, integer num, string str, key id)

  
linknum指的是要傳給訊息的物件的種類代號。代號有以下五種:
Constant Value Description
LINK_ROOT 1 root prim in linked set (but not in a single prim, which is 0)
LINK_SET -1 all prims in object
LINK_ALL_OTHERS -2 all other prims in object besides prim function is in
LINK_ALL_CHILDREN -3 all child prims in object
LINK_THIS -4 prim script is in

  在這邊翻譯一下,LINK_ROOT指的是要傳給parent。LINK_SET是要傳給所有被的物件。LINK_ALL_OTHERS是要傳給除了自己以外的物件。LINK_ALL_CHILDREN是要傳給所有的child。LINK_THIS則是傳給自己本身其他的Script。

  num是要傳給物件屬於數字的訊息。

  str是要傳給物件屬於字串的訊息。

  id是要傳給物件屬於key的訊息。

  llMessageLinked使用範例如下:
  llMessageLinked(LINK_THIS,1,"ohohohoh!!",NULL_KEY);

  這樣的用法就是我要傳給自己物件其他的script數字為1字串為
ohohohoh!!key值為NULL_KEY的訊息。

  而啟動的
link_message這個event要寫入的參數格式是(integer linknum, integer num, string str, key id),使用範例如下:

link_message(
integer linknum, integer num, string str, key id)
{
  if(str=="It is from A Object")
  {
    llSay(0,"A");
  }

  if(str=="
ohohohoh!!" && num==1)
  {
    llSay(0,"You're dead!!!");
  }
}

  意思就是收到字串為
It is from A Object就會說A,收到ohohohoh!!(喔喔喔喔!!)就會說You're dead!!!(你已經死了!!!)。

  
Link Message的整個使用範例如下:

  當A物件和B物件被Link起來的時候,A是parent,B是child,而A除了有A1程式碼外還有A2。A物件的A1程式碼如下:

integer LM_SEND_TO_CHILD=88;//和之前的Chat一樣,給定常數方便管理
integer LM_SEND_TO_OTHER_SCRIPT=2;
default
{
  state_entry()
  {
    llMessageLinked(LINK_ALL_CHILDREN,LM_SEND_TO_CHILD,"I am your father!!!",NULL_KEY);

    llMessageLinked(LINK_THIS,LM_SEND_TO_OTHER_SCRIPT,"I am your brother!!",NULL_KEY);
  }
}

  而A物件的A2程式碼如下:

integer LM_SEND_TO_OTHER_SCRIPT=2;
default
{
  link_message(integer linknum, integer num, string str, key id)
  {
    if(num== LM_SEND_TO_OTHER_SCRIPT)
    {
      llSay(0,"Btother!!!!!");
    }
  }
}

  因為A1有啟動了傳給其他Script的llMessageLinked,所以A2的 link_message event就一定會被啟動,而他if去判斷接收的num是不是我們要的,簡單來講,就是所謂的過濾。然後A物件就會很感傷地說"Btother!!!!!"

  而B物件的程式碼如下:
integer LM_SEND_TO_CHILD=88;
default
{
  link_message(integer linknum, integer num, string str, key id)
  {
    if(num== LM_SEND_TO_CHILD)
    {
      llSay(0,"No!!!!");
    }
  }
}

  因為A物件的A1是傳訊息給其他的child的,所以身為child的B物件就一定啟動link_message這個event然後再經由判斷正確後,B物件會像是路克天行者般地大喊:不!!!!因為A物件說了句"I am your father!!!"

  OK,以上就是利用Link Message傳遞資訊的方式,下一篇將會提到我們如何利用HTTPRequest來和外部溝通。

啥SL—【訊息傳遞—前言與Chat】

前言

  要在Second Life內開發,訊息的傳遞是很重要的。Second Life內的溝通在這個wiki頁面有介紹,但個人認為,最重要的只有四點,分別為:

  其中個人將以上四點又分為內部與外部。Chat、Link Message為內部;HTTPRequest、XML-RPC為外部,由於本人不是很了解XML-RPC,所以這裡暫不介紹,我本人是很希望有人能教教我,不過這也只是希望啦……

Chat

  Chat的方式大致就如同以上圖片所表示的,右邊的方塊用llWhisper或llSay或llShout這三種方式和其他物件溝通(這三者的差別在於距離的不同,分別為10m、20m、100m),而左邊的方塊可以用一個叫llListen的方法去聽取資訊,只要在state_entry內放置這個方法,就可以啟動listen這個event,而這樣的溝通方式不只出現在物件與物件間的溝通,玩家與物件間的溝通也是用Chat的方式。

  首先,先制定好頻道號碼(channel),頻道號碼為0是是和玩家溝通的頻道,而0頻道出現的訊息,就是左下角對話視窗的訊息,以我玩過的線上遊戲來說,就是範圍頻道……而Chat的溝通方式,就是在一定範圍內去聽取某些頻道號碼上的訊息,至於哪些號碼在SL是特定號碼,可以點選上面channel的連結。

  而在listen這個event內可以處理接收到的訊息,分別為(integer ch, string name, key id, string message)這裡的channel、name、id以及msg只是變數名稱,這個可以自訂,前面我標示的是變數型態。

  ch就是channel,意思是取得聽到資訊的來源是從哪個頻道來的,如果
llListen啟動太多種,不清楚是收到的資訊是哪個頻道來的,這裡可以用if條件來做判斷。

  name就是取得聽到訊息的來源名稱,可以是物件名也可以是人名。

  id指的是聽取訊息來源的key值,可以是物件的key也可以是人的key值。

  message就是聽取迅息的內容,是字串型式。

  Chat使用範例如下:
  
  A物件的程式碼:

integer CH_TEST=358;
default
{
state_entry()
{
While(TRUE)
{
llShout(CH_TEST,"Fcuk You!!!");//範圍為100m
}
}
}

  意思就是,A物件在100公尺內無限迴圈內一直大喊著"Fuck You!!!"而且是在第358(上我吧!!Zzz)頻道大喊。(用CH_TEST當358是好習慣,因為以後可以某些頻道想改號碼,直接這樣改CH_TEST的變數即可)

  此時B物件要去聽取資訊,他的程式碼如下:

integer CH_TEST=358;

default
{
state_entry()
{
llListen(CH_TEST,"",NULL_KEY,"");//這裡的NULL_KEY也可以寫""來取代
  llListen(0,"shortlin Yue","","I want to play H game!!!")
}

listen(integer ch,string name,key id,string message)
{
if(ch==CH_TEST)
{
llShout(0,"Don't fuck me!!!");
llShout(0,(string)ch);
llShout(0,name);
llShout(0,id);
llShout(0,message);
}

if(ch==0)
{
llShout(0,"Sorry, I can't help you");
}
}
}

  此時B物件如果在A物件100m範圍以內,他就會啟動了listen,因為他llListen中的參數並沒有給太多的限制,只有啟動了會聽取頻道358的訊息。因此他會大喊"Don't fuck me!!!"接著喊"358",如果A物件叫做A那他還會喊"A"而如果A物件的key值是"595c90dc-feff-5a80-9401-0cc111e8d8bb"那他接下來會喊"595c90dc-feff-5a80-9401-0cc111e8d8bb",最後,他會喊A喊過的訊息"Fcuk You!!!"。

   此時,如果有玩家或物品名稱叫做shortlin Yue,他在頻道0以及B物件100m以內大喊著"I want to play H game!!!",這時也會啟動B物件的listen event,此時B物件就會喊"Sorry, I can't help you"。如果有特別限制聽取某物的訊息,可以利用該物的key值。如何取得該物的key?可以利用llSay(0,(string)llGetKey)這樣的方式在你要知道key值的物件上寫下這個程式碼。

  其實Chat這樣的溝通方式代表著,當一物件啟動了listen這個event,這物件就會接收從四面八方而來的訊息……如此一來是會增加很多負擔的。還有一點要注意,不管是llSay或是llShout,他們都會有一個毛病,就是說出來的順序有可能會delay且不依照順序。

  意思就是,如果你寫了這樣的程式碼:


default
{
state_entry()
{
integer index;
for(index=0;index<10;index++)
{
llSay(0,(string)(index));
}
}
}

  這樣的程式照道理會依照順序出現0、1、2、3、4、5、6、7、8、9,但是由於llSay會delay,他可能會變成0、2、3、1、4、5、6、7、8、9這樣的情形出現。


  大體上來說,如果你要開發的東西是需要一個很大的環境,如RPG或FPS遊戲,Chat的方式還是比較常見,因為Link Message有距離的限制,而這點會在下篇談到。

啥SL—【Demo過後……】

我的工作,還沒有結束……

  大概在今年八月多的時候,梅興老師說我們的專題應該可以不錯,大概是看到了我們組員間都有東西可以報告,且因為我們三個人總是有聯絡,所以才會這麼說吧!?
 
  不過這樣的過程中其實是有一些犧牲的……

  還記得當初要放棄Second Life,原因無它,因為我知道,當我們的專題選擇了Second Life,我會變成主程式、企劃還有美工。

  我雖然確實看好Second Life,也想私底下自己進行觸碰,就算再怎麼不喜歡他的3D與大家總是把他當遊戲看待,我還是認為這是一個好的創作平台,可以讓我的作品,有機會和日本人交流……

  但重點是,我有我自己的人生規劃,擔任三種工作的負擔,會讓我自己的規劃前進不了……甚至毀了我三年前訂下要在大學四年做出一款至少自己認為好玩的遊戲的承諾……

  雖然如此,我還是扛了下來,不知道有人會不會說我後悔了?但我是覺得,我自己的道路,既然已經選擇,就不會後悔,也不能後悔……

  在摸熟LSL的過程中我很清楚,我們的遊戲,是達不到當初我自己的承諾的。這款遊戲,是無法讓我覺得好玩的……頂多就是完成三年前答應小賴要一起做完專題的承諾……但這樣的結果……不是我樂見的……

  所以我自己私底下訂下一個目標,那就是,這個專題,是要回報梅興老師的,雖然幫助不大,但至少,希望能讓下一屆的學弟在學習LSL時,不會像我們一樣一直遇到小小的問題就碰璧……

  所以專題完成了,Demo報告也過了……但我的工作,並沒有結束……

專題其實並沒有老師說得那麼好……

  不管是梅興老師,還是demo當天擔任評審的黃貞英老師,他們都覺得我們專題做得不錯(連國珍老師就不清楚了),但由於我是主程式、企劃兼美工,所以我很清楚,這個專題的企劃是失敗的……雖然程式我自己也在寫文件時發現了一些缺點,但這之後講解如何實作專題再談。美工很失敗不用講,但企劃有很多地方是很糟糕的……因為當初為了急於看程式跑出來的成果,所以企劃我就隨便訂了……

  在企劃中,每個怪物、道具以及技能的都還得再詳細分類,比如這招式延遲幾秒、這技能是屬於何種分類,後者意思就是,假若每隻魔王自己的補血技能並不同,而魔王因為自己的血量很低,想要補血,這時候判斷的不是自己會的招式,而是用技能種類判斷,因為有可能日後還要加個補全滿血的技能,這時候程式碼要再寫,就可以在技能判斷完後,繼續做判斷……

  所以有人能看得出來這企劃哪裡糟糕嗎?是的,就是彈性不夠。

  雖然這地方如果在遊戲業界的規劃可能不能只怪企劃,還得怪程式總監,因為這是這兩樣工作者得互相溝通的地方,程式總監知道哪邊的地方可以讓日後更有彈性,而企劃在寫一堆堆的表格時,也得要考慮這方面的問題……畢竟這是建立在溝通的問題,只是我因為是企劃姦程式,所以就沒這問題了,只是當時企劃想得太隨便了,才導致彈性不夠。喔,其實用姦還挺適合的,在遊戲界的話,企劃堅持就是要做到這樣那樣的時候,對程式而言就是被姦了(喂)。

  雖然說彈性還是有一點啦,就是可以修改魔王血量和會的招式與給予玩家物品= ="

  但總體來說,當十月多的時候,我想要在打魔王前有關卡可以玩,比如說射擊遊戲或獵魔蛛跑出來攻擊……玩家可以消滅他們,但想加的時候,卻發現彈性不夠,無法加入,要加入的話,一堆地方都得修改……

  我還想把Dr.M其實是最終大魔王給寫進去呀……還有那隻會一直顯示廣告,要玩家點的言靈魔王給寫進去呀……(淚)

  老師們問的問題……

  在DEMO問問題中,泰昇擋了很多問題,其實其中有一點他擋得讓我覺得我好像在說謊Orz……就是黃貞英老師在問我們為何不用XML-RPC時我先回答是因為先碰了HTTPRequest,後來才發現XML-RPC的,而一些架構已經出來了,所以才沒有改。但泰昇在後面接著回應其實有碰,但不太會,而且會導致架構變更。他這樣回答可能會變成說其實並不完全是會導致架構變更,很可能是早就知道XML-RPC了,是小組成員懶,所以才選擇了HTTPRequest……但其實我的部分並沒有說謊,我們先發現有HTTPRequest確實是事實。不過最重要的是後來再發現XML-RPC時,因為怎麼摸都摸不懂,加上之前了解了HTTPRequst時,我心裡確實是想了一些怎樣處理資訊的方法……這時如果要再碰我無法掌握的XML-RPC是會挺麻煩的……雖然泰昇是懂XML-RPC,也認為很簡單,但他願意碰一下LSL的時候是十一月的事了……

  嗯……現在想回憶一下老師當時問的問題……其實現在仔細想想,我的回答都回答挺含糊的= ="

  首先是連國珍老師的問題:

  1.Second Life沒有提供一個在裡面建立資料庫的服務,所以才要在外面用是吧?

  沒記錯的話,老師是這樣問的,當時我好像直接回答是的……說實在話的,那時我內心在想,要這樣的東西提供這樣的服務真的是不太可能,他已經做了太多了,還要做這方面的服務,會不會太OVER啦?而且資料庫最好還是建在自己的電腦呀……雖說可以把資料都寫進Second Life裡面,但這樣實在是不太好……因為在Seocnd Life裡面修改資料是很lag的……Orz

  2.如果你們要收費的話,是可以設定的對吧?

  嗯,一樣是那種已經幫我們做好回答的問題,所以我當然會說是的……

  3.在Second Life是否可以做投影片的效果?

  這個一樣,回答是的,像是我剛剛demo中的地下室就有。不過我內心的OS卻想,一張圖要10L$呀~~~雖然我是有想過把好幾張圖合在一起當一張圖,利用切換動畫的方式放……但這樣也很累……而且我試過了,有時候還會出問題……所以目前應該還沒有很適合做投影片的方法,除非你忍痛花那些L幣= =a

  沒記錯的話,連國珍老師都是問他已經幫我們做好回答的那種問題,我們只要回答是的就輕鬆過關……接下來是黃貞英老師的的問題:

  1.當初是怎樣的狀況,所以才不選擇XML-RPC?Seocnd Life應該還有更多像這樣的外部工具可以使用,為何你們不選擇?

  這問題除了上面的回答外,我在外部工具那裡說了一個我自己認為是白癡回答的回答……我明明知道老師指的外部工具是技術層面的,不是什麼編輯器……但有時候腦中一有想法閃過時,就會不自覺地說出口Orz……搞得老師認為我會錯意老師的問題了……因為想到外部工具,我直覺就是想到編輯器Orz……不過當我回答時,我發現不是這個東西,卻想停口也停不下來Orz……是最後泰昇幫我擋住的= ="

  2.你們的遊戲如果推出來,和外面的遊戲有什麼不同?

  老實說,之前在想老師會問的問題時我就想過了……但我還是回答的不好Orz……

  我回答我們的系統有參考洛克人,洛克人也是要選擇關卡,然後和打完每個關卡的魔王也都有相剋的設定……

  所以我們要推出,應該沒有什麼特點……(這句話我沒說,但我前面說成那樣,其實想要表達的是這句話)

  不過,前面的理由只要是讓內行人都知道……我們的遊戲這和洛克人還是差很多呀Orz……洛克人是ACT,我們的是FPS……像這樣要把洛克人這樣的設定和FPS結合應該可以算是創新……而因為一點都不好玩= ="所以我一直不敢自誇……

  3.為什麼會選擇Second Life,是自己選的還是指導老師指引的?

  這問題梅興老師幫我們擋了,他說是他逼的XD~主要是因為投影片我有放……但我那時候好像講太快了= ="不知道大家有沒有看到0 0"

  4.你們有打算讓學弟繼續你們的專題嗎?

  就我上面的說法,是有,所以我回答我們文件之所以那麼厚,都是程式碼……而每個程式碼都有流程圖,用意就在這裡。

  但事實上,我很清楚願意會去看人家程式碼的人並不多,其實我只是在做少量的幫助而已,因此我在我的blog寫Second Life教學,也是希望能對學弟有所幫助。而這也是我為什麼堅持要把未來很多應用的展望放在後面講,而不把重點放在我們的遊戲上,因為我認為這才是我們的重點,吸引更多的人觸碰Second Life,去做更多虛擬世界幫助現實世界的應用……

  不過感覺這樣回答怪怪的,所以我就只回答是有這樣的想法……

  5.你們的ER diagram是先畫再寫還是先寫再畫?

  這是泰昇回答的,他是說是先建好資料庫後再畫的……嗯,這地方就沒我插手的餘地了。

  黃貞英老師問的好像就是這樣了吧……

  最後我實在是沒有想到梅興老師竟然也會問= =",以下是梅興老師的問題:

  1.因為老師有給我800L幣玩其他人做出來的遊戲,所以老師問,他收800L$,那如果是你們的遊戲,你們會收多少?

  沒想到老師竟然會暴這個料Orz……不過我回答也回答很含糊……我說那款遊戲美工做得很好,坐上架駛時也很擬真,而我們的就……

  我大概就是很模糊的回答,其實我想要說的是,應該連收費都無法收費,因為外觀是一個很重要的商業模式,我們連外觀都沒達到,怎可以向外面收費……而且那邊是老師的地呀……當然重點是,我們的一點都不好玩……收費會很丟臉的= ="

  2.除了遊戲的應用,可以提出Second Life還可以有哪些應用?

  其實這問題我很想打算在之後寫一篇文章提一提,雖然之前確實是想過一些,但要我立刻回答,我腦袋瓜是回答不出來什麼的,只能說YouTube的影片有一個廣告的系統,就是輸入我想出去玩,就會有一個出去玩的廣告,輸入我想賺錢,就會出現這樣的相關廣告。這系統有圖片也有影片……

  要我現在想嘛,其實是有幾點可以去想的……不過用LSL做出的可行性還得再去觀望……有必要的話可能還得利用libsecondlife。

  1.blog的搭配,知道這人是否有在Second Life上線。
  2.Second Life照出的圖片上傳到flickr之類的相簿……
  3.機器人的導遊,記錄Second Life有哪些好玩的地方,只要設定好功能,他就會search這地方有哪些地方可以逛……帶玩家走過去並一一介紹……或請玩家teleport……這時或許可以搭配他網頁的api,每個人都可以在每個地方有特別標記並寫下記錄,有一點像趴哥做的虛擬版,趴哥做的是可以在google map記錄,比如哪邊發生了什麼樣的新聞,你可以在那些地方放上相關文章與圖片……而我剛講的是在Second Life版……
 
  其實應該還有很多應用,目前就想到這裡吧……

  這樣寫好像是我回答的問題比較多……我想我一定是忘了泰昇怎回答了,沒辦法,自己的事本來就是比較容易記得的 ̄▽ ̄

最後……

  雖然Demo感覺我好像說太快,但有看到有人笑了,這樣一來,我的目的也達到了(淚)。

  其實會不聽老師與助教建議—「把Second Life未來展望放在前面,不要讓我們專題看起來很弱」的主要原因是如果不把未來無限可能的展望放在最後說,是不符合我創作風格的,就算再爛,也要給人們感覺到希望,進而吸引更多的人來碰Second Life,這樣也是我的目的之一。

  OK,最後就是把最後我所會的教學完成,然後好好地把painter搞一搞……
  
  總之Demo過後,還有更多的工作……