player movement diagonally - too fast || NodeJS - javascript

If I move the player right, left, up or down I move 5px in that direction.
But if I press down and right for example player is moving 5px right and 5px down which is around 7 pixels from the previous position instead 5px.
I can add next IF statement: if (up and down) then spdX and spdY = (maxSpd - maxSpd√2) / or simple -25% ?.
But I think already my code is bit messy...
Any nice solutions which are fast and looks simple? :)
That is my code:
self.updateSpd = function(){
if(self.pressingRight){
self.spdX = self.maxSpd;
if(self.pressingShift && self.stamina > 0){
self.spdX += self.maxRun;
self.stamina --;
}
}
else if(self.pressingLeft){
self.spdX = -self.maxSpd;
if(self.pressingShift && self.stamina > 0){
self.spdX -= self.maxRun;
self.stamina --;
}
}
else{
self.spdX = 0;
}
if(self.pressingUp){
self.spdY = -self.maxSpd;
if(self.pressingShift && self.stamina > 0){
self.spdY -= self.maxRun;
self.stamina --;
}
}
else if(self.pressingDown){
self.spdY = self.maxSpd;
if(self.pressingShift && self.stamina > 0){
self.spdY += self.maxRun;
self.stamina --;
}
}
else{
self.spdY = 0;
}
}

You could make variables for X and Y direction with values -1, 0, 1:
var dirX = -self.pressingLeft + self.pressingRight;
var dirY = -self.pressingUp + self.pressingDown;
Then adjust when moving diagonally:
if (dirX !== 0 && dirY !== 0) {
dirX *= Math.SQRT1_2;
dirY *= Math.SQRT1_2;
}
Then apply the rest:
var speed = self.maxSpd;
if (self.pressingShift && self.stamina > 0 && (dirX !== 0 || dirY !== 0)) {
speed += self.maxRun;
self.stamina--;
}
self.spdX = speed * dirX;
self.spdY = speed * dirY;
All told:
self.updateSpd = function () {
var dirX = -self.pressingLeft + self.pressingRight;
var dirY = -self.pressingUp + self.pressingDown;
if (dirX !== 0 && dirY !== 0) {
dirX *= Math.SQRT1_2;
dirY *= Math.SQRT1_2;
}
var speed = self.maxSpd;
if (self.pressingShift && self.stamina > 0 && (dirX !== 0 || dirY !== 0)) {
speed += self.maxRun;
self.stamina--;
}
self.spdX = speed * dirX;
self.spdY = speed * dirY;
};
Or maybe:
self.updateSpd = function () {
var dirX = -self.pressingLeft + self.pressingRight;
var dirY = -self.pressingUp + self.pressingDown;
var speed = self.maxSpd;
if (self.pressingShift && self.stamina > 0 && (dirX !== 0 || dirY !== 0)) {
speed += self.maxRun;
self.stamina--;
}
if (dirX !== 0 && dirY !== 0) {
speed *= Math.SQRT1_2;
}
self.spdX = speed * dirX;
self.spdY = speed * dirY;
};
Note that this does behave differently from your original when both left and right are pressed (no movement, rather than moving right) or when both up and down are pressed (no movement, rather than moving up).

Related

I am sticking to the walls but only on the right

