Drawing a repeating sinusoidal wave with canvas api - javascript

I'm trying to get an image to flow horizontally in a sinusoidal fashion, and repeat seamlessly when it gets to the end of its own width in relation to its canvas size.
So far, I've got the image repeating and waving, but there is a significant jump when the x axis needs to be reset.
I think the problem is here:
if (x > canvasX) {
console.log('reset!!');
x = canvasX-imgW;
y = sineY(x);
}
//draw aditional image
if (x > (canvasX-imgW)) {
var ax = x-imgW+dx;
y = sineY(ax);
ctx.drawImage(img,ax,y,imgW,imgH);
}
Ultimately, what happens is that the sineY of the reset x value is about 19 degrees off of what it should be at the end of its regular period where the x value is highest. However, I can't really figure out how to adjust the bounds to make the movement seamless through the multiple periods.
Here's the fiddle: http://jsfiddle.net/3L7Dp/

The period variable needs to be normalized based on the total distance x will move.
In this case x will go image.width so period must be:
var period = x / imgW; //period must be a value in the range [0.0, 1.0]
This should give an usable value for cycling the image.
Modified fiddle
Hope this helps!

One way is to declare an offset by which x will be adjusted, such as var xOffset = 0. When calculating the sine, use x + xOffset. Every time you do x -= imgW, update the offset based on the current offset and the image width, so that the sin at the new position will equal the sin at the current position.
Doing this will allow you to have any period, even one unrelated to the width of your image.
I made my own version of your page with many simplifications, you can see it in this JsFiddle. The sine wave is seamless. My implementation also supports images much narrower than the canvas--they will be repeated all the way across, always filling the canvas (try img.width = 100 in my JsFiddle to see what I mean). In my function, since I based the period on a certain number of x-pixels, my xOffset recalculation is simplified and I can simply use modulus to calculate the new offset after subtracting from x.
Some style considerations I would like to suggest are:
Use more consistent variable names (such as context vs. ctx--if both are truly needed, give them prefixes such as baseContext, canvasContext so that context is consistent throughout the code).
Name variables closer to what they represent (for example, canvasX is not a good variable name for canvas.Width.
Don't be afraid of slightly longer variable names. imgW is less clear than imageWidth. W doesn't always mean width.
Put spaces after commas and the word function, and around operators.
Using parameter x in your sineY function is confusing as x is already declared outside.
Parameterizing your animation function is fine, but just as good is to wrap the entire script in a SEAF (self-executing anonymous function), as that properly gives all the variables a scope (keeping them out of global scope), thus simplifying your code by not having to pass around the variables.

Related

Procedural terrain generation with blocks

I am using three.js to create procedurally generated terrain using Perlin Noise.
I am creating the terrain using a series of blocks, but their heights along their borders are not corresponding to one another as you can see below.
How should I approach matching the height maps across blocks?
I'm using Perlin Noise Algorithm for generating heights; the problem is that the height of each point is indipendent from the heights of the near points. I've other noise algorithm, but i have the same problem..
There's a really good video on infinite terrain here: https://www.youtube.com/watch?v=IKB1hWWedMk
It's in processing, but the same concept can be applied to whichever noise library you're using - I'm going to assume that you're using Perlin noise. In which case, you need to look at the values you're passing into this function and change them based on how big your blocks are.
For example, imagine a 3x3 grid of blocks. If your middle block is (x, y), and each block is 10x10 units in size, if you move 'north' (for lack of a better term), you'd need to be getting (x, y - 10) from your noise function.
The video explains it way better than I can, but hopefully this has helped. Without more knowledge of the function you're using I can't really give a more detailed answer.
This answer will explain how to solve it for a single axis, x. It is then trivial to do the same for the y (z in three.js) axis.
The first step is to ensure the perlin noise is using the same random seed for each block. This will ensure that blocks share the same perlin noise map and so can transition smoothly between them.
The second part is to have a mapping between your block units and what is passed into the perlin noise function. For example your block x may be going from -512 to 512 units, so you get a height value for each x vertex by passing in -0.5 to 0.5 for each x vertex into the noise function.
E.g.
vertextHeight = perlin(vertexX / 1024, vertextY / 1024)
Your second block will then be offset so its edge interfaces with the first block. E.g. its x position will be +1024 more than the first block, and so will go from 512 to 1536.
So in this sense, block0 will have an x offset of 0, and block1 will have an x offset of 1024. 1024 being the block width/size in three.js units.
Finally, you need to give the same offsets to the noise function, but scaled based on the mapping described above. In this example, 512 would become 0.5 and 1536 would become 1.5 which looks like this:
size = 1024;
vertextHeight = perlin((vertexX + offsetX) / size, (vertextY + offsetY) / size)`
Therefore, the x value given to the noise function at the edge between block0 and block 1 will be the same, and so will return the same height value.

Distance between clusters in d3 multi foci force layout

I'm trying to understand this example of a multi-foci force layout...
http://bl.ocks.org/mbostock/1804919
It contains a "padding" variable (which defines the distance between nodes in each cluster), but I'm really struggling to see where the definition of the distances between clusters comes from - a combination of gravity and charge maybe?!
For example, if you wanted to double the distance between the clusters how could you achieve that? I've played with the customisable values in the example to no avail so would really appreciate any help from anyone. Thanks!
Setting m to a smaller value will increase the distance between clusters. This is the domain for the orginal scale x which is used to initialise the cx values on the elements of the nodes array.
Calling them cx and cy is a little bit confusing because they are not the cx and cy attributes of the circles.
The cx value for each node is is determined by feeding a random integer into the ordinal scale x By the statement cx: x(i).
The circles are moved toward the focii by calling gravity every tick (animation frame). This is done in the following statement...
d.x += (d.cx - d.x)*alpha
alpha is fixed at 0.5 in the tick function when calling gravity, but there is another alpha which could also be used. It's a variable maintained by the force object which is initially set to 0.1 before the first tick, and reduced by 1% every tick. It's passed to the tick function as e.alpha, so you could also try passing this value into the gravity function instead of a constant 0.5. The effect will be to cause the nodes to "cool down" more and more gradually until they stop.

JavaScript "pixel"-perfect collision detection for rotating sprites using math (probably linear algebra)

I'm making a 2D game in JavaScript. For it, I need to be able to "perfectly" check collision between two sprites which have x/y positions (corresponding to their centre), a rotation in radians, and of course known width/height.
After spending many weeks of work (yeah, I'm not even exaggerating), I finally came up with a working solution, which unfortunately turned out to be about 10,000x too slow and impossible to optimize in any meaningful manner. I have entirely abandoned the idea of actually drawing and reading pixels from a canvas. That's just not going to cut it, but please don't make me explain in detail why. This needs to be done with math and an "imaginated" 2D world/grid, and from talking to numerous people, the basic idea became obvious. However, the practical implementation is not. Here's what I do and want to do:
What I already have done
In the beginning of the program, each sprite is pixel-looked through in its default upright position and a 1-dimensional array is filled up with data corresponding to the alpha channel of the image: solid pixels get represented by a 1, and transparent ones by 0. See figure 3.
The idea behind that is that those 1s and 0s no longer represent "pixels", but "little math orbs positioned in perfect distances to each other", which can be rotated without "losing" or "adding" data, as happens with pixels if you rotate images in anything but 90 degrees at a time.
I naturally do the quick "bounding box" check first to see if I should bother calculating accurately. This is done. The problem is the fine/"for-sure" check...
What I cannot figure out
Now that I need to figure out whether the sprites collide for sure, I need to construct a math expression of some sort using "linear algebra" (which I do not know) to determine if these "rectangles of data points", positioned and rotated correctly, both have a "1" in an overlapping position.
Although the theory is very simple, the practical code needed to accomplish this is simply beyond my capabilities. I've stared at the code for many hours, asking numerous people (and had massive problems explaining my problem clearly) and really put in an effort. Now I finally want to give up. I would very, very much appreciate getting this done with. I can't even give up and "cheat" by using a library, because nothing I find even comes close to solving this problem from what I can tell. They are all impossible for me to understand, and seem to have entirely different assumptions/requirements in mind. Whatever I'm doing always seems to be some special case. It's annoying.
This is the pseudo code for the relevant part of the program:
function doThisAtTheStartOfTheProgram()
{
makeQuickVectorFromImageAlpha(sprite1);
makeQuickVectorFromImageAlpha(sprite2);
}
function detectCollision(sprite1, sprite2)
{
// This easy, outer check works. Please ignore it as it is unrelated to the problem.
if (bounding_box_match)
{
/*
This part is the entire problem.
I must do a math-based check to see if they really collide.
These are the relevant variables as I have named them:
sprite1.x
sprite1.y
sprite1.rotation // in radians
sprite1.width
sprite1.height
sprite1.diagonal // might not be needed, but is provided
sprite2.x
sprite2.y
sprite2.rotation // in radians
sprite2.width
sprite2.height
sprite2.diagonal // might not be needed, but is provided
sprite1.vectorForCollisionDetection
sprite2.vectorForCollisionDetection
Can you please help me construct the math expression, or the series of math expressions, needed to do this check?
To clarify, using the variables above, I need to check if the two sprites (which can rotate around their centre, have any position and any dimensions) are colliding. A collision happens when at least one "unit" (an imagined sphere) of BOTH sprites are on the same unit in our imaginated 2D world (starting from 0,0 in the top-left).
*/
if (accurate_check_goes_here)
return true;
}
return false;
}
In other words, "accurate_check_goes_here" is what I wonder what it should be. It doesn't need to be a single expression, of course, and I would very much prefer seeing it done in "steps" (with comments!) so that I have a chance of understanding it, but please don't see this as "spoon feeding". I fully admit I suck at math and this is beyond my capabilities. It's just a fact. I want to move on and work on the stuff I can actually solve on my own.
To clarify: the 1D arrays are 1D and not 2D due to performance. As it turns out, speed matters very much in JS World.
Although this is a non-profit project, entirely made for private satisfaction, I just don't have the time and energy to order and sit down with some math book and learn about that from the ground up. I take no pride in lacking the math skills which would help me a lot, but at this point, I need to get this game done or I'll go crazy. This particular problem has prevented me from getting any other work done for far too long.
I hope I have explained the problem well. However, one of the most frustrating feelings is when people send well-meaning replies that unfortunately show that the person helping has not read the question. I'm not pre-insulting you all -- I just wish that won't happen this time! Sorry if my description is poor. I really tried my best to be perfectly clear.
Okay, so I need "reputation" to be able to post the illustrations I spent time to create to illustrate my problem. So instead I link to them:
Illustrations
(censored by Stackoverflow)
(censored by Stackoverflow)
OK. This site won't let me even link to the images. Only one. Then I'll pick the most important one, but it would've helped a lot if I could link to the others...
First you need to understand that detecting such collisions cannot be done with a single/simple equation. Because the shapes of the sprites matter and these are described by an array of Width x Height = Area bits. So the worst-case complexity of the algorithm must be at least O(Area).
Here is how I would do it:
Represent the sprites in two ways:
1) a bitmap indicating where pixels are opaque,
2) a list of the coordinates of the opaque pixels. [Optional, for speedup, in case of hollow sprites.]
Choose the sprite with the shortest pixel list. Find the rigid transform (translation + rotation) that transforms the local coordinates of this sprite into the local coordinates of the other sprite (this is where linear algebra comes into play - the rotation is the difference of the angles, the translation is the vector between upper-left corners - see http://planning.cs.uiuc.edu/node99.html).
Now scan the opaque pixel list, transforming the local coordinates of the pixels to the local coordinates of the other sprite. Check if you fall on an opaque pixel by looking up the bitmap representation.
This takes at worst O(Opaque Area) coordinate transforms + pixel tests, which is optimal.
If you sprites are zoomed-in (big pixels), as a first approximation you can ignore the zooming. If you need more accuracy, you can think of sampling a few points per pixel. Exact computation will involve a square/square collision intersection algorithm (with rotation), more complex and costly. See http://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm.
Here is an exact solution that will work regardless the size of the pixels (zoomed or not).
Use both a bitmap representation (1 opacity bit per pixel) and a decomposition into squares or rectangles (rectangles are optional, just an optimization; single pixels are ok).
Process all rectangles of the (source) sprite in turn. By means of rotation/translation, map the rectangles to the coordinate space of the other sprite (target). You will obtain a rotated rectangle overlaid on a grid of pixels.
Now you will perform a filling of this rectangle with a scanline algorithm: first split the rectangle in three (two triangles and one parallelogram), using horizontal lines through the rectangle vertexes. For the three shapes independently, find all horizontal between-pixel lines that cross them (this is simply done by looking at the ranges of Y values). For every such horizontal line, compute the two intersections points. Then find all pixel corners that fall between the two intersections (range of X values). For any pixel having a corner inside the rectangle, lookup the corresponding bit in the (target) sprite bitmap.
No too difficult to program, no complicated data structure. The computational effort is roughly proportional to the number of target pixels covered by every source rectangle.
Although you have already stated that you don't feel rendering to the canvas and checking that data is a viable solution, I'd like to present an idea which may or may not have already occurred to you and which ought to be reasonably efficient.
This solution relies on the fact that rendering any pixel to the canvas with half-opacity twice will result in a pixel of full opacity. The steps follow:
Size the test canvas so that both sprites will fit on it (this will also clear the canvas, so you don't have to create a new element each time you need to test for collision).
Transform the sprite data such that any pixel that has any opacity or color is set to be black at 50% opacity.
Render the sprites at the appropriate distance and relative position to one another.
Loop through the resulting canvas data. If any pixels have an opacity of 100%, then a collision has been detected. Return true.
Else, return false.
Wash, rinse, repeat.
This method should run reasonably fast. Now, for optimization--the bottleneck here will likely be the final opacity check (although rendering the images to the canvas could be slow, as might be clearing/resizing it):
reduce the resolution of the opacity detection in the final step, by changing the increment in your loop through the pixels of the final data.
Loop from middle up and down, rather than from the top to bottom (and return as soon as you find any single collision). This way you have a higher chance of encountering any collisions earlier in the loop, thus reducing its length.
I don't know what your limitations are and why you can't render to canvas, since you have declined to comment on that, but hopefully this method will be of some use to you. If it isn't, perhaps it might come in handy to future users.
Please see if the following idea works for you. Here I create a linear array of points corresponding to pixels set in each of the two sprites. I then rotate/translate these points, to give me two sets of coordinates for individual pixels. Finally, I check the pixels against each other to see if any pair are within a distance of 1 - which is "collision".
You can obviously add some segmentation of your sprite (only test "boundary pixels"), test for bounding boxes, and do other things to speed this up - but it's actually pretty fast (once you take all the console.log() statements out that are just there to confirm things are behaving…). Note that I test for dx - if that is too large, there is no need to compute the entire distance. Also, I don't need the square root for knowing whether the distance is less than 1.
I am not sure whether the use of new array() inside the pixLocs function will cause a problem with memory leaks. Something to look at if you run this function 30 times per second...
<html>
<script type="text/javascript">
var s1 = {
'pix': new Array(0,0,1,1,0,0,1,0,0,1,1,0),
'x': 1,
'y': 2,
'width': 4,
'height': 3,
'rotation': 45};
var s2 = {
'pix': new Array(1,0,1,0,1,0,1,0,1,0,1,0),
'x': 0,
'y': 1,
'width': 4,
'height': 3,
'rotation': 90};
pixLocs(s1);
console.log("now rotating the second sprite...");
pixLocs(s2);
console.log("collision detector says " + collision(s1, s2));
function pixLocs(s) {
var i;
var x, y;
var l1, l2;
var ca, sa;
var pi;
s.locx = new Array();
s.locy = new Array();
pi = Math.acos(0.0) * 2;
var l = new Array();
ca = Math.cos(s.rotation * pi / 180.0);
sa = Math.sin(s.rotation * pi / 180.0);
i = 0;
for(x = 0; x < s.width; ++x) {
for(y = 0; y < s.height; ++y) {
// offset to center of sprite
if(s.pix[i++]==1) {
l1 = x - (s.width - 1) * 0.5;
l2 = y - (s.height - 1) * 0.5;
// rotate:
r1 = ca * l1 - sa * l2;
r2 = sa * l1 + ca * l2;
// add position:
p1 = r1 + s.x;
p2 = r2 + s.y;
console.log("rotated pixel [ " + x + "," + y + " ] is at ( " + p1 + "," + p2 + " ) " );
s.locx.push(p1);
s.locy.push(p2);
}
else console.log("no pixel at [" + x + "," + y + "]");
}
}
}
function collision(s1, s2) {
var i, j;
var dx, dy;
for (i = 0; i < s1.locx.length; i++) {
for (j = 0; j < s2.locx.length; j++) {
dx = Math.abs(s1.locx[i] - s2.locx[j]);
if(dx < 1) {
dy = Math.abs(s1.locy[i] - s2.locy[j]);
if (dx*dx + dy+dy < 1) return 1;
}
}
}
return 0;
}
</script>
</html>

Maths and Easing For Javascript/Canvas Preload Animation

I'm building an image preload animation, that is a circle/pie that gets drawn. Each 'slice' is totalImages / imagesLoaded. So if there are four images and 2 have loaded, it should draw to 180 over time.
I'm using requestAnimFrame, which is working great, and I've got a deltaTime setup to restrict animation to time, however I'm having trouble getting my head around the maths. The closest I can get is that it animates and eases to near where it's supposed to be, but then the value increments become smaller and smaller. Essentially it will never reach the completed value. (90 degrees, if one image has loaded, as an example).
var totalImages = 4;
var imagesLoaded = 1;
var currentArc = 0;
function drawPie(){
var newArc = 360 / totalImages * this.imagesLoaded // Get the value in degrees that we should animate to
var percentage = (isNaN(currentArc / newArc) || !isFinite(currentArc / newArc)) || (currentArc / newArc) > 1 ? 1 : (currentArc / newArc); // Dividing these two numbers sometimes returned NaN or Infinity/-Infinity, so this is a fallback
var easeValue = easeInOutExpo(percentage, 0, newArc, 1);
//This animates continuously (Obviously), because it's just constantly adding to itself:
currentArc += easedValue * this.time.delta;
OR
//This never reaches the full amount, as increments get infinitely smaller
currentArc += (newArc - easedValue) * this.time.delta;
}
function easeInOutExpo(t, b, c, d){
return c*((t=t/d-1)*t*t + 1) + b;
}
I feel like I've got all the right elements and values. I'm just putting them together incorrectly.
Any and all help appreciated.
You've got the idea of easing. The reality is that at some point you cap the value.
If you're up for a little learning, you can brush up on Zeno's paradoxes (the appropriate one here being Achilles and the Tortoise) -- it's really short... The Dichotomy Paradox is the other side of the same coin.
Basically, you're only ever half-way there, regardless of where "here" or "there" may be, and thus you can never take a "final"-step.
And when dealing with fractions, such as with easing, that's very true. You can always get smaller.
So the solution is just to clamp it. Set a minimum amount that you can move in an update (2px or 1px, or 0.5px... or play around).
The alternative (which ends up being similar, but perhaps a bit jumpier), is to set a threshold distance. To say "As soon as it's within 4px of home, snap to the end", or switch to a linear model, rather than continuing the easing.

Calculate overlap of two colliding objects?

UPDATE: I found this enormously helpful article explaining canvas per-pixel collision detection.
I'm working on a collision system for a javascript game using HTML5 canvas. Each object has an image as a sprite and when a non-transparent pixel of any one object overlaps another, the collision code is triggered. But before anything else the objects need to be moved so that they are just touching each other and no longer triggering a collision. I need help calculating the overlap of any two objects in terms of x and y in order to move one accordingly. Here's what we know:
The coordinates of the collision point relative to each object
The positions of the objects (and therefore the distance between them)
The width and height of the objects
The velocity of the objects in the x and y directions (a vector)
Another note: the images for these objects are uneven shapes, no perfect circles, but the radius from the center to the collision point can be calculated.
EDIT: I haven't seen a lot of response, so I'll be more specific. In the image below, two objects are colliding. The overlap area is in red. How would you go about finding the lengths of the green lines?
I'm honestly clueless about HTML 5 and how you can make games in pure HTML 5. But you would also need to know a velocity (IE, their direction. This way you can send them backwards from where they came)
If it was in a standard programming language, one method would be to use a while loop (moving the sprite back until the collision == false). Another method would be a more complicated calculation of how far the intersection is and subtract individual x and y values so they are not collided.
EDIT:
Then the easiest way is like I said, to put the object thats moving in a while loop that moves it backwards 1 pixel in each axis until its collision tests false. Example:
int x1 = 500; //x location on screen
int y2 = 500; //y location
public boolean fixOffSetX(Sprite s) {
int x2 = s.getX();
int y2 = s.getY();
//not writing the whole thing
//enter a while loop until its not colliding anymore
while(collision is still true) {
x--; or x++;
//depending on direction
//(which is why you need to know velocity/direction of your sprites)
//do the same for the Y axis.
}
}
//This method will return if the 2 sprites collided, you do this one
public boolean collisionTest(Sprite s1, Sprite s2) {}
You should look at doing very basic collisions, since it is a VERY complicated part of programming
If this is still an issue, I've found information about the subject in an e-book called Foundation Game Design with HTML5 en Javascript. Here: link to relevant pages. Hope this helps anyone in the future.

Categories