Towns
评价数不足
Towns Map Creation: Part 3: Water: Adding Rivers
由 Varsh 制作
Adding lakes was one thing, adding rivers is another. Unlike lakes, rivers have their own types of configuration and methods of creation. By the end of this tutorial you will know how to make a river and make it curve in any direction.
   
奖励
收藏
已收藏
取消收藏
Notes
Having a map without at least 1 river will seem a little boring and most likely doesn't give much in way of the map. As a lot of things in the game require you to have things next to a river then it's a very good idea to have a river in your map.
Understanding co-ordinates
In order to understand how the co-ordinates work for the rivers you need to understand how the map co-ordinates work.


As you can see in the above picture the X-axis runs from the left to the top, the Y-axis runs from the left to the bottom. If you have worked with graphics then you will understand the way this map works immediately, if you don't and you're still confused then think of it like this:

In maths whenever you create graphs you have 0,0 (X,Y) at the bottom left with the positive of X and Y going to the top right (e.g. 12,12). In computing and graphics you flip the Y-axis so the positive actually goes downwards rather than upwards, so instead of the top right it's now the bottom right.
Starting the river
Much like the lakes, rivers are also hard coded into the game engine currently so your type will be set in stone before you can even think of having something different, hopefully at some stage they will allow that to be modded but for the time being we'll have to stick to what is given.

Before we add the type though we need to add something called a bezier curve, this will allow us to draw an invisible line across the map between 2 path points and have the line change its form using control points that are related to their path points.

After the lake seed we will create the bezier curve with the tag:
<bezier id=”bezierRiver1”> <!-- This is where the river information goes --> </bezier>
Rivers aren't seeds but they kind of act like one, the reason it is not a seed is because in each bezier config you can have only one created, in order to create another river you will need to create a new bezier curve with a different id, in my id I put “bezierRiver1”, if I wanted to create a new river I would change the “1” to a “2”.
The base values
I have mentioned earlier that rivers are hard coded into the game so have the type as follows:
<type>_WATER_INF_</type>
We also want the river to start on the same layer as the ground so we'll set this to 24. The depth of the river can be any number of tiles, the more depth you have the further down the river will be underground, I have set this to 5 for this tutorial but you can have it as deep as you like. Don't have the river too deep otherwise when it comes to creating the dungeons you won't be able to get to the other side! Lastly we need the tile width of the river, I have set this to 5.
<level>24</level> <depth>5</depth> <wide>5</wide>
Adding the path points
Once you've got the general configuration down it will be time to create the paths in order for the rivers to be drawn. Each river can only have 4 points, 2 path points and 2 control points. The first points to create are the path points.

Unlike how other seeds are randomised, beziers instead have their points randomised with a minimum and maximum position. As there must be 2 path points you will need to add the following:
<point1_x_min>25</point1_x_min> <point1_x_max>175</point1_x_max> <point1_y_min>-50</point1_y_min> <point1_y_max>-50</point1_y_max> <point2_x_min>25</point2_x_min> <point2_x_max>175</point2_x_max> <point2_y_min>250</point2_y_min> <point2_y_max>250</point2_y_max>
As you can see each point has a number from 1 to 2, having more numbers like “point3” will not work and the game will not render the adjoining path. The minimum and maximum values shows the range in which I want the positions for the river's path points to start and end.

If you remember that the map runs up to 200, looking at some of the co-ordinates above shows that there are points off the map, this is not a problem and can actually lead to more control and variation of your rivers when randomised. If there is an instance where the curve of the river is so great then if the control point starts on the edge of the map it might appear that it stops prematurely and will in effect look odd.
Adding the control points
Next would be to add the control points. Each of these control points are connected to their numbered path point. They can be randomised in the exact same way as path points but it's a must to have these control points between the two path points and without too much variation away from the straight path between the two path points.

Control point 2 will affect the path coming from path point 2, if I had the control point to the right of the path point then the path will curve to that direction but it won't touch the control points location! It's important to keep this in mind. If you were to do the same for control point 1 but instead to the left of the path then it will bend to the left thus giving you an “S” shaped river.
<controlpoint1_x_min>-50</controlpoint1_x_min> <controlpoint1_x_max>250</controlpoint1_x_max> <controlpoint1_y_min>25</controlpoint1_y_min> <controlpoint1_y_max>75</controlpoint1_y_max> <controlpoint2_x_min>-50</controlpoint2_x_min> <controlpoint2_x_max>250</controlpoint2_x_max> <controlpoint2_y_min>125</controlpoint2_y_min> <controlpoint2_y_max>175</controlpoint2_y_max>
The above shows that the control points are between the two path points but allow for going wider on either side to allow for more variation without making the rivers too out of place.

Play around with the values for both the control points and the path points to see what you can come up with, for the rest of the tutorials I will be keeping to a single river and using the above values.
Tips
It's a good idea to draw out how you want your river to look like (if it's not fixed) on graph paper, when you have a rough idea turn the paper so that it is like a diamond rather than a square, you can then use the co-ordinates of your path points and your control points.
Code
Here's the code for the gen_map.xml file with the new additions:
<?xml version="1.0" encoding="UTF-8"?> <gen_map> <init id="init"> <numLevelsOutside>24</numLevelsOutside> <numLevelsUnderground>40</numLevelsUnderground> <mainTerrain>grass,dirt,stone</mainTerrain> <numCitizens>100</numCitizens> <startingLevel>23</startingLevel> </init> <seed id="seedLake"> <type>_WATER_</type> <num>1d3</num> <level>24</level> <pointx>1d160+20</pointx> <pointy>1d160+20</pointy> <turns>10</turns> <northPCT>100</northPCT> <southPCT>100</southPCT> <eastPCT>100</eastPCT> <westPCT>100</westPCT> <downPCT>100</downPCT> </seed> <bezier id="bezierRiver1"> <type>_WATER_INF_</type> <level>24</level> <depth>5</depth> <wide>5</wide> <point1_x_min>25</point1_x_min> <point1_x_max>175</point1_x_max> <point1_y_min>-50</point1_y_min> <point1_y_max>-50</point1_y_max> <point2_x_min>25</point2_x_min> <point2_x_max>175</point2_x_max> <point2_y_min>250</point2_y_min> <point2_y_max>250</point2_y_max> <controlpoint1_x_min>-50</controlpoint1_x_min> <controlpoint1_x_max>250</controlpoint1_x_max> <controlpoint1_y_min>25</controlpoint1_y_min> <controlpoint1_y_max>75</controlpoint1_y_max> <controlpoint2_x_min>-50</controlpoint2_x_min> <controlpoint2_x_max>250</controlpoint2_x_max> <controlpoint2_y_min>125</controlpoint2_y_min> <controlpoint2_y_max>175</controlpoint2_y_max> </bezier> </gen_map>