創作內容

1 GP

[RMMV 插件] 打磚塊-技能插件進階

作者:未来ずら│2016-08-23 19:05:49│巴幣:2│人氣:294
本篇要介紹的是 STLLA_BreakoutSkill.js 的附屬插件:

這個插件可讓使用者自行創造遊戲專用的飛道
不過,需要有一定腳本編寫能力



打開 STLLA_BreakoutBullets.js,以範例的 BulletFire 為教學範本:


首先一開始的:
STILILA.BO.BulletFire = function BulletFire() {
this.initialize.apply(this, arguments);
}
STILILA.BO.BulletFire.prototype = Object.create(Game_BreakoutBullet.prototype);
STILILA.BO.BulletFire.prototype.constructor = STILILA.BO.BulletFire;
就是告訴系統有 BulletFire 這個Class可以生成,BulletFire 你就當作是飛道的名字

簡單說,未來想建立新的飛道時,先複製這段,把 BulletFire 的部分改成你想要的名稱即可
例如要做一個 BulletIce
STILILA.BO.BulletIce = function BulletIce() {
this.initialize.apply(this, arguments);
}
STILILA.BO.BulletIce.prototype = Object.create(Game_BreakoutBullet.prototype);
STILILA.BO.BulletIce.prototype.constructor = STILILA.BO.BulletIce;

有概念的人會注意到他繼承了 Game_BreakoutBullet
表示可使用它所有方法,就不用為了同樣的方法(ex:撞到磚塊的計算)再寫一遍
總之就是基本處理 (定期更新、碰撞判斷) 已經有了


初始化

既然要做自定義飛道,就不能只有元類的東西
所以接下來要先進行屬於自己的初始化,需用到元類的 initCustom 這方法:
// ----------------------------------------------
// ● 自定義初始化
//   user:使用者(Game_BreakoutBullet、Game_Battler)
//   x、y:生成時的x、y(視板子位置而定)
// ----------------------------------------------
STILILA.BO.BulletFire.prototype.initCustom = function(user, x, y) {
// (必須)載入圖片 & 記錄快取Key
this.loadBitmap('fireball');
// (必須)裁切圖片的寬、高、橫向格數
this.bitmapW = 50;  
this.bitmapH = 50;
this.bitmapRow = 3;
// 設定初期判定塊
this.setAtkRects([[-10,-25,21,50]]);
// 設定運動能力
this.speedX = 0;
this.speedY = 7;
this.atk = 0;
// 設定圖片
this.setPicture(0);
}
藍字部分是你的飛道名稱
紅字則是方法名稱,這裡先知道 initCustom 是用來做初始化的就好,這篇最後會列出已有特定功能的方法和變數
綠字部分是調用時給予的參數,雖然參數在這方法內沒用到,但要知道還有這三個值可用

註解打必須的部分就是一定要做的事,不然會出問題

載入圖片
this.loadBitmap('fireball');

就是飛道要用的圖片名稱,讀取路徑和本體插件一樣,
總之和打磚塊系統有關的圖片都是同個資料夾

裁切圖片的寬、高、橫向格數
this.bitmapW = 50;  
this.bitmapH = 50;
this.bitmapRow = 3;
從上面的圖也看見了,有三格,所以要進行裁切,用這三個變數指定即可
做這動作同時也幫圖片編號了,見下

設定圖片:
this.setPicture(0)
裁切完之後就可以決定要顯示哪一格,這張圖只有3格
0的話就是最左邊那格,1就是中間、2是右邊
如果有更多,也是依此類推

設定初期攻擊判定:
this.setAtkRects([[-10,-25,21,50]])
設定判定塊,[x, y, w, h] 這樣就是一塊
可設定多塊,例如:
this.setAtkRects([[x1,y1,w1,h1], [x2,y2,w2,h2], [x3,y3,w3,h3]])
注意 x 和 y 要依圖片的原點位置修正(預設x、y各0.5,也就是圖片中心),
要確認可去 STLLA_BreakoutSkill.js 把顯示判定塊功能打開


設定運動能力:
this.speedX = 0;
this.speedY = 7;
this.atk = 0;
範例中X速度:0、Y速度7、攻擊力0


