PIXI 完整示例-PIXI文檔翻譯(7)

案例研究:尋寶者

所以我告訴你,你現在有所有你需要開始製作遊戲的技能。什麼?你不相信我?讓我向你證明吧!讓我們接近如何使一個簡單的對象集合和敵人迴避遊戲稱爲寶藏獵人。(你會找到它的examples 文件夾。)

[img]http://dl2.iteye.com/upload/attachment/0123/3482/db55d716-ffd2-3406-89bc-3ec9ecd0c5bc.png[/img]

寶藏獵人是一個最簡單的完整的遊戲,你可以使用迄今爲止所學到的工具之一的一個很好的例子。使用鍵盤箭頭鍵幫助資源管理器找到寶藏,並把它帶到出口。六個blob怪物在地牢牆之間上下移動,如果他們擊中探險家,他變得半透明,右上角的健康表收縮。如果所有的健康用完,“你失去!”顯示在舞臺上; 如果資源管理器到達帶有寶藏的出口,則顯示“You Won!”。雖然它是一個基本的原型,寶藏獵人包含大多數元素,你會發現在更大的遊戲:紋理地圖集圖形,交互性,碰撞和多個遊戲場景。讓我們來看看遊戲是如何組合在一起的,這樣你可以使用它作爲你自己的遊戲的起點。

代碼結構

打開treasureHunter.html文件,你會看到所有的遊戲代碼都在一個大文件。這裏是一個鳥瞰圖如何組織所有的代碼。


//Setup Pixi and load the texture atlas files - call the `setup`
//function when they've loaded

function setup() {
//Initialize the game sprites, set the game `state` to `play`
//and start the 'gameLoop'
}

function gameLoop() {
//Runs the current game `state` in a loop and renders the sprites
}

function play() {
//All the game logic goes here
}

function end() {
//All the code that should run at the end of the game
}

//The game's helper functions:
//`keyboard`, `hitTestRectangle`, `contain` and `randomInt`


使用它作爲你的世界地圖的遊戲,我們看看每個部分如何工作。


在設置功能中初始化遊戲

一旦紋理地圖集圖像已加載,setup函數就會運行。它只運行一次,並允許您爲您的遊戲執行一次性設置任務。它是創建和初始化對象,精靈,遊戲場景,填充數據數組或解析加載的JSON遊戲數據的好地方。

這裏是setup對Treasure Hunter中函數的簡略視圖,以及它執行的任務。


function setup() {
//Create the `gameScene` group
//Create the `door` sprite
//Create the `player` sprite
//Create the `treasure` sprite
//Make the enemies
//Create the health bar
//Add some text for the game over message
//Create a `gameOverScene` group
//Assign the player's keyboard controllers

//set the game state to `play`
state = play;

//Start the game loop
gameLoop();
}


最後兩行的碼,state = play;並且gameLoop()也許是最重要的。運行gameLoop遊戲引擎上的開關,並使得該play函數在連續循環中被調用。但在我們看看它是如何工作之前,讓我們看看setup函數中的具體代碼是什麼。


創建遊戲場景

該setup函數創建兩個Container稱爲gameScene和的組 gameOverScene。每個都添加到舞臺上。

gameScene = new Container();
stage.addChild(gameScene);

gameOverScene = new Container();
stage.addChild(gameOverScene);


作爲主遊戲的一部分的所有精靈都被添加到 gameScene組中。應該在遊戲結束時顯示的文本上的遊戲將添加到gameOverScene組中。


[img]http://dl2.iteye.com/upload/attachment/0123/3484/1a188c27-eb99-310d-8867-cbf6088afc39.png[/img]


雖然它是在setup函數中創建的,但是gameOverScene 當遊戲第一次啓動時它不應該是可見的,所以它的visible 屬性被初始化爲false。

gameOverScene.visible = false;


你會看到前方的是,當比賽結束時,gameOverScene的visible 屬性將被設置爲true以顯示出現在比賽結束的文本。


做地牢,門,探險家和寶藏

