I am using the Zdog library to create 3d objects in javascript. In the function that controls my animations I am trying to have a particle move around randomly and then after an interval return back to its original point. Here is my code:
if (radioOn == true){
radio.zoom = size;
path = [Math.floor((Math.random() * 3 - 1)),Math.floor((Math.random() * 2)),Math.floor((Math.random() * 2 - 1))];
origin[0] += path[0];
origin[1] += path[1];
origin[2] += path[2];
lightning.translate.x += path[0];
lightning.translate.y -= path[1];
lightning.translate.z += path[2];
timer++;
}
if (timer == 20){
timer = 0;
lightning.translate.x -= origin[0];
lightning.translate.y += origin[1];
lightning.translate.z -= origin[2];
origin = [0,0,0];
}
I have put alerts in the second if statement and timer is getting reset but origin is not. Also the particle initially does what I need but after it gets reset it will no longer move.
Related
Im creating an object that randomly moves in a natural way using noise like this (works as intended):
The objects encounter a collision and their trajectory is manipulated, the movement path now changes to straight line (words as intended)
thisRabbit.x = _world.width * (noise(thisRabbit.t));
thisRabbit.y = _world.height * (noise(thisRabbit.t+5));
thisRabbit.t += 0.001;
The problem is after this movement , i want the object to start moving in a random direction again as it was initially. If i use the same function, the object jumps to the last location before the trajectory was modified.
let vx = this.acquiredFood[0] - this.x;
let vy = this.acquiredFood[1] - this.y;
let f = (this.genes.speed + 10) / Math.sqrt(vx*vx+vy*vy);
vx = vx * f;
vy = vy * f;
let newX = this.x + vx;
let newY = this.y + vy;
So how do i get the object to move as before, given a starting position
edit: snippet here: https://editor.p5js.org/vince.chinner/sketches/HPFKR8eIw
Your problem is that you used a factor from 0 to 1 generated with noise and an incremented seed to generate the position by multiplying directly the world dimentions. When reaching food, you cannot increment the seed as to be in the exact position where the movement to get your food led you (I found no inverse function for noise to get the seed from the return value).
What you need to do instead is use the noise to increment or decrement the coordinates, so that no matter where the seed is, you don't loose your current position.
Here are the different corrections I applied to the code, as there were also syntax errors, I can't really paste the whole stuff here for copyright reasons (you didn't share the whole code here and the sketch belongs to you)
MAIN CORRECTION:
used a var found because returning from the forEach callback doesn't make you leave the findFood function, but the callback one. And the forEach loop doesn't stop. Using this var prevents the further forEach tests to be made and allows you to return from findFood so that no further move is made after seeing food.
noise is now applied to a value of 4 and I subtract 2, so that x and y now change with a range of -2 to 2 each. Of course, with this method, you need to check against world dimentions or else the rabbit could leave the world. The seed increment has been changed too or else it would vary too slowly (adapt values as you wish)
findFood(){
var thisRabbit = this, found = false;
_world.food.forEach(f => {
if(!found){
let d = int(dist(f[0], f[1], thisRabbit.x, thisRabbit.y));
if(d < (thisRabbit.genes.vision / 2)+3){
thisRabbit.state = "foundFood";
this.acquiredFood = f;
found = true;
}
}
});
if(found){ return; }
thisRabbit.x += (noise(thisRabbit.t) * 4) - 2;
if(thisRabbit.x < 0){ thisRabbit.x = 0; }
if(thisRabbit.x > _world.width){ thisRabbit.x = _world.width; }
thisRabbit.y += (noise(thisRabbit.t + 5) * 4) - 2;
if(thisRabbit.y < 0){ thisRabbit.y = 0; }
if(thisRabbit.y > _world.height){ thisRabbit.y = _world.height; }
thisRabbit.t += 0.01;
}
SYNTAX ERRORS:
lines 23 / 24: assignment should be with a value (null or false)
this.genes = null;
this.acquiredFood = null;
lines 129 to 133: end you instructions with a ; instead of a ,
this.width = w;
this.height = h;
this.foodDensity = foodDensity;
this.food = [];
this.rabits = [];
line 156 to 160: there should be no space between rabbit and .t. Additionnally, because the coordinates are not directly linked to t, I would prefer to use random for starting position:
let x = this.width * random();
let y = this.height * random();
let _rabbit = new rabbit(x, y);
_rabbit.genes = genes;
_rabbit.t = t;
I am working on a multiplayer game at the moment. I am experiencing an issue with my client side prediction. After moving around for a while, the server position and client position are offset. Here is the game currently. The server position is shown in orange. Your local position is shown in white. What I am doing, is simply simulating the players movement locally and on the server. Here is the movement code:
var xMov = 0;
var yMov = 0;
if (player.keys.up) {
yMov -= 1;
}
if (player.keys.down) {
yMov += 1;
}
if (player.keys.right) {
xMov += 1;
}
if (player.keys.left) {
xMov -= 1;
}
xMov /= REFRESH_INTERVAL;
yMov /= REFRESH_INTERVAL;
var length = Math.sqrt(xMov * xMov + yMov * yMov);
if (length != 0) {
playerMoved = true;
xMov /= length;
yMov /= length;
xMov *= player.speed;
yMov *= player.speed;
player.deltaX += xMov;
player.deltaY += yMov;
} else {
playerMoved = false;
}
var oldX = player.x;
var oldY = player.y;
player.deltaX *= c.speedDecel * delta;
if (player.deltaX <= 0.1 && player.deltaX >= -0.1)
player.deltaX = 0;
player.deltaY *= c.speedDecel * delta;
if (player.deltaY <= 0.1 && player.deltaY >= -0.1)
player.deltaY = 0;
player.x += player.deltaX * delta;
player.y += player.deltaY * delta;
player.x = Math.round(player.x);
player.y = Math.round(player.y);
The code on the client and server side is identical. When a user presses a key, the key information is sent to the server:
sendDataArray[0] = key;
sendDataArray[1] = val;
socket.emit('3', sendDataArray);
Then on the server, the key value is set. The problem I think I am having is a timing issue on the client and server side. The movement method shown above is called from a setInterval on both the client and server side:
setInterval(move, 31);
So when I press the key, on the client side, it could be 5ms until the next move() is called. Whereas on the server, when he receives the key info, it may be another 30ms. This might be causing an inconsistency.
How could this be resolved?
Using error correction info
From the client you should also be sending the position,and TIME with every call. That way the server can decide if X time has passed since last message and that time seems correct, then look at the position, if the position relative to the last known position and known time seem acceptable then adjust the server position to match.
This is my JSFiddle: http://jsfiddle.net/Au6br/13/
The problem is when I keep pressing keydown.up the player jump multiple times. What I want is to define a variable called JumpCount so when the player jump if the jump variable is greater than this value the jumping stop.
Character.prototype.Jump = function () { // Jumping
character.MaxJump += gravity;
character.y += character.MaxJump;
if (keydown.up) {
if (!character.jumping) {
character.jumping = true;
character.Pos = 4;
character.Row = 2;
character.h = 23;
character.MaxJump = -character.sp * 2.5;
}
}
if (character.y >= ch - character.h) { // if the character is under the bottom
character.y = ch - character.h;
character.jumping = false;
}
};
The first problem is that you can jump when you're not on the ground. It's because of the Onground function.
Replace this :
return this.y <= ch - this.h;
With this :
return this.y >= ch - this.h;
You should also use this function in Jump to avoid duplicate code :
if (character.Onground()) { // if the character is under the bottom
character.y = ch - character.h;
character.jumping = false;
}
Counting the jumps (I assume you want to make double jumps) can't work as long as you test if(keydown.up). When you press the UP key, this value will be true for more than one frame (depending on the duration the player presses it), so you'll never be able to correctly count the number of jumps. You must bind the jump on the onkeydown event, which is called once. After that, it will be simple to replace character.jumping with an integer.
I'd do it like this:
Character.prototype.Jump = function () {
character.MaxJump += gravity;
character.y += character.MaxJump;
if (keydown.up) {
if (character.CurrentJumps < character.JumpCount) {
character.CurrentJumps++
character.Pos = 4;
character.Row = 2;
character.h = 23;
character.MaxJump = -character.sp * 2.5;
}
}
if (character.y >= ch - character.h) {
character.y = ch - character.h;
character.CurrentJumps = 0
}
};
Were JumpCount is the max jumps, and CurrentJumps is the currently done jumps
And an example to set to double jump:
character.JumpCount = 2 // 2 Jumps
How about you add a variable called jumpCount or something that you increase every time the character jumps. Only allow the character to jump if jumpCount is smaller or equal to the number of jumps you like the character to be able to do. Then just set jumpCount to zero when the player touches the floor. This also gets rid of your jumping variable since this would mean the same thing as jumpCount === 0.
I have a problem with a script of mine. What I have is a tiled map made using a 2 dimensional array that specifies different tile types with different numbers and is drawn in a container div element. I also have a character div element that is movable. My problem is I can't figure out how to detect tiles and utilize the result of said detection in order to determine whether a character can move into nearby tiles or not.
The associated site that I have this hosted on is as follows;
http://brandynssite.webs.com/map_tile.html
As you can see with that example there is a container that draws the tiled map, a character element that starts at 0,0, and there are two buttons that check for character position and tile type. What I want to have happen is for the code to detect the tile the character is traveling to after a keypress event has happened and move their if possible. What functions would I need for this and is their a specific set of algorithms I would need for something as simple as what I have on that site?
I have provided one of the functions that allows the character to move as it seems to be the most related function in regards to possible collision detection that I can think of.
function anim(e) {
if(e.keyCode==39){
character_left += 10;
x += 1;
playerPos=mapArray[y][x];
character.style.left = character_left + "px";
if(character_left >= 190){
character_left -= 10;
x -= 1;
playerPos=mapArray[y][x];
}
}
if(e.keyCode==37){
character_left -= 10;
x -= 1;
playerPos=mapArray[y][x];
character.style.left = character_left + "px";
if(character_left <= 0){
character_left += 10;
x += 1;
playerPos=mapArray[y][x];
}
}
if(e.keyCode==40){
character_top += 10;
y += 1;
playerPos=mapArray[y][x];
character.style.top = character_top + "px";
if(character_top >= 190){
character_top -= 10;
y -= 1;
playerPos=mapArray[y][x];
}
}
if(e.keyCode==38){
character_top -= 10;
y -= 1;
playerPos=mapArray[y][x];
character.style.top = character_top + "px";
if(character_top <= 0){
character_top += 10;
y += 1;
playerPos=mapArray[y][x];
}
}
}
You need to create array where you specify on which tiles player can move. So:
var iCanMoveOn = [0, 2, 5];
And than you need to check if tile that is next to you is the one you can move on.
if(iCanMoveOn.indexOf(mapArray[y][x+1]) > -1){
//move player
}
x and y are coordinates where in array is a tile you are stading on. To check if you can step into the tile, you need to add or suntract "1" from one of coordinates. So:
[x+1] is tile on the right. Similarly: tile on the left is [x-1], tile on top: [y-1], bottom tile: [y+1]
To check if number is in array I used this
I'm making a game where you control your character with the arrow keys and attack with 'A'. My problem is that the attack has no delay so when I hold 'A' the enemy's hp depletes rapidly. How do I add delay? I tried adding delay, here is my code:
var DELAY = 2;
var cooldown = 0;
function update(time) {
// UP
if (38 in keysDown) {
player.y -= player.speed * time;
}
// DOWN
if (40 in keysDown) {
player.y += player.speed * time;
}
// LEFT
if (37 in keysDown) {
player.x -= player.speed * time;
}
// RIGHT
if (39 in keysDown) {
player.x += player.speed * time;
}
// 'A'
if(65 in keysDown) {
player.attacking = true;
cooldown -= time;
}
else
player.attacking = false;
// Collision
if( (player.x + pImage.width-5) >= monster.x &&
(player.x + pImage.width-5) < monster.x + enImage.width &&
player.y >= monster.y && player.y < (monster.y + enImage.height) &&
player.attacking)
{
if(cooldown <= 0) {
monster.hp -= player.dmg;
cooldown = DELAY;
}
if(monster.hp <= 0) {
relocEn();
}
}
}
The problem is that the cooldown counts only when I'm holding 'A' and resets only when the player is touching the monster. I want something like when I press 'A' the cooldown timer sets off. Also, I want the sprite(in attacking state) to go along with the delay and goes back to "standing" state. Thanks in advance
Here's what I would do:
I would create a variable for the time of the last attack and move all your code relevant to attacking to another function. I'm assuming time is measured in milliseconds so you're probably going to want your delay to be in the hundreds.
var DELAY = 400; //Change this to a higher value if it's not long enough.
var timeSinceLastAttack = -400; // The opposite of the DELAY if you want to attack at the start.
function update(time) {
...
// 'A'
if(65 in keysDown
&& time > (timeSinceLastAttack + DELAY) ) {
player.attack();
timeSinceLastAttack = time;
}
Then in your attack() function you can do your collision detection.
Okay,
1- Try assigning a larger value for the DELAY
2- Print the "time" value to see how much you add each loop to the DELAY if it was a big value - larger than 0.00x - divide it
Another thing:
Place the "cooldown -= time" outside the "A pressed" parentheses
It's not good, to force the user to hold the A button for a certain amount of time each time he want to shoot