EngineJS

開始

這個章節將會一步一步帶你做出一個完整的小遊戲,所有的步驟都會附上程式碼與實際範例,可以點擊範例程式執行並觀察成果。

設定背景

setBackdrop(path, x, y, width, height);path: 素材的網址
x: 背景圖左上角 x 座標
y: 背景圖左上角 y 座標
width: 長度
height: 寬度

setBackdrop("./assets/background.png", 0, 0, 470, 400);
範例程式

創造角色

創造出小鳥,預設位置為場景中央

var bird = createSprite("./assets/bird.png");

創造出上下水管,並設定座標位置

var tubeUp = createSprite({
    costumes: "./assets/up-tube.png",
    x: 450,
    y: -30
});
var tubeDown = createSprite({
    costumes: "./assets/down-tube.png",
    x: 450,
    y: 430
});
範例程式

遊戲迴圈

forever(fn) | aways(fn) | update(fn) fn: 遊戲迴圈,重複不斷執行的函式

在遊戲迴圈裡不斷移動水管,如果水管移動超出邊界就重置水管的位置

forever(function() {
    tubeUp.x -= 2;
    tubeDown.x -= 2;
    if(tubeUp.x < 0) {
        resetTube();
    } 
});

重置水管的函式,將水管移到右邊遊戲場景外,並隨機水管的位置

function resetTube () {
    var pos = Math.random()*300 + 50;
    tubeUp.x = 450;
    tubeDown.x = 450;
    tubeUp.y = pos - 230;
    tubeDown.y = pos + 230;
}
範例程式

遊戲事件

幫鳥加上重力,創造變數 vx 表示鳥的下降速度

var vy = 0;
forever(function() {
    bird.y + vy;
    vy += 0.2;
});

當滑鼠點擊時,鳥要往上飛行

when('click', function() { 
    vy = -5;
});

小鳥碰撞水管時停止遊戲

bird.when('touch', [tubeUp, tubeDown], function() {
    stop();
});
範例程式

遊戲音效

當滑鼠點擊銀幕時,播放跳耀的音效

 when('click', function() { 
     vy = -5; 
     sound.play('./assets/jump.ogg');
});

進入遊戲後就不斷重複播放背景音樂

 var bgm = sound.play('./assets/bgm.ogg');
 bgm.loop = true;
範例程式

顯示文字

設計計分板並顯示在畫面左上方

var scores = 0;
forever(function() {
   if(tubeUp.x < 0) {
       scores += 1;
   }
   print(scores, 10, 10, 'white', 45);
});
範例程式

完成

創造開始按鈕與遊戲結束Logo,並隱藏結束Logo

var startBtn = createSprite("./assets/start-button.png");
var gameOverLogo = createSprite({
    costumes: "./assets/gameOver.png",
    hidden: true,
    y: 100
});

當點擊開始按鈕時,執行初始化函式 start,遊戲初始化函式會初始角色的座標與歸零分數,並將飛行狀態改為 true

startBtn.when('click', start);
 
var flying = false;
function start () {
    startBtn.hidden = true;
    gameOverLogo.hidden = true;
    flying = true;
    bird.y = 200;
    scores = 0;
}

當玩家撞到水管或是超出上下的邊界,執行遊戲結束的函式 gameOver,將會顯示結束 logo 和重新開始的按鈕,並修改飛行狀態為 false

bird.when('touch', [tubeUp, tubeDown], gameOver);
forever(function() {
    if(bird.y > 400 || bird.y < 0) {
        gameOver();
    }
});
 
function gameOver () {
    gameOverLogo.hidden = false;
    startBtn.hidden = false;
    flying = false;
}

改寫遊戲迴圈的判斷式