玩家,出口門,寶箱和地牢背景圖像都是由紋理地圖框架製成的精靈。非常重要的是,他們都被添加爲孩子gameScene。


//Create an alias for the texture atlas frame ids
id = resources["images/treasureHunter.json"].textures;

//Dungeon
dungeon = new Sprite(id["dungeon.png"]);
gameScene.addChild(dungeon);

//Door
door = new Sprite(id["door.png"]);
door.position.set(32, 0);
gameScene.addChild(door);

//Explorer
explorer = new Sprite(id["explorer.png"]);
explorer.x = 68;
explorer.y = gameScene.height / 2 - explorer.height / 2;
explorer.vx = 0;
explorer.vy = 0;
gameScene.addChild(explorer);

//Treasure
treasure = new Sprite(id["treasure.png"]);
treasure.x = gameScene.width - treasure.width - 48;
treasure.y = gameScene.height / 2 - treasure.height / 2;
gameScene.addChild(treasure);


將它們保存在gameScene組中將使我們能夠在遊戲完成時隱藏gameScene和顯示gameOverScene遊戲。


製作blob的怪物

六個blob怪物在一個循環中創建。給每個斑點一個隨機的初始位置和速度。垂直速度交替地乘以1或-1針對每個斑點,並且這是什麼導致每個斑點沿與它旁邊的相反的方向移動。每個創建的Blob怪物都被推入一個名爲的數組 blobs。


var numberOfBlobs = 6,
spacing = 48,
xOffset = 150,
speed = 2,
direction = 1;

//An array to store all the blob monsters
blobs = [];

//Make as many blobs as there are `numberOfBlobs`
for (var i = 0; i < numberOfBlobs; i++) {

//Make a blob
var blob = new Sprite(id["blob.png"]);

//Space each blob horizontally according to the `spacing` value.
//`xOffset` determines the point from the left of the screen
//at which the first blob should be added
var x = spacing * i + xOffset;

//Give the blob a random `y` position
var y = randomInt(0, stage.height - blob.height);

//Set the blob's position
blob.x = x;
blob.y = y;

//Set the blob's vertical velocity. `direction` will be either `1` or
//`-1`. `1` means the enemy will move down and `-1` means the blob will
//move up. Multiplying `direction` by `speed` determines the blob's
//vertical direction
blob.vy = speed * direction;

//Reverse the direction for the next blob
direction *= -1;

//Push the blob into the `blobs` array
blobs.push(blob);

//Add the blob to the `gameScene`
gameScene.addChild(blob);
}


做健康吧

當你玩Treasure Hunter時,你會注意到當探險家觸及其中一個敵人時,屏幕右上角健康條的寬度減小。這個健康吧怎麼樣?它只是兩個重疊的矩形在完全相同的位置:後面的黑色矩形,和前面的紅色矩形。它們被分組成一個healthBar 組。然後healthBar將其添加到gameScene並定位在舞臺上。

//Create the health bar
healthBar = new PIXI.DisplayObjectContainer();
healthBar.position.set(stage.width - 170, 6)
gameScene.addChild(healthBar);

//Create the black background rectangle
var innerBar = new PIXI.Graphics();
innerBar.beginFill(0x000000);
innerBar.drawRect(0, 0, 128, 8);
innerBar.endFill();
healthBar.addChild(innerBar);

//Create the front red rectangle
var outerBar = new PIXI.Graphics();
outerBar.beginFill(0xFF3300);
outerBar.drawRect(0, 0, 128, 8);
outerBar.endFill();
healthBar.addChild(outerBar);

healthBar.outer = outerBar;


您可以看到一個名爲的屬性outer已添加到 healthBar。它只引用outerBar(紅色矩形),以便以後訪問方便。

healthBar.outer = outerBar;

你不必這樣做; 但是,嘿爲什麼不!這意味着如果你想控制紅色的寬度outerBar,你可以寫一些光滑的代碼,看起來像這樣:
healthBar.outer.width = 30;

這是非常整潔和可讀性,所以我們會保持它!