設定動畫(狀態機)表
這也是每個自訂飛道都要寫的東西
想說動作判斷都寫在 update 到最後會挺亂的,所以敲了這玩意,
哪種狀態、負責什麼一目了然:
// ----------------------------------------------
// ● 設置動畫表
// ----------------------------------------------
STILILA.BO.BulletFire.prototype.setAnimes = function() {
// 飛行
this.animes['normal'] = [];
this.animes['normal'][0] = {pic: 0, wait: 6, next: 1};
this.animes['normal'][1] = {pic: 1, wait: 6, next: 2};
this.animes['normal'][2] = {pic: 2, wait: 6, next: 0};
// 爆炸
this.animes['explosion'] = [];
this.animes['explosion'][0] = {pic: -1, wait: 4, next:1, atkPower: 2, atkRect:[[-45,-65,90,90]], animation: 14, speedY: 0};
this.animes['explosion'][1] = {pic: -1, wait: 36, next:'destorySelf', atkRect: 0};
}

(...有改過 LF2 應該對後面那個 pic、wait、next 不陌生吧,好你會了可以改了)


建立新動畫:
this.animes[動畫名稱] = [];
如果要加新動畫這行一定要先寫,不然會出現未定義的錯誤,
另外'normal' 是一開始被系統指定好的名字,可說一定要有
建立好後就能寫它的內容

設定動畫內容:
this.animes[動畫名稱][Frame號] = { Frame參數 }
一個動畫最小單位是 Frame (影格)
飛道運作就是靠動畫和Frame的切換、讀取Frame參數來實現
Frame起始編號為 0


然後,看到「normal」 的 0號Frame:
this.animes['normal'][0] = {pic: 0, wait: 6, next: 1};
參數表示「圖片編號 = 0」、「這格Frame停留6F」、「下一個Frame號 = 1」

normal」動畫只有三個Frame,
你也看到了,最後一個Frame寫了「next: 0」回到 0號Frame,構成了一個循環動畫
這就是BulletFire的飛行動畫


下面還有一個「explosion」動畫:
pic: -1, wait: 4, next:1, atkPower: 2, atkRect:[[-45,-65,90,90]], animation: 14, speedY: 0
用途分別為:
「圖片編號 = -1」、「停留4F」、「下格Frame號 = 1」
「攻擊力 = 2」、「變更攻擊判定塊」、「播放14號動畫」、「Y移動速度 = 0」

「圖片編號 = -1 」? 這樣有圖嗎?
是的,沒有,所以-1表示「不顯示圖片」

而下一格,只講比較特別的兩個:
next:'destorySelf', atkRect: 0
「接下來執行 destorySelf 方法」、「消除攻擊判定塊」

可以看到next不是數字了,next參數可設定三種類型的值:
數字--表示跳往 n 號Frame
Array--[動畫名稱, Frame編號] ,表示跳往指定動畫的Frame號(Frame號可省略)。
                例:next: ['break']
文字--表示執行這個Class的同名方法。例:next: 'destorySelf'

destorySelf 方法也是繼承自元類的,
就是告訴系統這飛道可以消除了,不然會一直留在場上


問題來了,這動畫表並沒有設定從「normal」 跳往「explosion」的方式啊?
所以,繼續往下看:
// ----------------------------------------------
// ● 撞到磚塊 (block:磚塊對象)
// ----------------------------------------------
STILILA.BO.BulletFire.prototype.collideBlock = function(block) {
// 飛行時,變為爆炸
if (this.animeName === 'normal') {
this.changeAnime('explosion');
return;
// 爆炸時
} else {
// 磚塊破壞
this.attackBlock(block, true); // 破壞磚塊,但不計算連擊
}
}
collideBlock 也是繼承自元類的方法(以下統稱預設行為),在飛道碰到磚塊時執行一次
這裡就得親自寫腳本了,
this.animeName 也是預設變量,表示目前動畫

這一串表示如果目前動畫是「normal」,就這樣做:
this.changeAnime('explosion');  // 切換動畫至「explosion
return;  // 中斷
this.changeAnime(動畫名稱[, Frame號])
切換到指定動畫,如果frame號省略,就是從0 frame開始
(引號內的參數表示它可以省略,實際寫的時候不要加引號)

於是在飛行時撞到磚塊瞬間,就會因條件分歧切換至「explosion」動畫
要注意的是,切換動畫瞬間,先前碰撞判定會消除
所以又會再執行一次collideBlock,但這次因為不符合「this.animeName === 'normal'」 的條件,所以變成執行 else 的內容:
this.attackBlock(block, true); // 破壞磚塊,但不計算連擊
this.attackBlock(block[, noCombo])
攻擊指定磚塊的方法,
block 表示某個磚塊物件,因為執行 collideBlock 時會取得接觸到的磚塊物件,可以直接用
noCombo 也是可選參數,為 true 的時候表示不累積Combo數,省略時則是false
我覺得 BulletFire 判定很大,所以不想讓它加Combo,不然很容易高分

