0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?