fixing height issues in isometric perlin noise - javascript

I've been using perlin noise to generate tile based, isometric landscapes. So far I've been using the noise value as a height map for the tiles themselves: Math.floor(noise * 10), basically. This generates perfectly nice looking but linear maps. However, I found the "mountains" rather boring looking so I applied an exponent: Math.floor(Math.pow((noise / 4), 2.3)). This pushes the higher values up, producing the image attached.
These height values are the are stored in a 2d grid, giving me the x, y and z i need to draw the map to the screen.
The drawback is kind of obvious: there are gaps in my mountain that should be filled up. I'm just not sure where to start since that is information that I can no longer store in a 2d grid. I guess I can cheat using "longer" tiles but that is kind of lame. Any suggestions?
If you need more info I'm happy to explain. Maybe I'm barking up the wrong tree.

Before you draw the first tile far in the back have a look to the two neighboring tiles on the left and right that are closer to the viewer. Get the lowest height of them and check if this height is lower than your back-tile minus one height. (Because this would cause a gap). Now you can start to draw on the pile in the back starting with this "low height" and stack tiles on it until you reach the height you want. Then you can draw the next tile that is closer to the viewer using the same algorithm.
Edit: But I am just wondering if it would maybe look a but awkward with so many stacked tiles. Maybe it better to just stretch the soil layer until the "low height".

Related

JavaScript canvas game development

Ive been having a really baffling slow down issue with the game I am working on probably because I am unsure how to handle graphics (most likely responsible for the slow down) in javascript without using a third party framework like Phaser/ImapactJS/EaselJS etc)*. The following is the low down on how I am approaching my graphics. I would be very thankful for some tips or methods on how to do this right.
My game is tile based - using tiles designed at 500x500 px because I want them to display decently on high definition devices.
I am using a spritesheet to load all (most of) my tiles before the main loop is run. This image is roughly 4000 x 4000 (keeping it below 4096 because the GPU cant handle texture sizes larger than that).
I then use the drawImage function to cycle through and draw each tile on a part of the canvas using information (w, h, x, y) stored in the tile array. I do this on every cycle of the main loop using my drawMap function.
The map is currently 6x6 tiles in size
A character spritesheet is also loaded and drawn on to the canvas after the map has been drawn. The character displays a different frame of the animation on every cycle of the main loop. There are sets of animations for the character each contained in the same spritesheet.
The character sprite sheet is roughly 4000x3500
The character is roughly 350x250 px
Other objects also use the same sprite sheet. Currently there is only one object.
Possibly helpful questions:
Am I using too many spritesheets or too few?
Should I only draw something if it's coordinates are in bounds of the screen?
How should I go about garbage collection? Do I need to set image objects to null when no longer in use?
Thanks in advance for input. I would just like to know if I am going about it the right way and pick your brains as how to speed it up enough.
*Note that I plan to port the JS game to cocoonJS which provides graphics acceleration for the canvas element on mobile.
** If interested please visit my Patreon page for fun!
You have asked lots of questions here, I'll address the ones I've run into.
I would like to start out by saying very clearly,
Use a profiler
Find out whether each thing you are advised to do, by anybody, is making an improvement. Unless we work on your code, we can only give you theories on how to optimise it.
How should I go about garbage collection? Do I need to set image objects to null when no longer in use?
If you are no longer using an object, setting its reference to null will probably mean it gets garbage collected. Having nulls around is not necessarily good but this is not within the scope of this question.
For high performance applications, you want to avoid too much allocation and therefore too much garbage collection activity. See what your profiler says - the chrome profiler can tell you how much CPU time the garbage collector is taking up. You might be OK at the moment.
I then use the drawImage function to cycle through and draw each tile on a part of the canvas using information (w, h, x, y) stored in the tile array. I do this on every cycle of the main loop using my drawMap function.
This is quite slow - instead consider drawing the current on screen tiles to a background canvas, and then only drawing areas which were previously obscured.
For example, if your player walks to the left, there is going to be a lot of tiles on the left hand side of the screen which have come into view; you will need to draw the background buffer onto the screen, offset to account for the movement, and then draw the missing tiles.
My game is tile based - using tiles designed at 500x500 px because I want them to display decently on high definition devices
If I interpret this right, your tiles are 500x500px in diameter, and you are drawing a small number of these on screen. and then for devices without such a high resolution, the canvas renderer is going to be scaling these down. You really want to be drawing pixels 1:1 on each device.
Would you be able, instead, to have a larger number of smaller tiles on screen - thereby avoiding the extra drawing at the edges? Its likely that the tiles around the edges will sometimes draw only a few pixels of one edge, and the rest of the image will be cropped anyway, so why not break them up further?
Should I only draw something if it's coordinates are in bounds of the screen?
Yes, this is a very common and good optimisation to take. You'll find it makes a big difference.
Am I using too many spritesheets or too few?
I have found that when I have a small number of sprite sheets, the big performance hit is when I frequently switch between them. If during one draw phase, you draw all your characters from character_sheet.png and then draw all the plants from plant_sheet.png you'll be ok. Switching between them can cause lots of trouble and you'll see a slow down. You will know this is happening if your profiler tells you that drawImage is taking a big proportion of your frame.

