Fengist's Forum Posts

  • I wrote a tutorial a while back on the basics of using Perlin noise and the advanced random plugin.

    Wow, that was dead easy. I just replaced the starting random array with what the Adv Random spat out.

    -> Array: Set value at (LoopIndex("IslandColumns"), LoopIndex("IslandRows")) to round(AdvancedRandom.Ridged2d(LoopIndex("IslandColumns"),LoopIndex("IslandRows"))×100)

    The difference was amazing. Added yet another example project using this to the OP.

  • Umm, would a 3 dimensional array work?

    Array.at(index0,difficulty1,level3)

  • You could MAYBE use chunking to make the world gen. real time ( so only generating the visible parts ) but this more trouble than it's worth I think.

    I got to thinking after I read this that I've already got a way to easily show some of the terrain generation. I have a function that copies the array over to the tilemap. So, I just copied and pasted that function into various parts of the routine and it shows a lot of the map being generated real time. I also set the viewport to show the entire map. There's a link to that version in the OP now.

    I'll take a look at your Perlin tutorial today and see if I can make heads or tails of it. While this does work pretty well, it's not exactly what I'm looking for.

    Thanks again.

  • Might be fun to try that with the Advanced Random plug using perlin with this height=beach , this=land, that=mountain, etc.

    I looked at Perlin. There's a lot of examples of people using it to generate heightmaps. One look at the wikipedia article on it an I realized I'd need at least a masters degree to translate their gobbledy-gook. I did find a few examples in PHP that I could follow though. Not quite sure where this is gonna go just yet. The plan is a simple but cute survival game. I may throw in a volcano just for giggles. Not sure if I wanna tackle mountains just yet. For now, I'm just goofin off with some free tilemaps and png's I ran across. I'd need to come up with a real tilemap before I tackled elevated terrain.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Would love to see it in action :)

    construct.net/en/forum/construct-3/your-construct-creations-9/procedural-archipelago-every-146271

    Your wish is my command. Unfortunately, since I do all the laboring in an array, there's no real output till it's all done. But it's the beginnings of procedural islands. Now, for rocks, trees and all the interaction fun.

  • Since my other major project has become a nightmare of 30+ database tables, I've decided perhaps it's time to take a break and try some lighter fare. As part of that, I've been experimenting with generating procedural islands in C3 using an array and a simple tilemap. Generating a basic set of islands is relatively easy. The hard part, finding the edges and properly applying a beach. And what's an island without a beach?

    Here's link where you can see the current results of testing.

    twistedvoid.com/c3examples/Castaway

    Here's a link to a 'zoomed' out view that shows the map generation in semi-real time. You'll barely be able to see the buttons so if you don't know what they are, just click and it'll do the rest.

    twistedvoid.com/c3examples/Castaway2

    Here's a link to a zoomed out view that demonstrates both the unpredictable random array generation used in the previous examples and, the 5 random generators used by the Advanced Random plugin. The difference is amazing.

    twistedvoid.com/c3examples/Castaway3

    THANK you to everyone who spoon'ed me solutions, ideas and encouragement on this thread:

    construct.net/en/forum/construct-3/how-do-i-8/god-need-repeat-until-146195

    The journey into the unknown begins.

    For those interested, the process for creating these islands is something like this.

    1. Start with a 200x200 array.
    2. Fill in Array 3,3 to 197,197 with random numbers.
    3. Run through the array 3 times, add up the 8 neighboring cells and set that one to the average.
    4. Total all the cells and get an average of all of them.
    5. Run through the array and set any cell below the average to the value for the tilemap's water. Anything above the average gets set to the tilemap's square land tile.
    6. Run through the array and look for small water 'ponds' that create an issue when placing beaches.
    7. Run through the array and look for 'anomalies' that also create issues when creating beaches until all anomalies are gone.
    8. Place beaches from one of 12 possible tiles depending on what land and water surrounds it.
    9. Plant some random tree sprites, change some random terrain sprites to bushes and rocks.

    Finding all of the anomalies that prevented beach placement (and identifying arrangements that caused issues) was the hard part. First, it looks to see if a land tile has at least 4 neighboring land tiles.

    If it doesn't, it sets it to water. Then, it looks for and fixes issues like this:

    X|X|X
    0|X|0
    X|X|X

    or

    0|X|X
    X|X|X
    X|X|0

    where X is land and 0 is water. In both of those cases, there was no way to properly place a beach on the center tile and have it match the surrounding beaches.

    Those above were easy to spot. It looks N/S or E/W or diagonally and see if there was a land tile. If not, put one there to smooth it out. The biggest pain in the ass to find and fix was this one which occasionally popped up.

    X|X|0|X
    X|X|T|X
    X|0|X|X
    X|0|0|X

    It passed by the '4 tile rule' just fine and passed the horizontal and diagonal checks. For that one, I had to create a special rule. For the one labeled T, it checks W and S for land. It then checks SW for water and then, checks N for water. If all those conditions are true, it sets the north tile to land.

    So, that's the basics.

  • The eventsheet blocks any other execution until it has completed. You need to split the work up somehow, ideally into chunks that occur in under 16ms. A wait action for 0 seconds should pause work until the next tick, allowing the layout to render.

    It can be quite hard to decide when to pause, often it's easier to pause more often than you need which slows down your loading significantly. But at least if your not blocking anymore you can show a nice loading animation.

    Perfect! Added the wait 0 after each function and the progress bar updates. An unexpected method for solving the problem, but hey, it works.

    Thanks!

  • So I have this function that calls a bunch of other functions. I wanted to add a progress bar so that after each of the inner functions are run, it would show the progress. However, I'm discovering (I think) that while a function is being run, the layout isn't being updated. Once I click the button to start, the progress bar doesn't move until the main function completes.

    Is there anyway to refresh the layout so that this progress bar shows movement?

    * On function 'Startup'
    -> Functions: Call BuildArrayRandom
    -> ProgressBar: Set progress to ProgressBar.Progress+1
    -> Functions: Call AverageTheArray
    -> ProgressBar: Set progress to ProgressBar.Progress+1
    -> System: Set ArrayTotal to round((ArrayTotal÷ArrayCount))×MapFilter
    -> Functions: Call SetTerrainIslandorWater
    -> ProgressBar: Set progress to ProgressBar.Progress+1
    -> System: Set ArrayCount to 0
    -> Functions: Call EliminateOrphans
    -> ProgressBar: Set progress to ProgressBar.Progress+1
    -> Functions: Call FillInPonds
    -> ProgressBar: Set progress to ProgressBar.Progress+1
    -> Functions: Call FixConnectors
    -> ProgressBar: Set progress to ProgressBar.Progress+1
    -> Functions: Call PlaceBeaches
    -> ProgressBar: Set progress to ProgressBar.Progress+1
    -> Functions: Call CopyToTilemap
    -> ProgressBar: Set progress to ProgressBar.Progress+1
  • Ah yeah that algorithm, I've actually looked at that in the past. I did a fair bit of reading on procedural terrain generation at one point and that was recommended for smoothing out caves.

    http://www.roguebasin.com/index.php?title=Cellular_Automata_Method_for_Generating_Random_Cave-Like_Levels

    You, sir, must be a mind reader. I'll study these links further today. Thanks for pointing them out!

  • Your project looks very exciting.. must be fun programming it! Would love to see it in action :)

    As soon as I get something solid, I'll update this post to a working example.

    Just wondering if the loops are causing any delay? or they're instantaneous?

    So far, it's not too horrible. A second or two. But, I'm far from being done. Nepeo pretty much figured out what I'm doing. I'm using a technique similar to what he linked to:

    roguebasin.com/index.php

    So far, these are the steps I'm taking but, I need at least one more routine and your Quadtree may just fit the bill. I'll study that today.

    * On function 'Startup'
    -> Functions: Call BuildArrayRandom
    -> Functions: Call AverageTheArray
    -> System: Set ArrayTotal to round((ArrayTotal÷ArrayCount))×MapFilter
    -> Functions: Call SetTerrainIslandorWater
    -> System: Set ArrayCount to 0
    -> Functions: Call FillInPonds
    -> Functions: Call EliminateOrphans
    -> Functions: Call PlaceBeaches
    -> Functions: Call CopyToTilemap

    First, it builds an array of random numbers.

    Then, it iterates through the array, looking at each cell. It looks at the 8 surrounding cells and replaces the one it's looking at with an average of the other 8.

    The ArrayTotal is the average of all cells in the entire array. By adding the MapFilter (say 0.9 to 1.1) I can easily generate more or less land mass.

    Then, it loops again through the array. If the cell is above that ArrayTotal average, it sets it to the value for the land tile, otherwise, it sets the value to the WaterTile.

    Next, it attempts to look at water tiles that have a lot of land around them and fills them with land tiles.

    The EliminateOrphans is the smoothing I posted above.

    And this next part I'm still working on. It loops again through the array, looks at surrounding tiles and attempts to create a beaches on the island borders from one of 12 possible tiles (N,S,E,W outside curved tiles NW,NE,SW,SE and inside curved tiles NW,NE,SW,SE).

    Finally, it copies the array over to the tilemap and shows it.

    But if your algorithm if fast enough, then you don't need anything else.

    So far, it's pretty quick. That may change as there are still trees, bushes, etc to place. I'm liberally stealing the idea from a game jam project and his would take a full minute or two to generate a map. I'm hoping to be a lot faster than that.

    This is a 200x200 array which it does in about 5 seconds.

    And to show how the map filter works, the above example was at 1.075. The one below was created just by changing that filter to 0.95.

  • No, that is not odd, that is the whole point of the image point.. :)

    LOL, yea, it is. It's what some of us would call an anchor point. Should you decide to like rotate the sprite, it'll rotate around that image point. It tells Construct where to place the actual sprite image in relation to the x,y location you choose.

    When you originally placed that sprite you looked at where you wanted the image. The actual location was down and right. When you moved the image point on the sprite, the x,y on the layout didn't change but the location of the graphic in relation to that x,y did.

  • Is that the image point that somehow got drug all the way down there? Edit your sprite, select edit image points on the left and click in the center and see if that doesn't fix it.

  • Would be interested to see the same project with the new beta Fengist

    New r161 version uploaded. Link in the OP for comparison.

  • Which means, let's say in the 500th recursion, if all the found = false, it won't repeat anymore.

    While a good idea, in my case, a recursion would likely cause an even bigger delay in completion. Each cycle through the loop I'm looking at an element in the array. I'm then looking at the 9 elements surrounding it (x-1, y-1 to x+1, y+1) and basing changes off the results of that. Changing the element the loop is looking at could affect the element prior to it but I wouldn't know that until I ran through the loop again. (I'm playing with procedurally generating island terrain using an array as the template for the tileset.)

    And as an update, the While worked great, just like a good ole' Pascal repeat until. Here's the resulting code. It's purpose is to 'smooth' out the terrain generation. The OrphanCheck is the conditional to stop the while and the -1 in the array indicates it's a water tile. ArrayOffset is a 'border' around the islands that's guaranteed to be water.

    * On function 'EliminateOrphans'
    ----+ System: While
    -----> System: Set OrphanCheck to False
    --------+ System: For "IslandColumns" from ArrayOffset-1 to ArrayWidth-ArrayOffset
    ------------+ System: For "IslandRows" from ArrayOffset-1 to ArrayHeight-ArrayOffset
    ----------------+ System: Array.At(LoopIndex("IslandColumns"),LoopIndex("IslandRows"))-1
    -----------------> Array: Set ThisX to LoopIndex("IslandColumns")
    -----------------> Array: Set ThisY to LoopIndex("IslandRows")
    -----------------> Array: Set ArrayAve to 0
    -----------------> Functions: Call OrphanCount
    --------------------+ System: Array.ArrayAve ≤ 4
    ---------------------> Array: Set value at (LoopIndex("IslandColumns"), LoopIndex("IslandRows")) to -1
    ---------------------> System: Set OrphanCheck to True
    ---------------------> System: Add 1 to ArrayCount
    --------+ System: [X] Is OrphanCheck
    ---------> System: Stop loop
    
    * On function 'OrphanCount'
    ----+ System: For "IslandXCheck" from Array.ThisX-1 to Array.ThisX+1
    --------+ System: For "IslandYCheck" from Array.ThisY-1 to Array.ThisY+1
    ------------+ Array: Value at (LoopIndex("IslandXCheck"), LoopIndex("IslandYCheck"))-1
    -------------> Array: Add 1 to ArrayAve

    And to show what I'm doing and why I needed this, here's what the 'island' terrain looks like without running this loop.

    And after running the while loop

    Basically, it's purpose was doing some 'cellular automata' to check and see if a land tile had at least 3 neighboring tiles that were terrain and if not, set it back to a water tile (-1)

  • Chrome:

    Click the 3 dots top right.

    Look for Zoom, click the +