摘要:javascript 小遊戲小技巧教學4(簡易密室遊戲part3)
這次的目標是讓使用者開門!
因為你有很多個場景,假如你都是用btnBackToMain回到前一個場景,
就需要做一下修改了。
先看範例:
<!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>小遊戲教學4</title>
</head>
<style type="text/css">
#scene_main{
background:url(ebg.gif);
}
#desk{
background:url(table.gif) no-repeat;
width: 135px;
height: 69px;
position:absolute;
left: 50px;
top: 150px;
cursor: pointer;
}
#door{
background:url(door.gif) no-repeat;
width: 60px;
height: 82px;
position:absolute;
left: 270px;
top: 44px;
cursor: pointer;
}
#scene_undertable{
background:url(under.gif);
}
#scene_door{
background:url(normalbg.gif);
}
#doorClose{
background:url(door.gif) no-repeat;
background-size: 100%;
width: 151px;
height: 204px;
position:absolute;
left: 191px;
top: 17px;
display: none;
}
.bg{
background-repeat:no-repeat;
width: 533px;
height: 273px;
position: absolute;
left: 0px;
top: 0px;
cursor: default;
z-index: -100;
}
.hide{
display: none;
}
input[type=button]{
border: none;
outline: none;
position: absolute;
cursor: pointer;
}
#btnBack{
background: #666666;
opacity: 0.5;
width: 533px;
height: 35px;
left: 0px;
top: 238px;
z-index: 100px;
}
#btnBack:hover{
opacity: 0.8;
}
#btnBack:enabled:active{
opacity: 0.1;
}
</style>
<script type="text/javascript">
window.onload=function(){
var scene={
main: new Array("desk","door","scene_main"),
undertable: new Array("btnBack","scene_undertable"),
door: new Array("doorClose","btnBack","scene_door")
};
var now="main";
getById("desk").onclick=function(){
hide(scene.main);
show(scene.undertable);
now="undertable";
}
getById("door").onclick=function(){
hide(scene.main);
show(scene.door);
now="door";
}
getById("btnBack").onclick=function(){
if(now=="undertable"){
show(scene.main);
hide(scene.undertable);
now="main";
}else if(now=="door"){
show(scene.main);
hide(scene.door);
now="main";
}
}
function getById(id){
return document.getElementById(id);
}
function hide(scene){
for(var i in scene){
getById(scene[i]).style.display="none";
}
}
function show(scene){
for(var i in scene){
getById(scene[i]).style.display="block";
}
}
}
</script>
<body>
<input type="button" id="btnBack" class="hide" />
<div id="desk"></div>
<div id="door"></div>
<div class="bg" id="scene_main"></div>
<div class="bg hide" id="scene_undertable"></div>
<div id="doorClose"></div>
<div class="bg hide" id="scene_door"></div>
</body>
</html>
這次我們在css做了一些變動,
主要是讓使用者按下門後,畫面來到門的畫面。
在css管理上,讓場景與其上面的元件排在一起。html部分則是依照場景將元件放在場景前面。
#doorClose多了background-size: 100%;設定,讓你改變div大小後,背景圖能隨著延伸。
其實門的畫面就是修改場景圖以及將門放大,導致有靠近的效果。
javascript的部分,多了門的場景。
當你點擊門後,除了顯示門,原本的btnBackToMain又出現了!
為了讓這個返回按鈕依照不同的場景回到不同的畫面,我們新增一個叫做now的變數。
因此每當場景切換時,now也要依照顯示的場景做修改。
因此按鈕btnBackToMain改成了btnBack(也就是專門處理返回場景的按鈕):
getById("btnBack").onclick=function(){
if(now=="undertable"){
show(scene.main);
hide(scene.undertable);
now="main";
}else if(now=="door"){
show(scene.main);
hide(scene.door);
now="main";
}
}
這樣一來所有的場景都換湯不換藥,
你可以使用btnBack按鈕根據now變數回到不同的場景。
此範例下載:lesson4_3.zip
因此,我們追加桌子底下點擊小紙條顯示提示吧!
由於我們的小紙條不是單一圖片,而是圖片的某個區域,我們要自己做一個感應區給他,神奇的div又來了~
首先看一下這個效果:
也就是追加了一個新元件作為感應區:hint
#hint{
background: #000000;
opacity: 0.5;
width: 20px;
height: 16px;
position:absolute;
left: 283px;
top: 114px;
cursor: pointer;
display: none;
}
這裡用背景顏色來讓你知道這個東西的用途。
也就是用div抓圖中小紙條大概的位置,而使用矩形作為感應區是最簡單的方法,你會發現很多遊戲也都是這樣用。
SV就很喜歡在玩FLASH遊戲時,用滑鼠測試元件看起來與我點起來的區域是矩形還是非矩形。
矩形的結果就是你人眼看到滑鼠沒有在物品上,仍然可以點擊,就是因為以矩形為作用範圍。
你可能覺得這樣好像很不細膩?然而現在很多遊戲還是這樣做,
否則就要用更難的技術:判斷透明像素來給圖片更精準的作用範圍了~
用矩形的話,使用碰撞偵測(兩個元件是否有重疊、碰在一起)也比較容易。
有了這個作用範圍,我們就能顯示提示囉(記得把hint的顏色拿掉呀):
這裡將提示隱藏的作法有兩種:
第一種:點擊提示將提示收起來
第二種:點擊btnBack將提示收起來
根據你的喜好來選擇哪一種,SV是用第二種。
顯示提示的部分跟scene陣列的處理不太一樣,
他不是將場景換成有提示的畫面,而是單純在提示上做顯示與隱藏,因此不能將code放在桌子場景的陣列中。
這邊還要注意,因為小紙條沒有另外變成圖片,因此我們顯示提示時(color那張提示)要蓋住小紙條才不會穿幫~
為了方便,我們又創建了一個方法:
function showHint(obj1,obj2){
getById(obj1).style.display="none";
getById(obj2).style.display="block";
}
因為你的提示可能有很多個,作法大都是這樣,就用方法做處理。
到目前為止的程式碼如下:
<!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>小遊戲教學4</title>
</head>
<style type="text/css">
#scene_main{
background:url(ebg.gif);
}
#desk{
background:url(table.gif) no-repeat;
width: 135px;
height: 69px;
position:absolute;
left: 50px;
top: 150px;
cursor: pointer;
}
#door{
background:url(door.gif) no-repeat;
width: 60px;
height: 82px;
position:absolute;
left: 270px;
top: 44px;
cursor: pointer;
}
#scene_undertable{
background:url(under.gif);
}
#hint{
width: 20px;
height: 16px;
position:absolute;
left: 283px;
top: 114px;
cursor: pointer;
display: none;
}
#code{
background:url(code.gif) no-repeat;
width: 328px;
height: 140px;
position:absolute;
left: 102px;
top: 50px;
cursor: default;
display: none;
}
#scene_door{
background:url(normalbg.gif);
}
#doorClose{
background:url(door.gif) no-repeat;
background-size: 100%;
width: 151px;
height: 204px;
position:absolute;
left: 191px;
top: 17px;
cursor: default;
display: none;
}
.bg{
background-repeat:no-repeat;
width: 533px;
height: 273px;
position: absolute;
left: 0px;
top: 0px;
cursor: default;
z-index: -100;
}
.hide{
display: none;
}
input[type=button]{
border: none;
outline: none;
position: absolute;
cursor: pointer;
}
#btnBack{
background: #666666;
opacity: 0.5;
width: 533px;
height: 35px;
left: 0px;
top: 238px;
z-index: 100px;
}
#btnBack:hover{
opacity: 0.8;
}
#btnBack:enabled:active{
opacity: 0.1;
}
</style>
<script type="text/javascript">
window.onload=function(){
var scene={
main: new Array("desk","door","scene_main"),
undertable: new Array("hint","btnBack","scene_undertable"),
door: new Array("doorClose","btnBack","scene_door")
};
var now="main";
getById("desk").onclick=function(){
hide(scene.main);
show(scene.undertable);
now="undertable";
}
getById("door").onclick=function(){
hide(scene.main);
show(scene.door);
now="door";
}
getById("btnBack").onclick=function(){
if(now=="undertable"){
show(scene.main);
hide(scene.undertable);
now="main";
}else if(now=="door"){
show(scene.main);
hide(scene.door);
now="main";
}else if(now=="code"){
showHint("code","hint")
now="undertable";
}
}
getById("hint").onclick=function(){
showHint("hint","code")
now="code";
}
function getById(id){
return document.getElementById(id);
}
function hide(scene){
for(var i in scene){
getById(scene[i]).style.display="none";
}
}
function show(scene){
for(var i in scene){
getById(scene[i]).style.display="block";
}
}
function showHint(obj1,obj2){
getById(obj1).style.display="none";
getById(obj2).style.display="block";
}
}
</script>
<body>
<input type="button" id="btnBack" class="hide" />
<div id="desk"></div>
<div id="door"></div>
<div class="bg" id="scene_main"></div>
<div id="code"></div>
<div id="hint"></div>
<div class="bg hide" id="scene_undertable"></div>
<div id="doorClose"></div>
<div class="bg hide" id="scene_door"></div>
</body>
</html>
範例下載連結:lesson4_3_3.zip
最後就是在門旁邊加入密碼鎖,使用者輸入結果後判斷是否為正確答案,若正確就顯示成功脫出畫面!
不是的話密碼鎖顯示error:
密碼鎖的部分則是使用了table,如果覺得太制式化了(不美觀),你還是可以用你的圖片來做排版。
而我也在html部分演示如何在html之間加註解。
我還加入了判斷是否有看過提示的條件,也就是不讓使用者用暴力法解~
若希望使用者退出密碼鎖後,再回來要歸零(回復到顯示AAA)則是要再修改喔。
最後的脫出很弱掉,你可以用漂亮的圖片代替(才能讓人有成就感)
當然,謎題的好壞就要靠喜歡解謎遊戲的人好好摸索,
這也是為什麼密室解謎之類的遊戲總能讓人百玩不厭!
有空的話應該是教隨機謎題還有Game Over之場景變暗的效果。
目前完整範例下載:lesson4_3_4.zip
20150714新增:
其實改變背景還有一個方法,不過頭腦要很好否則可能會自己亂掉,
就是直接用一個div當背景,並且切換那個div的背景圖。
假設一開始的背景div長這樣:
<div id="scene_main" class="bg">
在javascript修改其背景就是修改他的background: url()裡面的圖檔名:
document.getElementById("scene_main").style.backgroundImage="url(normalbg.gif)";
只要場景需要切換,就用上述方法切換。