Position resizable circles near each other

I am working on this browser-based experiment where i am given N specific circles (let's say they have a unique picture in them) and need to position them together, leaving as little space between them as possible. It doesn't have to be arranged in a circle, but they should be "clustered" together.
The circle sizes are customizable and a user will be able to change the sizes by dragging a javascript slider, changing some circles' sizes (for example, in 10% of the slider the circle 4 will have radius of 20px, circle 2 10px, circle 5 stays the same, etc...). As you may have already guessed, i will try to "transition" the resizing-repositioning smoothly when the slider is being moved.
The approach i have tried tried so far: instead of manually trying to position them i've tried to use a physics engine-
The idea:
place some kind of gravitational pull in the center of the screen
use a physics engine to take care of the balls collision
during the "drag the time" slider event i would just set different
ball sizes and let the engine take care of the rest
For this task i have used "box2Dweb". i placed a gravitational pull to the center of the screen, however, it took a really long time until the balls were placed in the center and they floated around. Then i put a small static piece of ball in the center so they would hit it and then stop. It looked like this:
The results were a bit better, but the circles still moved for some time before they went static. Even after playing around with variables like the ball friction and different gravitational pulls, the whole thing just floated around and felt very "wobbly", while i wanted the balls move only when i drag the time slider (when they change sizes). Plus, box2d doesn't allow to change the sizes of the objects and i would have to hack my way for a workaround.
So, the box2d approach made me realize that maybe to leave a physics engine to handle this isn't the best solution for the problem. Or maybe i have to include some other force i haven't thought of. I have found this similar question to mine on StackOverflow. However, the very important difference is that it just generates some n unspecific circles "at once" and doesn't allow for additional specific ball size and position manipulation.
I am really stuck now, does anyone have any ideas how to approach this problem?
update: it's been almost a year now and i totally forgot about this thread. what i did in the end is to stick to the physics model and reset forces/stop in almost idle conditions. the result can be seen here http://stateofwealth.net/
the triangles you see are inside those circles. the remaining lines are connected via "delaunay triangulation algorithm"
I recall seeing a d3.js demo that is very similar to what you're describing. It's written by Mike Bostock himself: http://bl.ocks.org/mbostock/1747543
It uses quadtrees for fast collision detection and uses a force based graph, which are both d3.js utilities.
In the tick function, you should be able to add a .attr("r", function(d) { return d.radius; }) which will update the radius each tick for when you change the nodes data. Just for starters you can set it to return random and the circles should jitter around like crazy.
(Not a comment because it wouldn't fit)
I'm impressed that you've brought in Box2D to help with the heavy-lifting, but it's true that unfortunately it is probably not well-suited to your requirements, as Box2D is at its best when you are after simulating rigid objects and their collision dynamics.
I think if you really consider what it is that you need, it isn't quite so much a rigid body dynamics problem at all. You actually want none of the complexity of box2d as all of your geometry consists of spheres (which I assure you are vastly simpler to model than arbitrary convex polygons, which is what IMO Box2D's complexity arises from), and like you mention, Box2D's inability to smoothly change the geometric parameters isn't helping as it will bog down the browser with unnecessary geometry allocations and deallocations and fail to apply any sort of smooth animation.
What you are probably looking for is an algorithm or method to evolve the positions of a set of coordinates (each with a radius that is also potentially changing) so that they stay separated by their radii and also minimize their distance to the center position. If this has to be smooth, you can't just apply the minimal solution every time, as you may get "warping" as the optimal configuration might shift dramatically at particular points along your slider's movement. Suffice it to say there is a lot of tweaking for you to do, but not really anything scarier than what one must contend with inside of Box2D.
How important is it that your circles do not overlap? I think you should just do a simple iterative "solver" that first tries to bring the circles toward their target (center of screen?), and then tries to separate them based on radii.
I believe if you try to come up with a simplified mathematical model for the motion that you want, it will be better than trying to get Box2D to do it. Box2D is magical, but it's only good at what it's good at.
At least for me, seems like the easiest solution is to first set up the circles in a cluster. So first set the largest circle in the center, put the second circle next to the first one. For the third one you can just put it next to the first circle, and then move it along the edge until it hits the second circle.
All the other circles can follow the same method: place it next to an arbitrary circle, and move it along the edge until it is touching, but not intersecting, another circle. Note that this won't make it the most efficient clustering, but it works. After that, when you expand, say, circle 1, you'd move all the adjacent circles outward, and shift them around to re-cluster.

OpenLayers as a large (changing and growing) image viewer

Basically, what I'm trying to do is use a map viewer as an image viewer with the same sort of efficient tile-loading, zoom/pan awesomeness without having to build it myself.
Specifically, I need an image viewer that will allow the image to grow and change while not altering the coordinates of any older (unchanged) tiles. This means that the center point (0,0), where the image started growing from, must always remain (0,0). So I'm looking for a library that will allow me to use a very basic Cartesian coordinate system (no map projection!), which will ask for tiles infinitely in all directions with no repetition (as opposed to how map libraries just ignore y-axis above and below the map, but the x axis repeats).
There's another catch. I need zoom level 0 to be zoomed in all the way. Since the image is constantly growing, there's no way to tell what the max zoom level will be, and the coordinates need to be based on the base image layer tiles so that every tile in zoom level z contains 2^z base layer tiles.
I am wondering if this is possible with OpenLayers and how to do it. If it's not, any suggestions of other (open-source javascript) libraries that can do this would be very appreciated! I've tried playing around with Polymaps, but the documentation is lacking too much for me to be able to tell if it will work. So far no luck.
Please let me know if none of this made sense, and I'll try to include some images or better explanations. Thanks!
I ended up using Polymaps after all, since I like it more than OpenLayers, because it's faster and has much smoother scrolling and panning. I wasn't able to do exactly what I wanted, but what I did was close enough.
I ended up writing my own layer (based on the po.image() layer), which disabled infinite horizontal looping of the map. I then wrote my own version of po.url() that modified the requests going to the server for tiles so that zooming was reversed (I just arbitrarily picked a 'max' zoom of 20, then when making a request subtract the zoom level from 20) and the x and y coordinates were converted to cartesian coordinates from the standard row, column coordinates Polymaps uses, based on the zoom level and the map centered at (0,0).
If anyone is interested in the code I can post it here. Let me know!
EDIT: I've posted the code on github at https://github.com/camupod/polymaps
The relevant files are src/Backwards* and examples/backwards (though it actually doesn't work, you might be able to clean some information about how it should work).

How can I (somewhat) evenly distribute dynamically-sized SVG shapes within a canvas?

I'm looking for some high-level recommendations for how to implement a project I'm starting for a client.
This is a web page that will include an SVG canvas (sized 920px W x 450px H) containing 20-40 "circular" images (i.e., they may just be square images cropped with a circle). The size of the images will probably range from about 50px to about 200px diameter, each one set dynamically within that range based on data from an API. It's basically a dynamic data visualization, so pretty much every aspect of this needs to be configurable/dynamic.
I think the hardest problem to solve is how to distribute these images within the given canvas area, considering that they will vary in size, and should appear to be evenly/randomly distributed (i.e., they shouldn't line up to a grid, be clumped together, or be in groups of similar sizes). It's OK if they overlap slightly. Here's a quick sketch of how this should look, ideally (each gray circle represents an image):
https://skitch.com/troywarr/gwj14/adobe-fireworks-cs5
FWIW, I was planning to use Raphaƫl as an SVG library; I'll also have jQuery available and can probably use any other libraries as needed. This needs to be cross-browser compatible back to IE7.
Can anyone suggest a general approach to this problem, any specific libraries or algorithms to look into, or provide any other guidance or suggestions? Please let me know if this description isn't clear, or if you need any additional details.
Thanks in advance!
Here is how I would tackle it:
First decide on the percentage of the screen that will be filled in with circles and the number of circles that will be displayed. You can use that to determine the average radius of each circle using the area of a circle formula - e.g. given x circles what would the average radius of all the circles have to be to cover y% of my container. You can then decide how much you want the radius to vary, that is +/- 50%. Unless the number of circles is very small you should get a good result - statistically that is.
Then I would divide the screen in to a rectangular grid - I know that is not what you want just be patient :) The dimensions of the grid are calculable from the number of circles, e.g. 16 circles would fit nicely into a 4 X 4 grid. The number of circles can be less than the number of cells but not a lot less.
I would then select a random x,y co-ordinate inside each grid cell as my circle's center. I would also leave a padding of about 25% around the edges so that my circle is not centered too close to an edge.
You could then check for overlap - the ratio of (r1 + r2) / distance between the circle center points will equal 1 if the circles touch, be less than 1 if they don't and greater than 1 if they overlap. A ratio of 1.1 is a small overlap; careful of the limit here - exact same centers result in a distance of 0 and a division by 0 error.
One thing to worry about but should not happen unless you pick a very high initial coverage percentage or the number if circles is much smaller than the number of cells. If all the cells adjacent to a given cell have circles close to that cells edges, especially if they overlap the edge, there may not be enough room (even with circle overlap) for the current cell's circle. This can be checked for and handled by shrinking the radius or moving a circle away...
NOTE if the number of desired circle's does not exactly match your square (or rectangular) grid, just randomly leave some cells empty...
Here's a rough description of the approach I took after all. Sorry, pressed for time so this may be inexact.
I initially approached the problem similarly to #BigMac66's answer. I laid out a grid corresponding to the quantity of circles I had, drew a circle in each and then randomly shifted the circles from the center point of each grid cell.
I built in a variety of "fudge factors" - circle radius bounds, offset from center, maximum overlap with adjacent cells, etc. - but, no matter how I tweaked my settings, you could still always tell that a grid was behind the layout; the circles aligned just enough to look like a wonky polka dot pattern rather than a truly random collection of circles.
So, I changed to a more brute-force approach.
First, I set up configurable bounds for the radius of a circle, tweaking the upper bound until I found a maximum size that didn't make the canvas look crowded based on the total number of circles I had.
Then, I applied my math to size the circles as needed (in short, the largest circles represented a 100% value, and the smallest represented a 0% value; the rest were sized accordingly based on where they fell in the spectrum).
Then, I sorted the circles descending by size. I laid them out randomly on the canvas, using an algorithm roughly like so:
Place a circle at random coordinates.
Place the next circle at random coordinates.
If the latter circle overlaps the former by more than X pixels (configurable param), place it at a new set of random coordinates.
Continue step #3 for up to Y times (another configurable param) until you successfully place another circle.
If you can't place the circle in Y times, clear the canvas, drop the maximum circle radius by Z pixels (another configurable param) and start over.
This worked surprisingly well, and I tweaked the params until I could draw the entire canvas very quickly while requiring few maximum circle radius reductions.
You can actually see the finished product here:
http://www.eonline.com/news/2012_sag_awards/heatgauge
It's out of season, so click the "Overall View" tab at the top of the main box to see cumulative stats (and hence a full canvas of circles).

Webkit 3D CSS. Rotate camera like in a First Person Shooter

What I want to achieve is a camera rotation like http://www.keithclark.co.uk/labs/3dcss/demo/ . It's not perfect and sometimes the camera breaks, but that's the idea.
I like the rotation to be similar like a human view, but I only managed to obtain a rotation across a certain point. This is an example of what I obtained http://jsfiddle.net/gaAXk/3/.
As i said before, i would like a human like behaviour.
I also tried with -webkit-transform-origin but with no better result.
Any help/suggestion will be highly appreciated.
The problem here is the following:
To give a human-like behavior, when the point of view moves, you should calculate the new positions on the x/y/z axis for the objects (not just the rotation angle in case of a rotation, for instance).
CSS transform should work in the follwing way, we give a perspective, for example of 800px to a scene. Then the objects will be visible with a Z position up to 800px, if the Z position is, for example 1000px, it will be behind our point of view, so we won't be able to see the element.
That said, after a rotation you should calculate the new position for the items based on our new point of view.
To be clearer I've updated your example with much simpler code (it only supports rotation and there's just one image): http://jsfiddle.net/gaAXk/12/
The perspective in the example is 800px.
The image is initially placed at x=0px, y=0px, z=0px. So it will be visible in front of us at a "distance" of 800px.
When we rotate the point of view, the element should move along a circumference around the point of view, so the x,z positions and the rotation angle of the element, needs to be updated.
The element in the example moves along a circumference with 800px radius (the calculatePos() function does the trick).
The same calculation should be updated if we change position (if the point of view gets closer to some objects, and further from others).
This isn't so trivial. If anyone has better solutions (I'm not a 3D expert), I will be glad to hear some.

Categories

Resources