Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 ... 411 412 [413] 414 415 ... 796

Author Topic: if self.isCoder(): post() #Programming Thread  (Read 883031 times)

cerapa

  • Bay Watcher
  • It wont bite....unless you are the sun.
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #6180 on: August 21, 2014, 03:56:11 pm »

The region idea wouldn't work. You would have to generate the entire infinite world, or generate the world in chunks, leaving the regions at the edges with hard and highly visible borders.

You can use Voronoi diagrams in an infinite field though, but it's gonna be a bit strange.

Basically you have a larger area. Say 10x10 tiles or whatever, and then by using whatever method you want(RNG seeded with Location+World_Seed?) you generate 1 or more Voronoi points in this area. When you want to generate a tile, you check the Voronoi points of the area it is in and every surrounding one(generated as needed). Should work, I'm actually kinda tempted to make a prototype of it.

It wouldn't look very much like the world in MoM you showed though. Voronoi diagrams are very...round and sharp at the same time. Basically the most unnatural looking way to generate terrain, and that's taking into account those things that have absolutely terrible directional artifacting.

Personally I advocate for perlin noise for terrain generation, and using whatever variables you want for biome generation.

EDIT:

Oh, and cities with roads and stuff. If you wanna do those, you gotta generate a whole chunk of terrain and then place the city onto it and do whatever you do with the roads and stuff. You can't do that crap on a tile-by-tile basis.
« Last Edit: August 21, 2014, 03:58:33 pm by cerapa »
Logged

Tick, tick, tick the time goes by,
tick, tick, tick the clock blows up.

Sergius

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #6181 on: August 21, 2014, 05:00:23 pm »

I'm down for Perlin if I can get that result. Yes, I was planning on having the program generate some sort of island/continent/country unit all at once instead of tile by tile somehow, then procedurally plant the towns/roads.

Do you happen to know how Minecraft generates rivers tho? If it's tile-by-tile it could be use for roads and then towns could be a result of roads, instead of the other way around.
Logged

alway

  • Bay Watcher
  • 🏳️‍⚧️
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #6182 on: August 21, 2014, 10:26:24 pm »

Right, so this is sorta my specialty (and I just got my infinite fractal perlin working in opencl-d3d interop lately too). So first of all, you can do all that stuff procedurally without pre-loading big globs of it. You just need to be sneaky about it. First of all, you're going to want to take a peak at some articles over here: http://www.iquilezles.org/www/index.htm
Inigo Quilez; a Pixar guy who does tons of noise related stuff both there and on Shadertoy.

Up next, you really need to understand the noise, why it works, how it works, and how to shape it to your will. So let's begin...
1. Noise function: At the heart of things is the basic noise function. It essentially works the same way a hash function should: it needs to be as fast as possible and give a desired distribution (usually uniform, but you may want other distributions depending on use). These should also be generally scale-invariant, and look close to the same no matter your sample size.

2. Gradient noise function: Basic perlin, Simplex noises fall under these categories. Essentially, these work by sampling points from a basic noise function, then using an interpolation curve to get a smooth gradient between points, rather than a random distribution. Essentially, these have a fixed (or at least known) 'scale' to them, and should look different when you zoom in or out.

3. Fractal noise function: in general, these are your gradient noise functions added together, often in 'octaves' in which magnitude decreases as frequency increases, giving a sort of natural terrain look to things (wide, big bumps like hills, thin, small bumps like ditches, etc). These do not need to be of a fixed frequency (the iq blog linked above details some neat uses of varying the variations) nor do they need to be applied exclusively to gradient noise.
Fractal cellular noise: https://www.shadertoy.com/view/4dSGWc
Simple procedural generator using a looping fractal perlin: https://www.shadertoy.com/view/MdSGWK
Fractal perlin modified with a second fractal perlin to create a lightning-like effect which blends smoothly into fractal perlin: https://www.shadertoy.com/view/Msj3Rm
Fractal cellular noise interpreted to look like craters: https://www.shadertoy.com/view/4dXGWf (side note: KSP uses this method in their procedural crater generation)


