I have a rather repetitive switch case statement and in my quest to learn the simplest way of doing things, I wanted to turn to SO and see if there is a more elegant solution to the following:
switch(id)
{
case 'ib-02a':
if(direction == 'left')
setHash('ib-02b');
break;
case 'ib-02b':
if(direction == 'right')
setHash('ib-02a');
if(direction == 'left')
setHash('ib-02c');
break;
case 'ib-02c':
if(direction == 'right')
setHash('ib-02b');
if(direction == 'left')
setHash('ib-02d');
break;
case 'ib-02d':
if(direction == 'right')
setHash('ib-02c');
break;
case 'ib-03a':
if(direction == 'left')
setHash('ib-03b');
break;
case 'ib-03b':
if(direction == 'right')
setHash('ib-03a');
if(direction == 'left')
setHash('ib-03c');
break;
case 'ib-03c':
if(direction == 'right')
setHash('ib-03b');
if(direction == 'left')
setHash('ib-03d');
break;
case 'ib-03d':
if(direction == 'right')
setHash('ib-03c');
break;
case 'pb-05a':
if(direction == 'left')
setHash('pb-05b');
break;
case 'pb-05b':
if(direction == 'right')
setHash('pb-05a');
if(direction == 'left')
setHash('pb-05c');
break;
case 'pb-05c':
if(direction == 'right')
setHash('pb-05b');
if(direction == 'left')
setHash('pb-05d');
break;
case 'pb-05d':
if(direction == 'right')
setHash('pb-05c');
break;
}
I'm reading swipe events, and if the ID of the element I am swiping on matches either ib-02*, ib-03*, or pb-05*, I am calling a setHash function for the appropriate ID. If I'm swiping on *a, I swipe left to *b. If I'm swiping on *b, I swipe right to *a and left to *c. So on and so forth, always between *a and *d.
There must be a less repetitive way to do this, but I'm not sure exactly what the best approach is.
How about mapping them to an object? Then just use the setHash with the retrieved value.
var ids = {
'pb-05c' : {
left : 'pb-05d',
right : 'pb-05b'
}
...
}
function setHashes(id,direction){
if(id && ids[id]){
id = ids[id];
if(direction && id[direction]){
setHash(id[direction]);
}
}
}
It's all retrieval and no condition evaluation, which can be good for performance.
There are 4 major cases that are a, b, c and d, you can base your switch statement on these strings, try this:
var c = id.slice(0, 5); // "ib-02" or "ib-03" or "ib-04" ...
var which = id.slice(-1); // "a" or "b" or "c" or "d"
switch(which) {
case 'a':
if(direction == 'left')
setHash(c+'b');
break;
case 'b':
if(direction == 'right')
setHash(c+'a');
if(direction == 'left')
setHash(c+'c');
break;
case 'c':
if(direction == 'right')
setHash(c+'b');
if(direction == 'left')
setHash(c+'d');
break;
case 'd':
if(direction == 'right')
setHash(c+'c');
break;
}
You can make the whole thing data table driven like this:
var logicData = {
// format is the id first and then an array with the left, then right value for the hash
// leave an item as an empty string if you don't ever want to go that direction
'ib-02a': ['ib-02b', ''],
'ib-02b': ['ib-02c', 'ib-02a'],
'ib-02c': ['ib-02d', 'ib-02d']
// fill in the rest of the data table here
};
function setNewHash(id, direction) {
var hash, data = logicData[id];
if (data) {
if (direction == 'left') {
hash = data[0];
} else if (direction == 'right') {
hash = data[1];
}
if (hash) {
setHash(hash);
}
}
}
id='ib-02a'; //you have string id, this one is for demo
id=[id.slice(0,--id.length), id.charAt(--id.length)];
switch(id[1]){
case 'a':
if(direction == 'left'){setHash(id[0]+'b');}
break;
case 'b':
if(direction =='right'){setHash(id[0]+'a');}
if(direction == 'left'){setHash(id[0]+'c');}
break;
case 'c':
if(direction == 'right'){setHash(id[0]+'b');}
if(direction == 'left'){setHash(id[0]+'d');}
break;
case 'd':
if(direction == 'right'){setHash(id[0]+'c');}
break;
}
If case b and c are only 'left' or 'right' you could use an else in those if statements.
I like the general direction of undefined and GitaarLab where they actually solved the algorithm and just implemented the algorithm. To review, the algorithm is basically that left increments the final letter and right decrements the final letter of the id, but you don't go below a or above d. So, I did a compact implementation of that where I convert the last letter to a number and increment or decrement it directly rather than using if/else or case statements:
function setNewHash(id, direction) {
var base = id.substr(0, 5);
var tag = id.charCodeAt(5), newTag;
var nav = {left: 1, right: -1};
var delta = nav[direction];
if (delta) {
tag += delta;
newTag = String.fromCharCode(tag);
if (newTag >= 'a' && newTag <= 'd') {
setHash(base + newTag);
}
}
}
Working test case: http://jsfiddle.net/jfriend00/gwfLD/
You could chunk up the id into different parts, then rebuild them right before you do setHash.
function chunkId(id) {
// use a regex or string split or something to convert
// "ib-05a" to ["ib-05", "a"]
return ["ib-05", "a"];
}
function next(str) {
// return the next letter in the alphabet here
return "b";
}
function prev(str) {
// return the prev letter in the alphabet here
return "b";
}
function swipe (id, direction) {
var array = chunkId(id);
// you can only swipe left if not on "d"
if (direction === "left" && id[1] != "d") {
setHash(id[0] + next(id[1])); // build hash based on next character
}
// you can only swipe right if not on "a"
if (direction === "right" && id[1] != "a") {
setHash(id[0] + prev(id[1])); // build hash based on prev character
}
}
You can switch the id and direction checks to make it clearer:
switch (direction) {
case 'left':
switch (id) {
case 'ib-02a': setHash('ib-02b'); break;
case 'ib-02b': setHash('ib-02c'); break;
case 'ib-02c': setHash('ib-02d'); break;
case 'ib-03a': setHash('ib-03b'); break;
case 'ib-03b': setHash('ib-03c'); break;
case 'ib-03c': setHash('ib-03d'); break;
case 'pb-05a': setHash('pb-05b'); break;
case 'pb-05b': setHash('pb-05c'); break;
case 'pb-05c': setHash('pb-05d'); break;
}
break;
case 'right':
switch (id) {
case 'ib-02b': setHash('ib-02a'); break;
case 'ib-02c': setHash('ib-02b'); break;
case 'ib-02d': setHash('ib-02c'); break;
case 'ib-03b': setHash('ib-03a'); break;
case 'ib-03c': setHash('ib-03b'); break;
case 'ib-03d': setHash('ib-03c'); break;
case 'pb-05b': setHash('pb-05a'); break;
case 'pb-05c': setHash('pb-05b'); break;
case 'pb-05d': setHash('pb-05c'); break;
}
break;
}
Then you can simplify if by splitting the id:
var first = id.substr(0, 5);
var last = id.substr(6);
switch (direction) {
case 'left':
switch (last) {
case 'a': setHash(first + 'b'); break;
case 'b': setHash(first + 'c'); break;
case 'c': setHash(first + 'd'); break;
}
break;
case 'right':
switch (last) {
case 'b': setHash(first + 'a'); break;
case 'c': setHash(first + 'b'); break;
case 'd': setHash(first + 'c'); break;
}
break;
}
Related
i want to change the way my Js game works, basically the game does not recognize input whenever the language is not english with no Capital letters ( only when the event.key is equal to wasd ) how can i fix this bug ?
thanks !
window.addEventListener('keydown', (event) => {
if (!player.isDead){
switch (event.key) {
case 'w':
keys.d.pressed = true;
player.lastkey = 'd';
break;
case 'a':
keys.a.pressed = true;
player.lastkey = 'a';
break;
case 'w':
if(player.position.y > 0)
{
player.velocity.y = -10;
}
break;
case ' ':
player.Attacking();
if(player.lastkey === 'd'){player.SwitchSprite('punch')}
else{player.SwitchSprite('fpunch')}
break;
}
}
You should use the event.code or event.keyCode properties to stay language independent;
switch (event.code) // <- not event.key
case "KeyW": // <- not 'w'
...
function control()
{
var ship = document.getElementById("ship");
document.onkeydown = function(e) {
switch (e.keyCode) {
case 38:
ship.style.top += "5%";
break;
case 40:
ship.style.top -= "5%";
break;
default:
break;
}
}
}
setInterval(control,1000);
This code is not working.
The object I'm trying to move is not moving when I'm pressing the Up & Down Arrow Key.
You can't do
ship.style.top += "5%";
because ship.style.top value is not a number but a string. the += opérator is concatening strings here.
You should do something like that:
const ship = document.getElementById("ship");
document.onkeydown = function (e) {
let winHeigth = window.innerHeight;
let top = ship.style.top;
switch (e.code) {
case "ArrowUp":
ship.style.top = (Number(top.substring(0, top.length - 2)) - (winHeigth / 20)) + "px";
break;
case "ArrowDown":
ship.style.top = (Number(top.substring(0, top.length - 2)) + (winHeigth / 20)) + "px";
break;
default:
break;
}
}
The position attribute of the "ship" must be like "relative".
By the way, e.keyCode is deprecated, you can use e.code instead ^^
I'm programming something withe Javascript which captures keyboard input, but the problem is that every time the user presses a key there an error sound. How can I disable it?
#Polaris878
function KeyPressed(e)
{
if (!e) e = window.event;
if (e.which)
{
keycode = e.which
}
else if (e.keyCode)
{
keycode = e.keyCode
}
switch (keycode)
{
case 49:
key = "1";
break;
case 50:
key = "2";
break;
case 51:
key = "3";
break;
case 52:
key = "4";
break;
case 53:
key = "5";
break;
case 54:
key = "6";
break;
case 55:
key = "7";
break;
case 56:
key = "8";
break;
case 57:
key = "9";
break;
case 48:
key = "0";
break;
default:
key = "";
return false;
break
}
if (keys == "NULL")
{
keys = key
}
else
{
keys = keys + key
} if (keys.length >= 5)
{
document.formular.submit();
}
document.formular.code.value = keys;
}
var keys = "";
document.onkeydown = KeyPressed
So I have a div you move with your arrow keys, but how do I make it so it can't go outside the "border div"?
$(document).ready(function(){
$(document).keydown(function(e) {
switch (e.which) {
case 37: // Left
$("#cube").css("left", $("#cube").offset().left - 101);
break;
case 38: // Up
$("#cube").css("top", $("#cube").offset().top - 11);
break;
case 39: // Right
$("#cube").css("left", $("#cube").offset().left - 97);
break;
case 40: // Down
$("#cube").css("top", $("#cube").offset().top - 7);
break;
}
});
});
http://jsfiddle.net/SfKHN/
Here you go:- I tested in FF and Chrome and seems to be fine....
Demo
Probably this is not completely perfect but you can build on it. Key here is to get the margins of the parent right and make sure the cube's left/right/top/bottom doesn't go beyond it. Border width also should be considered. Another thing is your Step should be a multiple of its width/height(as it is a square)
$(document).ready(function(){
$(document).keydown(function(e) {
var cube = $("#cube");
var leftMargin = 0;
var rightMargin = $('#outside').position().left + $('#outside').width() - cube.width();
var topMargin =0;
var bottomMargin = $('#outside').position().top + $('#outside').height() - cube.height();
switch (e.which) {
case 37: // Left
var newLeft = parseInt(cube.position().left - 50);
if(leftMargin <= newLeft)
{
cube.css("left", newLeft);
}
break;
case 38: // Up
var newTop = parseInt(cube.position().top - 50);
if(topMargin <= newTop)
{
cube.css("top",newTop);
}
break;
case 39: // Right
var newRight = (cube.position().left + 50);
if(rightMargin > newRight)
{
cube.css("left", newRight);
}
break;
case 40: // Down
var newBottom = parseInt(cube.position().top + 50);
if(bottomMargin > newBottom)
{
cube.css("top", newBottom);
}
break;
}
});
});
You add simple if statements to make sure you haven't passed the border. Here's an example:
$(document).ready(function(){
$(document).keydown(function(e) {
switch (e.which) {
case 38: // Up
if( ( $("#cube").offset().top - 11 ) >= 0 )
$("#cube").css("top", $("#cube").offset().top - 11);
break;
case 40: // Down
if( ( $( "#cube" ).offset( ).top - 7 ) < ( 400 - 50 ) )
$("#cube").css("top", $("#cube").offset().top - 7 );
break;
}
});
});
You'd make similar changes to the left and right arrows
$(document).ready(function () {
var $out = $('#outside'),
w = $out.width(),
$cube = $('#cube'),
cw = $cube.outerWidth();
$(document).up(function (e) {
switch (e.which) {
case 37:
$cube.css('left', function (_, left) {
left = parseInt(left, 10);
if (left !== 0) return left - cw;
});
break;
case 38:
$cube.css('top', function (_, top) {
top = parseInt(top, 10);
if (top !== -1) return top - cw;
});
break;
case 39:
$cube.css('left', function (_, left) {
left = parseInt(left, 10);
if (left + cw < w) return left + cw;
});
break;
case 40:
$cube.css('top', function (_, top) {
top = parseInt(top, 10);
if (top !== 349) return top + cw;
});
break;
}
});
});
http://jsfiddle.net/QmBNC/
How can i make a movement of a element while the user is "keydown" and then if he make "keyup" to stop the animation(movement), this is my code by now
$(document).ready(function(){
function checkKey(e){
switch (e.keyCode) {
case 40:
//alert('down');
$('#cube').animate({top: "+=20px"})
break;
case 38:
//alert('up');
$('#cube').animate({top: "-=20px"})
break;
case 37:
//alert('left');
$('#cube').animate({left: "-=20px"})
break;
case 39:
//alert('right');
$('#cube').animate({left: "+=20px"})
break;
default:
alert('???');
}
}
if ($.browser.mozilla) {
$(document).keydown (checkKey);
} else {
$(document).keydown (checkKey);
}
})
i want to move the cube while the user press the key (down, left, up, right), not with every press, is possible?
You need a simple 2D engine that will setup a game loop.
Simple demo: http://jsfiddle.net/kzXek/
Source: https://github.com/superrob/simple-2D-javascript-engine/blob/master/simple2d.html
Is that you are looking for?
$(document).on("keyup", function() {
$("#cube").stop(true);
});
DEMO: http://jsfiddle.net/LjGRe/
you can just change the checkKey function, and add this to it :
function checkKey(e){
$(document).keyup(return);
switch (e.keyCode) {
case 40:
//alert('down');
$('#cube').animate({top: "+=20px"})
break;
case 38:
//alert('up');
$('#cube').animate({top: "-=20px"})
break;
case 37:
//alert('left');
$('#cube').animate({left: "-=20px"})
break;
case 39:
//alert('right');
$('#cube').animate({left: "+=20px"})
break;
default:
alert('???');
}
}
I think using a timer to handle the animation is better.
You just start the timer when a key is pressed and stop it when the key is released ..
Here is a simple solution that handles multiple keypresses (can move diagonally)
var direction = {top:0,left:0},
animator = null,
cube = $("#cube");
function animate(){
cube.css({
top: '+=' + direction.top,
left: '+=' + direction.left
});
}
function setProperties(keyCode, unset){
switch (keyCode) {
case 40:
direction.top = (unset)?0:2;
break;
case 38:
direction.top = (unset)?0:-2;
break;
case 37:
direction.left = (unset)?0:-2;
break;
case 39:
direction.left = (unset)?0:2;
break;
}
}
function setKey(e) {
setProperties(e.keyCode);
if (animator === null){
animator = setInterval(animate, 10);
}
}
function unsetKey(e){
setProperties(e.keyCode, true);
if (direction.top === 0 && direction.left === 0){
clearTimeout(animator);
animator = null;
}
}
$(document)
.on("keyup", unsetKey)
.on('keydown', setKey);
Demo at http://jsfiddle.net/gaby/Cu6nW/