2019年6月28日 星期五

[啥Web]Adobe Animate CC 2018輸出HTML5後結合個人網頁的方式[含結合Swiper外掛做出動畫切換Slider效果]

 

   一直以來都有想把自自己學過的技術留下記錄,但因為很花時間所以有些記錄其實都沒來得及寫,比如過去的Game Maker教學還有After Effect光流教學(這個在宅學習有但其實那個是暫存,因為事實上還沒打完)。

  這次想記錄的是個人研究HTML5的動畫部分。在Adobe Animate CC 2018內做好的HTML5動畫或互動輸出後,我是如何將那些結合網頁的。基本上算是我個人研究出來的,實際上有沒有人也這樣做我不是很清楚,我是覺得反正只要懂一點html與js基本上應該差不多。當然這邊會這樣提只是想說可能會有更好的方式就是,我可能不清楚,畢竟這裡只是個人筆記,建議有人對這有興趣可以多找其他資源(當然如果有人有找到也希望能回覆分享一下)。

  在開始貼上我筆記前,我先放上我這邊的發佈設定

 
 
 

   這邊大概說明一下,在基本的標籤有個作出回應的選項,那個的意思就是做RWD,因為RWD的是Responsive Web Design的縮寫。所以Adobe就將make responsive翻成作出回應...也不能說翻錯啦,但我第一次看到時完全看不懂= =",好歹也翻成製作成響應性式或直接寫RWD...

  總之那是為了做RWD用的。不過Adobe Animate的RWD很單純,他就只是將輸出的網頁做等比例縮放,不像實際上在做rwd不是只是單純做等比例縮放這件事,有些是要因應不同視窗做出不同排版。這點Adobe Animate是無法做到的。Google出的Google Web Designer其實就是往這方向設計的,但我個人不太會用就是。而只有等比例縮放,我個人是認為這就已經很夠用了。畢竟做動畫你若要考慮到不同排版,除了累以外還很不直覺。如果不同平台的等比例縮放實在太怪或不方便閱讀的話,我會乾脆就另外做一個動畫取代顯示就是。

  然後就是大概說明一下我為何選擇依寬度做RWD,主要是在圖片做RWD縮放的網頁我還沒遇過以高度做等比例縮放的就是。我想應該是現在排版大多都是由左而右從上至下的關係,我們圖片的排版通常都是和文字做並排,像是Bootstrap在使用col時也都是以寬度為基準,也因此在針對縮放這邊以寬度做等比例縮放會比較好。

  而圖片輸出這邊的資料夾位置會和你之後主檔html(不是指輸出的html)一樣的相對位置的資料夾檔名一樣,所以輸出完檔案後記得把圖檔位置搬一下。

  再來是這邊要注意js要分開輸出,雖然我記得預設就是。只是這邊要稍微提醒一下, 要分開js他竟然不是用勾選的而是用按鈕顯示目前打包狀態的方式。所以當你想把js包在html裡面,看到按鈕狀態是寫將javascript包在HTML中就代表你是分開輸出的了

  輸出完後基本上就是打開你要放入的網頁,這邊我稱為mergeAdobeAnimate.html。而我因為之後會修改輸出後的原始碼,去針對我放的區域做等比例縮放,所以html檔我不用輸出的而是用自己寫的。Adobe Animate輸出是以整個視窗大小去做縮放的,沒那麼好心還為你寫你想顯示的局塊縮放。所以這邊我必須得自行判斷放入位置的寬度去做RWD。而這一塊因為我本身對js原始的呼叫方式沒那麼熟,我是用JQuery的方法。因此其實如果有看懂我在做什麼的,是不必一定要引入JQuery就是。

