仮想パッドによるキー入力を行うためには、画面上に配置したボタン画像が、押されているのかどうかを常に認識し続ける必要があります。
左右ボタンでリトルが左右に移動し、上ボタンでジャンプするサンプルです。
pointerdown
イベントと
pointermove
イベントは区別せず、ポインタリストに無ければ新たに押されたとして処理しています。
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
var frame = document.getElementById("frame");
var chara = { node:document.getElementById("chara"), x:0, y:64, u:1, v:0, count:0 };
var keys = new Array(3);
var bUpdateKeyPress = false;
initialize();
function initialize()
{
var ic, ib, nodes;
// ボタン構造配列
for(ic=0; ic<keys.length; ic++)
{
keys[ic] = { node:document.getElementById("key"+ic), bDown:0, ip:null };
nodes = keys[ic].node.childNodes;
for(ib=0; ib<nodes.length; ib++)
{
if(nodes[ib].getAttribute && nodes[ib].getAttribute("class") == "button"){ keys[ic].button = nodes[ib]; }
}
}
// イベント登録
if(window.PointerEvent)
{
frame.addEventListener("pointerdown", onPress, false);
document.addEventListener("pointermove", onPress, false);
document.addEventListener("pointerup", onRelease, false);
}else
{
frame.addEventListener("touchstart", onPress, false);
frame.addEventListener("mousedown", onPress, false);
document.addEventListener("touchmove", onPress, false);
document.addEventListener("mousemove", onPress, false);
document.addEventListener("touchend", onRelease, false);
document.addEventListener("mouseup", onRelease, false);
}
document.addEventListener("keydown", onKey, false);
document.addEventListener("keyup", onKey, false);
frame.addEventListener("selectstart", function(event){ event.preventDefault(); }, false);
frame.addEventListener("contextmenu", function(event){ event.preventDefault(); }, false);
if(requestAnimationFrame){ requestAnimationFrame(onAnimationFrame) }else{ setInterval(onInterval, 16); }
}
// ポインタイベント
function onPress(event)
{
var it, ic, ip, x, y, key, rect;
if(event.touches)
{
for(it=0; it<event.touches.length; it++){ onPress(event.touches[it]); }
if(event.cancelable){ event.preventDefault(); }
return;
}
ip = event.pointerId || event.identifier || 0;
x = event.clientX; y = event.clientY;
for(ic=0; ic<keys.length; ic++)
{
key = keys[ic];
rect = key.node.getClientRects()[0];
if(x >= rect.left && x < rect.right && y >= rect.top && y < rect.bottom)
{
if(key.ip != ip && ((event.type != "pointermove" || event.pointerType != "mouse") && event.type != "mousemove" || event.buttons > 0))
{
key.ip = ip;
if(!key.bDown){ key.bDown = true; bUpdateKeyPress = true; }
}
}else
{
if(key.ip == ip)
{
key.ip = null;
key.bDown = false; bUpdateKeyPress = true;
}
}
}
}
function onRelease(event)
{
var it, ic, ip, key;
if(event.touches)
{
for(ic=0; ic<keys.length; ic++)
{
for(var it=0; it<event.touches.length; it++){ if(keys[ic].ip == event.touches[it].identifier){ break; } }
if(it == event.touches.length){ onRelease({ identifier:keys[ic].ip }); }
}
if(event.cancelable){ event.preventDefault(); }
return;
}
ip = event.pointerId || event.identifier || 0;
for(ic=0; ic<keys.length; ic++)
{
key = keys[ic];
if(key.ip == ip)
{
key.ip = null;
key.bDown = false; bUpdateKeyPress = true;
}
}
}
// キーイベント
function onKey(event)
{
var ic = -1, code = event.code;;
if(code != undefined)
{
if(code == "ArrowLeft" || code == "Numpad4" || code == "KeyA"){ ic = 0; }
if(code == "ArrowRight" || code == "Numpad6" || code == "KeyD"){ ic = 1; }
if(code == "ArrowUp" || code == "Numpad8" || code == "KeyW" || code == "KeyZ" || code == "KeyX" || code == "Space"){ ic = 2; }
}else
{
code = event.keyCode;
if(code == 37 || code == 100 || code == 65){ ic = 0; }
if(code == 39 || code == 102 || code == 68){ ic = 1; }
if(code == 38 || code == 104 || code == 87 || code == 88 || code == 90 || code == 32){ ic = 2; }
}
if(ic >= 0)
{
var before = keys[ic].bDown;
keys[ic].bDown = event.type == "keydown";
if(before != keys[ic].bDown){ bUpdateKeyPress = true; }
event.preventDefault();
}
}
// 定期処理
function onAnimationFrame(){ onInterval(); requestAnimationFrame(onAnimationFrame); }
function onInterval()
{
// ボタン押下チェック
var ic;
if(bUpdateKeyPress)
{
bUpdateKeyPress = false;
for(ic=0; ic<keys.length; ic++)
{
if(keys[ic].button != null){ keys[ic].button.style.fillOpacity = keys[ic].bDown ? "1":""; }
}
}
/*
1フレームの処理
*/
}