Why is the bullet going the wrong way? - javascript

I'm trying to make a shooter game and the bullets are going the wrong way.
I've tried to mess a little bit with the formulas but I have no clue on how to solve this issue.
setInterval(function(){
$(".bullet").each(function(i,bullet) {
var x = parseFloat($(bullet).css("left")) + parseFloat($(bullet).attr("y"));
var y = parseFloat($(bullet).css("top")) + parseFloat($(bullet).attr("x"));
$(bullet).css({"top":y+"px","left":x+"px"});
});
},20);
$(window).click(function(e) {
var dx = (e.pageX - (x+37.5));
var dy = (e.pageY - (y+37.5));
var mag = Math.sqrt(dx * dx + dy * dy);
var velX = (dx / mag) * 15;
var velY = (dy / mag) * 15;
$("#game").append("<div class=\"bullet\" x=\""+velX+"\" y=\""+velY+"\" age=\"0\" style=\"top:"+(parseFloat($("#user").css("top"))+37.5)+"px;left:"+(parseFloat($("#user").css("left"))+37.5)+"px;\"></div>");
});
Here's a GIF of what's happening

You are adding X to Y and Y to X is one observation:
var x = parseFloat($(bullet).css("left")) + parseFloat($(bullet).attr("x"));
var y = parseFloat($(bullet).css("top")) + parseFloat($(bullet).attr("y"));
instead of
var x = parseFloat($(bullet).css("left")) + parseFloat($(bullet).attr("y"));
var y = parseFloat($(bullet).css("top")) + parseFloat($(bullet).attr("x"));

Related

Verlet 3D Ball Breaking

I am trying to use verlet integration for making a soft body sphere.
I basically create a mesh and attach each vertex by springs. I am using three.js to render the sphere. I believe everything is working correctly, but I am unsure about how to get the desired results. My ball collapses if the connections are too weak or explodes if too rigid. Something doesn't seem right. The problem occurs the moment the object falls and hits the ground. I will post the major parts of my code, however I am unsure if my approach is valid and can be used to produce the results I want.
function verletStick3D(p1, p2, distance, rigid){
this.type = "stick";
this.p1 = p1;
this.p2 = p2;
this.distance = distance;
this.rigid = rigid;
this.update = function(){
var dx = this.p1.x - this.p2.x;
var dy = this.p1.y - this.p2.y;
var dz = this.p1.z - this.p2.z;
var distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
var difference = this.distance - distance;
var percent = difference / distance / 2;
var offsetX = dx * percent * this.rigid;
var offsetY = dy * percent * this.rigid;
var offsetZ = dz * percent * this.rigid;
this.p1.x += offsetX;
this.p1.y += offsetY;
this.p1.z += offsetZ;
this.p2.x -= offsetX;
this.p2.y -= offsetY;
this.p2.z -= offsetZ;
}
}
function verletPoint3D(x, y,z, maxX, maxZ, bounce = 0.9, friction =
1.0, gravity = {x:0, y:-0.03, z:0}){
y = y + 10;
this.type = "point";
this.x=x;
this.y=y;
this.z=z;
this.xOld=x;
this.yOld=y;
this.zOld=z;
this.bounce = bounce;
this.friction = friction;
this.gravity = gravity;
this.update = function(){
var vx = (this.x - this.xOld) * this.friction;
var vy = (this.y - this.yOld) * this.friction;
var vz = (this.z - this.zOld) * this.friction;
this.xOld = this.x;
this.yOld = this.y;
this.zOld = this.z;
this.x += vx;
this.y += vy;
this.z += vz;
this.y += this.gravity.y;
this.x += this.gravity.x;
this.z += this.gravity.z;
}
this.setGravity = function(gravity){
this.gravity = gravity;
}
this.constrain = function(){
var vx = (this.x - this.xOld) ;
var vy = (this.y - this.yOld) ;
if(this.x > this.maxX){
this.x = width;
this.xOld = this.x + vx * this.bounce;
}
if(this.x < this.minX){
this.x ;
this.xOld = this.x + vx * this.bounce;
}
if(this.z > this.maxZ ){
this.z = height ;
this.zOld = this.z + vz * this.bounce;
}
if(this.z < this.minZ){
this.z = 0;
this.zOld = this.z + vz * this.bounce;
}
if(this.y < 0){
this.y = 0;
this.yOld = this.y + vy * this.bounce;
}
}
}
function verletFromMesh(vertices, faces, maxX, maxY){
var points = [];
for(var i = 0; i < vertices.length; i++){
var p = new verletPoint3D(vertices[i].x, vertices[i].y, vertices[i].z, maxX, maxY, 0.9, 0.9);
points.push(p);
}
var springs = []
/*
for(var i = 0; i < faces.length; i++){
var face = faces[i];
var p1 = face.a;
var p2 = face.b;
var p3 = face.c;
springs.push(new verletStick( p1,p2, distance3D(p1, p2), 1.0) )
springs.push(new verletStick( p2,p3, distance3D(p2, p3), 1.0) )
springs.push(new verletStick( p3,p1, distance3D(p3, p1), 1.0) )
}*/
for(var i = 0; i < points.length; i++){
var p1 = points[i];
for(var j= i+1; j < points.length; j++){
var p2 = points[j];
if(p1.x == p2.x && p1.y == p2.y && p1.z == p2.z)
continue;
var dist = distance3D(p1, p2)
springs.push(new verletStick3D( p1,p2, dist, 1.0) )
}
}
return new verletObj(points, springs);
}
Hmm, it's hard to see exactly where you're going wrong, but to me, it seems like your springs might not be able to reverse the motion. That would cause the explosions/collapses depending on their strength. I'd highly suggest trying to explicitly limit their effect on the sphere and hopefully that'll help you further debug this issue.
The way your math works, especially when setting offsets dx * percent * this.rigid; makes it seems like these dynamic forces are behaving statically, and therefore going too far into play.
Ps: have you checked out this post? It's about friction, but I think the answer is pretty quotable here:
Just introduce a small, constant acceleration on moving objects that
points in the direction opposite to the motion. And make sure it can't
actually reverse the motion; if you detect that in an integration
step, just set the velocity to zero.
Hope this sets you in the right direction somehow.