就這樣,BulletFire 完成了,就是一個往上飛、撞到磚塊會爆炸、然後消失的飛道
接下來範例有個更複雜的定時炸彈,就繼續講解


看到定時炸彈的Class:
STILILA.BO.TimeBomb = function TimeBomb() {
this.initialize.apply(this, arguments);
}
STILILA.BO.TimeBomb.prototype = Object.create(Game_BreakoutBullet.prototype);
STILILA.BO.TimeBomb.prototype.constructor = STILILA.BO.TimeBomb;
// ----------------------------------------------
// ● 自定義初始化
//   user:使用者(Game_BreakoutBullet、Game_Battler)
// ----------------------------------------------
STILILA.BO.TimeBomb.prototype.initCustom = function(user, x, y) {
// (必須)載入圖片 & 記錄快取Key
this.loadBitmap('timebomb');
// (必須)裁切圖片的寬、高、橫向格數
this.bitmapW = 30;
this.bitmapH = 30;
this.bitmapRow = 3;
// 設定初期判定塊
this.setAtkRects([[-13,-13,26,26]]);
// 設定運動能力
this.speedX = 0;
this.speedY = 6;
this.atk = 0;
// 設定目前圖片
this.setPicture(0);
// 專用變數:記憶黏著的目標
this.target = null;
}
可以發現大致結構和 BulletFire 相同,但是最後多了個「this.target = null」
這個就不是系統預設的變量了,是為了做額外判斷而特地宣告、屬於 TimeBomb 的專用變量

接下來看到動畫表:
STILILA.BO.TimeBomb.prototype.setAnimes = function() {
// 飛行
this.animes['normal'] = [];
this.animes['normal'][0] = {pic: 0, wait: -1, next: 0};
// 黏著&倒數
this.animes['countdown'] = [];
this.animes['countdown'][0] = {pic: 0, wait: 60, next: 1, se: ['Computer', 110, 95], speedY: 0};
this.animes['countdown'][1] = {pic: 1, wait: 60, next: 2, se: ['Computer', 110, 95]};
this.animes['countdown'][2] = {pic: 2, wait: 60, next: ['explosion'], se: ['Computer', 110, 95]};
// 爆破
this.animes['explosion'] = [];
this.animes['explosion'][0] = {pic: -1, wait: 4, next:1, atkPower: 5, atkRect:[[-80,-60,160,100], [-60,-90,120,150]], animation: 15};
this.animes['explosion'][1] = {pic: -1, wait: 36, next:'destorySelf', atkRect: 0};
}
大致上也差不多,
只是這個飛道的設定是「往上飛,碰到磚塊停住開始計時(球碰到立刻少1秒),時間到爆炸」
就是多了個計時的步驟

normal
動畫的時候 wait :-1 表示永久停留在這格,需要用其他方式讓它跳轉動畫

countdown
炸彈黏到東西開始倒數了,可以看到 wait 都是60,因為1秒是60f
而se參數就是播放音效,格式為 [檔名, 頻率, 音量]
最後next: ['explosion'],跳至「explosion」動畫,提醒一次,有 [] 的是跳轉動畫,沒 [] 的是執行方法
不過可以發現沒有跳至「countdown」的設定,表示應該又是用先前介紹的方式跳轉了

explosion
沒有反應,和上面那個飛道一樣爆炸然後消滅,不過範圍更大了點


那麼介紹最關鍵的「countdown」跳轉,先跳過 collideBall 方法看到 collideBlock
STILILA.BO.TimeBomb.prototype.collideBlock = function(block) {
// 黏著
if (this.animeName === 'normal') {
this.changeAnime('countdown');
this.target = block;
return;
// 引爆
} else if (this.animeName === 'explosion') {
// 磚塊破壞
this.attackBlock(block, true); // 攻擊磚塊,但不計算連擊
this.target = null;
}
}
其實大致也是和 BulletFire 一樣,只是接觸跳轉改成了「countdown
而且因為這次動畫有三種,就不能只寫 else 了,要改成 else if ,否則在倒數時就會炸磚
(分歧太多可以用switch)

要提的是綠字部分,在接觸開始讀秒的時候 this.target = block
這個動作是讓它記憶接觸到的磚塊(block),爆炸時因為已經不需要記憶了,就改成null

