phaser/src/input/InputManager.js

288 lines
7.5 KiB
JavaScript
Raw Normal View History

var Class = require('../utils/Class');
var EventEmitter = require('eventemitter3');
var Gamepad = require('./gamepad/GamepadManager');
var Keyboard = require('./keyboard/KeyboardManager');
var Mouse = require('./mouse/MouseManager');
var Pointer = require('./Pointer');
var Rectangle = require('../geom/rectangle/Rectangle');
var Touch = require('./touch/TouchManager');
var TransformXY = require('../math/TransformXY');
// Phaser.Input.InputManager
2018-01-16 16:14:21 +00:00
var InputManager = new Class({
initialize:
2018-01-16 16:14:21 +00:00
function InputManager (game, config)
{
this.game = game;
2017-06-14 00:20:01 +00:00
this.canvas;
this.config = config;
2017-06-14 00:20:01 +00:00
this.enabled = true;
2017-06-14 00:20:01 +00:00
this.events = new EventEmitter();
// Standard FIFO queue
this.queue = [];
2017-09-09 02:17:13 +00:00
// Listeners (will be based on config)
this.keyboard = new Keyboard(this);
this.mouse = new Mouse(this);
this.touch = new Touch(this);
2017-09-09 02:17:13 +00:00
this.gamepad = new Gamepad(this);
this.activePointer = new Pointer(this, 0);
this.scale = { x: 1, y: 1 };
// If the top-most Scene in the Scene List receives an input it will stop input from
// propagating any lower down the scene list, i.e. if you have a UI Scene at the top
// and click something on it, that click will not then be passed down to any other
// Scene below. Disable this to have input events passed through all Scenes, all the time.
this.globalTopOnly = true;
this.ignoreEvents = false;
this.bounds = new Rectangle();
this._tempPoint = { x: 0, y: 0 };
this._tempHitTest = [];
game.events.once('boot', this.boot, this);
},
/**
* The Boot handler is called by Phaser.Game when it first starts up.
* The renderer is available by now.
*/
boot: function ()
{
this.canvas = this.game.canvas;
this.updateBounds();
this.keyboard.boot();
this.mouse.boot();
this.touch.boot();
2017-09-09 02:17:13 +00:00
this.gamepad.boot();
},
updateBounds: function ()
{
var clientRect = this.canvas.getBoundingClientRect();
var bounds = this.bounds;
bounds.left = clientRect.left + window.pageXOffset;
bounds.top = clientRect.top + window.pageYOffset;
bounds.width = clientRect.width;
bounds.height = clientRect.height;
},
update: function (time)
{
this.keyboard.update();
2017-09-09 02:17:13 +00:00
this.gamepad.update();
2017-06-14 00:20:01 +00:00
this.ignoreEvents = false;
2017-06-14 00:20:01 +00:00
var len = this.queue.length;
// Currently just 1 pointer supported
var pointer = this.activePointer;
pointer.reset();
2017-06-14 00:20:01 +00:00
if (!this.enabled || len === 0)
{
return;
}
this.updateBounds();
this.scale.x = this.game.config.width / this.bounds.width;
this.scale.y = this.game.config.height / this.bounds.height;
2017-06-14 00:20:01 +00:00
// Clears the queue array, and also means we don't work on array data that could potentially
// be modified during the processing phase
var queue = this.queue.splice(0, len);
// Process the event queue, dispatching all of the events that have stored up
for (var i = 0; i < len; i++)
{
var event = queue[i];
// TODO: Move to CONSTs so we can do integer comparisons instead of strings.
2017-06-14 00:20:01 +00:00
switch (event.type)
{
case 'mousemove':
2017-07-27 02:40:58 +00:00
pointer.move(event, time);
2017-06-14 00:20:01 +00:00
break;
case 'mousedown':
2017-07-27 02:40:58 +00:00
pointer.down(event, time);
2017-06-14 00:20:01 +00:00
break;
case 'mouseup':
2017-07-27 02:40:58 +00:00
pointer.up(event, time);
break;
case 'touchmove':
pointer.touchmove(event, time);
break;
case 'touchstart':
pointer.touchstart(event, time);
break;
case 'touchend':
pointer.touchend(event, time);
break;
case 'pointerlockchange':
this.events.emit('pointerlockchange', event, this.mouse.locked);
break;
2017-06-14 00:20:01 +00:00
}
}
},
2018-01-16 15:46:49 +00:00
// Will always return an array.
// Array contains matching Interactive Objects.
// Array will be empty if no objects were matched.
// x/y = pointer x/y (un-translated)
hitTest: function (x, y, gameObjects, camera, output)
{
if (output === undefined) { output = this._tempHitTest; }
var tempPoint = this._tempPoint;
var cameraW = camera.width;
var cameraH = camera.height;
output.length = 0;
if (!(x >= camera.x && y >= camera.y && x <= camera.x + cameraW && y <= camera.y + cameraH))
{
return output;
}
// Stores the world point inside of tempPoint
camera.getWorldPoint(x, y, tempPoint);
var culledGameObjects = camera.cull(gameObjects);
var point = { x: 0, y: 0 };
for (var i = 0; i < culledGameObjects.length; i++)
{
var gameObject = culledGameObjects[i];
if (!gameObject.input || !gameObject.input.enabled || !gameObject.willRender())
{
continue;
}
var px = tempPoint.x + (camera.scrollX * gameObject.scrollFactorX) - camera.scrollX;
var py = tempPoint.y + (camera.scrollY * gameObject.scrollFactorY) - camera.scrollY;
TransformXY(px, py, gameObject.x, gameObject.y, gameObject.rotation, gameObject.scaleX, gameObject.scaleY, point);
if (this.pointWithinHitArea(gameObject, point.x, point.y))
{
output.push(gameObject);
}
}
return output;
},
// x/y MUST be translated before being passed to this function,
// unless the gameObject is guaranteed to not be rotated or scaled in any way
pointWithinHitArea: function (gameObject, x, y)
{
2018-01-16 15:46:49 +00:00
var input = gameObject.input;
// Normalize the origin
x += gameObject.displayOriginX;
y += gameObject.displayOriginY;
if (input.hitAreaCallback(input.hitArea, x, y, gameObject))
{
input.localX = x;
input.localY = y;
return true;
}
else
{
return false;
}
},
// x/y MUST be translated before being passed to this function, unless the gameObject is guaranteed to
// be not rotated or scaled in any way
pointWithinInteractiveObject: function (object, x, y)
{
if (!object.hitArea)
{
return false;
}
// Normalize the origin
x += object.gameObject.displayOriginX;
y += object.gameObject.displayOriginY;
object.localX = x;
object.localY = y;
return object.hitAreaCallback(object.hitArea, x, y, object);
},
2018-01-04 15:41:35 +00:00
// Called by Pointer class
transformX: function (pageX)
{
return (pageX - this.bounds.left) * this.scale.x;
},
transformY: function (pageY)
{
return (pageY - this.bounds.top) * this.scale.y;
},
getOffsetX: function ()
{
return this.bounds.left;
},
getOffsetY: function ()
{
return this.bounds.top;
},
getScaleX: function ()
{
return this.game.config.width / this.bounds.width;
},
getScaleY: function ()
{
return this.game.config.height / this.bounds.height;
}
});
2018-01-16 16:14:21 +00:00
module.exports = InputManager;