這次範例演練的是:
填寫人名,按下開始進行劇情。
當劇情中有選擇時,
依照不同的選擇做安排。
其實是心血來潮,
所以將教學6後面的跳過,先教7的~
總之,
第7章教學的目標就是將我的遊戲"獨二無三"從C#遊戲轉變成網頁版~(儲存功能則交由cookie)
有空也會改成flash版。
為了循序漸進的教學,
這次範例演練的是:
填寫人名,按下開始進行劇情。
當劇情中有選擇時,
依照不同的選擇做安排。
先上網址:
http://www.googledrive.com/host/0B7hg_8WvMyfJV0JFM3RHRGNvMGM
強烈建議將範例下載下來,在你電腦跑跑看(也比較流暢)。
也可以注意到這次將圖檔都放在images資料夾中,
比較好做管理。
因為有上註解了,
就直接貼程式碼再進行補充:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Lesson 7</title>
</head>
<style type="text/css">
.bg{
position: absolute;
left:0px;
top:0px;
width: 454px;
height: 340px;
z-index: -1000;
}
#scene_init{
background:url(images/intro.jpg);
}
#lbName{
position: absolute;
left:70px;
top:120px;
font-size: 24px;
font-weight:bold;
}
#txName{
position: absolute;
left:160px;
top:120px;
font-size: 24px;
width:200px;
}
#btnStart{
position: absolute;
left:100px;
top:180px;
width: 250px;
height: 40px;
font-size:21px;
cursor:pointer;
}
div{
font-size: 48px;
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Chrome/Safari/Opera */
-khtml-user-select: none; /* Konqueror */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE/Edge */
user-select: none; /* non-prefixed version, currently
not supported by any browser */
cursor:default;
}
#scene_plot{
background:url(images/school.jpg);
}
#character{
position: absolute;
left:10px;
top:220px;
width: 108px;
height: 110px;
background:url(images/IConfuse.jpg);
}
#convers{
position: absolute;
left:130px;
top:220px;
width: 290px;
height: 90px;
background:#FFFFFF;
padding:10px;
font-size:18px;
}
#sensor{
z-index:1000; /* sensor類似於背景,但是變成全景點選,因此要改在最前面 */
}
#select1,#select2{ cursor: pointer; font-size:24px; position:absolute; left: 150px; z-index: 1500; }
#select1{
top: 240px;
}
#select2{
top: 280px;
}
</style>
<body>
<!-- choice part -->
<div id="select2">456</div>
<div id="select1">123</div>
<!-- plot part -->
<div id="sensor" class="bg"></div>
<div id="convers">終於下課了......</div>
<div id="character"></div>
<div id="scene_plot" class="bg"></div>
<!-- end plot -->
<!-- init start -->
<div id="lbName">主角名:</div><input type="text" id="txName" autofocus value="永馨">
<input type="button" id="btnStart" value="開始">
<div id="scene_init" class="bg"></div>
<!-- end init -->
</body>
<script type="text/javascript">
var roleplayer=getById("txName").value; //若使用者沒修改,就是預設的名稱:永馨
var initArr=new Array("lbName","txName","btnStart","scene_init");
var plotArr=new Array("character","convers","sensor","scene_plot");
var scene=0; //現在是哪個場景
//這個陣列是用來對應每個角色的不同個性的圖檔,就不用記檔名了
var player=[];
player["I"]={normal: "I",happy: "IHappy",sad: "ISad",confused: "IConfuse", urgent: "IUrgent", end: "IEnd"};
player["Jen"]={normal: "Jen",happy: "JenHappy",sad: "JenSad", end: "JenEnd"};
player["her"]={normal: "her",happy: "herHappy",sad: "herSad", end: "herEnd"};
//這個陣列儲存每個場景的人物是哪個圖檔(統一jpg檔所以只要存檔名不用附檔名)
var charArr=new Array(player["I"].confused,player["Jen"].normal,player["I"].normal,player["Jen"].normal,player["I"].normal,player["Jen"].happy,player["Jen"].sad);
//這個陣列儲存每個場景是否可以按下一頁(換到下個對話或動作),若是數字則跳到抉擇陣列的部分
var cntiArr=new Array(true,true,true,false,0,true,true);
//這個陣列儲存每個場景的背景
var bgArr=new Array("school","school","school","school","school","school","school");
//這個陣列是儲存抉擇的部分
var choice=[];
choice[0]=new Array("嗯!","我有事......");
//這個陣列儲存每個場景人物的對話
var convArr=[];
//簡寫各個元件
var character=getById("character"), plot=getById("scene_plot"), conv=getById("convers"), sensor=getById("sensor"), select1=getById("select1"), select2=getById("select2");
//一開始將其他場景隱藏
hideArr(plotArr);
//一開始將抉擇隱藏
hideChoice();
/*******************************初始畫面(輸入主角按名並開始)******************************/
getById("btnStart").onclick=function(){
roleplayer=getById("txName").value; //假如使用者修改過名字,這個值就不會是預設的"永馨"
//接著將場景切換到一開始的劇情(可按跳過!)
//場景是由背景圖、人物框、對話框組成
hideArr(initArr); //先關閉按下開始的畫面
showArr(plotArr);
}
/*************************************這邊處理劇情部分***********************************/
sensor.onclick=function(){
//這個陣列比較特別,因為我們的roleplayer會隨著使用者輸入後修改,因此要放在這邊設定
//若原本的部分是抉擇,就將對話統一改成false,讓陣列與陣列對齊
convArr=new Array("終於下課了......","任同學:"+roleplayer+",妳有空嗎?",roleplayer+":有呀,怎麼了?","任同學:妳願意來我家玩嗎?",false,"任同學:真高興!","任同學:這樣呀......好吧......");
if(cntiArr[scene]){
if((scene+1)<charArr.length){ //以防練習時出錯(超出陣列範圍)
scene++;
character.style.background="url(images/"+charArr[scene]+".jpg)";
conv.innerHTML=convArr[scene];
plot.style.background="url(images/"+bgArr[scene]+".jpg)";
}
}else{
//會需要抉擇的場景
if((scene+1)<charArr.length){ //以防練習時出錯(超出陣列範圍)
scene++;
character.style.background="url(images/"+charArr[scene]+".jpg)";
//將對話與切換下個場景的sensor隱藏
hideConv();
//接著顯示抉擇選項(此處只有兩種選擇
//這邊顯示抉擇的選項有點複雜,
//根據上面的cntiArr陣列,我們的第一個抉擇(其實是陣列的第一個索引,也就是從0開始)是0
//而對應到了choice陣列,choice陣列的第一個(索引從0開始)抉擇選項是一個陣列
//而這個陣列的第一個選項是"嗯!"、第二個選項是"我有事......"
//因此遇到抉擇時就這樣以此類推。
select1.innerHTML=choice[parseInt(cntiArr[scene])][0];
select2.innerHTML=choice[parseInt(cntiArr[scene])][1];
show(select1);
show(select2);
//這邊處理使用者點擊選項後的結果
//使用者選擇的結果只有兩種:
//1:繼續下一個對話(可能是下一段劇情,或者詢問者給予你的抉擇做感想)
//2:切換畫面為位置選單(也就是可以到其他地點)
select1.onclick=function(){
if(parseInt(cntiArr[scene])==0){
scene++;
character.style.background="url(images/"+charArr[scene]+".jpg)";
conv.innerHTML=convArr[scene];
plot.style.background="url(images/"+bgArr[scene]+".jpg)";
hideChoice();
}
}
select2.onclick=function(){
if(parseInt(cntiArr[scene])==0){
scene++;
character.style.background="url(images/"+charArr[scene]+".jpg)";
conv.innerHTML=convArr[scene];
plot.style.background="url(images/"+bgArr[scene]+".jpg)";
hideChoice();
show(sensor);
fireClick(sensor);
}
}
plot.style.background="url(images/"+bgArr[scene]+".jpg)";
}
}
}
/******************這個部分是給你測試不同的劇情畫面的切換******************/
/*hideArr(initArr);
scene=2;
fireClick(sensor);
*/
function getById(id){
return document.getElementById(id);
}
function hideArr(arr){
for(var i in arr){
getById(arr[i]).style.display="none";
}
}
function showArr(arr){
for(var i in arr){
getById(arr[i]).style.display="block";
}
}
function hide(elem){
elem.style.display="none";
}
function show(elem){
elem.style.display="block";
}
function hideConv(){
conv.innerHTML="";
hide(sensor);
}
function hideChoice(){
hide(select1);
hide(select2);
}
//觸發點擊事件的方法
function fireClick(node){
// 不同瀏覽器有不同的寫法
if ( document.createEvent ) {
var evt = document.createEvent('MouseEvents');
evt.initEvent('click', true, false);
node.dispatchEvent(evt);
} else if( document.createEventObject ) {
node.fireEvent('onclick') ;
} else if (typeof node.onclick == 'function' ) {
node.onclick();
}
}
</script>
</html>
我在html(DOM)裡有用<!-- -->作註解,
所以就可以看出這個部分是用來做什麼的。
從最上面的css部份看到#select1,#select2這裡,
這表示如果有兩個以上元件需要設定一樣的數值時,就用這樣的方式一起設定,
而有個別的差異時,
才用#select1設定各自的。
而select1與select2的div中間的123和456,則是讓你在畫面切換時,更好對準位置。
在該顯示的時候會將123和456改成我們要的值。
這邊陣列的處理相當重要!
以前我是用var i去記錄使用者點到哪個狀態了,然後再用if..else..去做處理......當然就是耗時,且很容易牽一髮動全身Orz
簡單來說就是用陣列去跑劇情。
我把陣列分成幾個:
人物頭像、是否可到下個畫面(按感應區域跳到下一個情境)、背景畫面、人物對話。
除了人物對話陣列,都可以直接在變數編寫內容。
而人物對話的部分,則是改到sensor部分做修改,
這是因為我們可以改主角的名字,
因此要隨時取得修改後的名字。
由於抉擇跟跑劇情是不同的處理方式,所以我在cntiArr陣列約法三章,
若此時的值是false,表示他的下一個畫面是抉擇,而再下一個則是抉擇的對話選項,
因此false後面接0,
這0是對應對話選項的陣列choice,
而select1與select2也依據目前的抉擇是第幾個(雖然目前只有一個),
才做if...else...的處理。
這樣的話,原本才4格的劇情要用到4個if...else....,
現在就直接跑陣列就能解決問題,
而抉擇對話部分也交由choice陣列幫我們顯示選項,
其他就在select1與select2各自分析即可。
因此比較麻煩、還需要人工的就是select1與select2了。
最後,
後面的fireClick是上網找的,
也就是利用程式模擬按下(click)的動作。
而這邊也有一個區域是可以讓你瞬間跳到第n個畫面(雖然這個n一定要小於陣列長度),
找錯誤時就會比較好找了。(不用每次都從按開始那頁做測試)
而圖片切換部分,也演示了將路徑加入檔名的方式。
也希望能把圖片分另外資料夾的習慣學起來喔!
有空的話就是把itemBar教完還有進入到跑文字地圖切換場景的教學囉~