I'm looking for a simple line of code or an API, if it is as simple as that.
I am using BabylonJS to make an online game, and I have run into a problem. I can't find anything on the documentation to support my problem. I am using
canvas.requestPointerLock = canvas.requestPointerLock || canvas.mozRequestPointerLock;
canvas.requestPointerLock();
To lock the mouse, when normally you have to click and drag. I am also using this movement script for basic movement:
function KEY_DOWN(event)
{
if (event.keyCode == 87)
{
player.position.z -= 0.5;
}
else if (event.keyCode == 65)
{
player.position.x += 0.5;
}
else if (event.keyCode == 83)
{
player.position.z += 0.5;
}
else if (event.keyCode == 68)
{
player.position.x -= 0.5;
}
}
This only transforms on an axis unfortunately. Is there any way to determine where my mouse is looking and move towards that point, and not just move on a fixed axis? I can't seem to find anything that has the exact methods I need. Thanks!
I don't know of any API, but it shouldn't be so bad, if I understand your problem correctly. You'll need to hook into the mousemove event after the point has been locked, and instead of the simple handling like shown here: http://www.html5rocks.com/en/tutorials/pointerlock/intro/ you would need to do your vector calculations against each vector of movement possible with the keys in that handler. Effectively, you would compute the x, y, z deltas that each key press corresponds to within your pointerlockchange handler based on the mouse deltas. Probably not as bad as it sounds, since your mouse deltas are only going to affect up to 2 axes at a time.
Related
I have a snake game that's "finished" except for one pretty serious annoyance.
Previously, I had the following problem.
Say the snake is going right. If the player changed directions multiple times in quick succession, e.g., by pressing down then left, then the snake would go back into itself and reverse direction. Once I added collision detection code, this would cause the game to end and the player to lose because the snake collided with itself by going inward into itself. This problem was made possible because direction could be changed multiple times in one interval, e.g., from right to down then from down to left.
This problem was fixed by adding a bool that would store whether or not direction was allowed to change this interval. If the direction had not been changed yet this interval, then direction was allowed to change. If it had already been changed this interval, then it would have to wait until next interval to change again. This prevented the snake from ever going inward into itself because it guaranteed that the snake's direction could only change once per interval. But this created another problem in that in each interval, every key press after the first would not register.
Now, the problem is that the game no longer feels responsive. If the snake is going to the right, there is no reason that spamming down right in quick succession shouldn't do what the player expects. As it stands, the second right sometimes doesn't register because it was pressed too quickly (on the same interval as down was pressed). So by fixing one big issue in this way, I created another annoyance. How do I get the best of both worlds. How do I stay rid of the possibility to go inward into myself while restoring responsiveness?
I can provide code if necessary, but I thought that the question was pretty clear even in abstraction.
It sounds like the game either acts on the new direction in the next interval or the direction is lost until the user presses again.
Have you tried queuing the next direction? for instance, at every interval, you can check the queue to see if there is a new direction. If there is, change direction. If not, continue in the current direction.
This will probably accomplish the responsiveness you want while still being accurate to the user’s input.
Good luck
I had the exact same problem! Very annoying! I ended up implementing a queue, where recent keypresses are stored in a queue, and for each 'tick' I check if any elements in queue, and if so, shift it once (with Array.shift, which returns the shifted value) and then set the snakes's direction to the direction from the queue, like this:
if (dir_queue.length) {
let d = dir_queue.shift();
dx = d.dx;
dy = d.dy;
}
// move snake
x += dx;
y += dy;
Directions are pushed to the dir. queue in the keydown event handler, like this:
var key = evt.keyCode;
if (key === KEY.UP || key === KEY.DOWN || key === KEY.LEFT || key === KEY.RIGHT) {
switch (key) {
case 37:
dx = dx || -1; dy = 0;
break;
case 38:
dx = 0; dy = dy || -1;
break;
case 39:
dx = dx || 1; dy = 0;
break;
case 40:
dx = 0; dy = dy || 1;
}
// push to dir. queue
dir_queue.push({ dx: dx, dy: dy });
}
so I am having troubles with automatic movement
The code I am using is
if (myGameArea.key && myGameArea.key == 40) {
snake.y ++;
}
which is moving but only when the key is hold, is there a way to let the object move in one direction automatically after just pressing the button. Sorry, if that's a stupid question, I really am not an experienced coder.
You should consider giving the snake object another attribute: velocity! Since you are dealing with two dimensions you can define vx and vy as the two components of the velocity, and when a key is pressed you can change the velocity to the appropriate value, for example:
if (myGameArea.key && myGameArea.key==40) {
snake.vx = 0;
snake.vy = 1;
}
As well as this, inside the snake object you should define the position by updating the current position. For this you just add the current velocity.
Hopefully this gets you on the path to a working snake game! If not, let me know and I can try to help out more.
I would use flags, and when you press a key set the flag to true for a while loop. When you press a key, go to a move function and have it move the direction of the flag until another key is pressed or you hit a wall.
Just as a beginner in Javascript, I'm trying to create a code to allow an object to move across the y and x axis with the appropriate response to directional keys. How do I go about doing so?
I don't know if you are trying to make the object move on a <canvas> element or change its DOM position, but I can help with keydown events.
Here's a code snippet you can use to load the event and handle it:
// Load a document key down event
document.addEventListener("keydown", keyDown, false);
// Function to register and handle the event
function keyDown(e) {
var k = e.keyPressed;
if (k === 37) console.log("Left key"); // Or whatever code you have
else if (k === 38) console.log("Up key");
else if (k === 39) console.log("Right key");
else if (k === 40) console.log("Down key");
}
Note that you will need to know the key codes for this to work. I have written a small function that you can use to get the key code of a pressed key:
document.addEventListener("keydown", keyDown, false);
function keyDown(e) {
document.write(e.keyCode);
}
Here's a JSFiddle.
EDIT: For the fiddle to work, you may need to click inside of the "Result" window.
Since I don't know if you want DOM manipulation, a <canvas> method, or something else, all I can help you on is the key events. However, I hope I've sent you in the right direction. Good luck!
I've been battling with this for two days. I'm using an HTML5/JS game engine called ImpactJS and someone made a very useful plugin to create joystick touch zones for mobile devices. The idea is that you specify a zone on the screen where the joystick is activated when that area is touched.
The code for the plugin I am using is here. I have modified it slightly to add "curPos" (x and y coordinates of the spot that the user is currently touching), otherwise all code is identical. I have been trying to solve this problem myself as well as contacting the original creator, but they seem to be unreachable at this time and I'm getting nowhere.
I'm sure I'm doing something very wrong here, but while I can get the touch zones to work perfectly on their own, every time I try to use both joysticks at the same time they partially overwrite each other.
I have specified two zones as follows when my game initializes:
this.joystick1 = new TouchJoystickZone(0, 0, ig.system.width / 2, ig.system.height);
this.joystick2 = new TouchJoystickZone(ig.system.width / 2, 0, ig.system.width / 2, ig.system.height);
this.joystick1 is responsible for player rotation. this.joystick2 is responsible for player acceleration. In my Player entity I have the following movement code for the two joysticks. Again, this works perfectly when I only have one finger on the screen/one joystick in use:
if( ig.ua.mobile ) {
// ROTATION
if (ig.game.joystick1.touchStart.x > 0 && ig.game.joystick1.touchStart.x < ig.system.width/2) {
if (Math.abs(ig.game.joystick1.delta.x) >= 50 || Math.abs(ig.game.joystick1.delta.y) >= 50) {
this.joystickAngle = ig.game.Controller.toDegrees(ig.game.Controller.joystickAngle());
if (this.angle > this.joystickAngle + 20) {
this.angle -= this.turnSpeed * ig.system.tick;
}
else if (this.angle < this.joystickAngle - 20) {
this.angle += this.turnSpeed * ig.system.tick;
}
else {
this.angle = this.joystickAngle;
}
}
}
// THRUST
if (ig.game.joystick2.touchStart.x > ig.system.width / 2) {
if (ig.game.joystick2.delta.y <= -50) {
this.accel.x = Math.cos(this.angle*Math.PI/180)*this.thrust;
this.accel.y = (Math.sin(this.angle*Math.PI/180)*this.thrust);
this.fuel -= 0.1;
}
else if (ig.game.joystick2.delta.y >= 50) {
this.accel.x = Math.cos(this.angle*Math.PI/180)*-this.thrust;
this.accel.y = (Math.sin(this.angle*Math.PI/180)*-this.thrust);
this.fuel -= 0.1;
}
}
else {
this.accel.x = 0;
this.accel.y = 0;
}
}
As soon as I place a second finger on the screen, however, the first joystick becomes overwritten. I can rotate and then move or move and then rotate and it works fine, but I need to do both at the same time.
I found out that touchStart.x and touchStart.y seems to be being set for both joysticks when I tap to use the other stick and not just the relevant joystick1 or joystick2, even though in the plugin code those coordinates are only meant to be affected if the touch for that joystick is within the specified zone. I believe this is partly what is contributing to the issue. At this stage I've spent hours trying to figure this out and am just as lost as when I started.
Can someone possibly point me in the right direction with using both of these joysticks at the same time?
The joystick script you are using is only looking for the first finger. The following is from lines 47-48
var x = ev.touches[0].pageX - pos.left,
y = ev.touches[0].pageY - pos.top;
The '0' determines which finger to track.
The script would have the be changed to be aware which finger is on which element and then only track that finger. You could do that by either determining which element was pressed first or by location.
JSFiddle Example: http://jsfiddle.net/7WR88/5/
http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/
As mentioned by #Dcullen, there may be multiple touches in each event starting at the first touch.
It would be a simple solution to iterate through the ev.touches collection and see if each touch falls into a hotzone. If it falls under hot zone 1, treat it as a touch for joystick 1. If it falls under hotzone 2, treat it as a touch for joystick 2.
This would mean that it doesn't matter in which order the touches appear, because they will always map to the correct joystick if they are near to it.
I am working on a little HTML/JavaScript/CSS3 project for fun. I'm basically trying to make a wheel that rolls around in the browser window. To control the wheel I'm using keyup and keydown events for the cursor keys (left and right turn the wheel and up and down roll it forward or backward).
I've got it working pretty well so far, but there are two major glitches. Say I want to roll the wheel forward and without stopping I want to turn it a little to the right, then I would keep the up key pressed and press the right cursor key. When I do this there's a pause in the movement before it registers both events and keeps rolling.
That's one of the problems, the main problem is that, once I've performed the previous action and then wheel is at a desirable angle, if I let go of the right cursor key the browser registers both keys as released and the wheel comes to a stand still. Here is a jsFiddle of what it looks like: http://jsfiddle.net/UKqwu/1/. I know the code is a mess but it's a work in progress/learning experience and I've only been programming for a month or so.
Anyways thanks for any help. It only works in Chrome at the moment as far is I know. Haven't really been bothered fixing compatibility issues at this stage.
So, what is happening is essentially a limitation built in by your operating system, but there is a simple work-around. First I'll explain the limitation, and then the work-around.
If you were to (in a text box) hold down the "j" button, first one "j" would appear, and then after a short delay many "j"s would appear "jjjjjjjjjjjjjjjjjjjj"
This is the same problem your experiencing. The event fires once, waits for a moment, and then fires many more times.
The solution, however is simple. Instead of having your wheel move when the events are fired... have it update constantly, and separately keep track of what keys are up or down.
The Key Handler would look something like this...
function KeyHandler() {
this.left = false;
this.right= false;
...
function onKeyDown(e) {
if (e.keyCode == 37) {
this.left = true;
}
...
}
function onKeyUp(e) {
if (e.keyCode == 37) {
this.left = false;
}
...
}
}
(you'd attach the key handler to the body or whatever element you wish)
Your wheel would have an update function that looked like...
wheel.update = function() {
// the wheel is turning left
if (wheel.keyhandler.left) {
// make the appropriate adjustments
}
}
and then the game would have something like this...
wheel = new Wheel;
setInterval(function() {
wheel.update();
},100);
That way your wheel will always be updating based on the current state of the keys, and you wont have to rely on the limitations of events that are firing. :)
Here's a snippet of a simple game I once wrote
//key codes
var KEY_LEFT = 37;
var KEY_RIGHT = 39;
var KEY_A = 65;
var KEY_D = 68;
var KEY_SPACE = 32;
var keys = {};
function onKeyDown(e)
{
e = e || window.event;
var key = window.event.keyCode || e.which; // ie
keys[key] = true;
}
function onKeyUp(e)
{
var key = window.event.keyCode || e.which; // ie
delete keys[key];
}
This keeps track of all current key states. Then your game "tick" is on a setTimeout() rather than moving on key events and checks for appropriate keys.
function gameTick()
{
// update paddle angles
if (keys[KEY_LEFT])
{
// move left
}
if (keys[KEY_RIGHT])
{
// move right
}
}
Here's the game;
the problem you are facing is because your code is meant to detect single key press while your game needs 2 key press detection.
put this line in loop over size of e. that will set all pressed keys as 1. currently its detecting only one key press and processing for one at a time.
keys[e.keyCode] = 1;
check out this thread and u might get what you need. though its jquery, it might help conceptually. m also working on this with js... if anything new comes up will share...
Detect multiple keys on single keypress event in jQuery
your code and concept is cool if you are really one month old in programming.