撰寫html


  因為fla檔名就叫html5Example1,所以他會輸出html5Example1.html與html5Example1.js。這邊要把html5Example1.html裡的canvas tag貼在自己的mergeAdobeAnimate.html,並改名,避免之後有機會和其他canvas衝突。更改方式如下:

    <div id="id_html5Example1"><!--注意這邊要有寬高才會顯示-->
        <div id="id_html5Example1_animation_container">
            <canvas id="id_html5Example1_canvas" width="512" height="384" style="position: absolute; display: block; background-color:rgba(255, 255, 255, 1.00);"></canvas><!--注意這邊要有寬高只是參考用,RWD會自動修改,所以其實刪掉也行-->
            <div id="html5Example1_dom_overlay_container" style="pointer-events:none; overflow:hidden; width:512px; height:384px; position: absolute; left: 0px; top: 0px; display: block;"><!--注意這邊要有寬高只是參考用,RWD會自動修改,所以其實刪掉也行-->
            </div>
        </div>
    </div>

   注意到我改了3個地方的id,這代表之後js也有地方得動到。做這個的目的是為了避免之後若要引用其他地方的canvas會有衝突。

 完整獨立js


  再來看html5Example1.html檔。你會看到裡面還是有部分的js,我為了要做到在我們自己的html只要引入一個js檔並且使用一個函式乎叫,也為了避免之後引入其他檔案會有變數衝突,所以這邊要把那些js做合併全都放入html5Example1.js。這邊開始複製html5Example1.html裡從var canvas開始的語法。然後再打開html5Example1.js檔,拉到最底下寫一個呼叫的初始函式,比如html5Example1Init。把剛剛從html裡複製的語法通通貼到這個函式內。並更改剛剛改過的canvas、animation_container與dom_overlay_container。最後在var iw = window.innerWidth, ih=window.innerHeight這段改為取得的id_html5Example1的寬與高,不過這邊要注意,因為我們在發佈設定是以寬度為基準做RWD,所以其實高度的地方不會被用到就是。只要而改好後還有一個地方要改,就是要記得呼叫初始方法init();。總之整個要貼在html5Example1.js底端的原始碼如下:

function html5Example1Init()
{
    var canvas, stage, exportRoot, anim_container, dom_overlay_container, fnStartAnimation;
    init();
    function init() {
        canvas = document.getElementById("id_html5Example1_canvas");
        anim_container = document.getElementById("id_html5Example1_animation_container");
        dom_overlay_container = document.getElementById("id_html5Example1_dom_overlay_container");

        var comp=AdobeAn.getComposition("B1C74C98C1ED9C40A39A92EED8EFD7E6");
        var lib=comp.getLibrary();
        var loader = new createjs.LoadQueue(false);
        loader.addEventListener("fileload", function(evt){handleFileLoad(evt,comp)});
        loader.addEventListener("complete", function(evt){handleComplete(evt,comp)});
        var lib=comp.getLibrary();
        loader.loadManifest(lib.properties.manifest);
    }
    function handleFileLoad(evt, comp) {
        var images=comp.getImages();   
        if (evt && (evt.item.type == "image")) { images[evt.item.id] = evt.result; }   
    }
    function handleComplete(evt,comp) {
        //This function is always called, irrespective of the content. You can use the variable "stage" after it is created in token create_stage.
        var lib=comp.getLibrary();
        var ss=comp.getSpriteSheet();
        var queue = evt.target;
        var ssMetadata = lib.ssMetadata;
        for(i=0; i<ssMetadata.length; i++) {
            ss[ssMetadata[i].name] = new createjs.SpriteSheet( {"images": [queue.getResult(ssMetadata[i].name)], "frames": ssMetadata[i].frames} )
        }
        exportRoot = new lib.html5Example1();
        stage = new lib.Stage(canvas);   
        //Registers the "tick" event listener.
        fnStartAnimation = function() {
            stage.addChild(exportRoot);
            createjs.Ticker.setFPS(lib.properties.fps);
            createjs.Ticker.addEventListener("tick", stage);
        }       
        //Code to support hidpi screens and responsive scaling.
        function makeResponsive(isResp, respDim, isScale, scaleType) {       
            var lastW, lastH, lastS=1;       
            window.addEventListener('resize', resizeCanvas);       
            resizeCanvas();       
            function resizeCanvas() {           
                var w = lib.properties.width, h = lib.properties.height;           
                var iw = $('#id_html5Example1').width(), ih=$('#id_html5Example1').height();           
                var pRatio = window.devicePixelRatio || 1, xRatio=iw/w, yRatio=ih/h, sRatio=1;           
                if(isResp) {               
                    if((respDim=='width'&&lastW==iw) || (respDim=='height'&&lastH==ih)) {                   
                        sRatio = lastS;               
                    }               
                    else if(!isScale) {                   
                        if(iw<w || ih<h)                       
                            sRatio = Math.min(xRatio, yRatio);               
                    }               
                    else if(scaleType==1) {                   
                        sRatio = Math.min(xRatio, yRatio);               
                    }               
                    else if(scaleType==2) {                   
                        sRatio = Math.max(xRatio, yRatio);               
                    }           
                }           
                canvas.width = w*pRatio*sRatio;           
                canvas.height = h*pRatio*sRatio;
                canvas.style.width = dom_overlay_container.style.width = anim_container.style.width =  w*sRatio+'px';               
                canvas.style.height = anim_container.style.height = dom_overlay_container.style.height = h*sRatio+'px';
                stage.scaleX = pRatio*sRatio;           
                stage.scaleY = pRatio*sRatio;           
                lastW = iw; lastH = ih; lastS = sRatio;           
                stage.tickOnUpdate = false;           
                stage.update();           
                stage.tickOnUpdate = true;       
            }
        }
        makeResponsive(true,'width',true,1);   
        AdobeAn.compositionLoaded(lib.properties.id);
        fnStartAnimation();
    }
}

  上面藍色的地方要注意的是那個地方如果日後不小心更動到,要注意他那序號是否和an.compositions['這邊']序號一模一樣,不然他會出不來。寫好後就可以丟入自己的js資料夾了。還有一點就是如果有兩個以上canvas,這個序號必須要不一樣,不然不會顯示。所以如果發生一樣的狀況(可能是同一檔案複製),請記得去改,那個序號可以拿其他檔案的,但建議重新開檔輸出會比較好。

  只是說,我在使用這個的過程常常會出現經過縮放視窗後回不去原來大小的狀況。而我不是很清楚原來Adobe的RWD縮放方式到底如何調整,所以我後來的改法是,當視窗大小小於本身動畫預設的大小才要改就好,也不會像Adobe的好像還有記憶一些我不是很清楚的參數。所以一開始如果id_html5Example1的大小若大於本身在Animate做的動畫大小時他絕對不會經過縮放。這雖然聽起來有點問題,但對我來說是最單純的設計。我只要一開始做動畫時給他大一點就好。所以我這邊就開始改了蠻大的了,然後我又再寫了一個參數讓他們統一乘以該數字,方便我之後覺得那樣的大小不理想還可以去調整。因此我的改法還多了一個參數canvasSizeModified。 這是我比較常用的改法:

function html5Example1Init()
{
    var canvas, stage, exportRoot, anim_container, dom_overlay_container, fnStartAnimation;
    var canvasSizeModified=1;
    init();
    function init() {
        canvas = document.getElementById("id_html5Example1_canvas");
        anim_container = document.getElementById("id_html5Example1_animation_container");
        dom_overlay_container = document.getElementById("id_html5Example1_dom_overlay_container");
        var comp=AdobeAn.getComposition("B1C74C98C1ED9C40A39A92EED8EFD7E6");
        var lib=comp.getLibrary();
        var loader = new createjs.LoadQueue(false);
        loader.addEventListener("fileload", function(evt){handleFileLoad(evt,comp)});
        loader.addEventListener("complete", function(evt){handleComplete(evt,comp)});
        var lib=comp.getLibrary();
        loader.loadManifest(lib.properties.manifest);
    }
    function handleFileLoad(evt, comp) {
        var images=comp.getImages();   
        if (evt && (evt.item.type == "image")) { images[evt.item.id] = evt.result; }   
    }
    function handleComplete(evt,comp) {
        //This function is always called, irrespective of the content. You can use the variable "stage" after it is created in token create_stage.
        var lib=comp.getLibrary();
        var ss=comp.getSpriteSheet();
        var queue = evt.target;
        var ssMetadata = lib.ssMetadata;
        for(i=0; i<ssMetadata.length; i++) {
            ss[ssMetadata[i].name] = new createjs.SpriteSheet( {"images": [queue.getResult(ssMetadata[i].name)], "frames": ssMetadata[i].frames} )
        }
        exportRoot = new lib.html5Example1();
        stage = new lib.Stage(canvas);   
        //Registers the "tick" event listener.
        fnStartAnimation = function() {
            stage.addChild(exportRoot);
            createjs.Ticker.setFPS(lib.properties.fps);
            createjs.Ticker.addEventListener("tick", stage);
        }       
        //Code to support hidpi screens and responsive scaling.
        function makeResponsive(isResp, respDim, isScale, scaleType) {       
            var lastW, lastH, lastS=1;       
            window.addEventListener('resize', resizeCanvas);       
            resizeCanvas();       
            function resizeCanvas() {           
                var w = lib.properties.width, h = lib.properties.height;           
                var iw = $('#id_html5Example1').width();           
                var pRatio = window.devicePixelRatio || 1, xRatio=iw/w, sRatio=1;         
                 var pRatio = window.devicePixelRatio || 1, xRatio=iw/w,sRatio=1;         
                 if(isResp)
                 {             

/*
(如果你不在意失真,希望他完全隨著設定寬度做縮放的話,那你可能就得把判斷拿掉,直接讓sRatio=xRatio      
*/               
                     if(w>iw)
                    
                     {              
                        sRatio = xRatio;            
                     }
                 }          
                 canvas.width = w*pRatio*sRatio*canvasSizeModified;        
                 canvas.height = h*pRatio*sRatio*canvasSizeModified;
                 canvas.style.width = dom_overlay_container.style.width = anim_container.style.width =  w*sRatio*canvasSizeModified+'px';              
                 canvas.style.height = anim_container.style.height = dom_overlay_container.style.height = h*sRatio*canvasSizeModified+'px';
                 stage.scaleX = pRatio*sRatio*canvasSizeModified;          
                 stage.scaleY = pRatio*sRatio*canvasSizeModified;     
     

                stage.tickOnUpdate = false;           
                stage.update();           
                stage.tickOnUpdate = true;     
           
            }
        }
        makeResponsive(true,'width',true,1);   
        AdobeAn.compositionLoaded(lib.properties.id);
        fnStartAnimation();
    }
}

