首頁 > web前端 > H5教程 > 主體

HTML5遊戲框架cnGameJS開發實錄-外部輸入模組篇

黄舟
發布: 2017-03-24 16:13:37
原創
1763 人瀏覽過

1.為什麼我們需要外部輸入模組?

  在遊戲中我們常常用到類似這樣的操作:滑鼠點擊某個位置,玩家物件移動到該位置,或者按滑鼠方向鍵,玩家會向不同方向移動,等等。這些操作無一不用與外部輸入設備打交道。作為遊戲的設計者,我們很需要在任何時候知道滑鼠目前的位置,鍵盤的點擊狀況等,從而方便我們對遊戲元素加以控制。因此作為一個遊戲框架,外部輸入模組也是不可或缺的。

2.提供哪些功能,怎麼使用?

  外部輸入模組主要實現的功能就是動態記錄滑鼠相對於canvas的位置,以及記錄鍵盤上哪些鍵是按下的,哪些鍵剛剛放開,並觸發對應的回呼函數

  我們可以透過框架儲存的兩個欄位來取得滑鼠目前在canvas的位置:

var x=cnGame.input.mouseX;
var y=cnGame.input.mouseY;
登入後複製

  由於canvas下的遊戲程式模式是透過一個遊戲循環來實現的幀動畫(關於遊戲循環請看:HTML5遊戲框架cnGameJS開發實錄(遊戲循環篇)),因此單純對鍵盤keyup與keydown的綁定,往往並不能達到期望效果,舉個例子,我們如果想在鍵盤按下左鍵時使元素一直向左移動:

cnGame.input.onKeyDown("left",(){
    player.move(-10);
 })
登入後複製

  我們會發現這種方法並不能很好的運用在幀動畫的程式設計模型。由於當我們按下鍵盤左方向鍵時,其回調函數會不斷觸發,因此觸發頻率並不能和你的幀動畫的頻率一致(要么太快要么太慢,取決於你的幀頻率),所以更好的選擇是每次幀更新時,判斷左鍵是否按下,如果是按下遊戲元素就向左移動一定位置,這樣遊戲元素就成為幀動畫的一部分,隨著每次幀的更新而更新:

/*每次帧更新调用的函数*/
var update=function(){
   cnGame.input.isPressed("left",function(){player.move(-10);})
}
登入後複製

3.程式碼實作

  首先看如何保持滑鼠在canvas的位置。滑鼠相對於canvas的位置,其實就是滑鼠相對於頁面的位置和canvas的位置差。在先前的HTML5遊戲框架cnGameJS開發實錄(核心函數模組篇)裡已經介紹過,在框架的初始化函數裡,我們已經透過getCanvasPos取得到canvas在頁面的位置,因此滑鼠相對於canvas的位置可以如此計算:

/**
     *记录鼠标在canvas内的位置
    **/    
    var recordMouseMove=function(eve){
        var pageX,pageY,x,y;
        eve=cg.core.getEventObj(eve);
        pageX = eve.pageX || eve.clientX + document.documentElement.scrollLeft - document.documentElement.clientLeft;
        pageY = eve.pageY || eve.clientY + document.documentElement.scrollTop - document.documentElement.clientTop;
        cg.input.mouseX=pageX-cg.x;
        cg.input.mouseY=pageY-cg.y;
            
    }
登入後複製

  之後再看看鍵盤輸入的記錄如何實現,我們需要一個數組,保存每個鍵的名值對(鍵名和鍵編碼),以及一些對象,保存每個鍵對應的按下和鬆開的回呼函數,還有最後一個對象,保存那些需要禁止預設行為的鍵名。 (禁止鍵盤預設行為在遊戲開發中很必要,可以防止玩家在操控時遊戲物件時觸發不必要的瀏覽器預設行為,例如滾動條滾動等)。

 首先是建立鍵名和鍵編碼的字典:

/**
     *键盘按键编码和键名
    **/    
    var k=[];
    k[8] = "backspace"
    k[9] = "tab"
    k[13] = "enter"
    k[16] = "shift"
    k[17] = "ctrl"
    k[18] = "alt"
    k[19] = "pause"
    k[20] = "capslock"
    k[27] = "esc"
    k[32] = "space"
    k[33] = "pageup"
    k[34] = "pagedown"
    k[35] = "end"
    k[36] = "home"
    k[37] = "left"
    k[38] = "up"
    k[39] = "right"
    k[40] = "down" 
    k[45] = "insert"
    k[46] = "delete"
    
    k[91] = "leftwindowkey"
    k[92] = "rightwindowkey"
    k[93] = "selectkey"
    k[106] = "multiply"
    k[107] = "add"
    k[109] = "subtract"
    k[110] = "decimalpoint"
    k[111] = "divide"
    
    k[144] = "numlock"
    k[145] = "scrollock"
    k[186] = "semicolon"
    k[187] = "equalsign"
    k[188] = "comma"
    k[189] = "dash"
    k[190] = "period"
    k[191] = "forwardslash"
    k[192] = "graveaccent"
    k[219] = "openbracket"
    k[220] = "backslash"
    k[221] = "closebracket"
    k[222] = "singlequote"
    
    var numpadkeys = ["numpad1","numpad2","numpad3","numpad4","numpad5","numpad6","numpad7","numpad8","numpad9"]
    var fkeys = ["f1","f2","f3","f4","f5","f6","f7","f8","f9"]
    var numbers = ["0","1","2","3","4","5","6","7","8","9"]
    var letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
    for(var i = 0; numbers[i]; i++)     { k[48+i] = numbers[i] }
    for(var i = 0; letters[i]; i++)     { k[65+i] = letters[i] }
    for(var i = 0; numpadkeys[i]; i++)  { k[96+i] = numpadkeys[i] }
    for(var i = 0; fkeys[i]; i++)       { k[112+i] = fkeys[i] }
登入後複製

  有點長,不過其實沒啥技術含量,就是方便我們以後知道某個編碼的鍵名是什麼。例如我們按下左鍵,那麼流程就是:獲取到左鍵的鍵盤編碼->在字典中得到鍵名->在對像中通過鍵名獲取到之前同樣通過鍵名保存的處理程序,並執行。

  為鍵盤綁定處理程序的程式碼如下:

/**
     *记录键盘按下的键
    **/    
    var recordPress=function(eve){
        eve=cg.core.getEventObj(eve);
        var keyName=k[eve.keyCode];
        pressed_keys[keyName]=true;    
        if(keydown_callbacks[keyName]){
            for(var i=0,len=keydown_callbacks[keyName].length;i<len;i++){
                keydown_callbacks[keyName][i]();
                
            }
        
        }
        if(keydown_callbacks["allKeys"]){
            for(var i=0,len=keydown_callbacks["allKeys"].length;i<len;i++){
                keydown_callbacks["allKeys"][i]();
                
            }
        }
        if(preventDefault_keys[keyName]){
            cg.core.preventDefault(eve);
        }
    }
登入後複製


  每個鍵的處理程序可以有多個,所以這裡保存處理程序的物件保存的是一個陣列。另外要注意透過pressed_keys數組保存了按下的鍵(pressed_keys[keyName]=true;),就是為了方便實現之前說過的在幀更新中進行一致的參數更新(可以在每次update時通過isPressed(keyName )判斷某個鍵是否按下)。  

  最後附上此輸入模組所有原始碼:

/**
 *
 *输入记录模块
 *
**/
cnGame.register("cnGame.input",function(cg){
                                            
    this.mouseX=0;
    this.mouseY=0;
    /**
     *记录鼠标在canvas内的位置
    **/    
    var recordMouseMove=function(eve){
        var pageX,pageY,x,y;
        eve=cg.core.getEventObj(eve);
        pageX = eve.pageX || eve.clientX + document.documentElement.scrollLeft - document.documentElement.clientLeft;
        pageY = eve.pageY || eve.clientY + document.documentElement.scrollTop - document.documentElement.clientTop;
        cg.input.mouseX=pageX-cg.x;
        cg.input.mouseY=pageY-cg.y;
            
    }        
    
    cg.core.bindHandler(window,"mousemove",recordMouseMove);
    
    /**
     *被按下的键的集合
    **/    
    var pressed_keys={};
    /**
     *要求禁止默认行为的键的集合
    **/    
    var preventDefault_keys={};
    /**
     *键盘按下触发的处理函数
    **/    
    var keydown_callbacks={};
    /**
     *键盘弹起触发的处理函数
    **/    
    var keyup_callbacks={};

    
    /**
     *键盘按键编码和键名
    **/    
    var k=[];
    k[8] = "backspace"
    k[9] = "tab"
    k[13] = "enter"
    k[16] = "shift"
    k[17] = "ctrl"
    k[18] = "alt"
    k[19] = "pause"
    k[20] = "capslock"
    k[27] = "esc"
    k[32] = "space"
    k[33] = "pageup"
    k[34] = "pagedown"
    k[35] = "end"
    k[36] = "home"
    k[37] = "left"
    k[38] = "up"
    k[39] = "right"
    k[40] = "down" 
    k[45] = "insert"
    k[46] = "delete"
    
    k[91] = "leftwindowkey"
    k[92] = "rightwindowkey"
    k[93] = "selectkey"
    k[106] = "multiply"
    k[107] = "add"
    k[109] = "subtract"
    k[110] = "decimalpoint"
    k[111] = "divide"
    
    k[144] = "numlock"
    k[145] = "scrollock"
    k[186] = "semicolon"
    k[187] = "equalsign"
    k[188] = "comma"
    k[189] = "dash"
    k[190] = "period"
    k[191] = "forwardslash"
    k[192] = "graveaccent"
    k[219] = "openbracket"
    k[220] = "backslash"
    k[221] = "closebracket"
    k[222] = "singlequote"
    
    var numpadkeys = ["numpad1","numpad2","numpad3","numpad4","numpad5","numpad6","numpad7","numpad8","numpad9"]
    var fkeys = ["f1","f2","f3","f4","f5","f6","f7","f8","f9"]
    var numbers = ["0","1","2","3","4","5","6","7","8","9"]
    var letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
    for(var i = 0; numbers[i]; i++)     { k[48+i] = numbers[i] }
    for(var i = 0; letters[i]; i++)     { k[65+i] = letters[i] }
    for(var i = 0; numpadkeys[i]; i++)  { k[96+i] = numpadkeys[i] }
    for(var i = 0; fkeys[i]; i++)       { k[112+i] = fkeys[i] }
    
    /**
     *记录键盘按下的键
    **/    
    var recordPress=function(eve){
        eve=cg.core.getEventObj(eve);
        var keyName=k[eve.keyCode];
        pressed_keys[keyName]=true;    
        if(keydown_callbacks[keyName]){
            for(var i=0,len=keydown_callbacks[keyName].length;i<len;i++){
                keydown_callbacks[keyName][i]();
                
            }
        
        }
        if(keydown_callbacks["allKeys"]){
            for(var i=0,len=keydown_callbacks["allKeys"].length;i<len;i++){
                keydown_callbacks["allKeys"][i]();
                
            }
        }
        if(preventDefault_keys[keyName]){
            cg.core.preventDefault(eve);
        }
    }
    /**
     *记录键盘松开的键
    **/    
    var recordUp=function(eve){
        eve=cg.core.getEventObj(eve);
        var keyName=k[eve.keyCode];
        pressed_keys[keyName]=false;
        if(keyup_callbacks[keyName]){
            for(var i=0,len=keyup_callbacks[keyName].length;i
登入後複製

以上是HTML5遊戲框架cnGameJS開發實錄-外部輸入模組篇的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板