Rotate svg object with angularjs

I'm using svg shapes and I want to rotate those shapes. Here is the javascript code I'm using:
$scope.onobjectRotate = function (e)
{
$scope.isSaved = false;
var draggable = e.currentTarget;
e.clientX = e.clientX + 20;
e.clientY = e.clientY + 30;
var index = parseInt(draggable.attr('data-index'));
$scope.shapeobjects[index].isactive = true;
var R2D = 180 * 7 / 22;//radian to degree value(180/pie)
var center_x = $scope.shapeobjects[index].left + ($scope.shapeobjects[index].width / 2);
var center_y = $scope.shapeobjects[index].top + ($scope.shapeobjects[index].height / 2);
x = e.clientX - center_x;
y = e.clientY - center_y;
var radians = y / x;//slope in radians
var degree = radians * R2D;
$scope.shapeobjects[index].rotation = degree;
$scope.$apply();
}
It is working to some extent, in that it is rotating in a clockwise direction only. But how can I rotate both clockwise and anti-clockwise directions ?

How to have an element follow a dynamic moving element?

Okay, so I got most of this done. Here is the code:
function gi(a) {
return document.getElementById(a)
}
gameworld = document.getElementById('GameWorld');
character = document.getElementById('character');
var oldvX = 30;
var oldvY = 30;
gameworld.addEventListener('click', function(e) {
var offsetX = e.offsetX;
var offsetY = e.offsetY;
var element = e.target;
character.style.left = offsetX + 'px';
character.style.top = offsetY + 'px';
});
setInterval(function() {
monster = gi('monster');
oldvX += 10;
oldvY += 10;
gb = gameworld.getBoundingClientRect();
cb = character.getBoundingClientRect();
oldvX += cb.left / 10;
oldvY += cb.top / 10;
if (oldvX >= (cb.left)) {
return
}
if (oldvY >= (cb.top)) {
return
}
monster.style.left = oldvX + 'px';
monster.style.top = oldvY + 'px';
}, 500);
And here is the jsfiddle:
https://jsfiddle.net/g43nxhcw/12/
As you can see, the monster is making its way towards the player via the players' getBoundingClientRect(). My dilemma is: When I move around the red square, the monster is not following my character. I am not sure how to accomplish this or if this is even possible.
You should calculate a direction vector
vx = cb.left - parseInt(monster.style.left);
vy = cb.top - parseInt(monster.style.top);
vl = Math.sqrt(vx*vx+vy*vy);
vx = vx / vl
vy = vy / vl
it always have the length 1so you can multiply with the step size
vx = vx * 10
vy = vy * 10
and make it chase you like your little friend:
monster.style.left=(parseInt(monster.style.left) + vx) +'px';
monster.style.top=(parseInt(monster.style.top) + vy)+'px';
there is something wrong with your detection of collision also..
but I wont cover that here
https://jsfiddle.net/g43nxhcw/13/