製作消息文本

當遊戲結束時,根據遊戲的結果,一些文本顯示“你贏了!”或“你失去了!”。這是使用文本精靈並將其添加到gameOverScene。由於 gameOverScene的visible屬性設置爲false遊戲開始時,你無法看到這個文本。這裏是來自setup 函數的代碼,它創建消息文本並將其添加到 gameOverScene。


message = new Text(
"The End!",
{font: "64px Futura", fill: "white"}
);

message.x = 120;
message.y = stage.height / 2 - 32;

gameOverScene.addChild(message);


玩遊戲

所有的遊戲邏輯和使sprite移動的代碼發生在play函數內部,它在連續循環中運行。這裏有一個play功能的概述

function play() {
//Move the explorer and contain it inside the dungeon
//Move the blob monsters
//Check for a collision between the blobs and the explorer
//Check for a collision between the explorer and the treasure
//Check for a collsion between the treasure and the door
//Decide whether the game has been won or lost
//Change the game `state` to `end` when the game is finsihed
}


讓我們來了解所有這些功能如何工作。


移動資源管理器

使用鍵盤控制瀏覽器,並且其代碼與您之前學習的鍵盤控制代碼非常相似。該keyboard對象修改資源管理器的速度,並且速度加在裏面探險的位置play 的功能。


explorer.x += explorer.vx;
explorer.y += explorer.vy;



包含運動

但是新的東西是,探險家的運動包含在地牢的牆壁內。綠色輪廓顯示了探險者的運動的極限。


[img]http://dl2.iteye.com/upload/attachment/0123/3486/ac14777b-995b-324e-ad07-4ce809a78e89.png[/img]


這是通過調用自定義函數的幫助完成的 contain

contain(explorer, {x: 28, y: 10, width: 488, height: 480});


contain有兩個參數。第一個是你想保留的精靈。第二個是與任何對象x,y,width和 height屬性定義的矩形區域。在此示例中,包含對象定義了剛好稍微偏離舞臺並且小於舞臺的區域。它匹配地牢牆的尺寸。

這裏的contain功能,所有這些工作。該函數檢查sprite是否已經越過包含對象的邊界。如果它有,代碼將sprite移回到邊界。該contain函數還返回collision值爲“top”,“right”,“bottom”或“left”的變量,這取決於sprite命中的邊界的哪一側。(collision會undefined如果精靈沒有擊中任何的界限。)

function contain(sprite, container) {

var collision = undefined;

//Left
if (sprite.x < container.x) {
sprite.x = container.x;
collision = "left";
}

//Top
if (sprite.y < container.y) {
sprite.y = container.y;
collision = "top";
}

//Right
if (sprite.x + sprite.width > container.width) {
sprite.x = container.width - sprite.width;
collision = "right";
}

//Bottom
if (sprite.y + sprite.height > container.height) {
sprite.y = container.height - sprite.height;
collision = "bottom";
}

//Return the `collision` value
return collision;
}


你會看到collision返回值將如何使用在代碼前面,使blob的怪物反彈在頂部和底部的地下城牆之間。


移動怪物

該play功能還移動的怪物,保持它們包含在地牢的牆壁內,並檢查每一個與玩家的碰撞。如果一個斑點撞到地牢的頂壁或底壁,它的方向是相反的。所有這一切都是在一個forEach循環的幫助下完成的,該循環遍歷每個幀上blob的blobs數組中的每個sprite 。


blobs.forEach(function(blob) {

//Move the blob
blob.y += blob.vy;

//Check the blob's screen boundaries
var blobHitsWall = contain(blob, {x: 28, y: 10, width: 488, height: 480});

//If the blob hits the top or bottom of the stage, reverse
//its direction
if (blobHitsWall === "top" || blobHitsWall === "bottom") {
blob.vy *= -1;
}

//Test for a collision. If any of the enemies are touching
//the explorer, set `explorerHit` to `true`
if(hitTestRectangle(explorer, blob)) {
explorerHit = true;
}
});


