3 Commits

Autor SHA1 Mensagem Data
Andreas 7adf3fe018 improved gamepad controls 2012-10-27 12:51:26 +02:00
Andreas 520b862d8a gamepad works better with requestAnimationFrame + added events for shoulder buttons 2012-10-16 00:39:12 +02:00
Andreas 78d99a74ae Added experimental gamepad support (works only in chrome canary) 2012-10-15 22:32:14 +02:00
8 arquivos alterados com 321 adições e 19 exclusões
+41 -1
Ver Arquivo
@@ -54,4 +54,44 @@ $("*[data-action]").on "mousedown", (ev) ->
$("*[data-action]").on "mouseup", (ev) ->
faye.publish "/drone/move", action: $(@).attr("data-param"), speed: 0 if $(@).attr("data-action") == "move"
$("*[rel=tooltip]").tooltip();
$("*[rel=tooltip]").tooltip();
# experimental gamepad support
normalizeSpeed = (val) ->
return 0 if Math.abs(val) < 0.15
Math.abs(val / 4) # for safety reasons ;-)
gamepad.on "LEFT_STICK_VERT", (data) ->
direction = "back"
direction = "forward" if data.value < 0
faye.publish "/drone/move", action: direction, speed: normalizeSpeed(data.value)
gamepad.on "LEFT_STICK_HOR", (data) ->
direction = "right"
direction = "left" if data.value < 0
faye.publish "/drone/move", action: direction, speed: normalizeSpeed(data.value)
gamepad.on("ready", -> console.log("ready"))
gamepad.init(-> console.log("ready init?")) if gamepad.isSupported()
gamepad.on "RIGHT_STICK_VERT", (data) ->
direction = "up"
direction = "down" if data.value < 0
faye.publish "/drone/move", action: direction, speed: normalizeSpeed(data.value)
gamepad.on "RIGHT_STICK_HOR", (data) ->
direction = "clockwise"
direction = "counterClockwise" if data.value < 0
faye.publish "/drone/move", action: direction, speed: normalizeSpeed(data.value)
gamepad.on "LEFT_SHOULDER", (data) ->
faye.publish "/drone/move", action: "clockwise", speed: data.value
gamepad.on "RIGHT_SHOULDER", (data) ->
faye.publish "/drone/move", action: "counterClockwise", speed: data.value
gamepad.on "LEFT_SHOULDER_BOTTOM", (data) ->
faye.publish "/drone/move", action: "down", speed: data.value
gamepad.on "RIGHT_SHOULDER_BOTTOM", (data) ->
faye.publish "/drone/move", action: "up", speed: data.value
+83 -1
Ver Arquivo
@@ -1,5 +1,5 @@
(function() {
var faye, keymap, speed;
var faye, keymap, normalizeSpeed, speed;
faye = new Faye.Client("/faye", {
timeout: 120
});
@@ -132,4 +132,86 @@
});
});
$("*[rel=tooltip]").tooltip();
normalizeSpeed = function(val) {
if (Math.abs(val) < 0.15) {
return 0;
}
return Math.abs(val / 4);
};
gamepad.on("LEFT_STICK_VERT", function(data) {
var direction;
direction = "back";
if (data.value < 0) {
direction = "forward";
}
return faye.publish("/drone/move", {
action: direction,
speed: normalizeSpeed(data.value)
});
});
gamepad.on("LEFT_STICK_HOR", function(data) {
var direction;
direction = "right";
if (data.value < 0) {
direction = "left";
}
return faye.publish("/drone/move", {
action: direction,
speed: normalizeSpeed(data.value)
});
});
gamepad.on("ready", function() {
return console.log("ready");
});
if (gamepad.isSupported()) {
gamepad.init(function() {
return console.log("ready init?");
});
}
gamepad.on("RIGHT_STICK_VERT", function(data) {
var direction;
direction = "up";
if (data.value < 0) {
direction = "down";
}
return faye.publish("/drone/move", {
action: direction,
speed: normalizeSpeed(data.value)
});
});
gamepad.on("RIGHT_STICK_HOR", function(data) {
var direction;
direction = "clockwise";
if (data.value < 0) {
direction = "counterClockwise";
}
return faye.publish("/drone/move", {
action: direction,
speed: normalizeSpeed(data.value)
});
});
gamepad.on("LEFT_SHOULDER", function(data) {
return faye.publish("/drone/move", {
action: "clockwise",
speed: data.value
});
});
gamepad.on("RIGHT_SHOULDER", function(data) {
return faye.publish("/drone/move", {
action: "counterClockwise",
speed: data.value
});
});
gamepad.on("LEFT_SHOULDER_BOTTOM", function(data) {
return faye.publish("/drone/move", {
action: "down",
speed: data.value
});
});
gamepad.on("RIGHT_SHOULDER_BOTTOM", function(data) {
return faye.publish("/drone/move", {
action: "up",
speed: data.value
});
});
}).call(this);
+63
Ver Arquivo
@@ -0,0 +1,63 @@
listeners = {}
window.gamepad =
isSupported: ->
!!navigator.webkitGetGamepads || !!navigator.webkitGamepads
BUTTONS:
FACE_1: 0, # Face (main) buttons
FACE_2: 1,
FACE_3: 2,
FACE_4: 3,
LEFT_SHOULDER: 4, # Top shoulder buttons
RIGHT_SHOULDER: 5,
LEFT_SHOULDER_BOTTOM: 6, # Bottom shoulder buttons
RIGHT_SHOULDER_BOTTOM: 7,
SELECT: 8,
START: 9,
LEFT_STICK: 10, # Analogue sticks (if depressible)
RIGHT_STICK: 11,
PAD_TOP: 12, # Directional (discrete) pad
PAD_BOTTOM: 13,
PAD_LEFT: 14,
PAD_RIGHT: 15
AXES:
LEFT_STICK_HOR: 0,
LEFT_STICK_VERT: 1,
RIGHT_STICK_HOR: 2,
RIGHT_STICK_VERT: 3
on: (event, callback) ->
listeners[event] ?= []
listeners[event].push(callback)
fire: (event, value) ->
return unless listeners[event]?
for callback in listeners[event]
callback(value: value, event: event)
checkForGamePad = null
padStatus = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
axesStatus = [0, 0, 0, 0]
setupGamepad = (pad) ->
console.log("setting up gamepad")
requestAnimationFrame(checkButtons)
gamepad.fire("ready", {})
checkButtons = ->
pad = navigator.webkitGetGamepads()[0]
for name, index of gamepad.BUTTONS
if padStatus[index] != pad.buttons[index]
padStatus[index] = pad.buttons[index]
gamepad.fire(name, pad.buttons[index])
for name, index of gamepad.AXES
if 0.1 < Math.abs(axesStatus[index] - pad.axes[index])
axesStatus[index] = pad.axes[index]
gamepad.fire(name, pad.axes[index])
requestAnimationFrame(checkButtons)
checkForGamePad = ->
pad = navigator.webkitGetGamepads()[0]
if pad?
setupGamepad(pad)
else
setTimeout(checkForGamePad, 1000)
gamepad.init = (callback) ->
gamepad.on "ready", callback if callback?
checkForGamePad()
+102
Ver Arquivo
@@ -0,0 +1,102 @@
(function() {
var axesStatus, checkButtons, checkForGamePad, listeners, padStatus, setupGamepad;
listeners = {};
window.gamepad = {
isSupported: function() {
return !!navigator.webkitGetGamepads || !!navigator.webkitGamepads;
},
BUTTONS: {
FACE_1: 0,
FACE_2: 1,
FACE_3: 2,
FACE_4: 3,
LEFT_SHOULDER: 4,
RIGHT_SHOULDER: 5,
LEFT_SHOULDER_BOTTOM: 6,
RIGHT_SHOULDER_BOTTOM: 7,
SELECT: 8,
START: 9,
LEFT_STICK: 10,
RIGHT_STICK: 11,
PAD_TOP: 12,
PAD_BOTTOM: 13,
PAD_LEFT: 14,
PAD_RIGHT: 15
},
AXES: {
LEFT_STICK_HOR: 0,
LEFT_STICK_VERT: 1,
RIGHT_STICK_HOR: 2,
RIGHT_STICK_VERT: 3
},
on: function(event, callback) {
var _ref;
if ((_ref = listeners[event]) != null) {
_ref;
} else {
listeners[event] = [];
};
return listeners[event].push(callback);
},
fire: function(event, value) {
var callback, _i, _len, _ref, _results;
if (listeners[event] == null) {
return;
}
_ref = listeners[event];
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
callback = _ref[_i];
_results.push(callback({
value: value,
event: event
}));
}
return _results;
}
};
checkForGamePad = null;
padStatus = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
axesStatus = [0, 0, 0, 0];
setupGamepad = function(pad) {
console.log("setting up gamepad");
requestAnimationFrame(checkButtons);
return gamepad.fire("ready", {});
};
checkButtons = function() {
var index, name, pad, _ref, _ref2;
pad = navigator.webkitGetGamepads()[0];
_ref = gamepad.BUTTONS;
for (name in _ref) {
index = _ref[name];
if (padStatus[index] !== pad.buttons[index]) {
padStatus[index] = pad.buttons[index];
gamepad.fire(name, pad.buttons[index]);
}
}
_ref2 = gamepad.AXES;
for (name in _ref2) {
index = _ref2[name];
if (0.1 < Math.abs(axesStatus[index] - pad.axes[index])) {
axesStatus[index] = pad.axes[index];
gamepad.fire(name, pad.axes[index]);
}
}
return requestAnimationFrame(checkButtons);
};
checkForGamePad = function() {
var pad;
pad = navigator.webkitGetGamepads()[0];
if (pad != null) {
return setupGamepad(pad);
} else {
return setTimeout(checkForGamePad, 1000);
}
};
gamepad.init = function(callback) {
if (callback != null) {
gamepad.on("ready", callback);
}
return checkForGamePad();
};
}).call(this);
+2
Ver Arquivo
@@ -78,6 +78,8 @@
<script src="components/jquery/jquery.js"></script>
<script src="/faye/client.js"></script>
<script src="components/bootstrap/js/bootstrap.min.js"></script>
<script src="/requestAnimationFrame.js"></script>
<script src="/gamepad.js"></script>
<script src="/client.js"></script>
</body>
</html>
+24
Ver Arquivo
@@ -0,0 +1,24 @@
(function() {
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
|| window[vendors[x]+'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}());
+6 -6
Ver Arquivo
@@ -34,12 +34,12 @@ drone.on 'navdata', (data) ->
socket.publish "/drone/navdata", data
imageSendingPaused = false
drone.createPngStream().on "data", (frame) ->
currentImg = frame
return if imageSendingPaused
socket.publish("/drone/image", "/image/#{Math.random()}")
imageSendingPaused = true;
setTimeout( ( -> imageSendingPaused = false ), 100)
# drone.createPngStream().on "data", (frame) ->
# currentImg = frame
# return if imageSendingPaused
# socket.publish("/drone/image", "/image/#{Math.random()}")
# imageSendingPaused = true;
# setTimeout( ( -> imageSendingPaused = false ), 100)
app.get "/image/:id", (req, res) ->
res.writeHead(200, "Content-Type": "image/png")
-11
Ver Arquivo
@@ -40,17 +40,6 @@
return socket.publish("/drone/navdata", data);
});
imageSendingPaused = false;
drone.createPngStream().on("data", function(frame) {
currentImg = frame;
if (imageSendingPaused) {
return;
}
socket.publish("/drone/image", "/image/" + (Math.random()));
imageSendingPaused = true;
return setTimeout((function() {
return imageSendingPaused = false;
}), 100);
});
app.get("/image/:id", function(req, res) {
res.writeHead(200, {
"Content-Type": "image/png"