為什麼要設個變數記憶呢?接下來看到這個方法:
// ----------------------------------------------
// ● 定期更新B(受暫停系效果影響)
// ----------------------------------------------
STILILA.BO.TimeBomb.prototype.updateCommonB = function() {
if (this.target && this.target.hp === 0) { // 目標HP為0就馬上爆炸
this.changeAnime('explosion');
this.target = null;
}
}

updateCommonB 是一個每 F 調用一次的方法,因為覺得直接改update不好,所以獨立出來
另外updateCommonB,註解也說了會受暫停系效果影響
這個暫停不是指ESC那個暫停,而是技能插件的那個...
<ザ・ワールド!!時よ止まれ!!
的暫停效果

好,可以看到裡面的判斷,
用基本的英文也可以理解就是黏到的磚塊血量突然變為0 (還在倒數就被球打掉)
就會馬上爆炸,爆炸後也是把this.target = null,不然下1F又要爆一次
至於判斷式要是沒有加 this.target,則因為 this.target 有可能是 null ,而 null 沒有 hp 這個值,就會報錯,因此一定要加
不做這判斷其實無所謂,不過就是磚塊被球打掉時會看到炸彈浮空很詭異

再往下看,它還更改了預設的 destorySelf
STILILA.BO.TimeBomb.prototype.destorySelf = function() {
this.target = null;
Game_BreakoutBullet.prototype.destorySelf.call(this); // super
}
總之也是把this.target = null
下面這行 Game_BreakoutBullet.prototype.destorySelf.call(this) 則是繼續執行預設的內容
因為預設的 destorySelf 還要做別的事情
(先前initCustom、setAnimes等只是空方法,所以可以不寫)
不加,就只會執行this.target = null,而飛道無法正常銷毀

如果你要更改其他預設行為,而且又發現預設行為有寫東西,那建議 super 一下
不然複製全部原始內容來改也行,但注意把 prototype 前面的字改成「STILILA.BO.你飛道的名稱」


最後,講到剛剛被跳過的collideBall
// ----------------------------------------------
// ● 撞到球 (ball:球對象)
// ----------------------------------------------
STILILA.BO.TimeBomb.prototype.collideBall = function(ball) {
// 倒數快進
if (this.animeName === 'countdown') {
// 球反彈
if (!ball.smashing) {
ball.dirX *= -1;
ball.dirY *= -1;
}
switch (this.frameNumber) {
case 0:
this.updateAnime(1);
break;
case 1:
this.updateAnime(2);
break;
case 2:
this.changeAnime('explosion');
break;
}
}
}
collideBall 顧名思義就是接觸到球會執行一次的方法
可以看到全寫在「this.animeName === 'countdown'」條件內,實現「被球撞到,加速讀秒」

collideBlock一樣,這方法內可全程使用「ball」這個值,它代表接觸到飛道的球物件

ball.smashing」表示球的貫通判定,
可以看到「如果處於非貫通的時候(驚嘆號為否定)」,球的行進方向會相反,也就是實現反彈行為

之後看到了以 this.frameNumber 為分歧的地方
除了 this.changeAnime,還有「this.updateAnime
this.updateAnime 只能指定跳轉畫格,如果只想改變畫格,用這方法即可

總之就是--
Frame 0 的時候被球撞到跳至 Frame 1
Frame 1 的時候被撞到跳至 Frame 2
Frame 2 的時候被撞到 就爆了


好的,兩個預設飛道的講解到此結束
如果在自製飛道上有什麼困難或是教學實在看得一臉茫然但又想做,歡迎在底下留言或來信詢問




最後是列出預設可用的行為(方法)和變量以及動畫參數,
這些在 STLLA_BreakoutBullets.js 的插件說明也有


預設變數
預設利用率較高的變數

this.bitmapW、this.bitmapH、 this.bitmapRow
裁切圖片的寬、高、橫向格數,影響 this.setPicture(number) 得到的結果

this.sprite.anchor.x、this.sprite.anchor.y  
圖片X、Y 原點 (0.0~1.0),預設皆0.5,即圖片中心

this.x、this.y              
X、Y座標

this.speedX、this.speedY    
X、Y移動速度

this.dirX、this.dirY
X、Y移動方向
※移動公式為:
this.x += this.speedX * this.dirX
this.y += this.speedY * this.dirY

this.atk
飛道攻擊力

this.throughBlock          
貫通磚塊判定
※預設false,如果 false,且 collideBlock(block) 沒改,飛道撞到磚塊後就會自動消滅

this.scene
目前Scene(Scene_Breakout)
可利用 Scene_Breakout 的方法

this.user                 
使用者(Game_Battler、Game_BreakoutBullet)