引入createjs和合併後的js


  接下來要開始回到mergeAdobeAnimate.html檔, 要引入createjs和合併後的js,他和剛剛提的jquery順序如下:
    <script src="js/createjs-2015.11.26.min.js"></script>
    <script src="js/jquery-3.1.1.min.js"></script>  
    <script src="js/html5Example1.js"></script> 

  然後再寫入自定義的呼叫函式:
    <script>
        function animeInit()
        {
            html5Example1Init();
        }
    </script>

  最後再在body輸入初始化函式:
<body onload="animeInit();">

  這樣就差不多了,記得在css裡要給id_html5Example1寬與高,這樣整個canvas才會顯示出來。而我為了讓這樣的寫法更能顯示RWD,我的範例還加上了Bootstrap.將canvas與80pt大的文字放在一起分別給文字col-5與id_html5Example1這動畫col-7。差不多長這樣:

  <div class="container-fluid">
        <div class="row">
            <p style="font-size:80pt" class="col-5">This is Test</p>
            <div id="id_html5Example1" class="col-7"><!-這邊因為bootstrap已經給定RWD會有的長寬了,所以才會顯示-->
                <div id="id_html5Example1_animation_container">
                    <canvas id="id_html5Example1_canvas" width="512" height="384" style="position: absolute; display: block; background-color:rgba(255, 255, 255, 1.00);"></canvas><!--注意這邊要有寬高只是參考用,RWD會自動修改,所以其實刪掉也行-->
                    <div id="id_html5Example1_dom_overlay_container" style="pointer-events:none; overflow:hidden; width:512px; height:384px; position: absolute; left: 0px; top: 0px; display: block;"><!--注意這邊要有寬高只是參考用,RWD會自動修改,所以其實刪掉也行-->
                    </div>
                </div>
            </div>
        </div>
    </div>

  縮放視窗就會看到如下的縮放:

 


 放入另一個HTML5動畫


  因此我相信會寫網頁的大概就知道要怎麼應用了 ,我這邊再做一個利用Swiper這個知名效果外卦去做兩個動畫的Slider切換(不過可能要注意我因為是拿以前寫的範例來改,所以用的Swiper是舊版語法,新版語法應該也是沒問題的就是)。基本上是另外做一個js,照上面步驟另外命名所有id與初始函式名稱(我是把所有html5Example1都改為html5Example2,然後記得在html5Example1Init();下再多執行一行 html5Example2Init();),還有要注意顯示序號必須不一樣就可以了。詳細寫法可以直接看我demo2的檔案或載我放的打包檔看mergeAdobeAnimateWithSwiper.html檔了。以下是用該外掛的coverflow效果:



最後補充

  • 如果有寫互動建議把stage變數提取出來變全域變數。因為如果你是寫互動式的網頁,你有機會想用到stage.gotoAndPlay之類的指令,我個人認為這是蠻方便的就是。而這邊還有一點要注意就是請改名字比如html5Example1Stage,然後在我們修改的js全部取代,避免和另外一個canvas衝突。
     
  • 還有如果想做loading進度讀取%數,可在js裡的loader.addEventListener("fileload", function(evt){handleFileLoad(evt,comp)});上方加入loader.addEventListener("progress", handlePreload);  並新增一個function handlePreload:
    function handlePreload(v)
    {
    myProgress=v.loaded; 
    } 

    myProgress這邊是全域變數,總之建議可以寫個timer一直去讀取他就是,只是Animate的進度其實都很完整,我記得都是25%為倍數,所以我也不清楚是不是有更好的讀取進度的地方。
     
  • 有個要注意的是,有的模糊或濾鏡效果在Adobe Animate內看都有,但其實輸出是沒有出現效果的。目前只有alpha才可以使用(像我個人DEMO1全都是透明度變化),其他似乎都有問題。
     
  • 後來我在前端社群討論得知放出以下教學影片的大大:
     

    他在他的底下回應有提到要把makeResponsive這個函式註解掉,我才驚覺之前有點被這函式給限制住了。雖然我透過js去做等比例縮放也是一種方式,但我之所以採取這個的原因是因為我一開始對canvas不熟,然後css怎麼修改他的長和寬都不會改變,所以就只好另找方法。聽到他的回應我才想到改不了的原因就是那個makeResponsive在搞的鬼啊....所以要是有不怎麼熟js的朋友或許在css改是比較好的,且記得把makeResponsive註解掉。

2019年6月24日 星期一

[啥記錄]被遺忘的物語封面小遊戲《Braver Choice》

音樂音效來源: PANICPUMPKIN

  目前為了要整合一包方便訂制之後做新遊戲的流程,所以馬上將一些一定會用到的元件給打包並建立Default資料夾,讓之後做新遊戲時做過的地方不必再做一次,而打包完後必須要確定這流程有沒有錯,因此馬上就做了另一款遊戲-Braver Choice。

假冒勇者的鬪羅柏!

  基本上這款遊戲是我曾在Akaibaito製作的夯魚!喵3的玩法,就是簡單地選擇左邊與右邊。而因為這款小遊戲我亦曾經為了幫一家工作室測APP,所以其實也可以在Google Play找到一模一樣的玩法和外觀的遊戲。也由於已經做過,所以這款遊戲就被我拿來當做驗證我訂制的Default資料夾有沒有需要改進的地方的測試用小遊戲。

 
在寶箱內的史萊姆-史邁爾!

  然後,儘管這只是測試用小遊戲,但其實我有將《被遺忘的物語》第1話Children Treasure的背景給設計進去。雖然原本的封面設計是類似把物品藏在杯子裡,移動杯子位置,記住過程去猜史邁爾會在哪個寶箱的簡易小遊戲。

 
原本的小遊戲方式

  雖然這勇者看起來像是雷蒙丸的養父—鬪羅柏。但其實被我設定是16年前與魔王追根大戰的勇者-剛達。所以其實也代表著,勇者剛達和史萊姆-史邁爾是有關聯的。只是這個設定我暫時不在這描述太多,但我在google play的商品描述裡有提到那是勇者的抉擇。雖然遊戲方式是選擇金錢才是正確的方式,但事實上,他最後選擇的是Game Ovum,也就是甘姆之卵。

 
60年前開始,勇者與魔王持續了長達44年的戰爭。

  這邊就放上目前的遊玩影片:

 

2019年6月16日 星期日

[啥記錄]被遺忘的物語封面小遊戲《Sugar Tower》

  基本上這篇文章算是一樣留給自己記錄用的,雖然我想應該不會有什麼人看我漫畫以及玩我做的遊戲,但至少想留點自己奮鬥過的記錄。


  過去這一個月來我把《被遺忘的物語》第7話的Sugar Tower封面遊戲化了。這算是滿足自己一直以來的規劃—「不只將甘姆(被遺忘的物語世界觀)漫畫化還想將甘姆遊戲化」的方式就是。當然我希望未來有時間的話繼續把還沒遊戲化的封面小遊戲進行製作。


