moving svg box with js - javascript

This is a svg box which can move using arrow keys.
I want this box to stop when the arrows are realeased, and to continue moving accordingly to the key presed.
This app uses svg, js, and jquery.
I have looked and have found no answer. Please help the cause.
$(function() {
var y = 4;
var x = 4;
var n;
var move;
$(document).keydown(function(e) {
switch(e.which) {
case 37: // left
move = setInterval(move_left, .1);
break;
case 38: // up
move = setInterval(move_up, .1);
break;
case 39: // right
move = setInterval(move_right, .1);
break;
case 40: // down
move = setInterval(move_down, .1);
break;
default:
return;
}
e.preventDefault();
});
function move_left() {
$("#block_green").attr({
x: x
});
x--;
}
function move_up() {
$("#block_green").attr({
y: y
});
y--;
}
function move_right() {
$("#block_green").attr({
x: x
});
x++;
}
function move_down() {
$("#block_green").attr({
y: y
});
y++;
}
}
});
body {
margin: 0;
overflow: hidden;
}
svg {
background-color: black;
width: 100vw;
height: 100vh;
}
#block_green {
fill: black;
stroke: #00ff00;
stroke-width: .5px;
}
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<svg>
<rect x="4" y="4" width="80" height="60" id="block_green"/>
</svg>
</body>
</html>
The code doesn't seem to work here, so you may want to visit http://codepen.io/julian-a-avar/pen/PqZvxp to see it in action, and you may want to check an editor, because as I said before, The preview doesn't seem to work here!!!

I would make the loop seperate and set variables that determine which keys are pressed.
Use keydown to set the variables to true and keyup to set the variables back to false.
Something similar to this:
$(function() {
var y = 4;
var x = 4;
var n;
var move;
var leftPressed = false;
var rightPressed = false;
var downPressed = false;
var upPressed = false;
setInterval(function(){
if(leftPressed){
move_left();
}else if(rightPressed){
move_right();
}
if(upPressed){
move_up();
}else if(downPressed){
move_down();
}
},.01)
$(document).keydown(function(e) {
switch(e.which) {
case 37: // left
leftPressed = true;
break;
case 38: // up
upPressed = true;
break;
case 39: // right
rightPressed =true;
break;
case 40: // down
downPressed = true;
break;
default:
return;
}
e.preventDefault();
});
$(document).keyup(function(e) {
switch(e.which) {
case 37: // left
leftPressed = false;
break;
case 38: // up
upPressed = false;
break;
case 39: // right
rightPressed =false;
break;
case 40: // down
downPressed = false;
break;
default:
return;
}
e.preventDefault();
});
function move_left() {
$("#block_green").attr({
x: x
});
x--;
}
function move_up() {
$("#block_green").attr({
y: y
});
y--;
}
function move_right() {
$("#block_green").attr({
x: x
});
x++;
}
function move_down() {
$("#block_green").attr({
y: y
});
y++;
}
});
Notice setInterval is just checking the variables to determine which methods to call to move the box.
Here is a codepen with an example
Question 2
How to adjust the speed of the moving block?
One way to adjust the speed is to set a variable that determines how much x or y changes with each pass in setInterval. So make another variable n and setting that value higher makes the block move faster and lower makes it move slower.
Additionally, you asked if there are ways to shorten up the code. There are probably numerous ways that code could be improved if you get creative. Below I've provided an example with the variable n and provided one way you could shorten up the code. Instead of having variables for every key pressed just have two variables for the horizontal and vertical axis:
$(function() {
var y = 4;
var x = 4;
var n = 1;
var move;
var xDirection = 0;
var yDirection = 0;
setInterval(function(){
x = x + (xDirection * n);
y = y + (yDirection * n);
$("#block_green").attr({
y: y,
x: x
});
},.01)
$(document).keydown(function(e) {
xDirection = e.which == 37 ? -1 : xDirection;
xDirection = e.which == 39 ? 1 : xDirection;
yDirection = e.which == 38 ? -1 : yDirection;
yDirection = e.which == 40 ? 1 : yDirection;
e.preventDefault();
});
$(document).keyup(function(e) {
xDirection = e.which == 37 ? 0 : xDirection;
xDirection = e.which == 39 ? 0 : xDirection;
yDirection = e.which == 38 ? 0 : yDirection;
yDirection = e.which == 40 ? 0 : yDirection;
e.preventDefault();
});
});
And here is another codepen of the changes
Also i'd recommend looking into some basic game algos (like 80's arcade games, ie Space Invaders, etc) They will have this kind of game logic.
If you're interested, this video on vimeo is pretty cool and a good example of this kind of dev, developer creating space invaders real time in javascript