this.root                   
根使用者(Game_Battler)
如果想實現撞到磚塊回角色HP之類的,這兩個變數就需要了...

this.frameNumber            
Frame號

this.frameTime              
Frame經過時間

this.animeName              
動畫名稱

this.animeTime              
動畫經過時間



預設是空白,需自行定義內容的方法
這類方法已經決定好觸發時機,只要定義內容就好,不必特別去調用

initCustom(user,x,y)
user:飛道使用者(Game_Battler 或 Game_BreakoutBullet)
x、y:生成時的x、y,視板子位置、發射方式而定
自定義初始化
生成時會自動執行一次,不必特別使用

setAnimes()
設定動畫表
和自定義初始化一樣,生成時自動執行一次

updateCommonA()
updateCommonB()
每畫格定期執行一次,
A不受暫停系效果影響、B會,視需求決定要用哪個

collideBall(ball)
ball:球對象(Game_BreakoutBall)
接觸到球的時候執行一次

collideBlock(block)
block:磚塊對象(Game_BreakoutBlock)
接觸到磚塊的時候執行一次,注意內部已有簡單的判斷
如果只是簡單的子彈,只要設定this.atk(攻擊力)、this.throughBlock(貫通性)即可
不用改到這個方法

collidePaddle(paddle)
paddle:板子對象(Game_BreakoutPaddle),沒意外的話板子就唯一那個
接觸到板子的時候執行一次

collideWall(pos)
pos:up(上)、down(下)、left(左)、right(右),為String
接觸到畫面邊緣時執行一次
注意 down 的位置是防護罩的位置,防護罩不在場上不會判定



預設方法
已設好,可隨時利用的方法,必要時可自行更改

this.loadBitmap(filename)
filename:圖片名稱
載入圖片,這個動作會順便把做成的 bitmap 寫入臨時Cache,離開場景時釋放

this.setPicture(number)
number:圖片編號
切換圖片編號,顯示結果依 this.bitmapW、this.bitmapH、this.bitmapRow 三項數值來決定

this.destorySelf()
消滅自己,從場上移除

this.setAtkRects([rect1, rect2, rect3,...])
更改攻擊判定
rect 不是 Rectangle 對象,只是指定 「x, y, width, height」 的Array
ex:
this.setAtkRects([[-80,-60,160,100], [-60,-90,120,150]])

this.attackBlock(block[, noCombo])
block:block 對象
noCombo:為 true 時攻擊不計算連擊數,省略時為false
攻擊指定磚塊,通常寫在 collideBlock(block)
破壞磚塊的攻擊力純粹看 this.atk 的值,調用此方法前得先設好this.atk

this.changeAnime(name[, frame])
name:動畫名稱
frame:Frame號,省略時為0
跳轉至指定動畫,注意跳轉後接觸磚塊的判定會重置

this.updateAnime(frame)
frame:Frame號
跳轉至指定Frame



動畫表參數
設置動畫表時,可用的參數

pic (必須)
圖片號

wait (必須)          
此Frame的延遲值

next (必須)
Number:下個Frame號,同 this.updateAnime(frame)
Array:[動畫名[, Frame號]],變更為指定動畫,同 this.changeAnime(name[, frame])
String:執行同名方法(不過不能執行帶參數的方法)

atkRect             
設定攻擊判定塊([rect1, rect2,...]),0為消去。
this.setAtkRects([rect1, rect2, rect3,...])

atkReset            
消除已攻擊判定,可用來進行連擊

atkPower           
變更攻擊力

se                 
播放音效,格式:[檔名, 頻率, 音量]

animation           
播放指定ID的動畫
這邊的動畫指的是 RM 的戰鬥動畫

speedX、speedY     
變更X、Y速度

dirX、dirY          
變更X、Y方向

throughBlock        
貫通磚塊判定 (true/false)




boss戰插件預定......(爆
不過在那之前要先讓舊腳本對應主程式v1.31...

引用網址:https://home.gamer.com.tw/TrackBack.php?sn=3299125
All rights reserved. 版權所有,保留一切權利

相關創作

同標籤作品搜尋:RM|MV plugin

留言共 0 篇留言

我要留言提醒:您尚未登入,請先登入再留言

1喜歡★qootm2 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:[RMMV 插件] 打磚... 後一篇:[RMVA / MV /...

追蹤私訊切換新版閱覽

作品資料夾

leon770530巴友
我的小屋首頁共有4篇健身相關證照心得文,對健身有興趣的朋友可以來看看喔!看更多我要大聲說2小時前


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】