漫畫裡疊得高高的方糖動物們!

  這款的遊戲方式其實和我以前曾在Akaibaito擔任程式時開發的一款小遊戲《上吧棉花糖》幾乎一樣,就是一直保持在中間疊著塊狀動物。程式製作上因為有寫過,即便是要將unity script轉C#,還有一些長度判定得修正,但基本上原理不會差太多,方便從之前寫的程式修改也是我選擇這款的原因之一。先聲明雖然我在Akaibatio有完全個人製作(企劃程式和美術)過一款名叫《衝啊爆炸頭》的小遊戲,但在《上吧棉花糖》這款遊戲裡,我個人只是擔任程式而已,並未提供任何點子以及美術製作。會特別挑他除了剛提的理由外,還有這是我個人參與製作的遊戲中,目前給我成就感最大的小遊戲,除了下載量最高(2019至今累積47.85K)的原因以外,就是因為我曾經在2016台北電玩展獨立遊戲區裡看到有玩家玩得很開心。特此紀念所以才想先製作,才沒有選擇從第0話開始。畢竟之後還是得花時間畫漫畫,我沒辦法保證之後真的完全可以邊做小遊戲邊畫漫畫……所以先行製作了這款讓我值得紀念的遊戲。

 
2016年台北電玩展當時Akaibaito有參加獨立遊戲區

  當然我個人還是加入了自己的點子,那就是在方糖搖籃往左或右時你可以按相反的方向鍵讓他改變方向,以及只要接觸旁邊正在爬方糖動物的法門和巴克瑟爾就會讓他們掉落,兩個都掉落後就會Game Over。

法門掉下來了(被炸到右下)

  基本上這算是為了符合Game & Watch的設計,但卻是為設計而設計的遊戲方式就是。有點不應該, 畢竟這種小遊戲其實越單純越好,原本的單一點擊就可以玩的方式其實比較親民。但想想自己是個複雜的創作者,所以就不管那麼多了。加上我又是老遊戲玩家,小時候玩的都是這種不體諒玩家的遊戲,所以就這樣自我催眠了。不過最一開始的設計其實更容易操縱混亂,我是打算讓左右兩邊的法門與巴克瑟爾像漫畫一樣會互相競爭,所以打算讓他們互丟他們到達神族時會吃到的像素方糖,法門丟他吃的黑糖,巴克瑟爾丟他吃的白糖。但因為他們中間有他們沒看到的方糖搖籃與玩家疊的方糖塔,所以其實會打到搖籃中的方糖動物並讓他自動掉落。而左右鍵的設計是為了讓搖籃生出左右防禦塔(會以動畫方式生長出來並下降)。但在打算要開始做的開始時,一直想到有個問題,就是因為遙籃會左右位移,我很難設計出法門或巴克瑟爾的攻擊時機,怎麼想都覺得玩家鐵定很快Game Over。後來一直思考有什麼可以改進,就因為想到現在的玩法而放棄了原來的設計。

  這邊因為覺得應該不會有玩家玩到或發現我設計的巧思所以打算一一列出就是。基本上目前疊高會看到三個明顯分界,也就是四個領域。第一個領域一開始的樹林到天空看到日分界以及日之塔,要注意一下這款遊戲的目的是保持讓方糖動物在正間一直疊高,所以日之塔的輔助很重要,一直往斜的方向疊是會Game Over的,雖然因為這是寫程式的判斷問題,但我個人自以為這是代表遊戲裡不能太偏魔物與人類角度,要糖糖正正的意思XD...嗯,一開始的彩蛋差不多是這樣,還有一個比較有趣的大概是那個一直哭的地鐵霍格會以低機率出現唷(被遺忘的物語第6話初登場)。

 
 
霍格爺爺終於飛出來了!但我忘了畫讓他載魔物了XD

  而天空分黑白的用意其實也是象徵著人類與魔物的比喻就是。

  然後接下來是神族界,在看到月亮後會再看到站在雲上的邱妮和邱緹(被遺忘的物語第8話有兩人一起登場),在這個地方有麼四個地方比較有趣一點,就是第8話邱緹使用的萬用型坦克,還有成為神族的人類和魔物(史萊姆)在為工作而奔波著。