Related

Javascript moving div to new position with arrow keys

I want to make a div able to move with arrow keys in 4 direction with multikey support(e.x. moving to top left) onkeypress. When i click some of the arrows i expect moving to that direction until i put my finger up from that button. Although the move is just once which i don't understand why is happening.
function place(id,x_pos, y_pos) {
var element = document.getElementById(id);
element.style.position = "absolute";
element.style.left = x_pos+'px';
element.style.top = y_pos+'px';
}
setInterval(update,1);
function update(){
document.addEventListener('keydown', keyPress);
}
function keyPress(e) {
var x = e.keyCode;
switch (x) {
case 37:
place('move', move.style.left-10, move.style.top);
break;
case 39:
place('move', move.style.left+10, move.style.top);
break;
case 38:
place('move', move.style.left, move.style.top-10);
break;
case 40:
place('move', move.style.left, move.style.top+10);
break;
}
// console.log(x);
}
*{
margin:0;
padding:0;
}
div#move{
background-color:yellow;
width:5vw;
height:5vw;
}
<div id='move'></div>
The problem with your code is that element.style.left give result as 10px and when you add 10 on 10px it will be a string like 10px10 which will make the property value incorrect.Since the first time the property is not set so first assignment id working fine. You need to get the left and right in numerical.
You also do not need to bind the update function with document with setInterval. Once is enough.
Check the code below
function place(id,x_pos, y_pos) {
var element = document.getElementById(id);
element.style.position = "absolute";
element.style.left = x_pos+'px';
element.style.top = y_pos+'px';
}
function update(){
document.addEventListener('keydown', keyPress);
}
function keyPress(e) {
var x = e.keyCode;
var move = document.getElementById("move").getBoundingClientRect();
var left = parseInt(move.left,10);
var top = parseInt(move.top,10)
switch (x) {
case 37:
place('move', left -10, top);
break;
case 39:
place('move', left+10, top);
break;
case 38:
place('move', left, top-10);
break;
case 40:
place('move', left, top+10);
break;
}
// console.log(x);
}
update();
*{
margin:0;
padding:0;
}
div#move{
background-color:yellow;
width:5vw;
height:5vw;
}
<div id='move'></div>
const move=document.getElementById('move');
var moveLeft = 0;
function direction(e){
if(e.keyCode==39){
moveLeft +=2;
move.style.left = moveLeft + 'px';
if(moveLeft>=600){
moveLeft -=2;
}
}
if(e.keyCode==37){
moveLeft -=2;
move.style.left = moveLeft + 'px';
}
if(e.keyCode==38){
moveLeft -=2;
move.style.top = moveLeft + 'px';
if(moveLeft>=600){
moveLeft +=2;
}
}
if(e.keyCode==40){
moveLeft +=2;
move.style.top = moveLeft + 'px';
}
}
document.onkeydown = direction;
#move{
position: absolute;
height: 50px;
width: 50px;
background-color: yellow
}
<div id="move"></div>
You don't need setInterval. Just register your listener, and it will handle every keypress.
document.addEventListener('keydown', keyPress);
function keyPress(e) {
var x = e.keyCode;
switch (x) {
case 37:
place('move', move.style.left-10, move.style.top);
break;
case 39:
place('move', move.style.left+10, move.style.top);
break;
case 38:
place('move', move.style.left, move.style.top-10);
break;
case 40:
place('move', move.style.left, move.style.top+10);
break;
}
// console.log(x);
}

Moving diagonally in 2d canvas JavaScript game

