Jump to content




[WIP] [Infinity 1.7.0] Procedural building

command

25 replies to this topic

#1 Yarillo

  • Members
  • 81 posts
  • LocationFrance

Posted 11 July 2015 - 05:25 AM

EDIT: Project is pretty much dead for now. It's almost finished but I went out of town for a week. Now I can't bring myself to finish it. Things left to do:
- An algorithm that scans the city's empty spaces, separates them into rectangles of varying sizes, so that all of the available land is used and with a minimum amount of 1chunk by 1chunk buildings (here a chunk is 13x13 blocks wide)
- A function that "paints" the city. Divides it into neighborhoods. Maybe by creating some dots over the city and for each building, calculating which point is the closest to it. Associate each of those points to a particular colour and you have painted your city.
If anyone wants to finish it, go ahead please

pastebin get dj7hsjKU citybuilder

EDIT: If you want to use it as an API, be sure to set "activateTheExamples" to false at the beginning.


I'm looking for a distraction and I also want to be a little productive during the vacations. So I'm doing this thing and I intend to update it regularly.

If you guys are interested in helping me with it, I made a github since some friends of mine already came forward to tinker the city's generation code.


I just received my optical fiber connection from my french ISP so since it takes me only a couple of minutes to record and upload videos to Youtube, I will probably take advantage of that and upload a video of every big change.
It's not very useful per se but i'm self taught and the time lost will be compensated by the great motivation it gives me to me to be able to show my stuff to my friends and the world. :P
It's just not as fun if nobody sees my stuff.
So for those who enjoy watching progress videos, enjoy ! There's going to be quite a lot of them.


Current features:
  • Push the button and it'll spawn a different building everytime
  • Can work as an API to build structures quickly if cropped a little at the bottom of the code
  • It can build: cubes, floors, walls, rooms, rooms with windows, buildings
  • Smart placement and sizing of windows. It'll most likely make something nice.
  • Randomization of the materials that are used to build stuff
  • Sorting materials with categories ("brown", "gray"...) to make coherent buildings and allow for thematic neighborhoods
  • It will build ghost floors, ghost walls or ghost windows at will if any of the blocks in my list aren't there (aka not having the right mods installed)
  • Road making
  • Almost able to make a full city generation !
Plans

Update n°5


Youtube Videos

Spoiler

Edited by Yarillo, 16 October 2015 - 03:46 PM.


#2 MKlegoman357

  • Members
  • 1,170 posts
  • LocationKaunas, Lithuania

Posted 11 July 2015 - 08:53 AM

This is very very nice! I'd really like to see this being able to generate random cities. This kind of thing could be used for adventure maps, where users could replay the same map but with different structures generated every time. Good job!

#3 Yarillo

  • Members
  • 81 posts
  • LocationFrance

Posted 11 July 2015 - 09:10 AM

Thanks :D Glad to see there's some interest in such a thing.
I'll make the neighborhood+cities generator a priority then. I'll make the buildings nicer another time

Edited by Yarillo, 11 July 2015 - 09:11 AM.


#4 Yarillo

  • Members
  • 81 posts
  • LocationFrance

Posted 11 July 2015 - 10:46 AM

Alright, sorry to double post. I'll try not to respond to everyone so I can keep updating the post without double posting :D

I finished a couple of functions and it turned out way cooler than expected. It's amazing to watch. It makes roads and intersections easy as hell to make. A starting position, a direction and a length make a road. A position and two directions make an intersection.
It's amazing.
length = 20
x=0
y=0
z=0
road(x,y,z,"north", length)
road(x,y,z,"east", length)
roadIntersection(x,y,z,"north,east")
-- makes an intersection between a road going north and a road going east with walkways and shit


I hooked up a randomizer to the thing to show off a bit. Sorry for the music, I didn't realize I was recording it too.


Edited by Yarillo, 11 July 2015 - 11:16 AM.


#5 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 11 July 2015 - 12:11 PM