I am currently debugging a game im making in p5.js and have found that i stick to walls that are on the right of my player but not on my left. i have tried turning up the number of pixels away it checks but it doesn't look good and only will work with 5. here is the code:
move(){
let wallcheckL = get(this.x - 1, this.y);
let wallcheckR = get(this.x + (this.scale + 1), this.y);
let wallcheckLB = get(this.x - 1, this.y + this.scale - 5);
let wallcheckRB = get(this.x + (this.scale + 1), this.y + this.scale - 5);
if(wallcheckL[0] == 0 && wallcheckL[1] == 0 && wallcheckL[2] == 255 ||
this.x == 0 ||
wallcheckLB[0] == 0 && wallcheckLB[1] == 0 && wallcheckLB[2] == 255 ||
wallcheckL[0] == 0 && wallcheckL[1] == 128 && wallcheckL[2] == 0) {
this.wallL = true;
}
else{
this.wallL = false;
}
if(wallcheckR[0] == 0 && wallcheckR[1] == 0 && wallcheckR[2] == 255 ||
this.x == 400 - this.scale ||
wallcheckRB[0] == 0 && wallcheckRB[1] == 0 && wallcheckRB[2] == 255 ||
wallcheckR[0] == 0 && wallcheckR[1] == 128 && wallcheckR[2] == 0) {
this.wallR = true;
}
else{
this.wallR = false;
}
if(this.moveR == true && this.wallR == false){
this.x += this.speed;
}
else if(this.moveL == true && this.wallL == false){
this.x -= this.speed;
}
}
also here is the gravity:
gravity(){
let gc = get(this.x, this.y + 21);
let gc2 = get(this.x + this.scale, this.y + 21);
if(gc[0] == 0 && gc[1] == 0 && gc[2] == 255 && gc[3] == 255 ||
this.y >= 400 - this.scale ||
gc2[0] == 0 && gc2[1] == 0 && gc2[2] == 255 && gc2[3] == 255 ||
gc[0] == 255 && gc[1] == 255 && gc[2] == 0 && gc[3] == 255 ||
gc2[0] == 255 && gc2[1] == 255 && gc2[2] == 0 && gc2[3] == 255){
this.gravSpeed = this.dgrav;
this.isOnGround = true;
return;
}
else{
this.y += this.gravSpeed;
if(this.gravSpeed < this.tv){
this.gravSpeed += this.ac;
}
else{
this.gravSpeed = this.tv;
}
this.isOnGround = false;
}
}
Your main problem is in your gravity method, particularly this block of code:
if(gc[0] == 0 && gc[1] == 0 && gc[2] == 255 && gc[3] == 255 ||
this.y >= 400 - this.scale ||
gc2[0] == 0 && gc2[1] == 0 && gc2[2] == 255 && gc2[3] == 255 ||
gc[0] == 255 && gc[1] == 255 && gc[2] == 0 && gc[3] == 255 ||
gc2[0] == 255 && gc2[1] == 255 && gc2[2] == 0 && gc2[3] == 255){
this.gravSpeed = this.dgrav;
this.isOnGround = true;
return;
}
This evaluates irrespective of whether the player is actually on the ground, which results in the issue where the player is getting stuck on the right-hand block.
A potential way to solve it is with actually using code you already have tucked within that condition:
if (this.y >= height - this.scale) {
this.y = height - this.scale; // ensure the player's height is properly constrained
this.gravSpeed = this.dgrav;
this.isOnGround = true;
}
This prevents the sticking as it doesn't set the player variable isOnGround = true when it's not.
Here's a working example:
class player {
constructor(x, y, scale, grav, ac, speed) {
this.x = x;
this.y = y;
this.dtime = 20;
this.jumpTimer = 20;
this.jumpLimit = 12;
this.jumpedHeight = 0;
this.jumping = false;
this.wallR = false;
this.wallL = false;
this.moveR = false;
this.moveL = false;
this.tv = 10;
this.dgrav = grav;
this.ac = ac;
this.speed = speed;
this.gravSpeed = grav;
this.canGravity = true;
this.isOnGround = false;
this.scale = scale;
}
draw() {
fill("red");
rect(this.x, this.y, this.scale, this.scale);
}
gravity() {
let gc = get(this.x, this.y + 21);
let gc2 = get(this.x + this.scale, this.y + 21);
if (this.y >= height - this.scale) {
this.y = height - this.scale;
this.gravSpeed = this.dgrav;
this.isOnGround = true;
} else {
this.y += this.gravSpeed;
if (this.gravSpeed < this.tv) {
this.gravSpeed += this.ac;
} else {
this.gravSpeed = this.tv;
}
this.isOnGround = false;
}
}
move() {
let wallcheckL = get(this.x - 1, this.y);
let wallcheckR = get(this.x + this.scale + 2, this.y);
let wallcheckLB = get(this.x - 1, this.y + this.scale - 5);
let wallcheckRB = get(this.x + this.scale + 2, this.y + this.scale - 5);
if (
(wallcheckL[0] == 0 && wallcheckL[1] == 0 && wallcheckL[2] == 255) ||
this.x == 0 ||
(wallcheckLB[0] == 0 && wallcheckLB[1] == 0 && wallcheckLB[2] == 255) ||
(wallcheckL[0] == 0 && wallcheckL[1] == 128 && wallcheckL[2] == 0)
) {
this.wallL = true;
} else {
this.wallL = false;
}
if (
(wallcheckR[0] == 0 && wallcheckR[1] == 0 && wallcheckR[2] == 255) ||
this.x >= 400 - this.scale ||
(wallcheckRB[0] == 0 && wallcheckRB[1] == 0 && wallcheckRB[2] == 255) ||
(wallcheckR[0] == 0 && wallcheckR[1] == 128 && wallcheckR[2] == 0)
) {
this.wallR = true;
} else {
this.wallR = false;
}
if (this.moveR == true && this.wallR == false) {
this.x += this.speed;
} else if (this.moveL == true && this.wallL == false) {
this.x -= this.speed;
}
}
jump() {
let uc = get(this.x, this.y - 2);
let ucr = get(this.x + this.scale, this.y - 2);
if (
uc[0] == 255 &&
uc[1] == 255 &&
uc[2] == 0 &&
ucr[0] == 255 &&
ucr[1] == 255 &&
ucr[2] == 0
) {
this.y -= 5;
this.jumpedHeight += 1;
} else {
if (
(this.jumpedHeight < this.jumpLimit &&
this.isOnGround == true &&
uc[0] == 255 &&
uc[1] == 255 &&
uc[2] == 255 &&
ucr[0] == 255 &&
ucr[1] == 255 &&
ucr[2] == 255) ||
(this.jumpedHeight < this.jumpLimit &&
this.isOnGround == true &&
uc[0] == 255 &&
uc[1] == 255 &&
uc[2] == 0 &&
ucr[0] == 255 &&
ucr[1] == 255 &&
ucr[2] == 0) ||
(this.jumpedHeight < this.jumpLimit &&
this.isOnGround == true &&
uc[0] == 255 &&
uc[1] == 255 &&
uc[2] == 0 &&
ucr[0] == 255 &&
ucr[1] == 255 &&
ucr[2] == 255)
) {
this.y -= 5;
this.jumpedHeight += 1;
} else {
this.gravSpeed = this.dgrav;
this.jumping = false;
}
}
}
}
class ground{
constructor(x, y, color){
this.x = x;
this.color = color;
this.y = y;
}
draw(){
fill(this.color);
rect(this.x, this.y, 40, 40);
}
}
var groundArray = [];
groundArray[0] = [0];
groundArray[1] = [0];
groundArray[2] = [0];
groundArray[3] = [0];
groundArray[4] = [0];
groundArray[5] = [0];
groundArray[6] = [1,0,0,0,0,0,0,1];
groundArray[7] = [1,0,0,0,0,0,0,1];
groundArray[8] = [1,0,0,0,0,0,0,1];
groundArray[9] = [1,0,0,0,0,0,0,1];
function setup() {
noStroke();
createCanvas(400, 400);
for(let y = 0; y < groundArray.length; y++){
for(let x = 0; x < groundArray[y].length; x++){
if(groundArray[y][x] == 1){
groundArray[y][x] = new ground(x * 40, y * 40, "blue");
}
else if(groundArray[y][x] == 2){
groundArray[y][x] = new ground(x * 40, y * 40, "yellow");
}
else if(groundArray[y][x] == 3){
groundArray[y][x] = new ground(x * 40, y * 40, "green");
}
}
}
}
var play = new player(200, 0, 20, 3, 0.06, 4);
function draw() {
background(255);
for(let y = 0; y < groundArray.length; y++){
for(let x = 0; x < groundArray[y].length; x++){
if(groundArray[y][x] != 0){
groundArray[y][x].draw();
}
}
}
play.move();
if(play.jumping == true){
play.jump();
}
else{
play.gravity();
}
play.draw();
}
function keyPressed(){
if(keyCode == RIGHT_ARROW){
play.moveL = false;
play.moveR = true;
}
else if(keyCode == LEFT_ARROW){
play.moveR = false;
play.moveL = true;
}
if(keyCode == UP_ARROW){
play.jumping = true;
}
}
function keyReleased(){
if(keyCode == RIGHT_ARROW){
play.moveR = false;
}
if(keyCode == LEFT_ARROW){
play.moveL = false;
}
if(keyCode == UP_ARROW){
play.jumping = false;
play.gravSpeed = play.dgrav;
play.jumpedHeight = 0;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
I have fixed my problem. i found that in my gravity script it was checking too far to the right where it would collide with the wall so i changed it to this and it now works
gravity(){
let gc = get(this.x, this.y + 21);
let gc2 = get(this.x + this.scale - 2, this.y + 21);
if(gc[0] == 0 && gc[1] == 0 && gc[2] == 255 && gc[3] == 255 ||
this.y >= 400 - this.scale ||
gc2[0] == 0 && gc2[1] == 0 && gc2[2] == 255 && gc2[3] == 255 ||
gc[0] == 255 && gc[1] == 255 && gc[2] == 0 && gc[3] == 255 ||
gc2[0] == 255 && gc2[1] == 255 && gc2[2] == 0 && gc2[3] == 255){
this.gravSpeed = this.dgrav;
this.isOnGround = true;
return;
}
else{
this.y += this.gravSpeed;
if(this.gravSpeed < this.tv){
this.gravSpeed += this.ac;
}
else{
this.gravSpeed = this.tv;
}
this.isOnGround = false;
}
}

How can I check if the current location is outside of a set radius?

I'm currently working on an app that triggers a notification when someone is within a square. The following defines the square:
var zonebounds = [[30,35], [40,45]];
var zone = L.rectangle(zonebounds, {color: "#ff7800", weight: 1, oppacity: .5});
I've made the following statement to check if someone is within the square.
if (posY > zonebounds[0][0] && posY < zonebounds[1][0] && posX > zonebounds[0][1] && posX < zonebounds[1][1] && zoneTimer == 0) {
ons.notification.toast('Test', { timeout: 5000 });
zoneTimer = 1;
} else if (posY >! zonebounds[0][0] && posY <! zonebounds[1][0] && posX >! zonebounds[0][1] && posX <! zonebounds[1][1] && zoneTimer == 1) {
zoneTimer = 0;
}
I think >! sadly doesn't behave as I would like it to.
I've made the zoneTimer variable so that the notification doesn't repeat itself. Maybe there is an even better way to do this.
Update
I fixed it by using a combination of the two answers I got, here is the final result:
if(zoneBoundslatLng.contains(latLng)){
if (inZone == 0) {
inZone = 1;
ons.notification.toast('Zone 1, klik voor informatie.', { timeout: 5000 });
}
} else {
inZone = 0;
}
You could take the reverse of >, <= for checking.
For the second check, you need an OR condition.
if (
posY > zonebounds[0][0] && posY < zonebounds[1][0] &&
posX > zonebounds[0][1] && posX < zonebounds[1][1] &&
zoneTimer === 0
) {
ons.notification.toast('Test', { timeout: 5000 });
zoneTimer = 1;
} else if (
(posY <= zonebounds[0][0] || posY >= zonebounds[1][0] ||
posX <= zonebounds[0][1] || posX >= zonebounds[1][1]) &&
zoneTimer === 1
) {
zoneTimer = 0;
}
A shorter check.
if (posY > zonebounds[0][0] && posY < zonebounds[1][0] && posX > zonebounds[0][1] && posX < zonebounds[1][1]) {
if (zoneTimer === 0) {
ons.notification.toast('Test', { timeout: 5000 });
zoneTimer = 1;
}
} else {
if (zoneTimer === 1) {
zoneTimer = 0;
}
}
You can check with leaflet if point is in the rectangle.
var bounds = L.latLngBounds(zonebounds);
if(bounds.contains(latlng) ){
console.log("notify");
}else{
console.log("nothing");
}
If your point (posX and posY) are pixels you can use this to convert:
var point = L.point(posX ,posY); // x=0,y=0
var latlng = map.layerPointToLatLng(point);
Update ...
var bounds = L.latLngBounds(zonebounds);
if(bounds.contains(latlng) && zoneTimer == 0){
zoneTimer = 1;
ons.notification.toast('Test', { timeout: 5000 });
console.log("notify");
}else{
zoneTimer = 0;
console.log("nothing");
}

Character will not jump after touching in JS

I am programming collision detection in JS for a platformer. For some reason, when my character touches the ground on the top, it won't jump again. Here's my code:
if (isCollideY(platforms[i].getBoundingClientRect(), document.getElementById('spriteNotReal').getBoundingClientRect()) == true) {
if (falling == true && (jumping == false)) {
moveY = platforms[i].getBoundingClientRect().y + 3;
momentumY = 0;
onSolidGround = true;
}
}
if (event.code == 'KeyW' && (moveY <= 300)) {
moveY += 1;
move (moveX, moveY);
momentumY = momentumY + 20;
onSolidGround = false;
falling = false;
jumping = true;
}
else if (onSolidGround == false) {
if (momentumY < 0) {
falling = true;
}
else if (momentumY > 0) {
jumping = true;
}
else {
jumping = false;
}
moveX += momentumX / 3 + 1;
document.getElementById("spriteNotReal").src = "jumpmain.gif";
}
My problem was somewhat stupid. After checking the input code, I realized that the jump wasn't happening because it would only jump while on the "platform" I set up to test, not while it was actually on a platform. Here's the improved code:
if (event.code == 'KeyW' && (onSolidGround == true)) {
moveY += 1;
move (moveX, moveY);
momentumY = momentumY + 20;
onSolidGround = false;
falling = false;
jumping = true;
}

Why isn't my condition working?

In javascript, I'm making an HTML canvas game, and in that game I have an object type/constructor called gamePiece. gamePiece has a function called checkCollision:
this.checkCollision = function(piece){
var collisionX = piece.x >= this.x && piece.x <= (this.x + this.width);
var collisionY = piece.y <= this.y && piece.y <= (this.y - this.height);
if(collisionX || collisionY){
return true;
} else {
return false;
}
}
which is called by update()
function update(){
context.clearRect(0, 0, game.width, game.height);
for(var i = 0; i < gamePieces.length; i++){
gamePieces[i].update();
for(var mi = 0; mi < gamePieces.length; mi++){
gamePieces[i].checkCollision(gamePieces[mi]);
if(gamePieces[i].checkCollision(gamePieces[mi]) == true){
gamePieces[i].collisionFunction();
}
}
}
}
setInterval(function(){update();}, 1);
I have another object that is supposed to give a speed boost upon colliding with another game piece, and it logs every time it gives a speed boost.
var speedBooster = new gamePiece(25,25,"red",300,300,0);
speedBooster.collisionFunction = function(){
for(var whichpiece = 0; whichpiece < gamePieces.length; whichpiece++){
if(speedBooster.checkCollision(gamePieces[whichpiece]) == true && gamePieces[whichpiece] != this){
gamePieces[whichpiece].speed += 10;
console.log("gamePieces[" + whichpiece + "] has been given a speed boost.");
}
}
}
But it gives a speed boost whenever a piece is behind it, and I put the "piece.x >= this.x &&" there for a reason. Why is JavaScript ignoring the condition I gave it?
Try
var collisionX = piece.x >= this.x && piece.x <= (this.x + this.width);
var collisionY = piece.y >= this.y && piece.y <= (this.y + this.height);
if(collisionX && collisionY){
return true;
} else {
return false;
}
To test if two objects overlap. Where the object has x,y as the top left and w,h as width and height
//Returns true if any part of box1 touches box2
function areaTouching(box1,box2){
return ! (box1.x > box2.x + box2.w ||
box1.x + box1.w < box2.x ||
box1.y > box2.y + box2.h ||
box1.y + box1.h < box2.y)
}

Wall collision detection, clitches though walls

I'm doing an app in React/html5/canvas. In the canvas, you as the user can move around in different rooms with mouseclicks. That works, and I have made the collision detection for all the walls for the rooms (the view is 2d like a RTS game).
Now to the problem: When I hit a wall I set user.collision = true; And the next mouseclick will set user.collision = false;and this will make my character move again. Problem is that I now can clip through walls if I click some more times (it clitches through).
Have thought about the logical around this and I can't figure it out, and my research did not help me.
Here is my collision detection function: (All the walls are in the this.props.data)
collision: function(){
for (var i = 0; i < this.props.data.length; i++){
if (user.posX > this.props.data[i].x2 && user.posX < this.props.data[i].x1 &&
user.posY < this.props.data[i].y2 && user.posY > this.props.data[i].y1){
user.collision = true;
}
}
},
Here is my handleMouseClick function:
handleMouseClick: function(event){
var rect = game.getBoundingClientRect();
mouseClick.y = event.nativeEvent.clientY - rect.top;
mouseClick.x = event.nativeEvent.clientX - rect.left;
distance = Math.sqrt(Math.pow(mouseClick.x - user.posX, 2) + Math.pow(mouseClick.y - user.posY,2));
user.directionX = (mouseClick.x - user.posX) / distance;
user.directionY = (mouseClick.y - user.posY) / distance;
if (user.collision = true){
user.collision = false;
}
},
Here is my update function:
update: function(){
context.canvas.height);
if (!user.collision){
if(user.moving === true){
user.posX += user.directionX * user.speed * elapsed;
user.posY += user.directionY * user.speed * elapsed;
this.collision();
if(user.posX >= mouseClick.x -5 && user.posX <= mouseClick.x + 5 && user.posY >= mouseClick.y -5 && user.posY <= mouseClick.y + 5){
user.moving = false;
}
}
}
this.drawUser();
this.drawWalls();
},
How about just reverting to the previous pos if the collision test fails ?
update: function(){
context.canvas.height);
var prevPosX = user.posX;
var prevPosY = user.posY;
if (!user.collision){
if(user.moving === true){
user.posX += user.directionX * user.speed * elapsed;
user.posY += user.directionY * user.speed * elapsed;
this.collision();
if( user.collision ) { // ooops !
user.posX = prevPosX;
user.posY = prevPosY;
}
if(user.posX >= mouseClick.x -5 && user.posX <= mouseClick.x + 5 && user.posY >= mouseClick.y -5 && user.posY <= mouseClick.y + 5){
user.moving = false;
}
}
}
this.drawUser();
this.drawWalls();
},
NB: typo here
if (user.collision = true){

Categories

Resources