月亮(所以其實底下的森林應該要有部分塗黑代表月之林,但我忘了) 


 左邱緹右邱妮

 萬用型坦克

人類天使

魔物天使

  第四個有趣的是有天屎(?),這個在後面兩個領域都會出現。就是第8話裡有畫面帶到的,從上級降下的任務訊息。所以就是屎缺的意思。

在巴克瑟爾旁邊的天屎

  天神界往上會看到左邊的白天已經不在,全都是黑暗,代表進入宇宙,可以看到各種行星。這邊比較有趣的是大概會看到從上面不知道從哪降落的天屎。剩下其實都還好,勉強講比較有趣的是那個XO酒瓶。這邊稍微解釋一下為何有那東西,因為在我小學四年級的時候,老師徵求一名學生參加畫圖比賽,我當時竟然會舉手。我已經忘記我當時的想法了,只記得我是主動說我要參加的,這對一直很閉俗的我來說是很難想像的,因為我記得我小時候也是很不愛說話然後不喜歡舉手。總之當時接下這個比賽時,我畫了一幅畫,是底下是地球有很多人在做不各自不同的事,上方中間是大太陽(接近遊戲中的畫法,除了中間那個點),旁邊一堆星球,其中有個星球就是畫那樣的XO瓶子。現在我已經找不到那些畫了,只記得我畫很多張,因為被老師打掉重練。其中一個被打掉的第一個概念就是那個XO瓶子,老師說既然這作品叫我的世界那小孩子的世界怎麼會有XO酒瓶?其實我會畫只是單純地想到什麼畫什麼就是,我根本不愛喝酒更別提小時候。只是XO這名字讓我當時莫名地容易記住就是。總之因為那是我畫那張圖第一次被打槍打掉重畫的圖,所以印象深刻就是。這裡不能說是老師的問題,當年那個老師我是很喜歡的,我還留著她送給我的卡片。總之那畫雖然參加比賽了,但平常沒啥在畫圖,畫圖也不是很厲害的我明顯不會得獎。這段往事我一直很難忘記,那大概是我人生裡第一次主動想參加畫圖比賽了。

從上方降落的天屎 (右邊)

XO酒瓶

  嗯,扯太多,總之宇宙區的最上面,會看到日之塔已經到頂了,日之塔的設計其實是第一代人類-獨眼巨人為了監視太陽而建造的,所以日之塔再往上會看到太陽

  
日之塔到頂了

太陽

   因為想做出第0話提到的,世界外還有世界的領域,所以看到大鷗歐爾上就是更高的領域了。這個領域在我甘姆的設計就是GOS(Game Operating System),GOS領域不是一般人可以到達的,所以會有干擾現象(glitch)。因此其實也代表著法門與巴克瑟爾之後會來到這個領域,只是我目前設計他們將來會透過卡巴拉之樹上去,所以到那邊的方糖塔應該要換成樹,但是是打這篇文章才想到的,製作時沒想到。

刁著鷗陸亞大陸的鷗爾

 干擾現象

  而這邊除了干擾現象,會出現兩個較有趣的設計。一個是前面提的,在三個領域都有出現的天屎,被我稱為屎達一號的星星手上拿著的就是天屎,所以代表那些屎缺就是他丟的。也可以說神族的那些工作全都是GOS指派的。

屎達一號

  還有另一個是被我稱為飛天義大利烏龍麵的奇怪飛行物就是,單純是致敬飛天義大利麵,也代表GOS的領域就像是宗教裡神的領域。

飛天義大利烏龍麵

  然後這款遊戲大概提一下最後的設計,和《上吧棉花糖》一樣最後會有讓方糖動物都亂飛的按鈕。也就是按下那個像炸彈的選項就可以讓包括掉下來的法門與巴克瑟爾飛高高再掉下來,使用手機還可以擺動手機讓他們掉往你要的方向。算是單純好玩的設計就是。還有網頁版因為不是google play,所以沒有獎勵式影片廣告,只要等20秒就可以接關。也因為沒有google所以點了排行榜的圖示(炸彈右邊)也不會有反應。

  最後放上三段遊戲影片,都是在我Unity引擎編輯器玩的,我都是用直接到達高度程式去跑,不是我個人玩到的記錄就是。


遊戲影片1

遊戲影片2

遊戲影片3