Would it be of any interest to you if I were to rig my own building script, WorldPorter, to operate in a silent mode by way of command line arguments? The structures it builds aren't "dynamic" in the way you're going for, but I reckon it'd provide an easy avenue for dotting rather more "abstract" and "unique" buildings around your cities.

I do suggest implementing roads of different widths, and also diagonals, if you're up for it. Certainly vary the textures a bit. A system for implementing slopes would also make your landscapes much more visually interesting.

Good job so far. :)

Edited by Bomb Bloke, 11 July 2015 - 12:11 PM.


#6 MKlegoman357

  • Members
  • 1,170 posts
  • LocationKaunas, Lithuania

Posted 11 July 2015 - 01:11 PM

 Yarillo, on 11 July 2015 - 10:46 AM, said:

Alright, sorry to double post. I'll try not to respond to everyone so I can keep updating the post without double posting :D

It's perfectly fine to double-post if those two posts are not related. You can also edit a post by clicking on the 'edit' button on the bottom-right of the post.

Anyway, I'm really interested to see what might come out of this, keep up the good work! :)

EDIT:

 Yarillo, on 11 July 2015 - 10:46 AM, said:

Sorry for the music, I didn't realize I was recording it too.

It starts at the same time the video starts so it's OK, makes the video more interesting to watch :P

Edited by MKlegoman357, 11 July 2015 - 01:13 PM.


#7 Yarillo

  • Members
  • 81 posts
  • LocationFrance

Posted 11 July 2015 - 01:41 PM

 MKlegoman357, on 11 July 2015 - 01:11 PM, said:

It starts at the same time the video starts so it's OK, makes the video more interesting to watch :P

It's even kind of synchronized ! It drops when I open the computer and start typing.

I made a new thingy, but it sucks. I thought it would be a good idea to make a city like this but clearly it isn't a good idea.



Look at the clusterfuck ! Also, you can see a sneak peak of how I transfer the files from my computer to Minecraft. I use an FTP and macros and shit. c:

My new idea is to make a couple of parallel roads with random amounts of space between them. Keep track of where they start and where they end, then, I'd run a script that would search for nearby roads at those points and create perpendicular roads to connect them to each other. And keep track of the point they connect to.

If I were to implement slopes, I think this would become very difficult, as I would have to make everything look good in addition to making it work. And I can foresee how hard it would be to make a nice looking sloped road.
Diagonal roads on the other hand could be cool. Simple as "mx+b". But that's indeed still a challenge. I'd have to make triangular buildings. That's not hard, but I'd have to re-write another function to give them windows. And now that's hard !
To avoid the trouble of making triangular buildings, I could simply fill any triangle with a grassy park though.

EDIT: Oh and I forgot about WorldPorter !
I've seen it and the idea crossed my mind. I like the idea of having a couple of "unique" buildings. But I don't even have the working city building thing yet so that would come later !
But indeed, if you could rig it to operate in silent, I would definetly use it. I would love to have some personnalized trees and stuff. Maybe not the buildings at first because it's hard to implement. But that'll come later maybe

Edited by Yarillo, 11 July 2015 - 02:14 PM.


#8 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 12 July 2015 - 12:23 AM

 Yarillo, on 11 July 2015 - 01:41 PM, said:

My new idea is to make a couple of parallel roads with random amounts of space between them. Keep track of where they start and where they end, then, I'd run a script that would search for nearby roads at those points and create perpendicular roads to connect them to each other. And keep track of the point they connect to.

One method would be to define "blocks" of land (which will eventually contain one or more buildings), and then to simply space them apart by whatever your road width is and running said roads along the east-most and south-most sides of each block.

The size of each block would be mostly random, but assuming you were generating them west-to-east, north-to-south, you'd maybe incorporate a flat 25% chance that the width of a new block would line its east end up with the east end of the block to the north of it, and a separate flat 25% chance that its length would line its south end up with the south end of the block to the west of it. This'd hopefully make the layout tend towards having lengthier "streets" while at the same time not looking too boring.

