又一個跨平台遊戲開發工具?Game Closure 體驗

市場上可用於跨平台遊戲開發的工具已經愈來愈多,Corona,Unity3D 等等,現在又來了一個 Game Closure,號稱用 HTML5 來開發遊戲的它,到底有什麼特別之處呢?其官網就提到,100﹪ Javascript 以及擁有和原生遊戲一樣的速度,為什麼它可以用 HTML5 都做到原生速度呢?原來它在 iOS 和 Android 都研發了自家的引擎,加入了硬件加速,所以即使是運行 HTML5 亦能做到原生速度一樣。

本文將會使用 Game Closure 來開發一款簡單遊戲﹣是男人就堅持 20 秒,以此來體驗一下 Game Closure。

先說一下結論,覺得沒有用的可以不看。

結論:用來做網頁遊戲還可以(不過如果只做網頁遊戲用 canvas 就已經可以了吧...),用來做 iOS 和 Android 遊戲就自求多福了。

安裝過程不算困難,有些時候可能會安裝不了,只要跟著說明執行 command 就可以解決了。

官網說 Git 要版本要新於 1.7.10,但我 1.7.9 都能安裝,其實應該只要可以從 Github 拿 project 就可以了吧。

第一步先從 Github clone 一份檔案下來

git clone https://github.com/gameclosure/devkit

然後執行安裝

cd devkit
./install.sh

安裝途中我曾經遇到過這個錯誤:

其實就跟它執行一下 chown 這句就解決了,為什麼它不一早就提醒我呢

就這樣就安裝完成,還有問題就看官網

安裝完成後就來建立一個新 Project 玩玩,只需輸入以下 command。

basil init man20

新 Project man20 就建立好了。

或者你會注意到 command line 有這樣的一行:

[register] adding man20何謂 register?你可以想像成 basil 是一個遊戲平台,在你建立新 Project 時,它還會把這個 Project 自動登記到這個平台上,就像介面所示。

因此要記住:當你想移除一個 Project 時,除了執行 "rm" 把檔案系統中的 Project 移除之外,還要叫 basil 清理一下平台上的資料庫。

basil clean-register

亦因此,如果你從網上下載了別人的 Project,你也要把這個 Project register 到平台上才可以運行。這一步其實很奇怪,為什麼要把遊戲平台和開發平台結合在一起而不是兩者分開呢?西杰想不通!

建立了新 Project 後就要運行了,執行一下:

basil serve -p 8080

用了 -p 8080 就會把平台運行在 8080 port 之上。

按一下 Simulate 就會開始運行遊戲。

好,一切運作正常,開始寫遊戲!學習新事物,最好當然是動手玩玩,現在就開始寫代碼。

第一步當然是載入遊戲中的自己:


import device;

import ui.TextView as TextView;
import ui.ImageView as ImageView;

exports = Class(GC.Application, function () {

	this.initUI = function () {
		var me = new ImageView({
			superview: this.view,
			x: device.width / 2,
			y: device.height / 2,
			layout: "box",
			autoSize: true,
			image: "resources/images/me.gif"
		});
	};

	this.launchUI = function () {};
});


注意事項:

  1. superview 是指這個 View 應該是哪個 view 的 child view
  2. device 的闊和高是 device.width 及 device.height
  3. layout 是用來控制 child view 如何 render,這裏應該沒有影響
  4. autoSize 為 false 的話 ImageView 會擴大到整個 superview 的大小
  5. image 中的 path 是按照以下結構設定

簡單易明吧!還有一樣,就是要要角色的位置糾正好,把它真正的“置中”,GC 的 view 提供了 offsetX, offsetY 的屬性:

//regulating the position
me.style.offsetX = - me.style.width / 2;
me.style.offsetY = - me.style.height / 2;


第二步,讓角色跟著手指走。GC 提供了 Input* 的 event 來解決跨平台的需要(本來在手機要用 touch*,在桌面電腦要用 mouse*),加一個 InputMove 的 event 吧!


this.view.on("InputMove", function (event, point){
	me.style.x = point.x;
	me.style.y = point.y;
});


這樣角色就會跟著手指走了,而且還會置中!好了,下一步就是製造敵人,這個要放在 Game Loop 中處理了,跟據官方文件,Game Loop 應該放在 this.launchUI 之中。每個人天生就有對手(不是左手跟右手),遊戲裏的角色當然也有對手,這是由電腦產生的,會從上下左右四個方向進入遊戲畫面。


var Config = {
	enemyInterval: 130,
	gameLoopInterval: 1000 / 60
};

var enemies = [];

var EnemyBuilder = {
	lastEnemyCreateTime: 0,

	buildWhenAppropriate: function (view){
		if (new Date - this.lastEnemyCreateTime > Config.enemyInterval){
			//create a new enemy
			var newEnemy = new ImageView({
				superview: view,
				layout: "box",
				autoSize: true,
				image: "resources/images/enemy.gif"
			});

			newEnemy.velocity = {
				x: (Math.random() < 0.5 ? 1 : -1) * (Math.random() * 200 + 200) / 1000,
				y: (Math.random() < 0.5 ? 1 : -1) * (Math.random() * 200 + 200) / 1000
			};

			var rand = Math.random();
			if (rand < 0.25){
				//left
				newEnemy.style.x = - newEnemy.style.width;
				newEnemy.style.y = Math.random() * device.height;

				if (newEnemy.velocity.x < 0){
					newEnemy.velocity.x *= -1;
				}
			}else if (rand < 0.5){
				//top
				//...
			}else if (rand < 0.75){
				//right
				//...
			}else{
				//bottom
				//...
			}

			enemies.push(newEnemy);

			this.lastEnemyCreateTime = + new Date;
		}
	}
};

