2015年4月4日 星期六

Javascript遊戲撰寫初挑戰 WORDKEEPER (二)範例分析

身為一個業餘的programmer
接下來的內容都是以我自己的方式來進行開發
請大家不要太認真,輕鬆面對就好XD
而以我自己的習慣來說
在所有規劃開始之前,要先了解一下整個程式的運作流程
所以針對所使用的createjs進行範例分析,成為整個計劃開始的第一步


createjs的官網中有提供一些範例
其中一個範例相當適合做為這次的範本↓











好山,好水,以及一個愛跳躍的好人


在這個範例中,包含了幾項值得參考的東西:

1.圖片素材的載入
背景的山或地面很明顯不是即時繪製,而是載入圖檔
且人物圖片也有影格控制甚至切割的行為控制

2.時間軸控制
畫面隨著時間不斷自己更新移動
表示已經在程式中設定了時序動作

3.互動功能
點擊滑鼠後人物會跳動
顯示可以在時序中設定與使用者溝通的滑鼠動作

而實際觀察解讀範例程式碼後
也成功從裡面找到了想要的東西~
詳細程式碼(以及解讀注釋)如下:

--------------------------------------------------------------------

變數的宣告
var stage, w, h, loader;
var sky, grant, ground, hill, hill2;

整個Canvas的初始化與主要配置
function init() {
      在載入與配置的過程中顯示類似"loading中"的訊息
examples.showDistractor();
      將Canvas作為createjs的舞台
stage = new createjs.Stage("testCanvas");

// grab canvas width and height for later calculations:
w = stage.canvas.width;
h = stage.canvas.height;

      設定要載入的圖片資源
manifest = [
{src: "spritesheet_grant.png", id: "grant"},
{src: "sky.png", id: "sky"},
{src: "ground.png", id: "ground"},
{src: "hill1.png", id: "hill"},
{src: "hill2.png", id: "hill2"}
];

      開始載入資源,並且設定載入完成時觸發的事件(配置事件handleComplete)
loader = new createjs.LoadQueue(false);
loader.addEventListener("complete", handleComplete);
loader.loadManifest(manifest, true, "../_assets/art/");
}

各物件的配置函式
function handleComplete() {
      消除"Loading中"的訊息
examples.hideDistractor();

      從預載資源中找出背景天空的圖片,並設置物件(sky)
sky = new createjs.Shape();
sky.graphics.beginBitmapFill(loader.getResult("sky")).drawRect(0, 0, w, h);

      從預載資源中找出地面的圖片,並設置物件(ground)
var groundImg = loader.getResult("ground");
ground = new createjs.Shape();
ground.graphics.beginBitmapFill(groundImg).drawRect(0, 0, w + groundImg.width, groundImg.height);
ground.tileW = groundImg.width;
ground.y = h - groundImg.height;

      從預載資源中找出背景山丘的圖片,並設置物件(hill, hill2)
hill = new createjs.Bitmap(loader.getResult("hill"));
hill.setTransform(Math.random() * w, h - hill.image.height * 4 - groundImg.height, 4, 4);
hill.alpha = 0.5;

hill2 = new createjs.Bitmap(loader.getResult("hill2"));
hill2.setTransform(Math.random() * w, h - hill2.image.height * 3 - groundImg.height, 3, 3);

      從預載資源中找出人物圖片,切割並設置動作,完成物件(grant)的設定與配置
var spriteSheet = new createjs.SpriteSheet({
  framerate: 30,
  "images": [loader.getResult("grant")],
  "frames": {"regX": 82, "height": 292, "count": 64, "regY": 0, "width": 165},
  // define two animations, run (loops, 1.5x speed) and jump (returns to run):
  "animations": {
  "run": [0, 25, "run", 1.5],
  "jump": [26, 63, "run"]
  }
  });
grant = new createjs.Sprite(spriteSheet, "run");
grant.y = 35;

      將配置好的物件加入舞台
stage.addChild(sky, hill, hill2, ground, grant);
stage.addEventListener("stagemousedown", handleJumpStart);

      設定舞台的時序控制函式(tick)
createjs.Ticker.timingMode = createjs.Ticker.RAF;
createjs.Ticker.addEventListener("tick", tick);
}

人物切換為跳躍(jump)狀態的函式
function handleJumpStart() {
grant.gotoAndPlay("jump");
}

整個舞台的時序控制函式
function tick(event) {
      取得間隔時間,並且計算人物、地面、山丘的新位置
var deltaS = event.delta / 1000;
var position = grant.x + 150 * deltaS;

var grantW = grant.getBounds().width * grant.scaleX;
grant.x = (position >= w + grantW) ? -grantW : position;

ground.x = (ground.x - deltaS * 150) % ground.tileW;
hill.x = (hill.x - deltaS * 30);
if (hill.x + hill.image.width * hill.scaleX <= 0) {
hill.x = w;
}
hill2.x = (hill2.x - deltaS * 45);
if (hill2.x + hill2.image.width * hill2.scaleX <= 0) {
hill2.x = w;
}

stage.update(event);
}

---------------------------------------------------------------------------------

整體來說並不是很複雜
概念上也與之前寫過的java遊戲類似
都是藉由一個主要的時序控制來計算"下一個瞬間"的狀態
因此,只要能預先規劃好每一個物件狀態的規則與變動順序
相信要實踐就不會太過困難

時間已晚,WORDKEEPER的規劃就留到下一篇再寫~

沒有留言 :

張貼留言