I'm trying to use brownian motion to create a group of random moving particles.
http://jsfiddle.net/J75Em/16/
So far I've got the particles moving randomly but I'm not sure how to set the forward direction to make it look more natural.
I've tried to use the change in x and y axis to calculate rotation using atan, you can see this by uncommenting rotate but this doesn't seem to perform well.
Is this the right approach for this type of movement? thanks;
This is pretty neat!
You are sort of going about it the right way but you should actually use the atan2 function. This removes the need for any 0 checks.
The atan2 function gives you an angle which is anticlockwise from the positive x vector
(1, 0) --->
The bees are 90 degrees off from this starting angle so you must subtract 90 degrees from the direction. (depending on which way round you do the dy and dx calculation, you might need to add)
You could find that the direction changes rapidly, so you could consider limiting the next change to a set of changes that cause an angle change below some threshold. This will make the movement a little smoother.
I would actually go about it by generating an angle between say -pi/8 and pi/8 radians, and a random length. Essentially using polar coordinates. Then add this new random polar offset to the x and y position like
newX = currentX + (randomLength * cos(randomAngle + currentAngle)) and
newY = currentY + (randomLength * sin(randomAngle + currentAngle))
If you work with angles you can also get more natural effects like if you want the bees to stay within a certain area, you can force a bias towards the center of the area as they get closer and closer to the edge.
Update:
So I've taken a closer look. The trouble is that you expect .rotate to set the rotation when it actually adds to the rotation
There are 2 options for fixing this.
Rotate by the difference between the previous and the current angle
Set the rotation using the .transform method
You can see solution 2 in action here http://jsfiddle.net/c5A2A/
Related
How can I find a position relative to a point that has been rotated? The idea is, that I'm rotating an entity at a certain position, and need to be able to find a position relative to that entity's rotation, such that 10 units above the entity relative to its rotation is different from 10 units directly above the entity. Hopefully this diagram should give you an idea of what I mean:
Note: I'm doing this in the <canvas> tag with pure Javascript.
Also note: I'm only just finishing Algebra, and have done just a little trigonometry and some geometry, so please make your explanation relatively clear. Sin, cos, and tangent are only just beginning to make sense, and I had to look up the concept of radians myself the other day in order to work with <canvas>'s rotation function (thanks, Wikipedia!).
Also also note: I have tried looking this up myself (Google, SO, elsewhere), but not knowing the proper terms, I wasn't able to find anything. I'm sure this must be fairly simple, but it may as well be Greek to me.
If all you're looking for is a point that is d units from a point (x,y) at an angle θ, where the angle is taken relative to the point as its origin, in the clockwise direction, from the positive y-axis, the point is given by (x + d*cos(π/2-θ), y + d*sin(π/2-θ))
You can do it with vectors and matrices.Let's say that the direction to the 25,10 is forward vector of your cube.So you can apply the rotation matrix to this vector ,that is multiplying this vector by rotation matrix which is rotated amount of degrees you need.That will return you your relative position.Hope it is clear.I am not JavaScript expert.But I am sure there is some Vector math API out there you can use.
You have to do these steps:
Calculate the vector from cubes position to your desired offset before the rotation.
Calculate rotation matrix with some rotation.
Multiply that vector by the rotation matrix to get the new rotated vector.
I found this JavaScript Vector math lib.Take a look at the Matrix object.It has a method for vector multiplication.
If you kow how to rotate the square, you know howto rotate the vector.
What you did with the square (25,25), do with the vector(25,15)
Manipulating the slider until the end, the circle that represents the star disappears or does a different motion. See: jsfiddle.net/NxNXJ/13 Unlike this: astro.unl.edu/naap/hr/animations/hrExplorer.html
Can you help me?? Thanks
When you supply a big luminosity, You're rendering a circle which is millions of pixels tall. The broswer might not render it because it's so big.
However, you are really only interested in a small slice of that big circle - namely, the bit that fits in your tiny window.
At some point, it doesn't make sense to increase the size of the circle, since you can't observe a change in the curvature of the circle - it just looks like a straight vertical line.
This apparent verticality occurs around when x^2 + y^2 = R^2, where R is the radius of the star, Y is half the height of your window, and x is R-1. Solve for R in terms of Y, and you get
function maximumNecessaryRadius(windowHeight){
y = windowHeight / 2;
maxRadius = (y*y - 1)/2;
return Math.round(maxRadius);
}
When resizing the star, check to make sure that its radius doesn't exceed the maximum necessary radius. Rendering it any larger than that is overkill.
Example Implementation
For example it may be used in the application of manually adjusting the hands of the clock. I guess it probably involves translating the needle (to make the end point of the needle the centre of rotation) then rotating it, then translating the needle again.
But since the needle listens to the mouse event all the time, the 1st mouse event will be captured. The result is that the needle ends up being translated and not rotated at all. Mouse event is impossible to debug too...
Any idea or code snippets that I can refer to? Using Javascript or CSS to rotate both fine.
In your example, you will want to calculate the angle between the centre of the clock face (black dot), and the current mouse position (red dot), relative to the Y axis (cardinal north if you imagine a compass).
If I remember my trig correctly, you can calculate this by using the following:
var angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
// alter the angle to be relative to Y axis instead of X
angle += 90;
if(angle < 0) { angle = 360 + angle; }
In the formula, x and y are the coordinates of the two points, one of which you will know (it is the centre of the clock face), and the other you can get from the mouse move event.
Once you have the angle, you can simply translate to the the centre of the circle, rotate the canvas by the calculated amount, and draw the hand.
Update: I created a jsfiddle to illustrate the angle calculation:
http://jsfiddle.net/DAEpy/1/
Alright, I have a HTML canvas with a bunch of circles on it. I want mouseclick events on circles to trigger some Javascript function. I already have the basics, but the coordinates are obviously so precise that it takes me like 30 times to hit the exact coordinates of a certain circle.
Is there a way I could implement an "about equal to"; in other words, I would like the x and y of the mouseclick to trigger a function when it's pretty close to (let's say 10px) the coordinates of something on canvas?
Thanks
Alex
You can use something like this to test if one point is within a certain radius of another point:
function withinRadius (x1, y1, x2, y2, radius) {
var dX = x1 - x2, dY = y1 - y2;
return ((dX*dX) + (dY*dY) < radius*radius);
}
First thoughts:
if ((mouselocx >= (corodinatex - 10)) && (mouselocx <= (corodinatex + 10)) {
if ((mouselocy >= (corodinatey - 10)) && (mouselocy <= (corodinatey + 10)) {
Do something...
}
}
General case, you want to check if you have clicked within a polygon created by expanding your curve outward in both left and right directions. Calculation of this polygon in the case of bezier curves, general conic sections, etc. is tricky. Most graphic libraries allow you to set a stroke-width parameter and do it for you. Draw a wide curve in background color below your 1px curve and check for hits on the wide one. Just make sure you draw all the background color ones before any of the foreground color ones.
In your specific case of circles, if you don't have such a graphic library, it will suffice to see if you have clicked within your tolerance of a distance from the circle center. If you have a very small number of circles you can go through the whole list. If you have more than a half dozen (gut feel for when to cut over to better algorithm) divide the screen up into quarters with a list of which circles a hit in one of the rectangles might have hit, then divide into quarters within that rectangle and check with circles it might be until you have just a half dozen or so possibilities. Then go down the list of possibilities checking if you are within your delta for any of the circles.
I'm trying to figure out how I can get the correct "active" tile under the mouse when I have "ramp" and +1 height tiles (see picture below).
When my world is flat, everything works no problem. Once I add a tile with a height of say +1, along with a ramp going back to +0, my screen -> map routine is still looking as if everything is "flat".
In the picture above, the green "ramp" is the real tile I want to render and calculate mouse -> map, however the blue tile you see "below" it is the area which gets calculated. So if you move your mouse into any of the dark green areas, it thinks you're on another tile.
Here is my map render (very simple)
canvas.width = canvas.width; // cheap clear in firefox 3.6, does not work in other browsers
for(i=0;i<map_y;i++){
for(j=0;j<map_x;j++){
var xpos = (i-j)*tile_h + current_x;
var ypos = (i+j)*tile_h/2+ current_y;
context.beginPath();
context.moveTo(xpos, ypos+(tile_h/2));
context.lineTo(xpos+(tile_w/2), ypos);
context.lineTo(xpos+(tile_w), ypos+(tile_h/2));
context.lineTo(xpos+(tile_w/2), ypos+(tile_h));
context.fill();
}
}
And here is my mouse -> map routine:
ymouse=( (2*(ev.pageY-canvas.offsetTop-current_y)-ev.pageX+canvas.offsetLeft+current_x)/2 );
xmouse=( ev.pageX+ymouse-current_x-(tile_w/2)-canvas.offsetLeft );
ymouse=Math.round(ymouse/tile_h);
xmouse=Math.round(xmouse/(tile_w/2));
current_tile=[xmouse,ymouse];
I have a feeling I'll have to start over and implement a world based map system rather than a simple screen -> map routine.
Thanks.
Your assumption is correct. In order to "pick" against world geometry, your routine needs to be aware of the world (and not just the base-level tile configuration). That is, without any concept of the height of the tiles near the one that is currently picked (by your current algorithm), there's no way to determine whether a neighboring tile (or one even further away, depending on the permitted height) should be intercepted by picking ray.
You've got the final possible point of your picking ray, already. What remains is to define the remainder of the ray, in world-space, and to check that ray for intersections with world geometry.
If, like the picture, your view angle is always 45 degrees and always from the same direction, your mouse -> map routine could use an algorithm something like:
calculate i,j of tile as you're doing currently (your final value of xmouse, ymouse)
look up height and angle of tile at i,j
given the height and angle, does this tile intersect the picking ray? If so, set lasti, lastj = i, j
increment/decrement i,j one step diagonally toward viewer
have we fallen off the edge of the map? If so, return lasti, lastj. Otherwise go back to 2.
Depending on the maximum height of a tile, you might have to check only 2 tiles, rather than going all the way to the edge of the map.
3 is the tricky part, and depends on your world geometry. Draw some triangles and you should be able to figure it out. Or you might try looking at the function intersect_quadrilateral_ray() here.