#9 Yarillo

  • Members
  • 81 posts
  • LocationFrance

Posted 14 July 2015 - 06:42 AM

It was a rather slow progress because of some bugs I have been battling with (:'D) and me celebrating my high school graduation. But it has progressed quite a bite nonetheless !

First of all a friend of mine joined me and helped for a bit with the terrain generator. He was able to make a function that can draw the map of the city (here it is displayed at a scale of 1:12).

(He didn't wake up yet so I won't quote his name before he tells me to)



What do you think Bomb Bloke ?

I discovered not long after making that video that some variables responsible for the randomization of the city will only change their value if they are equal to nil. Meaning, if you launch the program twice, the city won't change much. You have to reboot the computer. So that's why all the maps look similar in the video. It's just me using his code the wrong way.


While he did this, I upgraded the building generator (I love doing that :D !)



I added penthouses, spiky buildings that shrink as they build up, terraces...
It's starting to look pretty cool.

EDIT: I also discovered something quite worrying when using FRAPS. My computer really has trouble video capturing AND generating my buildings.

Posted Image

This, gentlemen, is a bunch of spikes representing my CPU getting on its knees when my building generator starts working. Fraps was not capturing when I took the screenshot.
When the CPU usage is around ~10% that's when the building generator is in his waiting phase. 4 seconds of waiting between each building.
This is weird because I have an Intel i7 8 cores 950 @3.07GHz and I thought it was quite good.

Also, we're approaching 1000 lines of code !

Edited by Yarillo, 14 July 2015 - 07:07 AM.


#10 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 14 July 2015 - 08:31 AM

 Yarillo, on 14 July 2015 - 06:42 AM, said:

What do you think Bomb Bloke ?

Quite a few gaps, overlaps, and disconnected roads (getting worse as generation moves away from the computer), but even assuming those are unintended and need to be fixed, it captures the basics of the idea. :)

 Yarillo, on 14 July 2015 - 06:42 AM, said:

EDIT: I also discovered something quite worrying when using FRAPS. My computer really has trouble video capturing AND generating my buildings.

Well, yeah.

Most ComputerCraft scripts don't run code "constantly". They yield often, and do so in order to wait for something - keypresses, timers, rednet messages, whatever. They end up spending more time yielding than executing.

Some scripts, on the other hand, manage to come up with a large workload that doesn't require any pauses. This one simply shovels commands into MineCraft's queue as fast as it can, the intent being to get the whole build done ASAP - and so a core gets maxed out until that happens.

You could, if you wanted, rig up a timer system so that the script only allows a certain amount of blocks to be placed per second. So long as the processor could keep up with that demand, usage would drop off. Frankly, though, I don't see the point - there's not much point in having a decent processor if you don't intend to use it!

#11 Yarillo

  • Members
  • 81 posts
  • LocationFrance

Posted 14 July 2015 - 08:37 AM

 Bomb Bloke, on 14 July 2015 - 08:31 AM, said:

You could, if you wanted, rig up a timer system so that the script only allows a certain amount of blocks to be placed per second. So long as the processor could keep up with that demand, usage would drop off. Frankly, though, I don't see the point - there's not much point in having a decent processor if you don't intend to use it!

I actually did implement that right at the beginning. I added a safeguard inside the commands.execAsync function to avoid "toolongwithoutyielding" errors and the commands queue getting too large.

old.execAsync = commands.execAsync -- Editing the default execAsync command to include a safeguard
local function execAsync(str) -- Too many queries in a single blast will cause problems.
		if execAsyncQueries == nil then
				execAsyncQueries = 0
		end
	  
		timeDiff2 = deltaT("execAsync")
		-- I will measure how long I waited between each queries
		-- As CC time units do not go after the 2d decimal i will wait 0.1s every 850 queries
		-- I call a row of queries a "blast"
		-- (8500 q/s at best)
		if timeDiff2 > restingTime then
				execAsyncQueries = 0 --Blast of queries was cut off. I consider this one finished
		else
				execAsyncQueries = execAsyncQueries+1
		end
		-- console(execAsyncQueries, 7)
		if execAsyncQueries > dangerousAmountOfQueries then
				sleep(restingTime)
				execAsyncQueries = 0 --just to be sure, manually consider the blast as finished
		end
	  
		return old.execAsync(str)