2D simple ball collision vector

Trying to get two balls to collide and bounce back at appropriate angles.
When the balls collide however they get stuck together and I have no idea what I'm doing wrong here.
I'm calling this checkCollision() function within my animate function
Obviously cx is ball1 xpos, cx2 is ball2 xpos. Same for cy.
function checkCollision () {
var dx = cx2 - cx; // distance between x
var dy = cy2 - cy; // distance between y
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < (radius1 + radius2)) {
// Collision detected. Find the normal.
var normalX = dx / distance;
var normalY = dy / distance;
//find the middle point of the distance
var midpointX = (cx + cx2)/2;
var midpointY = (cy + cy2)/2;
//bounce back
cx = midpointX - radius1*normalX;
cy = midpointY - radius1*normalY;
cx2 = midpointX - radius2*normalX;
cy2 = midpointY - radius2*normalY;
var dVector = (vx - vx2) * normalX;
dVector += (vy - vy2) * normalY;
var dvx = dVector * normalX;
var dvy = dVector * normalY;
vx -= dvx;
vy -= dvy;
vx2 += dvx;
vy2 += dvy;
}
...
I've never done much/any vector work. Is there any easier way to do this?
How would I write this with angles instead?
You need to use some basic maths to detect the intersection between two circles.
A similar problem is described here:
algorithm to detect if a Circles intersect with any other circle in the same plane
There is a C# sample that could be easily adapted to Javascript.

Draw divs in elliptical shape with jQuery

It seems that my math is not enough for my current task, so thats why i would like to ask help. The main thing is solved, i display the divs in elipsis shape, but i cannot solve how to take care to the dimension of the divs. The current solution works for shapes with equal sides, but my divs are not like that, their width are bigger than their height.
The current function look like this:
function drawEllipse(selector, x, y, a, b, angle) {
var steps = jQuery(selector).length;
var i = 0;
var beta = -angle * (Math.PI / 180);
var sinbeta = Math.sin(beta);
var cosbeta = Math.cos(beta);
jQuery(selector).each(function(index) {
var alpha = i * (Math.PI / 180);
i += (360 / steps);
var sinalpha = Math.sin(alpha);
var cosalpha = Math.cos(alpha);
var X = x + (a * sinalpha * cosbeta - b * cosalpha * sinbeta);
var Y = y - (a * sinalpha * sinbeta + b * cosalpha * cosbeta);
X = Math.floor(X);
Y = Math.floor(Y);
//again, here's where the important X and Y coordinates are being output
jQuery(this).css('margin-top', Y + 'px');
jQuery(this).css('margin-left', X + 'px');
});
}
Thank you in advance.
Instead of offsetting your divs with margin, why don't you use position: absolute? Then you can place them exactly where you want them.
You can combine this with a negative margin of half the div's width and height to center them at that position.
Demo: http://jsfiddle.net/jtbowden/gRb5r/
I was able to make your code work by this (needed it for very different reason):
Plugin.prototype.drawEllipse = function (element, x, y, a, b, angle) {
var steps = 120;
var i = 0;
var beta = -angle * (Math.PI / 180);
var sinbeta = Math.sin(beta);
var cosbeta = Math.cos(beta);
for (var i=0; i<steps; i++) {
element.html(element.html() + "<div class='ellipsemarker'></div>");
}
$('.ellipsemarker').each(function(index) {
var alpha = i * (Math.PI / 180);
i += (360 / steps);
var sinalpha = Math.sin(alpha);
var cosalpha = Math.cos(alpha);
var X = x + (a * sinalpha * cosbeta - b * cosalpha * sinbeta);
var Y = y - (a * sinalpha * sinbeta + b * cosalpha * cosbeta);
X = Math.floor(X);
Y = Math.floor(Y);
//again, here's where the important X and Y coordinates are being output
$(this).css('top', Y + 'px');
$(this).css('left', X + 'px');
});
};
Sorry about the refactoring, most of that is personal preference things.
The CSS that makes these constrained in width and height was (in my case):
.ellipsemarker {
background-color: #fff;
border: #e8e8e8 2px solid;
width: 15px;
height: 10px;
position: absolute;
}
Note the position: absolute as another poster suggested.
The supplementary calling code in my case was this, just for reference:
var x, y;
var pos = $('#ringwrapper').position();
x = pos.left;
y = pos.top;
console.log(x + " : " + y);
this.drawEllipse($('#ringwrapper'), x + (this.ringSize.width / 2.85),
y + (this.ringSize.height / 3.1), 235, 350, 90);

Categories

Resources