forever(function() {
    if(!flying) {
        return;
    }
}
範例程式

角色屬性

座標

Sprite.x, Sprite.y角色的 x, y 座標

bird.x = 50;
bird.y = 50;
範例程式

方向

Sprite.direction角色面向的方向,值介於 0 ~ 359 度

bird.direction = 180;
範例程式

縮放

Sprite.sacle角色大小縮放比例,預設為 1

bird.scale = 0.5;
範例程式

旋轉方式

Sprite.rotationStyle角色旋轉的方式,三種方式
full (預設)
flipped (左右翻轉)
fixed (固定不旋轉)

Sprite.rotationStyle = 'fixed'
範例程式

透明度

Sprite.opacity值介於 0 ~ 1

Sprite.opacity
範例程式

造型編號

Sprite.costumeId角色當前造型,造型列表的索引

Sprite.costumeId = 1;
範例程式

圖層

Sprite.layer角色當前所在的圖層

 
Sprite.layer = 2;
範例程式

隱藏

Sprite.hiddentrue 設為隱藏,false 設為不隱藏

Sprite.hidden = true;
範例程式

角色方法

移動到

Sprite.moveTo(x, y);x: 目的位置 x 座標
y: 目的位置 y 座標

bird.moveTo(100, 100);
範例程式

移動

Sprite.move(vx, vy);vx: 水平移動距離 vx
vy: 垂直移動距離 vy

Sprite.move(100, 100);
範例程式

朝向前移動

Sprite.stepForward(d);d: 移動的步數

Sprite.stepForward(50);
範例程式

碰到邊界就反彈

Sprite.bounceEdge();

bird.forever(function() {
    this.stepForward(10);
    this.bounceEdge();
});
範例程式

朝向

Sprite.toward(target);target: Sprite 角色對象

Sprite.toward(target);                           
範例程式

綁定事件

Sprite.when(eventName, fun);eventname: "click", "touched", "hover"
fun: 事件觸發執行的函式

bird_1.when('touch', bird_2, function() {
    bird_2.moveTo(10, 10);
});
範例程式

碰撞檢測

sprite.touched(target);target: 若 sprite 碰撞到 target 返回 true

Sprite.touched(target);
範例程式

角色迴圈

Sprite.forever(fun);fun: 不斷執行的函式,this 綁定角色對象

bird.forever(function() {
    this.stepForward(1);
});
範例程式

播放動畫

Sprite.animate(frames, time, callback);frames: 動畫造型的順序
time: 動畫每一秒切換的幀數
callback: 動畫結束後執行的回呼函式

bird.animate([0, 1, 2, 3, 4, 5], 100);
範例程式

銷毀

Sprite.destroy();

bird.destroy();
範例程式

廣播

Sprite.destroy();

bird.when('listen', 'gameOver', function () {
    this.destroy();
});
broadcast("gameOver");
範例程式

角色之間的距離

Sprite.distanceTo();

bird_1.distanceTo(bird_2);
範例程式

事件

when | on綁定遊戲的事件的方法 Sprite.when | Sprite.on綁定角色事件的方法

碰撞

Sprite.when("touch", target, callback);單一對象的碰撞

bird.when("touch", bird, callback);
範例程式

Sprite.when("touch", [target], callback);多個對象的碰撞,可以傳入陣列

bird.when("touch",[bird_1, bird_2], callback);
範例程式

點擊事件

when("click", sprite, callback);當滑鼠點擊 sprite 執行函式

when("click", bird, function () {
    bird.scale += 0.5;
});
範例程式

Sprite.when("click", callback);當滑鼠點擊 sprite 執行函式

bird.when("click", function () {
    this.scale += 0.5;
});
範例程式

滑鼠按下

when("mousedown", callback);

when("mousedown", function() {
    bird.scale += 1;
});
範例程式

Sprite.when("mousedown", callback);

bird.when("mousedown", function() {
    this.scale += 1;
});
範例程式

滑鼠放開

when("mouseup", callback);

when("mouseup", function() {
    bird.scale += 1;
});
範例程式

Sprite.when("mouseup", callback);

bird.when("mouseup", function() {
    bird.scale += 1;
});
範例程式

鍵盤按下

when("keydown", keyName, callback);

當按下特定按鍵,觸發執行函式

when('keydown', "space", function() {
    bird.scale += 0.2;        
});
範例程式

when("keydown", keyName, callback);

當按下任意按鍵,觸發執行函式,觸發執行函式,可以傳入 "any" 或是省略參數

when('keydown', function() {
    bird.scale += 0.2;        
});
範例程式

鍵盤放開

when("keyup";, keyName, callback);

當放開特定按鍵,觸發執行函式

when("keyup", "space" , function() {
    bird.scale += 0.5;        
});
範例程式

when("keyup";, keyName, callback);

當放開任意按鍵,觸發執行函式,可以傳入 "any" 或是省略參數

when("keyup", function() {
    bird.scale += 0.5;        
});
範例程式

按鍵持續按壓

when("holding", keyName, callback);

持續按壓特定按鍵,觸發執行函式

when("holding", "right", function() {
    bird.x += 1;
});
範例程式

when("holding", callback);

持續按壓任意按鍵,觸發執行函式,可以傳入 "any" 或是省略參數

when("holding", function() {
    bird.direction += 3;
});
範例程式

鍵盤&滑鼠

滑鼠

cursor.x, cursor.y滑鼠 x,y 座標 cursor.left, cursor.right滑鼠左右鍵狀態 cursor.isDown滑鼠是否被按住

var cursor = cursor;
forever(function(){
    var y = 80
    print('**滑鼠測試**', 30, y, 'white');
    print('cursor.x: ' + cursor.x, 30, y+ 20, 'white');
    print('cursor.y: ' + cursor.y, 30, y + 2*20, 'white');
    print('cursor.left: ' + cursor.left, 30, y + 3*20, 'white');
    print('cursor.right: ' + cursor.right, 30, y + 4*20, 'white');
    print('cursor.isDown: ' + cursor.isDown, 30, y + 5*20, 'white');
});
範例程式

鍵盤

key[keyName] 鍵盤中特定鍵的狀態

forever(function(){
    var y = 80
    print('**鍵盤測試**', 30, y + 8*20, 'white');
    print('key.q: ' + key.q, 30, y + 9*20, 'white');
    print('key.w: ' + key.w, 30, y + 10*20, 'white');
    print('key.e: ' + key.e, 30, y + 11*20, 'white');
    print('key.r: ' + key.r, 30, y + 12*20, 'white');
});
範例程式

聲音

播放

sound.play(fileName, loop);fileName: 音效素材的路徑
loop: 非必要參數,傳入 true 則音效會不斷反覆播放

sound.play("shoot.mp3");
範例程式
範例程式

設定音量

sound.setVolume(num);num: 0 ~ 1 的音量大小

sound.setVolume(0.5);
範例程式

靜音

sound.mute(bool);bool: 若為 true 則將所有音效靜音

sound.mute(true);
範例程式

停止播放

sound.stop();停止所有的音效

sound.stop();
範例程式

繪筆

畫筆的屬性

設定繪筆的顏色、大小

pen.color繪筆線條的顏色 pen.size繪筆線條的寬度尺寸 pen.fillColor幾何圖形的填充的顏色

var pen = pen;
 
pen.color = "red";
pen.size = 30;
pen.fillColor = "blue";
範例程式

線條

pen.drawLine(x1, y1, x2, y2);

x1: 起點 x 座標
y1: 起點 y 座標
x2: 終點 x 座標
y2: 終點 y 座標

pen.drawLine(10, 10, 150, 150);
範例程式

矩形

pen.drawRect(x, y, width, height);

x: x 座標
y: y 座標
width: 長
height: 寬

pen.drawRect(400, 40, 200, 100);
範例程式

圓形

pen.drawCircle(x, y, r);

x: 圓心 x 座標
y: 圓心 y 座標
r: 半徑長

pen.drawCircle(200, 100, 100);
範例程式

三角形

pen.drawTriangle(x1, y1, x2, y2, x3, y3);

x1, y1: 角 1 的座標
x2, y2: 角 2 的座標
x3, y3: 角 3 的座標

pen.drawTriangle(200, 200, 300, 300, 200, 300);
範例程式

多邊形

pen.drawCircle(x1, y1, x2, y2, x3, y3, ...);

pen.drawPolygon(320, 240, 520, 120, 520, 420, 100, 400, 100, 200);
範例程式

文字

pen.drawText(text, x, y, font);

text: 文字的內容
x: X 座標
y: Y 座標
font: 字型,預設為 "Arial"

pen.drawText('測試123', 100, 100);
範例程式

雲端變數

設定雲端變數

DB.variables.set(variableName, value);

variableName: 變數名稱
value: 值

DB.variables.set("bestPlayer", USER_NAME);
DB.variables.set("bestScore", 300);

讀取雲端變數

DB.variables[variableName]

variableName: 變數名稱

forever(function () {
    print("最高分玩家:" + DB.variables.bestPlayer, 10, 10);
    print("得分:" + DB.variables.bestScore, 40, 10);
});

資料庫

初始化

DB.table(tableName)

tableName: 資料表的名稱

var users = DB.table("users");

新增

table.insert(data, callback);

data: 新增資料
callback: 回呼函式

// 新增五筆個人資料
users.insert({name: "David", age: 22});
users.insert({name: "Lily", age: 18});
users.insert({name: "Kevin", age: 25});
users.insert({name: "Allen", age: 18});
users.insert({name: "Williams", age: 21});

讀取

table.find(query, callback);

query: 符合條件的資料
callback: 回呼函式

 // 讀取所有資料
users.find({}, console.log);

// 讀取符合名字為 David 的資料
users.find({name: "David"}, console.log);

// 讀取符合年齡為 18 歲的資料
users.find({age: 18}, console.log);

更新

table.update(query, data, callback);

query: 符合條件的資料
data: 更新的資料

 // 符合名字為 Lily 的資料,年齡改成 17 歲
user.update({"name": "Lily"}, {age: 17});

刪除

table.remove(query, callback);

query: 符合條件的資料
callback: 回呼函式

user.remove({}, console.log); // 刪除所有的資料

Socket

發送訊息

DB.broadcast(port, message);

port: 接口名稱
message: 廣播的訊息

when("click", function () {
    var msg = prompt();
    DB.broadcast("say", msg);
});

接收訊息

DB.onMessage(port, handler);

port: 接口名稱
handler: 接收到訊息執行的回呼函式

DB.onMessage("say", console.log);