Adobe Flash Builder 4 簡體中文正式版 Windows版點擊下載:http://g.csdn.net/5134151
Adobe Flash Builder 4 簡體中文正式版 Mac版點擊下載
:http://g.csdn.net/5134152
Adobe 在線課堂:http://adobev.csdn.net/zx/index.html
Adobe平臺技術峯會課程視頻:http://adobev.csdn.net/
http://blog.flashgen.com/gaming/pushbutton-engine/pushbutton-engine-handling-user-input/
在前幾篇文章中,我已經介紹瞭如何創建你的工作區 (Flash Professional 或 Flash Builder) 以及如何創建場景,並添加 玩家 實體 – 一般稱爲 主角 實體。在本文中,我將向你介紹如何關聯基本的鍵盤輸入,以控制玩家在場景中實際移動。
在瞭解代碼前,最好對你添加輸入控制時打開的不同選項有一定了解。你可以直接關聯 PBE 主類的 InputManager 實例,也可使用輸入映射。直接關聯很簡單,但是需要保證你的實體和 InputManager 之間有緊密的關係。
例如,如果你想要使使用者自定義遊戲控制按鍵 ( 這是非常對我胃口的一項設計,因爲我是左撇子,我的右手操作鍵盤不如左手那麼靈活 ) 。這同樣也使得用 PBE 對基於 XML 的描述符文件的支持變得難於實施,因爲他們期望一種替代機制 – 一種輸入映射來配置輸入。 該輸入映射是直接與進行關聯的一種替代 ( 更準確地說是一種擴展 ) 方案。
使用一種輸入映射的優點在於其可從 InputManager 提取鍵位關聯。這使得你可更方便地在任何一點改變鍵位。另外,輸入映射還使得從基於 XML 的 .pbelevel 文件中進行配置變得更爲簡單 ( 這會在以後的文章中詳述)。現在,讓我們看看如何通過兩種機制來進行鍵盤輸入映射。
使用
InputManager
進行鍵盤控制
將鍵盤控制添加至你的遊戲的最簡單的方法是
InputManager
類中的
isKeyDown()
方法。但是,如你將看到的,這可能導致過多複雜而難以控制的映射信息。讓我們就從這個入門,以便你在今後加以提高。和其他情況一樣,你需要創建一個類來管理輸入操作。這將從
TickedComponent
來繼承,這樣在每個遊戲時間(
game-tick
),都可以對其加以調用。基本架構是採用你的控制權,而不管
onTick()
方法。
要對你的實體進行各方面的關聯,你需要導入相關屬性引用。你可以發佈所需 ( 類型 PropertyReference) 的變量,然後通過所有人引用來在需要時進行訪問。因此,你可以從如下範例代碼中看出,有一個變量名爲 positionReference( 屬於類型 PropertyReference ),要訪問它,只需調用 owner.getProperty() 方法,並導入你想要訪問的引用,作爲方法簽名。
1 2 3 4 5 6 7 8 9 10 |
public var positionReference:PropertyReference;
override public function onTick ( deltaTime: Number ) : void { super . onTick ( deltaTime ) ;
var _position:Point = owner. getProperty ( positionReference ) ;
owner. setProperty ( positionReference, _position ) ; } |
要對一條屬性進行任何更改, 只需調用計數方法 getProperty() ,即 setProperty() 。 這種方法涉及兩種參數 – 引用的屬性和你想要爲其所設的值(如上述代碼底部所示)。 .
對鍵盤輸入進行映射是很簡單的,因爲 PBE 開發者已經提供了你關聯所想使用的幾乎每個按鍵的常數 ( 可點擊此處查看列表 here )。
完整的鍵盤控制類( KeyboardController class )如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
package com. flashgen . gaming . controllers { import com. pblabs . engine . PBE ; import com. pblabs . engine . components . TickedComponent ; import com. pblabs . engine . core . InputKey ; import com. pblabs . engine . entity . PropertyReference ;
import flash. geom . Point ;
publicclass KeyboardController extends TickedComponent { publicvar positionReference:PropertyReference;
publicfunction KeyboardController () { super () ; }
overridepublicfunction onTick ( deltaTime: Number ) : void { super . onTick ( deltaTime ) ;
var _position:Point = owner. getProperty ( positionReference ) ;
if ( PBE. isKeyDown ( InputKey. UP )) _position. y -= 5 ;
if ( PBE. isKeyDown ( InputKey. DOWN )) _position. y += 5 ;
if ( PBE. isKeyDown ( InputKey. LEFT )) _position. x -= 5 ;
if ( PBE. isKeyDown ( InputKey. RIGHT )) _position. x += 5 ;
if ( _position. x > 190 ) _position. x = 190 ;
if ( _position. x < - 190 ) _position. x = - 190 ;
if ( _position. y > 105 ) _position. y = 105 ;
if ( _position. y < - 105 ) _position. y = - 105 ;
owner. setProperty ( positionReference, _position ) ; } } } |
將控制器添加至你的實際實體是很簡單的。只需發佈元素即可 – 這裏指你的 KeyboardController ,併爲其分配所需屬性。最後,確保其添加至實體本身;如下列代碼所示:
1 2 3 |
var _input:SimpleKeyboardController = new SimpleKeyboardController () ; _input. positionProperty = new PropertyReference ( "@Spatial.position" ) ; _hero. addComponent ( _input, "Input" ) ; |
這都是基於上一篇文章《開始使用 Pushbutton引擎 》中介紹的玩家(主角)來設置的。但該代碼是整潔而簡要的 – 假設我只映射了4 個按鍵,它不能將輸入控制指令和實際控制類中定義的指令進行緊密關聯。一種更好的方法是將該信息進行提取,以便其可有用戶或外部配置來進行定義。可採用 InputMap 類來實現這一目的。
通過
InputMap
進行靈活得鍵盤映射
使用
InputMap
類需要一點逆向思維,這主要是因爲最好是從控制器開始,再回到將使用它的實體。現在
InputMap
類既有一些你肯定不會陌生的方便方法:
· mapActionToHandler()
· mapKeyToAction()
· mapKeyToHandler()
列表中最後一個是不言自明的,通過它,你可以輸入 InputKey 任務、每個處理器( handler ) 的名稱,且當按鍵按下時,處理器被調用。關於這些方法,有一點你必須瞭解,即它們不會將一個事件對象傳給處理器。它們只是早按鍵按下時傳遞值 1( 一),在按鍵彈起時傳遞值 0( 零)。
下列範例顯示瞭如何使用前兩個方法: mapActionToHandler() 和 mapKeyToAction() 。將這兩者想象爲一個物體的兩半。你把它們中的一個用於控制器內,而另一個在實體內(或你想映射的任何地方)。看看完整的鍵盤控制器 ( 我之前稱之爲 InputMapKeyboardController) ,對其進行分解,即可有更深的認識。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
package com. flashgen . gaming . controllers { import com. pblabs . engine . PBE ; import com. pblabs . engine . components . TickedComponent ; import com. pblabs . engine . core . InputKey ; import com. pblabs . engine . core . InputMap ; import com. pblabs . engine . entity . PropertyReference ;
import flash. geom . Point ;
public class InputMapKeyboardController extends TickedComponent { private var _inputMap:InputMap;
public var positionProperty:PropertyReference; private var _right: Number ; private var _left: Number ; private var _down: Number ; private var _up: Number ;
public function InputMapKeyboardController () { super () ; }
protected function onRight ( value: Number ) : void { _right = value; }
protected function onLeft ( value: Number ) : void { _left = value; }
protected function onDown ( value: Number ) : void { _down = value; }
protected function onUp ( value: Number ) : void { _up = value }
public override function onTick ( deltaTime: Number ) : void { super . onTick ( deltaTime ) ;
var _position:Point = owner. getProperty ( positionProperty ) ;
if ( Boolean ( _up )) _position. y -= 5 ;
if ( Boolean ( _down )) _position. y += 5 ;
if ( Boolean ( _left )) _position. x -= 5 ;
if ( Boolean ( _right )) _position. x += 5 ;
if ( _position. x > 190 ) _position. x = 190 ;
if ( _position. x < - 190 ) _position. x = - 190 ;
if ( _position. y > 105 ) _position. y = 105 ;
if ( _position. y < - 105 ) _position. y = - 105 ;
owner. setProperty ( positionProperty, _position ) ; }
public function get inputMap () :InputMap { return _inputMap; }
public function set inputMap ( value:InputMap ) : void { _inputMap = value;
if ( _inputMap ! = null ) { _inputMap. mapActionToHandler ( "Up" , onUp ) ; _inputMap. mapActionToHandler ( "Down" ,onDown ) ; _inputMap. mapActionToHandler ( "Left" , onLeft ) ; _inputMap. mapActionToHandler ( "Right" ,onRight ) ; } } } } |
如你所見,這與第一個控制器類並非差之千里。但是,最大的不同是與最後的 getter / setter 方法有關。我在 setter 中查看是否有一個有效的 InputMap 對象,如果有,則使用 mapActionToHandler() 在控制器中創建一個映射。如你所見,其取一個串值並將其與一個事先確定的處理器向關聯。
1 2 3 4 5 6 7 8 9 10 11 12 |
public function set inputMap ( value:InputMap ) : void { _inputMap = value;
if ( _inputMap ! = null ) { _inputMap. mapActionToHandler ( "Up" , onUp ) ; _inputMap. mapActionToHandler ( "Down" ,onDown ) ; _inputMap. mapActionToHandler ( "Left" , onLeft ) ; _inputMap. mapActionToHandler ( "Right" ,onRight ) ; } } |
在這些相關處理器中,只有一個變量,該變量設爲傳遞給它的當前數值 – 具體取決於該鍵是上還是下 (0 或 1 )。最後的不同是在 onTick() 方法中。與之前的控制器範例(明確檢視每個鍵來確定是否按下)不同,該範例採用的是處理器變量值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public override function onTick ( deltaTime: Number ) : void { super . onTick ( deltaTime ) ;
var _position:Point = owner. getProperty ( positionProperty ) ;
if ( Boolean ( _up )) _position. y -= 5 ;
if ( Boolean ( _down )) _position. y += 5 ;
if ( Boolean ( _left )) _position. x -= 5 ;
if ( Boolean ( _right )) _position. x += 5 ; ... } |
再觀察完整代碼,你可能會發現,我沒有在代碼中任何地方發佈實際輸入按鍵; 而是提供了一種抽象的方法來幫助你進行鍵盤映射。但是,對於控制器類來說,這就夠了。不過你將如何進行實際的映射工作?在本例中,你是在實體本身內進行映射。與你過去用來將添加基本鍵盤控制器添加至實體所用的三行代碼不同,你需要添加更多的參數:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var _input:InputMapKeyboardController = new InputMapKeyboardController () ;
_input. inputMap = new InputMap () ; _input. inputMap . mapKeyToAction ( InputKey. UP , "Up" ) ; _input. inputMap . mapKeyToAction ( InputKey. DOWN , "Down" ) ; _input. inputMap . mapKeyToAction ( InputKey. LEFT , "Left" ) ; _input. inputMap . mapKeyToAction ( InputKey. RIGHT , "Right" ) ;
_input. inputMap .
_input. positionProperty = new PropertyReference ( "@Spatial.position" ) ;
_hero. addComponent ( _input, "Input" ) ; |
這並沒有那麼難,但是你可以看出,你是通過我們的控制器的 InputMap 範例中的 mapKeyToAction() 方法來對輸入按鍵進行映射的。簡言之,要確保你記得例示 InputMap ,否則就會失敗 – 我當然知道,但還是要說明下,因爲我們常常因忽略簡單的事情而失敗。
小結
在本文中,你學到了如何通過
InputManage
實施簡單的鍵盤控制,首先通過你的控制器類裏明確定義輸入鍵,然後通過
InputMap
類(作爲
InputManager
的
一種外觀
)進行提取。你還學到了如何使用
InputMap
類來輕鬆地解除實際輸入鍵和遊戲之間的關聯
–
使得使用者可自定義鍵盤配置。
相關文件
PBE002_HandlingUserInput.zip