4. Cellular noise function: Cellular noise essentially looks like a Voronoi diagram, cells, or what have you. The basic idea behind it is that you have a bunch of 'cells' with some sort of more or less smooth boundary region between them. In general, these are very much related to gradient noise, in that both are based on sampling on a grid (as IQ demonstrates here: http://www.iquilezles.org/www/articles/voronoise/voronoise.htm). There's some differences in regards to weighting the grid cells, ect; but overall the idea is similar.
Custom cellular noise meant to look like shrinking tiles along a border region:
https://www.shadertoy.com/view/4s2GDt

But in any case; hit up the Shadertoy website for ideas of what you can do with noise. Because, again, you can do just about anything with noise given you're willing to be clever enough.
« Last Edit: August 21, 2014, 10:52:49 pm by alway »
Logged

cerapa

  • Bay Watcher
  • It wont bite....unless you are the sun.
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #6183 on: August 22, 2014, 08:59:49 am »

Right, so this is sorta my specialty (and I just got my infinite fractal perlin working in opencl-d3d interop lately too). So first of all, you can do all that stuff procedurally without pre-loading big globs of it. You just need to be sneaky about it. First of all, you're going to want to take a peak at some articles over here: http://www.iquilezles.org/www/index.htm
Inigo Quilez; a Pixar guy who does tons of noise related stuff both there and on Shadertoy.

Dem variable names.

Seriously, I have no idea what i'm looking at. All I see is an alphabet.

EDIT:
Spoiler: Wtf (click to show/hide)
I think I did something wrong while trying to understand what's going on. I'm fairly certain I am now capable of translating what most of the letters of the alphabet mean(in the voronoi function), but I suppose I reversed a couple of minus signs or something.
« Last Edit: August 22, 2014, 09:29:46 am by cerapa »
Logged

Tick, tick, tick the time goes by,
tick, tick, tick the clock blows up.

alexandertnt

  • Bay Watcher
  • (map 'list (lambda (post) (+ post awesome)) posts)
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #6184 on: August 22, 2014, 09:49:36 am »

This shadertoy website does an absolutely splendid job of crashing my laptops video card drivers and black-screening my phone (while making it get very hot) :-\
Logged
This is when I imagine the hilarity which may happen if certain things are glichy. Such as targeting your own body parts to eat.

You eat your own head
YOU HAVE BEEN STRUCK DOWN!

alway

  • Bay Watcher
  • 🏳️‍⚧️
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #6185 on: August 22, 2014, 12:49:21 pm »

Right, so this is sorta my specialty (and I just got my infinite fractal perlin working in opencl-d3d interop lately too). So first of all, you can do all that stuff procedurally without pre-loading big globs of it. You just need to be sneaky about it. First of all, you're going to want to take a peak at some articles over here: http://www.iquilezles.org/www/index.htm
Inigo Quilez; a Pixar guy who does tons of noise related stuff both there and on Shadertoy.

Dem variable names.

Seriously, I have no idea what i'm looking at. All I see is an alphabet.

EDIT:
Spoiler: Wtf (click to show/hide)
I think I did something wrong while trying to understand what's going on. I'm fairly certain I am now capable of translating what most of the letters of the alphabet mean(in the voronoi function), but I suppose I reversed a couple of minus signs or something.
So looking at that image, what you're seeing there is the underlying grid. So a bit more on the specifics of why there is a grid at all and what that means for both gradient and worley noise (worley noise is the actual name of the cellular noise there). Essentially, these algorithms work on a 'pull' basis, rather than a 'push' basis. You specify some position and get out some value, as opposed to running some equation and getting an output with a position attached. In order for this to be coherent spatially (unlike basic, random noise), you need a method of 'pulling' which gives neighboring points data which is related. Sort of a search problem; though more explicitly in cellular noise than gradient noise.

Given some arbitrary point P, you need to find the set of noise samples which will have an effect on the final outcome. For gradient noise, all noise samples will typically be on a regular grid, and all positioned equally along the grid with no offsets and equal weight given to each point. As such, you can pretty easily find all necessary samples by calculating which grid cell your point P is in. For cellular noise, these constraints are loosened. Your samples have an arbitrary weight and an arbitrary offset; thus it can become an intractably hard problem to figure out which samples have an effect on your output at point P. Luckily, in techniques like Worley noise, these constraints are only loosened, and not removed altogether. The samples are given 'wiggle room' in which they can move up to some offset and some weight scale, but no more. For the 2D case, if you can offset your samples no more than .5 regular grid units in distance, you can find your nearest sample point by sampling a 3x3 grid around you (as opposed to the 2x2 grid of perlin and related gradient noises). By constraining it further, as shown here: http://briansharpe.wordpress.com/2011/12/01/optimized-artifact-free-gpu-cellular-noise/ that can even be reduced down to a 2x2 grid. Essentially a 'wiggle room' vs 'computational cost' tradeoff.

Or in short, what you're seeing in that image is the result of increasing the limits to the 'wiggle room' beyond what the grid can accurately sample without taking into account more points; or something related to that.
Logged

cerapa

  • Bay Watcher
  • It wont bite....unless you are the sun.
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #6186 on: August 22, 2014, 01:03:53 pm »

Yup. Fixed it a while back but didn't post or edit. My hashing function wasn't working properly and was outputting values outside of the allowed range. They're now bouncing around quite happily.

Spoiler (click to show/hide)

Guess that's another thing added to my bag of tricks. The variable names were incredibly annoying to decipher though.
Logged

Tick, tick, tick the time goes by,
tick, tick, tick the clock blows up.

alway

  • Bay Watcher
  • 🏳️‍⚧️
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #6187 on: August 22, 2014, 10:26:51 pm »

Protip for those doing volume calculations on polygonal meshes:
If you're calculating face normals using cross products, you can leave them non-normalized and use them for easily (and cheaply) calculating the volume of any non-self-intersecting polyhedron with coherent normals (either facing inside or outside). For each face, calculate the offset between an arbitrary point making up the face and some constant arbitrary point. Since doing work is something we want to avoid, we will make that arbitrary point the origin, and just use the points from the faces.

Do a dot product of that offset (position) vector with the non-normalized face normal from the cross product, and sum those up. Divide the sum by 6 and take the absolute value. Assuming my mental math is correct, that should be your volume in (3 * NumPolygons + 1) multiplication operations and (3 * NumPolygons) addition operations.

#ExteriorAlgebra
Logged

Sergius

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #6188 on: August 24, 2014, 12:22:13 am »

Great stuff alway. I'm sure one of those can be tweaked enough to make paths. In fact, just taking some altitude and turning it into paths would make them conform to terrain like hills, and while it can get repetitive and predictable, I suppose I could define whether an area is populated or not ("roady") independently of actually trying to decide if I'm going to have road in a specific place.

So basically, either roads everywhere or roads nowhere...
Logged

tuypo1

  • Bay Watcher
  • i really apreciate a good analogy
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #6189 on: August 24, 2014, 08:17:11 am »

what sorcery is this it was apparently done with just javascript/CSS holy shit thats impressive

holy shit look how many lines of code that took

oh wait most of those are the comments still im impressed
« Last Edit: August 24, 2014, 08:22:59 am by tuypo1 »
Logged
important project progress

have some basic idea of whats going to go in it

Telgin

  • Bay Watcher
  • Professional Programmer
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #6190 on: August 27, 2014, 11:57:25 am »

Warning, rant ahead.

I've been growing less fond of JavaScript as of late, because I'm starting to get the feeling that it's nigh impossible to make high quality software using it.  Especially when it's combined with HTML and thrown into embedded equipment to be used as the primary programming language.  Case in point: the set top boxes produced by Amino.

These STBs have an image of BusyBox Linux installed with [some video stuff] overlaid with an install of Opera 11.  Inside Opera, the JavaScript environment has been extended to include API objects and methods for interfacing with the rest of the STB's systems, such as the video player, network, hard disks, DVR and so on.  In theory, it's pretty great.  You can build up a complete middleware software stack using HTML5 and JavaScript inside Opera.  Theory is about where that ends, and pretty soon after you start working with it you fall down a gradual hill of pain and misery.

Fingers could be pointed in many places, but I'll start with the JavaScript API.  There is an object at top level scope called PVR, which is used to manage the recording device.  It has a method called GetAssetIdList, which is supposed to return, well, the list of asset IDs identifying recordings.  Sounds easy.  Let's take a look at the documentation:

Quote from: Documentation
string PVR.GetAssetIdList()

*description goes here*

Return Value - An object with the following properties:

count - The number of asset IDs in the list
Array - The assets

I was quite baffled by the return value being an object with properties called .count and .Array, but whatever.  Nevermind that it's documented as returning a string earlier, that's an easy goof and I forgive them.  What I don't forgive is that return object.

See, first of all, if there are no asset IDs, it returns undefined.  What?  That's not documented anywhere and completely screws up code that checks for .count or .Array.  Whatever, it took me 2 hours to figure out that it was returning undefined instead of an object because debugging this thing is impossible.  More on that later.

Next up was figuring out why .Array is not a member of the returned object.  Some of you may already suspect what's really going on here, but I didn't yet.  I tried looping through it like so:

Code: [Select]
result = PVR.GetAssetIdList();

for (var i = 0; i < result.Array.length; i++) {
    // Stuff
}

Predictably that causes the interpreter to die silently, because .Array doesn't exist and there's no debug output to tell me that.  Eventually I gave up on that and tried enumerating the properties of the returned object to see what it had in it.  Hey, no properties are returned!  It's an empty object.  What?  That's not documented anywhere either!

Cursing profusely in my head at this point for wasting hours on something stupid, I finally decided to try alerting result.count.  Lo and behold, it has a value, and it appears to be correct.  But... if I try:

Code: [Select]
for (var key in result) {
}

I get no keys.  So... the keys can't be enumerated.  .Array holds nothing still, and I can't enumerate what the name of the property really is!

By now any sensible person would have made the assumption I finally came to: the result is an array.  I tried:

Code: [Select]
for (var i = 0; i < result.count; i++) {
    blah = result[i];
}

And it works.

Let me restate that: they reimplemented JavaScript arrays, don't document this, and on top of it use count instead of the ubiquitous length property.  I was mad enough to destroy anything fragile nearby when I realized this.  Fortunately, nothing fragile was within arm's reach, so I wasn't escorted off the premises for property damage.

I could rant on JavaScript's decision to include undefined in the first place, or how trying to use an undeclared variable before assigning to it causes exceptions but you can do that with object properties just fine, but that's for another day.  Instead, I'll just mention that I had to waste another hour trying to figure out why our templating library didn't work unless I prefixed all of the JavaScript replacement targets with full.object.sub_object.references instead of just the references I wanted.  It was because of that stupid enumerable property thing again.  What point is there to hiding properties this way if you can still access them?  I really hate some of these parts of JavaScript.

Anyway, this was all 100x worse because of the development environment.  We could do some basic stuff directly in our browsers (Chrome, not Opera, but I trusted the two were similar enough), but anything of substance required special code to account for the JavaScript API not being available in our browsers.  Oh, and if anything went wrong on the STB, you had to guess why, comment out blocks of code and use custom alerts (built in alerts are disabled) to figure it out.  I don't know of any way to attach a debugger to it to get console output, but there might be something.  The emulator claims to support that but I never figured out how to use its debugging interface either.  Doesn't help that the emulator doesn't match the real thing in some ways.  For example, the real thing is painfully slow for reasons I haven't yet figured out.

And to top it off, we had to slap this together with duct tape, prayers and the sacrifice of virgin bottles of Mountain Dew because of the development deadline.  It's buggy as heck and the code is a mess.  I know you can do that in any language, but trying to do all of this stuff in a single, self contained web page feels like it  encourages the worst development practices.  There are global variables storing things like the channel and program data.  I accidentally aliased that once and wasted forever trying to figure out why something was null in one place but not another.  This is largely a consequence of JavaScript's awful class system.  I honestly thought (and still think) that I could get it done faster and in less effort with purely procedural code.  Except when it's time to add features, because you can't pollute the global namespace forever...
Logged
Through pain, I find wisdom.

Orange Wizard

  • Bay Watcher
  • mou ii yo
    • View Profile
    • S M U G
Re: if self.isCoder(): post() #Programming Thread
« Reply #6191 on: August 27, 2014, 04:35:51 pm »

TL;DR: JavaScript is to programming what Satan's hairy taint is to life.
Logged
Please don't shitpost, it lowers the quality of discourse
Hard science is like a sword, and soft science is like fear. You can use both to equally powerful results, but even if your opponent disbelieve your stabs, they will still die.

alway

  • Bay Watcher
  • 🏳️‍⚧️
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #6192 on: August 27, 2014, 11:30:49 pm »

This column sums it all up nicely: https://www.usenix.org/system/files/1403_02-08_mickens.pdf
James Mickens' To Wash it All Away

Even if you don't care about web you should read it; it's thoroughly enjoyable. Including such gems as: "Describing why the Web is horrible is like describing why it's horrible to drown in an ocean composed of pufferfish that are pregnant with tiny Freddy Kruegers -- each detail is horrendous in isolation, but the aggregate sum is delightfully arranged into a hate flower that blooms all year."

Also, there most certainly was something very fragile within arms' reach of you at the time. The stack of technologies in your browser. :v
« Last Edit: August 27, 2014, 11:37:18 pm by alway »
Logged

Telgin

  • Bay Watcher
  • Professional Programmer
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #6193 on: August 28, 2014, 07:38:24 am »

Oh, wow, that link is turning out to be hilarious already.  I have to read this during lunch at work today.

It makes me feel a tiny bit better that it's not just me that thinks programming this way is awful.
Logged
Through pain, I find wisdom.

miauw62

  • Bay Watcher
  • Every time you get ahead / it's just another hit
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #6194 on: August 28, 2014, 12:31:42 pm »

Going to crosspost this here because I'm so proud of it:
I made homing projectile code.

I look at it and I realized quickly enough that it shouldn't work. Doesn't stop it. I can't avoid it. I can't even outrun it even though it goes at 1/5 my speed.

EDIT: It's just as fast as I am when I'm farther away from its origin... I should probably redefine its origin regularly so that doesn't happen.
It shouldn't work but does? You should probably move out of Rl'yeh.
Nah, that's not unusual when programming things :V

In my own programming-related happy, I finished completely rewriting a major (and old and shitty) system for /tg/station.
End result:
1,246 lines added, 1,994 lines removed, 75 files changed. Which took me 23 days, although not all of those were spent coding.
The speed increase should be significant, but it's hard to profile the system in question. Either way, it's now much more polymorphic, understandable and I fixed ten (!) bugs. this should get me some mad maintainercred.
(statistics woo!)
This is probably the largest thing I've ever programmed, even if it was in a shitty (yet really simple) language for some backwater game.

Link to the PR
Logged

Quote from: NW_Kohaku
they wouldn't be able to tell the difference between the raving confessions of a mass murdering cannibal from a recipe to bake a pie.
Knowing Belgium, everyone will vote for themselves out of mistrust for anyone else, and some kind of weird direct democracy coalition will need to be formed from 11 million or so individuals.
Pages: 1 ... 411 412 [413] 414 415 ... 796