I've scoured the web for this answer. If it is buried in a StackOverflow answer somewhere I apologize.
I am working on a 2d canvas JavaScript game.
I am handling arrow key input with onkeydown and onkeyup events.
I store this input in an object called Keys.
var Keys = {
up: false,
down: false,
left: false,
right: false
};
This is what my event handlers look like:
window.onkeydown = function(e){
var kc = e.keyCode;
e.preventDefault();
if(kc === 37) Keys.left = true;
else if(kc === 38) Keys.up = true;
else if(kc === 39) Keys.right = true;
else if(kc === 40) Keys.down = true;
move();
};
window.onkeyup = function(e){
var kc = e.keyCode;
e.preventDefault();
if(kc === 37) Keys.left = false;
else if(kc === 38) Keys.up = false;
else if(kc === 39) Keys.right = false;
else if(kc === 40) Keys.down = false;
};
Then each time the keydown event occurs, I call my move() function:
var move = function(){
if(Keys.up){
hero.y -= 10;
}
else if(Keys.down){
hero.y += 10;
}
if(Keys.left){
hero.x -= 10;
}
else if(Keys.right){
hero.x += 10;
}
main();
}
The move() function calls my main() function which just draws the map again.
I'm trying to avoid looping the game, and instead update the map each time the player moves.
So my problem arises when I try to move diagonally. I am able to do it, however once I release the second key pressed, my character stops.
For example:
Right key pressed and then up key pressed, character moves northeast.
Up key released, player stops.
However, if I release the right key, the character continues moving up.
Another glitch is when I hold both left and right, the character will move left,
but I want it to stop moving.
Quickly sketched an example, jsfiddle: http://jsfiddle.net/ofnp4vj4/
HTML: <div id="log"></div>
JS:
var Keys = {
up: false,
down: false,
left: false,
right: false
};
var hero = {
x: 0,
y: 0
};
var log = document.getElementById("log");
window.onkeydown = function(e){
var kc = e.keyCode;
e.preventDefault();
if(kc === 37) Keys.left = true;
if(kc === 38) Keys.up = true;
if(kc === 39) Keys.right = true;
if(kc === 40) Keys.down = true;
};
window.onkeyup = function(e){
var kc = e.keyCode;
e.preventDefault();
if(kc === 37) Keys.left = false;
if(kc === 38) Keys.up = false;
if(kc === 39) Keys.right = false;
if(kc === 40) Keys.down = false;
};
function main() {
/* body */
move();
log.innerHTML = "x: "+hero.x+", y: "+hero.y;
};
function move(){
if(Keys.up){
hero.y -= 10;
}
if(Keys.down){
hero.y += 10;
}
if(Keys.left) {
hero.x -= 10;
}
if(Keys.right){
hero.x += 10;
}
}
setInterval(main, 100);
You mention that you want the player to stop moving when you press the left and right keys simultaneously. It appears you should be able to easily do this by replacing the else if statements in move with if statements, resulting in a move function similar to:
var move = function(){
if(Keys.up){
hero.y -= 10;
}
if(Keys.down){
hero.y += 10;
}
if(Keys.left){
hero.x -= 10;
}
if(Keys.right){
hero.x += 10;
}
main();
}

How to make window scroll at a slower rate with arrow keys?

How can I make the window scroll at a slower rate (horizontally and vertically) when triggered with the arrow keys? I've looked at some parallax demos, but they don't really do what I need. They mostly focus on background images, whereas I want my entire window and/or html body to slow down.
thanks!
Try to fiddle with this code:
addEventListener('keydown', function(e){
move = false;
x = false;
y = false;
var keycode;
if (window.event) keycode = window.event.keyCode;
else if (e) keycode = e.which;
switch(keycode){
case 37:
move = true;
x = 'negative';
break;
case 38:
move = true;
y = 'negative'
break;
case 39:
move = true;
x = 'positive'
break;
case 40:
move = true;
y = 'positive'
break;
}
if(move){
animation.move(x,y);
}
return false;
})

jquery position changing with .css() behaving strange