end
commands.execAsync = execAsync

Edited by Yarillo, 14 July 2015 - 08:40 AM.


#12 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 15 July 2015 - 01:26 AM

So all you need to do is reduce "dangerousAmountOfQueries" to taste. :)

#13 Forgotten_Boy

  • Members
  • 72 posts
  • LocationOntario, Canada

Posted 15 July 2015 - 04:13 PM

This is really sweet. It would be perfect to implement my dream of playing ye olde game "Railroad Tycoon" in Minecraft by combining Railcraft with this to make villages that actually grow; this could make cities and new industries pop up as you deliver/pickup your goods...

#14 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 16 July 2015 - 03:59 AM

Egad, you could play a full-on Sim City clone - have players interact via a monitor to zone out areas, then have buildings appear on them over time, maybe spawn the occasional Testificate, and so on...

#15 Yarillo

  • Members
  • 81 posts
  • LocationFrance

Posted 16 July 2015 - 12:40 PM

Yeah, or even both. You could link the command computer to a screen and it would displays a map of the city. You could add new buildings or make them grow higher and higher by clicking buttons. Each upgrade would cost some blocks and you'd have to use the classic FTB mechanics to move forward in the game.

Some buildings could have a purpose and you could basically invest a shit-load of ressources into industries that would "print" you some hard to craft items.

Possibilities are endless, that's why I'm implementing in the code an "API mode", so that anyone can use it and make awesome things on their own.

Edited by Yarillo, 16 July 2015 - 12:42 PM.


#16 Forgotten_Boy

  • Members
  • 72 posts
  • LocationOntario, Canada

Posted 16 July 2015 - 07:34 PM

So... hmmm... couldn't get it to work. Load it up, run "citybuilder", nothing happens. Tried some of your lua/api examples but no deal. How to use?

#17 Yarillo

  • Members
  • 81 posts
  • LocationFrance

Posted 17 July 2015 - 07:23 AM

By default, the examples are deactivated. It's basically just an API. It launches, registers a lot of functions then stops because no commands have been issued. You have to set activateTheExamples to true at the beginning !
I think I'll activate the examples by default from now on. Those who plan to use it as an API won't mind having to fiddle with one variable.

local activateTheExamples = false -- You won't be able to use it as an API if you activate this but you will have access to cool examples when you launch it

Quote

Tried some of your lua/api examples but no deal.

Wut ? Could you be more specific on what happens and how did you achieve that ?

Edited by Yarillo, 17 July 2015 - 08:20 AM.


#18 Forgotten_Boy

  • Members
  • 72 posts
  • LocationOntario, Canada

Posted 17 July 2015 - 09:21 PM

I'll try it again with examples activated. I just wanted my kids to be able to build random stuff! I was trying to follow along with the video when I did the API examples so I did something wrong for sure.

#19 Yarillo

  • Members
  • 81 posts
  • LocationFrance

Posted 18 July 2015 - 05:00 PM

I stumbled upon the weirdest bug.

Posted Image

See the ores everywhere ? That's the bug. I'm only using stone and obsidian here.
Looks like Minecraft tends to add ores everywhere when I generate large amounts of stone blocks. Especially when i'm generating them far away from the computer.

EDIT: Oh damn ! That's because I'm generating stone in undiscovered areas, so when I go there Minecraft loads the area, with my stone in it, and runs his little coroutine to add ores inside it ! Awesome !
I guess using stone in my city will be forbidden ! :D

Edited by Yarillo, 18 July 2015 - 05:03 PM.


#20 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 18 July 2015 - 11:55 PM

Huh, and here I thought the chunks would need to be loaded to place blocks into them.

I know that commands.getBlockInfo() can be used to load chunks.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users