I have this game where I'm planning to make it into some kind of shooter (please also state if that's too hard considering the level I'm currently at) and I'm at the point of making things collide, like the player with point rectangles (should make orbs instead soon).
I've looked at different examples like
Collision Detection with javascript on the html canvas element without using jquery
and
http://jlongster.com/Making-Sprite-based-Games-with-Canvas
but it seems like I didn't understand the code well enough. Here's what I have:
if( (rX + (rX + 20)) >= x && rX <= (x + 20) && (rY + (rY + 20)) >= y && rY <= (y + 20)){
poeng++;
genererRandom();
}
Didn't work, so tried this one:
if (x >= rX || (rX+19) < (x+49) ||
y >= rY || (rY+19) < (y+49)) {
poeng++;
genererRandom();
}
x is the x position of the sprite I'm using (which is 60x60 large)
y is the y of x
rX is a randomly generated number and the x position of the point rectangle (again, think I should make it into orbs soon)
rY is the y of rX
Also, just ask if you want to see more code, although it is mostly not mine, I was given an unfinished game that I could make something out of.
Given a 2d axis aligned rectangle of width=w and height=h with its origin of x and y being in the top left corner, the check whether a point r with position rx and ry lies in the rectangle would be:
if (rx >= x && rx <= x+w && ry >= y && ry <= ry+h)
{
// we're inside the rectangle!
}
In simple terms this means:
check if the point's x lies between the rectangle's x and x+w
check if the point's y lies between the rectangle's y and y+h
In maths you could write it this way (doesn't work in JS though):
x <= rX <= x+w ∧ y <= rY <= y+h
The statements above imply that the coordinate system has the origin in the top left corner and the values increase towards bottom right.
Related
I'm new to JavaScript and I'm trying to code a somewhat simplified version of the breakout game. It is not done yet, and pretty messy regarding the coding, but it works, almost. My collision detector has some trouble detecting the ball. It does what it is supposed to for the most part, but from time to time the ball just goes straight through, and I cannot figure out how to remake that part.
The code looks like this
function collisionDetection(){
for(var c=0; c<brickColumnCount; c++){
for(var r=0; r<brickRowCount; r++){
var b=bricks[c][r];
//collisionDetection
if(b.status == 1){
if(x+15 > b.x && x+15 < b.x+brickWidth && y-10 > b.y && y-10 < b.y+brickHight){
dy = -dy;
b.status = 0;
score++;
color = getRandomColor();
}
}
}
}
}
I made the paddle as long as the canvas for testing - I have not yet made something to get the ball to change the angle, only speed. And I haven't defined a maxSpeed yet which I will do later on, but first I want my collision to work properly.
Do you have an idea why this is not working?
I noticed that at 200 points the collision will not work at all. Might be the speed(Which is insanely high, yes)?
The full code can be found here
Thanks
If the x and y values are the top left corners of your ball and brick elements, then the if statement should probably be:
if (x + 15 > b.x && x < b.x + brickWidth && y + 15 > b.y && y < b.y + brickHight)
For proper collision detection you'll have to implement some side detection as well. I.e. if the ball hits the side of the brick, dx must be reversed and not dy.
I have an animation using JS and Fabric.js whereby circles more around the screen. I'm trying to contain them to a specific area but having some issues.
After some reading yesterday I thought that testing to see if the circle was inside the rectangle (their container) would be quite simple but I've yet to get it working properly.
The circles are created at the bottom of the screen which is also where their container is. With the code that I have they 'float' to the top and stay there in one spot.
The console logs that I have indicate that they are outside the rectangle immediately so I'm assuming that something is wrong with my collision function.
My aim is for them to stay within the containing moving about and when they hit the edges they should change direction so that they will stay inside again.
Thanks for any help.
EDIT : EDITED TO ENABLE A TOUCH OF CLARITY AND USING THE COLSIOSN DETECTION FROM BELOW ANSWER AS NOW THINK THE PROBLEM IS WITH THE RESPONSE INSTEAD OF THE DETECTION.
Collision function:
function testCollision(circle, rectangle) {
return circle.left + circle.radius < rectangle.left + rectangle.width/2 //right side
&& circle.left - circle.radius < rectangle.left - rectangle.width/2 //left side
&& circle.top + circle.radius < rectangle.top + rectangle.height/2 //top
&& circle.top - circle.radius < rectangle.top - rectangle.height/2;
}
left = x & top = y
There are maxX and maxY values which is the width and height of the container.
this is the test:
if(testCollision(circle, rect) == false){
var r = Math.atan2(y - maxY / 2, x - maxX / 2);
vx = -Math.cos(r);
vy = -Math.sin(r);
}
any help is hugely appreciated, thanks!
The way i see it, a circle defined by (x,y,r) coordinates of the center and radius is inside a n axis-aligned rectangle defined by (x,y,w,h) coordinates of the center, the width and the height if the 4 points top,right,bottom,left of the circle are inside the rectangle:
function testCollision(circle, rectangle) {
return circle.x + circle.r < rectangle.x + rectangle.w/2
&& circle.x - circle.r > rectangle.x - rectangle.w/2
&& circle.y + circle.r < rectangle.y + rectangle.h/2
&& circle.y - circle.r > rectangle.y - rectangle.h/2
}
I considered the positive direction of y to be towards the bottom, as is usual in coordinate systems on the web.
I'm working on a HTML5 game and have what I think is a math problem. The player and enemy objects have a pos.x and pos.y value indicating where they are on the screen. I have implemented proximity check code for some enemies and am not totally happy with it. Currently the enemy is checking if the player is within a certain distance from it, 200 or -200 on the x and y axis. What this means is that the entity is scanning a 400x400 square around itself.
I would like to make this a circle with a radius of 200 instead. My code as it stands.
if ((player.pos.x - enemy.pos.x > 200 && player.pos.x - enemy.pos.x < 200)
&& (player.pos.y - enemy.pos.y > 200 && player.pos.y - enemy.pos.y < 200)) {
//Do something...
}
Here's my game if you want to check it out. Proximity enemies are on the second and currently last level :)
http://project.dnsalias.com/
It's very basic math.
Check that (x1 - x0)2 + (y1 - y0)2 < r2
function inRange(p0, p1, r) {
r = r || 200;
var dx = p0.x - p1.x;
var dy = p0.y - p1.y;
return (dx * dx + dy * dy) < (r * r);
}
Call it like so:
if (inRange(player.pos, enemy.pos)) {
...
}
You can supply a third optional argument to change the detection radius.
Perhaps you could use the Euclidean distance function instead? It would be something like (player.pos.x - enemy.pos.x) x (player.pos.x - enemy.pos.x) + (player.pos.y - enemy.pos.y) x (player.pos.y - enemy.pos.y) = 200 x 200. Sorry I don't know the syntax for square root and square functions.
I need to turn a click location into a polar coordinate.
This is my current algorithm. Location is the location on the canvas of the click ({x:evt.clientX, y:evt.clientY}), center is the offset of the origin from 0,0. For example, if the circle is centered on 250, 250, center is {x:250, y:250}. Scale is the scale of the radius. For example, if the radius of a circle from the center would normally be 50 and the scale is .5, the radius becomes 25. (it's for zooming in/out)
this.getPolarLocation = function(location){
var unscaledFromCenter = {
x: location.x - center.x,
y: location.y - center.y
};
var angle = this.getAngleOnCircle(unscaledFromCenter);
var dist = Math.sqrt(unscaledFromCenter.x * unscaledFromCenter.x + unscaledFromCenter.y * unscaledFromCenter.y) * this.ds.scale;
return {
angle:angle,
dist:dist,
toString: function(){
return "Theta: ".concat(angle).concat("; dist: ").concat(dist);
}
};
}
this.getAngleOnCircle = function(location){
var x = location.x;
var y = location.y;
if(x == 0 && y > 0)
return Math.PI / 2;
if(x == 0 && y < 0)
return 3 * Math.PI / 2;
if(y == 0 && x > 0)
return 0;
if(y == 0 && x < 0)
return Math.PI;
var angle = Math.atan(y/x);
if(x > 0 && y > 0)
return angle;
if(x < 0)
return Math.PI + angle
return Math.PI * 2 + angle;
}
Screenshots of the issue. The left is what happens zoomed out (and is not supposed to happen). The right is zoomed in (scale >= 1), and is what is supposed to happen.
I'm under the impression that my center coordinates are being shifted slightly off. It seems to work fine for scale >= 1, but not for scale < 1
Source:
circos.html: http://pastie.org/private/cowsjz7mcihy8wtv4u4ag
circos.js: http://pastie.org/private/o9w3dwccmimalez9fropa
datasource.js: http://pastie.org/private/iko9bqq8eztbfh8xpvnoaw
Run in Firefox
So my question is: why doesn't this work?
For some reason, the program automagically works when I close firebug. It doesn't seem to work on Firefox 5, only the version I have (in the 3s somewhere). Either way, I'm scrapping the project for something more object oriented. There's no way the current algorithm could handle a genome. (which is exactly what I'm going to be mapping)
UPDATE:
I figured out the problem... I was measuring the distance from the top left of the page, not the top left of the canvas. Thus, when firebug was enabled, the screen was shifted, making the problems worse. The solution is the use canvas.offsetLeft and canvas.offsetTop to calculate the position on the canvas.
I'm currently working on making an interface where I have image links that lean towards the mouse cursor. This is more for fun than as a serious project, but nevertheless the information I'm learning from it will be useful in the future. Right now I have several variables setup...
diffx/y = the distance, in pixels, of the cursor from the link's original location. This value goes negative if the cursor goes to the left of or above the link's original location (already calculated).
spacex/y = the amount of distance that I want in between the cursor and the link
calcx/y = the calculated number will be added to the 'style.top' and 'style.left' of the link
calcx = diffx - spacex
calcy = diffy - spacey
link.style.top = calcx
link.style.top = calcy
If I set spacex/y = 0 the link is centered on the cursor
If I set spacex/y = diffx/y the link is set to its normal position
My goal is to have a link that leans slightly towards the cursor (maybe at max 40px from the original position) and
as the cursor gets closer to the link, the link will slowly return to its original position.
When the cursor gets within, let's say, 100px the link should (smoothly) jump towards the cursor as if to say "pick me!"
Here's what the equation would look like as a graph.
I need a way to write this as a javascript equation. I haven't taken algebra in awhile and I'm pretty sure we didn't go over anything that looked like this exactly. I'm guessing it has an exponent and a conditional in there somewhere, but I'm not quite sure. If your able to figure this out, I'd be really thankful (not to mention impressed).
Thank You for your help!
You'll definitely want a piecewise function here (the "conditional" you spoke of). The middle section appears to be an odd-powered polynomial of the form y = Ax^3 or y = Ax^5 for some small value of A (chosen to make y = 150 when x = 150). The curve appears to be essentially linear for |x| >= 200, that is y = x + B for x >= 200 and y = x - B for x <= -200. The transitions between 150 <= |x| <= 200 seem a little trickier, like a shifted exponential or quadratic. But you might start with this (pseudo code):
if (x < -150) {
y = x;
}
else if (x < 150) {
y = (1.0/22500.0) * pow(x, 3);
}
else { // x > 150
y = x;
}
Note that this ignores the transitions between x = 150 and 200 and correspondingly assumes the constants B I mentioned above are zero. But it might get you started.
Edit:
After looking at a plot of my function, I think a 5th order polynomial matches your desired shape more closely. In this case, the middle function will be y = (1.0/506250000.0) * pow(x,5). Results are below. By the way, the constant values are equivalent to 150^-2 for the cubic, and 150^-4 for the quintic function.
I agree it is probably easier to model your function if you split it in parts:
f(x) = x + 50 if x < -200
-150 if -200 <= x < -150
150*(x/150)^k if -150 <= x < 150:
150 if 150 <= x < 200
x - 50 if 200 <= x
for k some big odd number (I'd try 4-10 out...)
You can use one or combination of these:
http://drawlogic.com/2007/09/14/tweener-robert-penner-easing-equation-cheat-sheets/
Or http://www.robertpenner.com/easing/easing_demo.html