java键盘监听wasd控制_dota2rpg自定义按键绑定及WASD移动的实现

news/2024/11/9 9:53:02/

本文的目的是在DOTA2自定义游戏中实现一个WASD控制的8方向移动,如果你想实现的是4方向的,稍微修改一点点代码也可以做到。

通过本文,你也可以了解到DOTA2自定义按键的流程。

本文的所有代码你都可以在我开源的Endless Dungeon项目中找到

一、声明按键绑定

按键绑定需要写在 game/dota_addons/你的项目文件夹/addon_info.txt中(完整代码)

"Default_Keys"

{

"01"

{

"Key" "D"

"Command" "+PlayerMoveRight"

"Name" "PlayerMoveRight"

}

"02"

{

"Key" "W"

"Command" "+PlayerMoveUp"

"Name" "PlayerMoveUp"

}

"03"

{

"Key" "S"

"Command" "+PlayerMoveDown"

"Name" "PlayerMoveDown"

}

"04"

{

"Key" "A"

"Command" "+PlayerMoveLeft"

"Name" "PlayerMoveLeft"

}

}

就完成了按键的声明。

命令的回调声明则是在content/dota_addons/你的项目名称/panorama/scripts/custom_game/key_binding.js文件中(完整代码)

其中,要注意的是+代表按键按下,-代表按键抬起。

function WrapFunction(name) {

return function() {

Game[name]();

};

}

