LoginSignup
0
0

More than 3 years have passed since last update.

ゲームパッドの入力と変換

Last updated at Posted at 2021-04-26
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>


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0