I tried to make a moving img, and it works partially. If I press the right, up or down button, it moves right, up or down. But, if I press the left button, it jumps very fast very far to the right, and then back to the left and doesn't stop moving (I believe. I said it was fast).
JSFiddle;
Javascript:
$(document).ready(function() {
var up = down = left = right = false;
var top = 100, left = 500;
$("body").on("keydown", function(e) {
if(e.keyCode == 39) {e.preventDefault(); if (right == false) right = setInterval(moveRight, 80);}
else if(e.keyCode == 37) {e.preventDefault(); if (left == false) left = setInterval(moveLeft, 80);}
else if(e.keyCode == 38) {e.preventDefault(); if (up == false) up = setInterval(moveUp, 80);}
else if(e.keyCode == 40) {e.preventDefault(); if (down == false) down = setInterval(moveDown, 80);}
});
$("body").on("keyup", function(e) {
if(e.keyCode == 39) {clearInterval(right); right = false;}
else if(e.keyCode == 37) {clearInterval(left); left = false;}
else if(e.keyCode == 38) {clearInterval(up); up = false;}
else if(e.keyCode == 40) {clearInterval(down); down = false;}
});
function moveUp() {
top -= 2;
$("#player").css("top", top + "px");
}
function moveDown() {
top += 2;
$("#player").css("top", top + "px");
}
function moveLeft() {
left -= 2;
$("#player").css("left", left + "px");
}
function moveRight() {
left += 2;
$("#player").css("left", left + "px");
}
});
This is probably not the best way to do this, I'm open for better suggestions.
You're defining two "left" variables, and they are getting in the way of each other. Change one of their names (perhaps leftInterval for the interval variable), and things should go better.
The variables are overwritten, try something like :
$("body").on("keydown", function(e) {
e.preventDefault();
var elm = $("#player"),
top = parseInt(elm.css('top')),
left = parseInt(elm.css('left'));
switch(e.which) {
case 37:
elm.css("left", left-2);
break;
case 38:
elm.css("top", top-2);
break;
case 39:
elm.css("left", left+2);
break;
case 40:
elm.css("top", top+2);
break;
}
});
​
FIDDLE

In Javascript, how do I tell if a user is pressing two keys at the same time?

In Javascript, how do I tell if a user is pressing two keys at the same time?
For example, I have drawn a circle in the middle of the screen. I want to move it up while the user holds down the up arrow and right while the user holds down the right arrow. That part works easy. If user holds both the up and right arrows, I want to move the circle diagonally, up and to the right.
It doesn't look like this possible with basic Javascript event handling, but surely someone has figured out a work around/hack/improvement.
Here is what you need to do conceptually (I guess this is called pseudo code):
Start with something like this:
var PIXEL_DELTA = 10; // Distance to move in pixels
var leftPressed = 0,
upPressed = 0,
downPressed = 0,
rightPressed = 0;
Then on every keydown event, test if it the key pressed is left, up, etc and turn its variable from 0 to PIXEL_DELTA.
On every keyup event, run the same test and turn the correct variable back to 0.
Then, in your moving code (real code): (This code adapted from Crescent Fresh's awesome example):
function move() {
var dot = document.getElementById('dot'),
deltaX = rightPressed - leftPressed,
deltaY = downPressed - upPressed;
if(deltaX) {
dot.style.left = (parseInt(dot.style.left, 10) || 0) + deltaX + 'px';
}
if (deltaY) {
dot.style.top = (parseInt(dot.style.top, 10) || 0) + deltaY + 'px';
}
}
The browser will (should) fire a separate keydown/keyup event for each key, even if they are "simultaneously" pressed.
Working Example
Crescent Fresh put together a full example on JSBin. Be sure to visit the editable version as well to play with the code.
Javascript has onkeydown, and onkeyup events. You can simple fiddle a bit onkeydown for left arrow, and fiddle another bit for the up arrow. On keyup, fiddle the respective bit back.
var leftPressed,
upPressed,
rightPressed,
downPressed;
var milli = 100;
window.addEventListener('onkeydown', function(e) {
switch(e.keycode) {
case 37: //left
leftPressed = true;
case 38: //up
upPressed = true;
case 39: //right
rightPressed = true;
case 40: //down
downPressed = true;
default:
break;
}
});
window.addEventListener('onkeyup', function(e) {
switch(e.keycode) {
case 37: //left
leftPressed = false;
case 38: //up
upPressed = false;
case 39: //right
rightPressed = false;
case 40: //down
downPressed = false;
default:
break;
}
});
function moveCircle() {
if(leftPressed && !rightPressed) {
// move left
}
if(rightPressed && !leftPressed) {
// move right
}
if(upPressed && !downPressed) {
// move up
}
if(downPressed && !upPressed) {
// move down
}
}
setInterval(moveCircle, milli);
Maybe you can do it by keeping track of keydown and keyup event for each key and you'll know if two keys are being held at the same time.
Sample pseudo-code:
var keydown = {};
function onkeydown(event) {
keydown[event.key] = true;
}
function onkeyup(event) {
keydown[event.key] = false;
}
// in some function at some other places
if (keydown['up'] && keydown['right']) {
move_diagonal('up', 'right');
}
elseif (keydown['up'] && keydown['left']) {
move_diagonal('up', 'left');
}
elseif .. blah blah
Javascript keyboard events fire on keypress and keydown, but don't contain the additional keymask info to determine if other keys are pressed at the same time.

Categories