(function() {

Game.AddCommand( "+PlayerMoveUp", WrapFunction("PlayerMoveUp"), "", 0 );

Game.AddCommand( "+PlayerMoveDown", WrapFunction("PlayerMoveDown"), "", 0 );

Game.AddCommand( "+PlayerMoveLeft", WrapFunction("PlayerMoveLeft"), "", 0 );

Game.AddCommand( "+PlayerMoveRight", WrapFunction("PlayerMoveRight"), "", 0 );

Game.AddCommand( "-PlayerMoveUp", WrapFunction("PlayerMoveUp_End"), "", 0 );

Game.AddCommand( "-PlayerMoveDown", WrapFunction("PlayerMoveDown_End"), "", 0 );

Game.AddCommand( "-PlayerMoveLeft", WrapFunction("PlayerMoveLeft_End"), "", 0 );

Game.AddCommand( "-PlayerMoveRight", WrapFunction("PlayerMoveRight_End"), "", 0 );

)();

这里需要注意的问题是,这个js文件,你最好一次性写完之后,只在custom_ui_menifest.xml里面引用他,这也是为什么需要用WrapFunction方法来把回调放在其他的文件中,这样如果你如果修改回调方法并保存js文件后,引擎重新运行js文件就不会运行到Game.AddCommand,否则,命令绑定就会失效导致按键就会无响应(这是一个已知的BUG,很影响debug的效率)。

二、js的命令回调

在任意被引用的js文件中写明命令的回调如下:

Game.PlayerMoveUp = function() {

GameEvents.SendCustomGameEventToServer("ed_player_start_move_up", {})

};

Game.PlayerMoveDown = function() {

GameEvents.SendCustomGameEventToServer("ed_player_start_move_down", {})

};

Game.PlayerMoveLeft = function() {

GameEvents.SendCustomGameEventToServer("ed_player_start_move_left", {})

};

Game.PlayerMoveRight = function() {

GameEvents.SendCustomGameEventToServer("ed_player_start_move_right", {})

};

Game.PlayerMoveUp_End = function() {

GameEvents.SendCustomGameEventToServer("ed_player_end_move_up", {})

};

Game.PlayerMoveDown_End = function() {

GameEvents.SendCustomGameEventToServer("ed_player_end_move_down", {})

};

Game.PlayerMoveLeft_End = function() {

GameEvents.SendCustomGameEventToServer("ed_player_end_move_left", {})

};

Game.PlayerMoveRight_End = function() {

GameEvents.SendCustomGameEventToServer("ed_player_end_move_right", {})

};

三、服务器端的事件响应

服务器在收到ed_player_start_move_up之类的事件之后,做出具体的响应,代码如下,具体说明见注释

function CEDGameMode:_RegisterCustomGameEventListeners()

-- 注册移动的事件响应,上下左右的开始和结束(按下即开始,松开即结束)

CustomGameEventManager:RegisterListener("ed_player_start_move_up", function(_, keys)

self:On_ed_player_start_move_up(keys)

end)

CustomGameEventManager:RegisterListener("ed_player_start_move_down", function(_, keys)

self:On_ed_player_start_move_down(keys)

end)

CustomGameEventManager:RegisterListener("ed_player_start_move_left", function(_, keys)

self:On_ed_player_start_move_left(keys)

end)

CustomGameEventManager:RegisterListener("ed_player_start_move_right", function(_, keys)

self:On_ed_player_start_move_right(keys)

end)

CustomGameEventManager:RegisterListener("ed_player_end_move_up", function(_, keys)

self:On_ed_player_end_move_up(keys)

end)

CustomGameEventManager:RegisterListener("ed_player_end_move_down", function(_, keys)

self:On_ed_player_end_move_down(keys)

end)

CustomGameEventManager:RegisterListener("ed_player_end_move_left", function(_, keys)

self:On_ed_player_end_move_left(keys)

end)

CustomGameEventManager:RegisterListener("ed_player_end_move_right", function(_, keys)

self:On_ed_player_end_move_right(keys)

end)

end

-- 上下左右四个方向

local upVector = Vector(0, 1, 0)

local downVector = Vector(0, - 1, 0)

local leftVector = Vector(- 1, 0, 0)

local rightVector = Vector(1, 0, 0)

-- 核心的控制上下左右移动的循环

local function createMovingTimer(hero)

if hero.m_MovingTimer then

return

end

-- 创建按键计时器,Timer函数需要https://github.com/XavierCHN/EndlessDungeon/blob/master/game/ed/scripts/vscripts/utils/funcs.lua

-- 中的Timer函数

hero.m_MovingTimer = Timer(function()

if not (IsValidEntity(hero) and hero:IsAlive()) then

hero.bMovingUp = false

hero.bMovingDown = false

hero.bMovingLeft = false

hero.bMovingRight = false

return 0.03

end

local movingVector = Vector(0, 0, 0)

-- 根据玩家英雄当前上下左右的状态,计算玩家当前应该移动的方向

-- 如按下A则应当向左移动

-- 同时按AD应当不移动

-- 同时按WD应当向右上方移动

if hero.bMovingUp then

movingVector = movingVector + upVector

end

if hero.bMovingDown then

movingVector = movingVector + downVector

end

if hero.bMovingLeft then

movingVector = movingVector + leftVector

end

if hero.bMovingRight then

movingVector = movingVector + rightVector

end

movingVector = movingVector:Normalized()

-- 具体的移动

if movingVector.x == 0 and movingVector.y == 0 then

-- 如果x, y均等于0,则不移动

else

-- 开始移动

if not hero:IsStunned() then

-- 直接设定面向,这样快速交替按AD才会有响应

hero:SetForwardVector(movingVector)

-- 往移动的方向移动一小步

ExecuteOrderFromTable({

UnitIndex = hero:entindex(),

OrderType = DOTA_UNIT_ORDER_MOVE_TO_POSITION,

Position = hero:GetOrigin() + movingVector * 32

})

else

hero:Stop()

end

end

return 0.03

end)

end

-- 开始向上移动的按键响应,其他方向的与此类似

function CEDGameMode:On_ed_player_start_move_up(keys)

local player = PlayerResource:GetPlayer(keys.PlayerID)

if not player then

return

end

local hero = player:GetAssignedHero()

if not hero then

return

end

if not (IsValidEntity(hero) and hero:IsAlive()) then

hero.bMovingUp = false

ShowError("ed_hud_error_cannot_move", keys.PlayerID)

return

end

if not hero.m_MovingTimer then

createMovingTimer(hero)

end

-- 置向上移动为true

hero.bMovingUp = true

end

function CEDGameMode:On_ed_player_start_move_down(keys)

local player = PlayerResource:GetPlayer(keys.PlayerID)

if not player then

return

end

local hero = player:GetAssignedHero()

if not hero then

return

end

if not (IsValidEntity(hero) and hero:IsAlive()) then

hero.bMovingDown = false

ShowError("ed_hud_error_cannot_move", keys.PlayerID)

return

end

if not hero.m_MovingTimer then

createMovingTimer(hero)

end

hero.bMovingDown = true

end

function CEDGameMode:On_ed_player_start_move_left(keys)

local player = PlayerResource:GetPlayer(keys.PlayerID)

if not player then

return

end

local hero = player:GetAssignedHero()

if not hero then

return

end

if not (IsValidEntity(hero) and hero:IsAlive()) then

hero.bMovingLeft = false

ShowError("ed_hud_error_cannot_move", keys.PlayerID)

return

end

if not hero.m_MovingTimer then

createMovingTimer(hero)

end

hero.bMovingLeft = true

end

function CEDGameMode:On_ed_player_start_move_right(keys)

local player = PlayerResource:GetPlayer(keys.PlayerID)

if not player then

return

end

local hero = player:GetAssignedHero()

if not hero then

return

end

if not (IsValidEntity(hero) and hero:IsAlive()) then

hero.bMovingRight = false

ShowError("ed_hud_error_cannot_move", keys.PlayerID)

return

end

if not hero.m_MovingTimer then

createMovingTimer(hero)

end

hero.bMovingRight = true

end

function CEDGameMode:On_ed_player_end_move_up(keys)

local player = PlayerResource:GetPlayer(keys.PlayerID)

if not player then

return

end

local hero = player:GetAssignedHero()

if not hero then

return

end

if not (IsValidEntity(hero) and hero:IsAlive()) then

hero.bMovingUp = false

ShowError("ed_hud_error_cannot_move", keys.PlayerID)

return

end

if not hero.m_MovingTimer then

createMovingTimer(hero)

end

hero.bMovingUp = false

end

function CEDGameMode:On_ed_player_end_move_down(keys)

local player = PlayerResource:GetPlayer(keys.PlayerID)

if not player then

return

end

local hero = player:GetAssignedHero()

if not hero then

return

end

if not (IsValidEntity(hero) and hero:IsAlive()) then

hero.bMovingDown = false

ShowError("ed_hud_error_cannot_move", keys.PlayerID)

return

end

if not hero.m_MovingTimer then

createMovingTimer(hero)

end

hero.bMovingDown = false

end

function CEDGameMode:On_ed_player_end_move_left(keys)

local player = PlayerResource:GetPlayer(keys.PlayerID)

if not player then

return

end

local hero = player:GetAssignedHero()

if not hero then

return

end

if not (IsValidEntity(hero) and hero:IsAlive()) then

hero.bMovingLeft = false

ShowError("ed_hud_error_cannot_move", keys.PlayerID)

return

end

if not hero.m_MovingTimer then

createMovingTimer(hero)

end

hero.bMovingLeft = false

end

function CEDGameMode:On_ed_player_end_move_right(keys)

local player = PlayerResource:GetPlayer(keys.PlayerID)

if not player then

return

end

local hero = player:GetAssignedHero()

if not hero then

return

end

if not (IsValidEntity(hero) and hero:IsAlive()) then

hero.bMovingRight = false

ShowError("ed_hud_error_cannot_move", keys.PlayerID)

return

end

if not hero.m_MovingTimer then

createMovingTimer(hero)

end

hero.bMovingRight = false

end


http://www.ppmy.cn/news/570472.html

相关文章

用C#钩子写一个改键外挂

我的微信群——软件开发测试工程师交流群,欢迎扫码: 改键是一种习惯,比如在玩儿lol或者dota的时候。理论上玩儿什么游戏都可以改键。 做一个窗体(点击Install——应用改键,点击Uninstall——撤销应用)&…

笑傲江湖客户端服务器地址修改,《笑傲江湖》改键调整操作手把手教你玩笑傲...

《笑傲江湖》采用全新引擎AngelicaIII打造,秉承原著武侠精髓,首推新派动作武侠网游概念——融入动作及格斗游戏要素,强调真实的打击感与流畅的动作连贯度,并运用方向判定、位移闪避、移动战斗、攻防一体等多重技术手段&#xff0c…

dota2html颜色代码,技术向教程 如何在DotA2中使用彩色字体

技术向教程 如何在DotA2中使用彩色字体 编译:M82A1炸菜 如何使用16进制编辑器对DotA2文字就行颜色编辑 需要:十六进制编辑器、记事本、控制台 1.打开steam平台 2.在游戏库中选择DotA2,右击,选择属性 3.设置启动项,填入“-console”,确定 4.打开DotA2游戏,并且使用“`”键…

基于低级键盘钩子的dota改键(全局+免DLL注入)MFC实现(源码+总结)

上一篇文章已经写了基于 普通键盘钩子(单线程DLL)来实现dota改键。http://blog.csdn.net/a576323437/article/details/8037138 这一次,基于 低级键盘钩子 (全局 免DLL注入)来实现。先看下总结: 低级键盘钩…

dota2游戏c语言,新手科普:Dota2操作按键设置和游戏设置详解

DOTA2的设置里有四个大项。控制,游戏,视频,音频。 后面两个自己根据自己配置水平设置就是。我主要讲控制和游戏。 控制: 页面1:单位行为 攻击,移动,停止,保持这种命令就不用说了。这…

基于键盘钩子的dota改键(单线程+DLL)MFC实现(源码+总结)

呼。。终于可以摒弃网上带广告的改键工具了。。 历经三天,写出自己的dota改键软件最简单版了。 还学习了两个新知识,钩子和动态链接库。下面以一个新手的角度,总结下这三天遇到的大小问题。 一般钩子在什么时刻被调用? 操作系统把…

War3Tool dota改键v3.3版

wartool魔兽全屏改键功能:1.支持11平台自定义改建,自动进局域网(同类软件暂时没发现这个功能)2.技能改键,可以有效的切换适合你的技能键3.war3路径扫描,运行本程序一键就能打开war3 (翻遍用户) 喜欢的朋友可…

Dota改键

利用全局钩子 制作一个个性化的dota游戏改键&#xff01; dll部分&#xff1a; // FileName: add.cpp#include <Windows.h>/* 定义全局变量 */ HWND g_hwnd NULL; HHOOK g_hKeyboard NULL;// 设置数据段 #pragma data_seg("MySec") static WORD g_keyNum[6]{…