Тёмный

Generating 2d levels 

Nick Brooking
Подписаться 515
Просмотров 2,7 тыс.
50% 1

I adventure into the world of procedural terrain generation for my 2D roguelite platformer and learn a bunch of gamedev maths.
The game engine is Godot 4.2.
I used Canva for the illustrations.
If you want to create x and y like I do at the end of the video you can do it like this:
First generate a random angle between two bounds
var theta = _rng.randf_range(theta_lower, theta_upper)
Next generate a radius length between two bounds
var r = _rng.randf_range(r_lower, r_upper)
Then convert theta and r back from polar coordinates to cartesian coordinates
var x = r * cos(theta)
var y = r * sin(theta)

Игры

Опубликовано:

 

5 июл 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 37   
@TheAstroPhoenix
@TheAstroPhoenix 17 дней назад
An elegant solution! Polar coordinates in situations like this definitely make life a lot easier. For more complicated scenarios (which don't follow circular spawing points), it might be worth reading into basic monte carlo implementations. These will randomly sample a space of x,y points (which you can restrict the range of using polar coordinates), and when chained, you can make them converge to a region of interest.
@dorusie5
@dorusie5 18 дней назад
Very cool. Nice thing with your approach is that you can also clamp the generated values to the allowed range of the angle and distance, so any generated number is valid.
@nick-brooking
@nick-brooking 18 дней назад
Yeah that's exactly right!
@HappyGaminz
@HappyGaminz 18 дней назад
Amazing video! you are so under-rated!!
@nick-brooking
@nick-brooking 18 дней назад
Thanks! Glad you enjoyed it
@bellbobs
@bellbobs 19 дней назад
Randommmmmm (but thoughtful)
@thedopesquad7179
@thedopesquad7179 19 дней назад
Awesome video omg!!!
@nick-brooking
@nick-brooking 19 дней назад
Thanks so much :)
@Descifrando_la_economia
@Descifrando_la_economia 19 дней назад
Great video,Great explanation, anyone could understand it
@davidvarga2916
@davidvarga2916 17 дней назад
You know you could just code like 20-30-ish next platform positions based on the current one and just pick one at random from that list. Well you could play around with it by adding weights to the randomness so that you get more of the ones you want or don't want at certain times. Like let's say 3 minutes in you start adding more of the thin platforms or what not. If you read my previous comment about adding more objects in. I'll give you an example: You have current platform and in the next platform you won't only have the info about the next platform stored, but also some coins and spikes and what not. This would simplify the work greatly. I think.
@nick-brooking
@nick-brooking 17 дней назад
Yeah interesting. I'm thinking I will have some set pieces, ie areas where I have specifically laid out the positions. But I think I've done enough on the platforms for now, I'll come back to them once I've added a few other things to the game
@rikvanduijn7060
@rikvanduijn7060 18 дней назад
Very nice loved the explanation. Not very good at math would like to see how you actually implement this.
@nick-brooking
@nick-brooking 18 дней назад
Hey glad you liked it! I just added a code example to the description of the video
@pavloburyanov5842
@pavloburyanov5842 9 дней назад
Very simple: 1. Pick random angle from range: var a = rand(range(deg(20), deg(100))) 2. Pick random distance from range: var dist = rand(40, 80) 3. Grab x coordinate: var x = dist * cos(a) 4. Grab y coordinate: var y = dist * sin(a) 5. Place platform at (x, y)
@nick-brooking
@nick-brooking 9 дней назад
Yep, that's exactly right. It turns out so easy this way
@pavloburyanov5842
@pavloburyanov5842 9 дней назад
@@nick-brooking it makes a bit difficult when you need to add branching, or when platforms have various widths. The best way, imo, is doing recursion by storing position ant width of last placed platform. ^ can be idea for your next video
@nick-brooking
@nick-brooking 9 дней назад
I don't need recursion because I'm just generating one platform at a time. I store a list of all the platforms with the most recent one at the end so adding the randomly generated coords to the position of the last platform is thankfully also trivial.
@nick-brooking
@nick-brooking 9 дней назад
But yeah you're right about more platform variability. I haven't got to that yet
@aqua-bery
@aqua-bery 17 дней назад
How are you generating the shape for the sprite at the end? To represent the spawning range I mean
@nick-brooking
@nick-brooking 17 дней назад
When I create a new platform I create a Polygon2D and add it as a child. Polygon2D has a variable called 'polygon' which is just a list of vertices. So I calculate a bunch of points around the far edge and then calculate more but backwards on the near edge which creates the loop of the shape. Then I can rerender it when it needs updating by calling the same function again. I wrote it super quick and dirty because it's just a debug tool, not intended for the game.
@davidvarga2916
@davidvarga2916 17 дней назад
Just jumping on platforms is boring. Add a few more interesting objects that change the mechanics like a simple moving platform or pick ups or an objects that deals damage like spikes or what not. And you can start scratching your head on how to place them in correlation to one another randomly, but thoughtfully.
@nick-brooking
@nick-brooking 17 дней назад
Yeah I have plenty more planned. Just need to keep testing what is actually fun
@WildKiwiUnleashed
@WildKiwiUnleashed 15 дней назад
Anyone else notice his eyebrow movement.
@nick-brooking
@nick-brooking 15 дней назад
🤨
@WildKiwiUnleashed
@WildKiwiUnleashed 14 дней назад
@@nick-brooking No its good, very engaging.
@user-dw5ch6ux3u
@user-dw5ch6ux3u 18 дней назад
3:48 realistically speaking the "make a guess and if it is wrong through it out and try again approach" is absolutely fine. did you notice any lag? what did your code look like? you would need to run this code no more than ten-fifteen times (judging by eye) and not every frame and that should take a negligible amount of time. if you really want to squeeze out maximum efficiency from your code to the point where you would care about such small optimizations i suggest gdnative instead of gdscript (i am not trying to judge you btw. if you want to go full optimization on your code be my guest, i am just saying that it's not the best use of your time, especially if you are an indi dev)
@nick-brooking
@nick-brooking 18 дней назад
Yeah for sure. And you're right that I'm not overly concerned with performance at this stage. However the guess and check method involves the conversion between polar and Cartesian coords anyway so by the time you've gotten 1 wrong guess, the other method has finished running, forget the other 10 - 50 other guesses you might need. Imo the code is also less intuitive making it messier. Imagine I made the shape really tiny so it took up 1/500th of the x and y range. I would expect to need this to run 500 times, in which case I might want to cut down the range of x and y so it doesn't miss so much and all of that is unnecessary complexity. My point is not that I care about performance too much at this stage, more that it's a decision with no trade offs 1. We like the bias it introduces 2. The code is more straight forward and simple 3. It's more perfomant
@user-dw5ch6ux3u
@user-dw5ch6ux3u 18 дней назад
​@@nick-brooking ok fair enough but to clarify a couple of things : the 10-50 other guesses are a matter of milliseconds, your computer is capable of running billions of calculations it truly does not matter at all for code that runs once a second if you made the shape really tiny you would make the x,y range really tiny as well. for example if your shape had values of x [0,0.005] you wouldnt generate random numbers from 0 to 1. unless you had some really weird shape with some really thin areas that require a lot of empty space in between them it truly doesn't matter now to give the devil his due i agree with the benefits of the bias but there are more "brainless" ways to induce said or similar bias that would need less thinking and time. now the reason i am saying all that is that i see a lot of gamedevs that are working on personal projects overthink and over-engineer unimportant parts of their code without taking into account their lack of time/manpower. to write the function in the brainless way i suggested would land you with a couple ms of delay but could be accomplished in 5-10 minutes while to actually sit down and think on how to deform the random generator to fit the area i had in mind and how to change the biases of the generation function to get more platforms slightly closer to the player would take a lot longer which is time an indi-dev could use to add a more important mechanic to their game or to fix bugs. that is not to say you shouldn't do what you want with your project but i am just saying for most indi-devs its not a good idea to focus on such things because most indi-devs leave their projects half way through and over-engineering (i believe) is a big reason why.
@nick-brooking
@nick-brooking 18 дней назад
@@user-dw5ch6ux3u I completely agree with you that people waste time on things that don't matter and that in general, people spend way too long on solving problems they shouldn't. I laid it out my video the way that I did because I believe it made the most sense to explain the concepts that way. My goal is to share info about such concepts and describe what solutions I choose then let people do what they want with that info. When I actually wrote the code it took about one minute. Here it is, I don't know how to write the guess and check method and simpler than this but let me know if there's a way. var theta = _rng.randf_range(_theta_1, _theta_2) var r = _rng.randf_range(_r_1, _r_2) var x = r * cos(theta) var y = r * sin(theta)
@user-dw5ch6ux3u
@user-dw5ch6ux3u 18 дней назад
@@nick-brooking oh i don't disagree that the code is simple but you also have to factor in the time you spent thinking about it up until it clicked in your head to use polar coordinates and just mess with the radius and angle. now you might have polar coordinates and imaginary numbers fresh in your mind in which case it might come to you automatically or even faster than the "guess randomly and throw away" method but if you haven't recently worked with it it will take some time until that metaphorical light bulb lights up. since you asked the naive method would have been to get a random x,y pair and do these checks: x^2+y^2r_small vector from center to the x,y pair has angle within theta_1 and theta_2 the good with this method is that its easier to come up as a first thought not that its programmatically easier. that is because if you have a specific amount of time to allocate to a project it doesn't matter if that time is spent in thought looking at the ceiling or actually coding.
@nick-brooking
@nick-brooking 18 дней назад
Yeah totally, thanks for sharing. Hey are you working on any projects of your own? I'd be keen to hear how you apply this progress-focussed mindset
@tomitomislav8180
@tomitomislav8180 15 дней назад
Nice video but why you talk and look so funny, why are you flirting with me 😭😭😭
Далее
Making a Game with 3 Different Dimensions
8:52
Просмотров 43 тыс.
МЕГА ФОКУС С КАЛЬКУЛЯТОРОМ
00:33
Я ВЕРНУЛСЯ 🔴 | WICSUR #shorts
00:57
Просмотров 906 тыс.
Optimizing my Game so it Runs on a Potato
19:02
Просмотров 500 тыс.
How One Change Transformed my Indie Game!
11:05
Просмотров 27 тыс.
How I Created a Voxel Raycaster in Python...
5:47
Просмотров 6 тыс.
How I Solved Real Time Motion Blur
10:20
Просмотров 38 тыс.
Why Do So Many Indie Games Use Pixel Art?
9:23
Просмотров 16 тыс.
How To Fail At Game Feel
3:48
Просмотров 65 тыс.
10 Minutes vs. 10 Years of Animation
19:29
Просмотров 721 тыс.
Turning Your 2D Character into 3D • 02
9:20
Просмотров 456 тыс.