I have a sprite representing a bullet and its basic implementation is as follows:
function Bullet(x, y, rotation) {
this.x = x;
this.y = y;
this.direction = rotation;
this.speed = 5;
}
Bullet.prototype.update = function() {
// Move the bullet forward
this.x = Math.sin(this.rotation) * this.speed;
this.x = Math.cos(this.rotation) * this.speed;
}
What I'm trying to do here is move the bullet forward in the direction it's facing and relative to its speed. However, when calling the update() method this.x and this.x is NaN.
What's the correct way of making a sprite move in the direction it's facing if given its x, y and rotation information?
You have a typo. This:
this.x = Math.sin(this.rotation) * this.speed;
should be
this.x = Math.sin(this.direction) * this.speed;
Related
I built centipede in javascript from a Khan Academy tutorial. Then I figured out how to put it into a web browser. however, the key presses are not working. I have tried to change the keyCode values, and change some of the function definitions to "void" but nothing has worked. The app uses processing .js to work. Here is the section of js dealing with the keys:
var Player = function(x,y,size,speed){
this.x = x;
this.y = y;
this.size = size;
this.speed = speed;
this.update = function(){
if(keys[LEFT]){
this.x -= this.speed;
}
if(keys[RIGHT]){
this.x += this.speed;
}
if(keys[DOWN]){
this.y += this.speed;
}
if(keys[UP]){
this.y -= this.speed;
}
if(keys[76] && bulletDelay < 0){
var b = new Bullet(this.x, this.y, 5,5);
bullets.push(b);
bulletDelay = 40;
}
if (this.x < 0){
this.x = 0;
}
if (this.x > width){
this.x = width;
}
if (this.y > 800){
this.y = 800;
}
//This adjusts the max height the player can move up on y-axis. Adjust to make more like Atari version
if (this.y < 100) {
this.y = 100;
}
noStroke();
fill(0,255,0);
ellipse(this.x, this.y, this.size, this.size);
};
};
I sorted it out. The keyPress and keyRelease functions needed to be changed from
var keyPressed = function(){
to
void keyPressed() . . .
similar for the keyReleased function
The syntax
if(keys[LEFT])
should be
if(keyCode == LEFT)
See the Processing.js keyCode reference and key
EDIT 1: For special keys (arrow, space), you should use keyCode instead of key.
Im trying to make an particle move towards where on canvas was clicked however the formula returns NaN. Why is this and how can I fix this?
step 1: Particle gets placed at player.x, player.y properly.
step 2: At first tick the particle goes to the upper left point of the canvas without x,y position.
Screenie of particle props
example at jsfiddle
Particle Object
function Shuriken(mouseX, mouseY) {
this.rot = 0;
this.vel = 2;
this.angle = 0;
this.x = player.x || WIDTH / 2;
this.y = player.y || HEIGHT / 2;
this.mouseX = mouseX || WIDTH /2;
this.mouseY = mouseY || HEIGHT /2
this.width = shurikenImg.width;
this.height = shurikenImg.height;
}
update on tick
Shuriken.prototype.move = function() {
this.angle = Math.atan2(this.mouseY, this.x) * (180 / Math.PI);
this.x += this.vel * Math.cos(this.angle);
this.y += this.vel * Math.sin(this.angle);
}
You convert angle from radians into degrees. Nicer to debug (because degrees are still taught in school) but alas, the sin and cos in the next lines expect their arguments to be in radians again. Granted, the functions ought still to work; but the values you get are no longer what you expect.
this.vel is undefined in the jsfiddle. This is most likely what lead to the observed NaN.
This is a wrong calculation:
this.x = this.vel * Math.cos(this.angle);
this.y = this.vel * Math.sin(this.angle);
You don't want the x and y positions calculated this way. Add or subtract the (adjusted) velocity from the x/y coordinates.
i need to zoom to a particular coordinate(X,Y) on the canvas in fabrics js.
I know that there will be 2 functions being called
1. Scaled (x times)
2. Move the image to some x,y location so that the image appears to be at that coordinate.
Also i need that once zoomed in , i specify some other coordinate and it should zoom to that new coordinate. Any tips
You can define yourself a camera.
You have some absolute coordinate system and you want to project things from that system to the screen. That is done by the camera object.
The camera has a position somewhere in your absolute coordinate system and it has a zoom factor and a rotation angle. The toScreen function takes absolute coordinates and translates them into coordinates on the screen. fromScreen does the opposite. moveBy is a relative move i.e. it moves in screen coordinates not absolute coordinates. That is useful for example if you have an image and you want it to follow your mouse pointer since the mouse pointer coordinates are screen coordinates. So you just calculate by how much the pointer moved and then call moveBy on the camera with the negative of those numbers. (negative because if a camera is moved left the image it produces moves right on the screen)
Or lets say you click on a point on the screen and you then want the camera to zoom onto that point. Then you just say camera.moveBy(pointX, pointY) (where pointX/Y is the mouse position relative to the center of the screen i.e. the position of the camera since in screen coordinates the camera is always at position (0, 0)) and change the zoom factor if needed. btw. the "screen" here is of course your canvas. And pos (0,0) in screen coordinates should be the center of the canvas. So just to emphasize, the canvas is not your absolute coordinate system but the screen onto which the camera projects its image.
function Camera() {
this.x = 0;
this.y = 0;
this.zoom = 1;
this.angle = 0;
}
Camera.prototype.moveTo = function(x, y) {
this.x = x; this.y = y;
};
Camera.prototype.moveBy = function(x, y) {
var xy = this.fromScreen(x, y);
this.moveTo(xy.x, xy.y);
};
Camera.prototype.rotateTo = function(angle) {
while(angle < 0) angle += 360;
angle %= 360;
this.angle = angle;
};
Camera.prototype.rotateBy = function(angle) {
this.rotateTo(this.angle + angle);
};
Camera.prototype.zoomTo = function(zoom) {
this.zoom = zoom;
};
Camera.prototype.zoomBy = function(zoom) {
this.zoom *= zoom;
};
Camera.prototype.toScreen = function(x, y) {
x -= this.x; y -= this.y;
if(this.angle !== 0) {
var rad = Math.PI * this.angle / 180;
rad = 2 * Math.PI - rad;
var _x = x * Math.cos(rad) - y * Math.sin(rad),
_y = x * Math.sin(rad) + y * Math.cos(rad);
x = _x; y = _y;
}
return {x: x * this.zoom,
y: y * this.zoom}
};
Camera.prototype.fromScreen = function(x, y) {
x /= this.zoom;
y /= this.zoom;
if(this.angle !== 0) {
var rad = Math.PI * this.angle / 180;
var _x = x * Math.cos(rad) - y * Math.sin(rad),
_y = x * Math.sin(rad) + y * Math.cos(rad);
x = _x; y = _y;
}
x += this.x; y += this.y;
return {x: x,
y: y};
};
Okay, so I want to make a javascript/html canvas game where the player is being followed by some enemies, and after a little bit of 'research' her is the most important part of my Monster (enemy) class:
this.UpdateAngle = function() {
this.dx = this.x - player.x;
this.dy = this.y - player.y;
this.angle = Math.atan2(this.dy, this.dx) * 180 / Math.PI;
if (this.angle < 0) {
this.angle += 2 * Math.PI;
}
}
this.UpdateSpeed = function() {
this.speedX = this.speed * Math.cos(this.angle);
this.speedY = this.speed * Math.sin(this.angle);
}
this.Move = function() {
this.UpdateAngle();
this.UpdateSpeed();
this.x += this.speedX;
this.y += this.speedY;
}
So what I meant to do here, was to calculate the angle from the enemy to the player with atan2() and then calculate how much I should move in the x and y axis by using cos() and sin(), the speed and the angle I calculated, and then just moved the calculated pixels.
This all seems to work well, until I move the player, then the enemies start to move in weird directions. I have no idea whats wrong, it would be awesome if someone could learn me how this is meant to be done. :D
You can see it in action here. *I have updated the code with PremierBromanov's suggestion.
It may have something to do with this block
this.angle = Math.atan2(this.dy,this.dx) * 180 / Math.PI;
if (this.angle < 0) {
this.angle += 2 * Math.PI;
You are using Math.atan2 which outputs the angle in radians, then you are converting to degrees with * 180 / Math.PI; After that, you're checking to see if it's less than zero and adding 2Pi to the angle to make sure it's correctly calculating it's actual angle of a full circle minus the angle. BUT, you are using radians here instead of degrees. So when your code is negative, you're adding 2Pi to the degree, which isn't very much, but sometimes causes it to go positive. This is why your dots are spinning when you move. If you notice, the dots spin slower when you are farther away, meaning the negative angle is larger than 2Pi and so doesn't circle around right away.
in short, try changing it to this
if (this.angle < 0) {
this.angle += 360;
}
Ok, so it was actually Premier Bromanov who answered this, thanks, but I can't accept a comment, which it was, so I will just do this to make it more clear, if anyone should come by and want the answer too.
The math i did was a bit wrong, and here is how my code ended up looking like:
this.UpdateAngle = function() {
this.dx = player.x - this.x;
this.dy = player.y - this.y;
this.distance = Math.sqrt((this.dx*this.dx) + (this.dy*this.dy));
this.angle = Math.atan2(this.dy,this.dx) * 180 / Math.PI;
}
this.UpdateSpeed = function() {
this.speedX = this.speed * (this.dx/this.distance);
this.speedY = this.speed * (this.dy/this.distance);
}
this.Move = function() {
this.UpdateAngle();
this.UpdateSpeed();
this.x += this.speedX;
this.y += this.speedY;
}
Thanks again to Premier Bromanov, this is his answer, and also to everyone else, this was my first post and i am glad how fast i got a response! (I was the slowest one here) :D
I am trying to make a shooter game, but I have got some troubles with bullet animation. Each time I click, a new bullet object created and animation starts, but after each click the created bullet disappears and same bullet starts over again which is faster than previous bullet. So I am trying to create new bullet after each click. A basic shooter game logic. Here is my code:
function newBullet(x,y,angle,speed,id,type) {
this.x = x;
this.y = y;
this.speed = speed;
this.angle = angle;
this.radians = this.angle * Math.PI / 180;
this.id = id;
this.type = type;
this.drawBullet = drawBullet;
this.moveBullet = moveBullet;
}
function moveBullet() {
this.x = this.x + Math.cos(this.radians) * this.speed ;
this.y = this.y + Math.sin(this.radians) * this.speed;
ctx.drawImage( bulletImg, this.x, this.y);
}
function drawBullet() {
bullet = new newBullet(playerX,playerY,getAngle(),2,1,1);
bullets[bullets.length] = bullet;
setInterval("bullets[bullets.length - 1].moveBullet()", 25);
}
canvas.addEventListener("mousedown",drawBullet,false);
Try adding var here:
var bullet = new newBullet(playerX,playerY,getAngle(),2,1,1);
If you want to add a bullet to an array you should use push. This will update bullets.length:
function drawBullet() {
var bullet = new newBullet(playerX,playerY,getAngle(),2,1,1);
bullets.push(bullet);
setInterval(bullets[bullets.length - 1].moveBullet, 25);
}
The reason your created bullet disappeared: you replaced bullets[0] each time. And the new bullet was faster then the old one because bullets[0].moveBullet was called n-times in each 25ms interval, where n is the number of bullets you "created".