Gamepad.html
<!DOCTYPE html>
<html lang="ja"><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
var Minecraft = {
keys:{
X:'LeftButton', Y:'RightButton',
A:'Space', B:'E',
LY_NEGATIVE:'W',
LX_NEGATIVE:'A',
LY_POSITIVE:'S',
LX_POSITIVE:'D',
UP:'F5',
DOWN:'Q',
LEFT:'F',
SELECT:'F11',
START:'Escape',
LB:e=>{return Minecraft.hotbar(e,-1)},
RB:e=>{return Minecraft.hotbar(e,1)},
LT:'LControlKey', RT:'LShiftKey',
LS:'F3', RS:'F11',
},
mousemove:'RightStick',
hotbarId:0,
hotbar(e,d){
if(e.type=='down'){
Minecraft.hotbarId += 9+d
Minecraft.hotbarId %= 9
}
e.type = 'key'+e.type
e.key = 'D'+(Minecraft.hotbarId+1)
return e
}
}
$(e=>{
var n = new Controller.Native()
var v = new Controller.View()
var s = new Controller.Status().on(e=>{
var event = new Controller.Event(e,Minecraft)
n.dispatch(event)
if(event.type) v.log(JSON.stringify(event).replace(/"/g,''))
})
setInterval(e=>{
s.loop()
v.fps().sticks(s.gamepadAxes)
},1000/60)
})
var Controller = {}
Controller.Native = class{
constructor(){
if(chrome.webview){
this.bridge = chrome.webview.hostObjects.bridge
this.host = chrome.webview.hostObjects
}else{
this.bridge = {dispatch:console.log}
this.host = {bridge:this.bridge}
}
}
dispatch(e){
if(e.type){
var s = JSON.stringify(e)
this.host.bridge.dispatch(s)
}
}
}
Object.assign((Controller.Data = class{
constructor(){
this.count = 0
this.connection = {}
this.listener = console.log
this.dummy = {
buttons:this.buttons.map(k=>{return {pressed:false}}),
axes:this.axes.map(k=>{return 0})
}
}
button(a,b,i){
if(a.pressed==b.pressed) return null
switch(b.pressed){
case(true): this.listener({type:'down', key:this.buttons[i]});break
default: this.listener({type:'up', key:this.buttons[i]})
}
}
stick(a,b,i){
if(a==b) return null
var p = this.axes[i]+'_POSITIVE'
var n = this.axes[i]+'_NEGATIVE'
switch(true){
case(a>0): this.listener({type:'up', key:p});break
case(a<0): this.listener({type:'up', key:n});break
}
switch(true){
case(b>0): this.listener({type:'down', key:p});break
case(b<0): this.listener({type:'down', key:n});break
}
}
move(axes,s){
if(axes.filter(v=>Math.abs(v)>0.15).length==0) return null
this.listener({type:'move',axes:axes,stick:s})
}
}).prototype,{
buttons:'A,B,X,Y,LB,RB,LT,RT,SELECT,START,LS,RS,UP,DOWN,LEFT,RIGHT,B16'.split(','),
axes:'LX,LY,RX,RY'.split(',')
})
Controller.Status = class extends Controller.Data {
constructor(){
super()
window.addEventListener("gamepadconnected",e=>{
console.log(e)
this.count++
this.status(e.gamepad)
});
window.addEventListener("gamepaddisconnected",e=>{
console.log(e)
this.connection[e.gamepad.index] = null
this.count--
});
this.gamepadAxes = []
}
on(f){
this.listener = f
return this
}
loop(){
if(this.count==0) return
this.item = Array.prototype.slice.call(navigator.getGamepads())
this.item.forEach(g=>this.status(g))
return this
}
status(gamepad){
if(gamepad == null) return
var g = this.connection[gamepad.index]||this.dummy
gamepad.buttons.slice(0,16).forEach((v,i)=>this.button(g.buttons[i],v,i))
gamepad.axes.forEach((v,i)=>this.stick(Math.round(g.axes[i]),Math.round(v),i))
this.move(gamepad.axes.slice(0,2),'LeftStick')
this.move(gamepad.axes.slice(2,4),'RightStick')
this.connection[gamepad.index] = gamepad
this.gamepadAxes = gamepad.axes
}
}
Object.assign((Controller.Event = class{
constructor(e,data){
var v = data.keys[e.key]||null
if(e.type=='move'){
if(e.stick==data.mousemove) this.mouseMove(e)
}else if(v){
if(typeof v==='string'){
var k = data.keys[e.key]
var i = this.MOUSE_BUTTONS.indexOf(k)
if(i==-1){
this.type = 'key'+e.type
this.key = k
}else{
this.type = 'mouse'+e.type
this.button = i
}
}else{
Object.assign(this,v(e))
}
}
}
mouseMove(e){
this.type = 'mousemove'
this.x = this.mouseSpeed(e.axes[0])
this.y = this.mouseSpeed(e.axes[1])
}
mouseSpeed(v){
var a = Math.abs(v)
if(a==1) return v*18
return v*6
}
}).prototype,{
type:null,
MOUSE_BUTTONS:'LeftButton,MiddleButton,RightButton'.split(',')
})
Controller.View = class{
constructor(){
this.time = performance.now()
this.$view=$('<div id="View">').append(
this.$log=$('<div id="Log">'),
this.$axe=$('<div id="Axis">').append(
$('<div class="range">').append(this.$ls=$('<div class="stick">')),
$('<div class="range">').append(this.$rs=$('<div class="stick">'))
),
this.$fps=$('<div id="Fps">')
)
$('body').append(this.$view)
}
log(v){
this.$log.append($('<div>').append(v))
this.$log.children().slice(0,-100).remove()
window.scroll(0,$(document).height())
return this
}
sticks(a){
if(a==null) return
if(a.length<4) return
this.$ls.css({left:a[0]*30,top:a[1]*30})
this.$rs.css({left:a[2]*30,top:a[3]*30})
return this
}
fps(){
var t = performance.now()
this.$fps.empty().append(Math.round(1000/(t-this.time)),'FPS')
this.time = t
return this
}
}
</script>
<style>
*{
box-sizing:border-box;
margin:0;padding:0;
}
body{
font-size:12px;
line-height:20px;
}
#Log div{
border-bottom:1px solid rgba(0,0,0,0.04);
padding:0 10px;
white-space:nowrap;
text-overflow:ellipsis;
overflow:hidden;
}
#Axis{
position:fixed;
right:0;top:0;
width:280px;height:160px;
}
#Axis .range{
position:absolute;
top:30px;
width:100px;
height:100px;
border-radius:100px;
background-color:rgba(0,0,0,0.1);
}
#Axis .range:nth-child(1){left:30px;}
#Axis .range:nth-child(2){right:30px;}
#Axis .stick{
position:absolute;
transform: translate(25px,25px);
width:50px;
height:50px;
border-radius:30px;
border:1px solid rgba(0,0,0,0.1);
background-color: white;
}
#Fps{
position: fixed;
right:0;top:0;
padding:10px;
}
</style>
</head></html>