你可以在上面的代碼中看到contain 函數的返回值是用來使blob從牆上彈起。一個變量called blobHitsWall用於捕獲返回值:

var blobHitsWall = contain(blob, {x: 28, y: 10, width: 488, height: 480});


blobHitsWall通常會undefined。但是如果blob擊中頂壁,blobHitsWall將具有值“top”。如果blob命中底壁,blobHitsWall將具有值“bottom”。如果這些情況之一true,你可以通過反轉它的速度顛倒blob的方向。這裏是這樣做的代碼:

if (blobHitsWall === "top" || blobHitsWall === "bottom") {
blob.vy *= -1;
}


乘以blob的vy(垂直速度)值-1將翻轉它的運動方向。

檢查衝突

上面的循環中的代碼hitTestRectangle用來確定是否有任何敵人觸摸了資源管理器。

if(hitTestRectangle(explorer, blob)) {
explorerHit = true;
}


如果hitTestRectangle返回true,這意味着有一直碰撞和稱爲變量explorerHit被設定爲true。如果explorerHit 是true,該play函數使瀏覽器半透明,並減少條的寬度health1個像素。

if(explorerHit) {

//Make the explorer semi-transparent
explorer.alpha = 0.5;

//Reduce the width of the health bar's inner rectangle by 1 pixel
healthBar.outer.width -= 1;

} else {

//Make the explorer fully opaque (non-transparent) if it hasn't been hit
explorer.alpha = 1;
}


如果 explorerHit是false,則explorer的alpha屬性保持爲1,這使得它完全不透明。

該play功能還檢查寶庫和資源管理器之間的碰撞。如果有一個命中,treasure被設置爲資源管理器的位置,有輕微的偏移。這使它看起來像探險家攜帶的寶藏。


[img]http://dl2.iteye.com/upload/attachment/0123/3496/45daaf5d-4eda-3ea5-a24d-14e7dc8161e0.png[/img]


這裏是這樣做的代碼:
if (hitTestRectangle(explorer, treasure)) {
treasure.x = explorer.x + 8;
treasure.y = explorer.y + 8;
}


到達出口門並結束遊戲

遊戲有兩種方式可以結束:如果你把寶藏帶到出口,你可以贏;如果你失去健康,你可以失去。

要贏得比賽,寶箱只需要觸摸出口門。如果發生這種情況,遊戲state設置爲end,message文本顯示“你贏了”。

if (hitTestRectangle(treasure, door)) {
state = end;
message.text = "You won!";
}


如果你的健康,你失去了遊戲。遊戲state也設置爲end,message文本顯示“你失去了!

if (healthBar.outer.width < 0) {
state = end;
message.text = "You lost!";
}


但這是什麼意思?

state = end;


你會記住從前面的例子,gameLoop不斷更新一個函數調用 state每秒60次。這是gameLoop做到這一點:

function gameLoop(){

//Loop this function 60 times per second
requestAnimationFrame(gameLoop);

//Update the current game state
state();

//Render the stage
renderer.render(stage);
}


您還記得我們最初設定的值 state來play,這就是爲什麼play函數在一個循環中運行。通過設置state到end我們告訴我們想要另一個函數的代碼,被稱爲end在循環中運行。在一個更大的遊戲中,你可以有一個tileScene狀態,併爲每個遊戲關卡,如 leveOne,levelTwo和levelThree。

那麼這個end功能是什麼呢?這裏是!

function end() {
gameScene.visible = false;
gameOverScene.visible = true;
}


它只是翻轉遊戲場景的可見性。這是隱藏gameScene和顯示gameOverScene遊戲結束時。

這是一個非常簡單的例子,如何切換遊戲的狀態,但你可以擁有儘可能多的遊戲狀態,你喜歡在你的遊戲,並填充他們需要儘可能多的代碼。只需將值更改爲state要在循環中運行的任何函數。

這真的是所有的寶藏獵人!有了更多的工作,你可以把這個簡單的原型成一個完整的遊戲 - 試試吧!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章