this.launchUI = function () {
	var tht = this;
	setInterval(function (){
		//Game Loop
		EnemyBuilder.buildWhenAppropriate(tht.view);

	}, Config.gameLoopInterval);
};

注意事項:

  1. velocity 就是對手的移動速度及方向
  2. 每隔 130 ms (隨機選擇的一個常數而已) 就會有新對手出現
  3. Game Loop 要放在 this.launchUI 之中

下一步是要令對手動起來!

var lastUpdateTime = + new Date;

setInterval(function (){
	//Game Loop
	var now = + new Date;
	var delta = now - lastUpdateTime;

	EnemyBuilder.buildWhenAppropriate(tht.view);

	//starting from last one such that we can remove from array at any time
	for (var i = enemies.length - 1; i >= 0; i--){
		var enemy = enemies[i];
		enemy.style.x += enemy.velocity.x * delta;
		enemy.style.y += enemy.velocity.y * delta;

		if (enemy.style.x < -Config.removeBound || enemy.style.x > device.width + Config.removeBound ||
			enemy.style.y < -Config.removeBound || enemy.style.y > device.height + Config.removeBound){

			enemy.removeFromSuperview();
			enemies.splice(i, 1);

		}
	}

	lastUpdateTime = now;
}, Config.gameLoopInterval);

在 Game Loop 中,所有對手的位置都會更新一次,如果超出了界限就當然要移除掉,不然會愈用愈多記憶體,而且愈來愈慢......對手會動,角色也會動,下一步就是撞擊檢查,GC 提供了一個簡單的 library 來做數學運算,其中包括多種撞擊檢查,雖然我們的角色和對手都是圓形,理論上可以有更簡單更有效率的檢查方法,但為了測試 GC,這裏就當它們是長方形來檢查!

if (intersect.rectAndRect(me.getBoundingShape(), enemy.getBoundingShape())){
	//collision
	console.log("collision");
}


很好很簡單,另外亦可看到,使用 GC 的話大家可以直接在瀏覽器中 debug 或 log message,這就是使用 HTML5 的力量了!下一步,加個計時器。

timeLabel = new TextView({
	superview: this.view,
	x: device.width / 2,
	y: device.height / 2,
	layout: "box",
	color: "#CCC",
	fontFamily: "Georgia",
	size: 24,
	text: "test"
});

...

timeLabel.setText("Time: " + ((now - gameStartTime) / 1000).toFixed(2) + "s");

奇怪了,計時器在哪?這個時候可以開一開平台中內置的 UI Inspector(不能用瀏覽器的 Inspector,因為這是 canvas...),看看有什麼錯。

一目了然,修改一下。

timeLabel = new TextView({
	superview: this.view,
	x: device.width / 2,
	y: 20,
	width: 200,
	height: 100,
	offsetX: -100,
	offsetY: -50,
	zIndex: 1,
	layout: "box",
	color: "#CCC",
	fontFamily: "Georgia",
	size: 24,
	text: "test"
});

出來了!

最後加個結局就完成了。

var restartBtn = new ImageView({
	superview: tht.view,
	layout: "box",
	x: device.width / 2,
	y: device.height / 2,
	zIndex: 1,
	autoSize: true,
	image: "resources/images/restart.png"
});

restartBtn.style.offsetX = - restartBtn.style.width / 2;
restartBtn.style.offsetY = - restartBtn.style.height / 2;

restartBtn.on("InputSelect", function (event, point){
	this.removeFromSuperview();
	gameStartTime = + new Date;
	lastUpdateTime = + new Date;
	end = false;

	for (var i = 0, l = enemies.length; i < l; i++){
		var enemy = enemies[i];
		enemy.removeFromSuperview();
	}
	enemies = [];

	me.style.x = device.width / 2;
	me.style.y = device.height / 2;
});
所謂的結局其實就是一個重新開始按鈕 。大功告成!由於發現內置的撞擊檢查不太準確,還是重新寫一下。
var xDiff = me.style.x - enemy.style.x;
var yDiff = me.style.y - enemy.style.y;
var rSum = (me.style.width + enemy.style.width) / 2;
if (xDiff * xDiff + yDiff * yDiff < rSum * rSum){

下一步就當然要驗証一下跨平台能力嚕!要在 iOS 中測試,第一步是先讓 basil 在 Xcode 注入它的東西,我也不知道是什麼東西,反正我就信了。

basil install native-ios

然後執行這句 command 就會把你的 project 變為 Xcode project 了。

basil debug native-ios

一 Run!

好像能夠運行,但...變了低清,大概是因為它沒有處理好 Retina 的東西吧。放到 iPhone 中如何呢?

扁過陳水扁...iOS 測試 Fail,Google 了一分鐘也找不到答案,看來相關文檔不多。同事提醒,試試打直又如何?

完美運行,而且也沒變低清,而是圖片縮小了!那麼 Android 如何呢?首先要安裝 SDK 和 NDK,教學在這裏找,由於西杰之前已經安裝了 SDK,現在只需把 SDK path 加到 PATH 中,NDK 我就選擇在官網直接下載。好了,忙完一大輪,是白花了十五分鐘的

結論:用來做網頁遊戲還可以(不過如果只做網頁遊戲用 canvas 就已經可以了吧...),用來做 iOS 和 Android 遊戲就自求多福了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值