In my top-view game, I have an object that can walk in four basic directions and four additional directions, but only has four animations and a still animation.
Base = left, right, up, down
Extra = top left, top right, bottom left, bottom right
Buttons are the arrow keys on the keyboard.
If the object first walks up and (while up arrow is pressed) after this it wants to move a little to the right (right arrow) then it should look like this:
Input arrow-up-down
Move up + Up animation
Input arrow-right-down while arrow-up-down
Move UP + Move RIGHT + RIGHT animation
Input right-up-arrow
Move UP + Move UP animation
Release and END
Other way around!
Feed right arrow down
Move to the RIGHT + RIGHT animation
Input arrow-up-down while arrow-right-down
Move RIGHT + Up arrow + Up arrow animation
Input arrow-up-up
Move RIGHT + RIGHT animation
Release and END
But this is where I get stuck, I get either one or the other.
Who can help me?
So what I want is to check which button was pressed first to determine what can happen next.
My code:
update() {
speed = 100;
left = arrow.left.isDown;
right = arrow.right.isDown;
up = arrow.up.isDown;
down = arrow.down.isDown;
//left
if (left && !right && !up && !down) {
movementFunction(-speed, 0, 'leftA');
}
else if (left && !right && up && !down) {
movementFunction(-speed, -speed, 'upA');
}
else if (left && !right && !up && down) {
movementFunction(-speed, speed, 'downA');
}
//right
else if (!left && right && !up && !down) {
movementFunction(speed, 0, 'rightA');
}
else if (!left && right && up && !down) {
movementFunction(speed, -speed, 'upA');
}
else if (!left && right && !up && down) {
movementFunction(speed, speed, 'downA');
}
//up
else if (!left && !right && up && !down) {
movementFunction(0, -speed, 'upA');
}
else if (left && !right && up && !down) {
movementFunction(-speed, -speed, 'leftA');
}
else if (!left && right && up && !down) {
movementFunction(speed, -speed, 'rightA');
}
//down
else if (!left && !right && !up && down) {
movementFunction(0, speed, 'downA');
}
else if (left && !right && !up && down) {
movementFunction(-speed, speed, 'leftA');
}
else if (!left && right && !up && down) {
movementFunction(speed, speed, 'rightA');
}
if (!left && !right && !up && !down) {
movementFunction(0, 0, 'standby');
}
}
Format movementFunction(X-axle, Y-axle, 'animation name');
Four different if/else if created for each basic movement.
Example psuedo:
if (left)
move left
else if (left+up)
move up and left and animate up
else if (left+down)
move down and left and animate down
if (up)
move up
else if (up+left)
move up and left and animate left
else if (up+right)
move up and right and animate right
The moves belonging to a base move as an if/else nested within the if of the base move.
Example psuedo:
if (left)
move left
if (left+up)
move up and left and animate up
else if (left+down)
move down and left and animate down
Related
I am working on a multi-image slider (i.e. several images appear next to each other at the same time and move together) that can be moved with the mouse wheel. I detect the direction of the mouse wheel (up or down) and the slider moves to the left or the right accordingly. It works quite well, the only problem is that I can't get the last picture to stop at the edge of the slider, so it doesn't jump inside if you roll a bigger with the mouse wheel (same for the first picture if you scroll backwards). I would be really grateful for some assistance. Thank you in advance. This is my JS code:
// move slider on mouse wheel scrolling depending on mouse wheel direction
aboutSliders[i].addEventListener('wheel', () => {
// let slideWidth = firstImg.getBoundingClientRect().width;
// get the first slide's position from left side of screen
let sliderLeft = firstImg.getBoundingClientRect().left;
// get the slider wrapper's position from left side of screen
let sliderWrapperLeft = aboutSliders[i].getBoundingClientRect().left;
// get the last slide's position from left side of screen
let sliderRight = lastImg.getBoundingClientRect().right;
// get the slider wrapper's position from left side of screen
let sliderWrapperRight = aboutSliders[i].getBoundingClientRect().right;
// detect mouse wheel's direction (up or down)
function detectMouseWheelDirection(e) {
var delta = null,
direction = false;
if (!e) {
// if the event is not provided, we get it from the window object
e = window.event;
}
if (e.wheelDelta) {
// will work in most cases
delta = e.wheelDelta / 60;
} else if (e.detail) {
// fallback for Firefox
delta = -e.detail / 2;
}
if (delta !== null) {
direction = delta > 0 ? 'up' : 'down';
}
return direction;
}
function handleMouseWheelDirection(direction) {
// if mousewheel direction is 'down' and the slider wrapper's position is not further to the right than the last slide's, move the slider to the left
if (direction == 'down' && sliderRight >= sliderWrapperRight) {
innerSlider.style.marginLeft = --count * 5 + '%';
// if mousewheel direction is 'up', and the slider wrapper's position is not further to the left than the first slide's, move the slider to the right
} else if (direction == 'up' && sliderLeft <= sliderWrapperLeft) {
innerSlider.style.marginLeft = ++count * 5 + '%';
}
}
document.onmousewheel = function (e) {
handleMouseWheelDirection(detectMouseWheelDirection(e));
};
if (window.addEventListener) {
document.addEventListener('DOMMouseScroll', function (e) {
handleMouseWheelDirection(detectMouseWheelDirection(e));
});
}
});
I have an element I would like to show resize handles on. My current code:
const cursorMove = (e) => {
if (!curData.doAnimate) {
mouse.x = e.clientX;
mouse.y = e.clientY;
resize = {
top: mouse.y < curPos.y + settings.resizeMargin,
right: mouse.x > curPos.x + curPos.w - settings.resizeMargin,
bottom: mouse.y > curPos.y + curPos.h - settings.resizeMargin,
left: mouse.x < curPos.x + settings.resizeMargin,
};
const {top, right, bottom, left} = resize;
if (top || left || right || bottom) {
// mouse over border
if ((top && left) || (bottom && right)) {
wrap.style.cursor = 'nwse-resize';
} else if ((top && right) || (bottom && left)) {
wrap.style.cursor = 'nesw-resize';
} else if (top || bottom) {
wrap.style.cursor = 'ns-resize';
} else if (left || right) {
wrap.style.cursor = 'ew-resize';
}
} else {
wrap.style.cursor = 'default';
}
}
};
wrap.addEventListener('mousemove', cursorMove);
as you can see I use javascript to add an eventlistener for mouse movments, and every time the mouse moves I check weather it is on a border of the element. I can turn the eventlistener off if I do something with the node using curData.doAnimate. I could remove the eventlistener if I move out of the element, but I dont think this would improve the performence.
Ideal would be a solution using Css or a solution without an eventlistener permanently listening to move events.
Thank you in advance :)
Edit: I am only interested in the changed cursor - I already have a function to resize the node (unless you know a super slick way of doing so using some magic).
Luckily, CSS already has a property for handling this: resize
I have a webgame I made in pure javascript using processing.js
It works fine on desktop but I want it to work on mobile.
It's on this website: https://www.ricarddokifuri.tk/mlg/
I found a function to detect swipes
function swipedetect(el, callback){
var touchsurface = el,
swipedir,
startX,
startY,
distX,
distY,
threshold = 150, //required min distance traveled to be considered swipe
restraint = 100, // maximum distance allowed at the same time in perpendicular direction
allowedTime = 300, // maximum time allowed to travel that distance
elapsedTime,
startTime,
handleswipe = callback || function(swipedir){}
touchsurface.addEventListener('touchstart', function(e){
var touchobj = e.changedTouches[0]
swipedir = 'none'
dist = 0
startX = touchobj.pageX
startY = touchobj.pageY
startTime = new Date().getTime() // record time when finger first makes contact with surface
e.preventDefault()
}, false)
touchsurface.addEventListener('touchmove', function(e){
e.preventDefault() // prevent scrolling when inside DIV
}, false)
touchsurface.addEventListener('touchend', function(e){
var touchobj = e.changedTouches[0]
distX = touchobj.pageX - startX // get horizontal dist traveled by finger while in contact with surface
distY = touchobj.pageY - startY // get vertical dist traveled by finger while in contact with surface
elapsedTime = new Date().getTime() - startTime // get time elapsed
if (elapsedTime <= allowedTime){ // first condition for awipe met
if (Math.abs(distX) >= threshold && Math.abs(distY) <= restraint){ // 2nd condition for horizontal swipe met
swipedir = (distX < 0)? 'left' : 'right' // if dist traveled is negative, it indicates left swipe
}
else if (Math.abs(distY) >= threshold && Math.abs(distX) <= restraint){ // 2nd condition for vertical swipe met
swipedir = (distY < 0)? 'up' : 'down' // if dist traveled is negative, it indicates up swipe
}
}
handleswipe(swipedir)
e.preventDefault()
}, false)
}
I can activate and detect which direction was swiped like this
swipedetect(el, function(swipedir){
if (swipedir == 'left')
alert('You just swiped left!')
});
My function to move the player is like this
var movePlayer = function(){
if(keyCode === LEFT){
x -= 3.5*scaless;
}
if(keyCode === RIGHT){
x += 3.5*scaless;
}
if(keyCode === UP){
y -= 3.5*scaless;
}
if(keyCode === DOWN){
y += 3.5*scaless;
}
};
if(keyPressed){
movePlayer();
}
How could I make the function that detects a swipe, simulate a keypress?
If you want to reuse your movePlayer function both for the keyboard and for swipes, then I would probably make it accept an argument and then call it either from a keypress event handler with the event keycode either from the swipe handler with an appropriate argument.
So basically, according to this: https://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes
The keycodes for up,right,down,left are:
UP: 38
RIGHT: 39
DOWN: 40
LEFT: 37
so you could modify your move player like so:
var movePlayer = function(keyCode){
if(keyCode === LEFT){
x -= 3.5*scaless;
}
if(keyCode === RIGHT){
x += 3.5*scaless;
}
if(keyCode === UP){
y -= 3.5*scaless;
}
if(keyCode === DOWN){
y += 3.5*scaless;
}
};
From your code snippet, I am assuming that LEFT, RIGHT, UP and DOWN are constant values, somewhere else in your program, so then I would modify my swipe detect function like:
swipedetect(el, function(swipedir){
if (swipedir == 'left'){
movePlayer(LEFT);
}else if(swipedir == 'right'){
movePlayer(RIGHT);
}else if(swipedir == 'up'){
movePlayer(UP);
}else if(swipedir == 'down'){
movePlayer(DOWN);
}
//you can have the default case in an else here
});
Then, you would need to modify the keypress code that calls movePlayer when the user uses the keyboard to pass the code of the key that was pressed i.e. by doing movePlayer(event.keyCode) in your keypress event handler.
I am new to javascript games.
I have an idea of game, As an example if I am taking Solidsnake's character.
I want character view changes on pressing navigation keys.
If I press left key it should show left view, right key for right view and so on.
How do i get change in image on pressing keys , how can I do this in javascript?
Idea of game-
Code in brief-
var leftKey,upKey,rightKey,downKey;
var box = $("#plane"),
left = 37,
up = 38,
right = 39,
down = 40;
function key(e) {
console.log(e.keyCode);
var $key = e.keyCode;
$(document).keydown(function(e) {
if (e.keyCode == left)
leftKey = true;
if (e.keyCode == up)
upKey = true;
if (e.keyCode == right)
rightKey = true;
if (e.keyCode == down)
downKey = true;
}).keyup(function(e) {
if (e.keyCode == left)
leftKey = false;
if (e.keyCode == up)
upKey = false;
if (e.keyCode == right)
rightKey = false;
if (e.keyCode == down)
downKey = false;
});
}
$("body").keydown(function(){
key(event);
});
setInterval(function() {
if (upKey) {
box.css("top", "-=10");
}
if (rightKey) {
box.css("left", "+=10");
}
if (downKey) {
box.css("top", "+=10");
}
if (leftKey) {
box.css("left", "-=10");
}
},20);
Right now i have this code with simple navigation moves.
Js fiddle
You can do this with CSS to set it right and avoid multiple image requests. You need to have a sprite with all images of the character in a row and then mask with a div the area you need to show. Then with javascript you can change the position of the image either by using marginLeft or marginRight or left and right (you need to set position relative or absolute for left and right).
When you do e.keyCode == up and the like, you can change the image source then:
if (e.keyCode == up) {
upKey = true;
$("#plane").attr('src', 'up-img-src');
}
Either do this: http://jsfiddle.net/VMM5P/1/
Change the image src on keypress:
if (upKey) {
box.attr("src", "http://cdn3.iconfinder.com/data/icons/blackblue/128/iChat.png");
}
if (rightKey) {
box.attr("src", "http://cdn2.iconfinder.com/data/icons/blackblue/128/guitar.png");
}
if (downKey) {
box.attr("src", "http://cdn3.iconfinder.com/data/icons/blackblue/128/TextEdit.png");
}
if (leftKey) {
box.attr("src", "http://cdn2.iconfinder.com/data/icons/blackblue/128/preview.png");
}
or you can make a sprite and position them accordingly:
Suppose box is the div which has a background sprite image
if (upKey) {
box.css("background-position", "0px 0px"); // pos 1
}
if (rightKey) {
box.css("background-position", "120px 0px"); // pos 2
}
if (downKey) {
box.css("background-position", "240px 0px"); // pos 3
}
if (leftKey) {
box.css("background-position", "360px 0px"); // pos 4
}
You would want to change the attr source for the image.
if (leftKey) {
box.find('img').attr('src', 'ENTER NEW IMAGE URL HERE');
}
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