FeXoR Posted February 27, 2012 Report Share Posted February 27, 2012 (edited) I wrote a random map generator and now want to know where to talk about it and where to share it if it's good enough.I found it hard to find the things I need inside the code of the helper functions inside the "rmgen" directory. Is there a documentation or a small tutorial out there?And what variables can be set in the .json file?For those who have similar issues:- The directory own scripts can be added and then work with the game and the editor in windows is (similar to the player made "scenarios" folder):c:\users\[username]\AppData\Roaming\0ad\cache\mods\public\maps\random Edited February 28, 2012 by FeXoR Quote Link to comment Share on other sites More sharing options...
historic_bruno Posted February 28, 2012 Report Share Posted February 28, 2012 It's all fairly well documented on Trac actually: http://trac.wildfiregames.com/wiki/Random_Map_GeneratorExcept for the .json file, I don't see documentation for that yet Basically it follows the same format as scenarios, if you look in maps\scenarios\*.xml in the <scriptSettings> element, you will see for example:{ "CircularMap": true, "Description": "Arch enemies, Rome and Carthage, square off on a richly detailed map of Southern Italy.\u000a\u000aScout the lands to find free Treasures and to secure new resources.", "GameType": "conquest", "Keywords": [], "LockTeams": false, "Name": "Acropolis III", "PlayerData": [ { "AI": "", "Civ": "rome", "Colour": { "b": 13, "g": 13, "r": 166 }, "Name": "Player 1", "Resources": { "food": 400, "wood": 400 }, "Team": -1 }, { "AI": "qbot", "Civ": "cart", "Colour": { "b": 168, "g": 64, "r": 55 }, "Name": "Player 2", "Resources": { "food": 400, "wood": 400 }, "Team": -1 } ], "RevealMap": false} I'll try adding documentation about this. Quote Link to comment Share on other sites More sharing options...
historic_bruno Posted February 28, 2012 Report Share Posted February 28, 2012 Documented the JSON here: http://trac.wildfiregames.com/wiki/Random_Map_Generator_Internals#DefiningtheMap Quote Link to comment Share on other sites More sharing options...
FeXoR Posted February 28, 2012 Author Report Share Posted February 28, 2012 THX, that helps.I made the different civil centers align to the diagonal grid that is used in-game for placing structures by default but roughly facing the center of the map (1*PI/4, 3*PI/4, 5*PI/4 and 7*PI/4).I thought that wouldn't result in problems since a change of the wired const "BUILDING_ANGlE" (with a small written "L" ^^) did'nt change anything in-game (but the orientation of all map-generated buildings of cause).So I made them different for each player and set them as a variable.Well, but sometimes, often enough to occur 50% at 8 player maps, one or two civil centers are facing in a non-alligned directions (And some functions afterwards are not called).Is the orientation for buildings in general needed as a const or even need to be named "BUILDING_ANGlE"? Quote Link to comment Share on other sites More sharing options...
historic_bruno Posted February 28, 2012 Report Share Posted February 28, 2012 Is the orientation for buildings in general needed as a const or even need to be named "BUILDING_ANGlE"?It's just the convention to have all the buildings facing in the same direction for aesthetic reasons, in other words facing towards the starting camera which is the same for all players (Mythos_Ruler was very insistent on that ). That constant might be defined in each separate file, but it should be moved to the rmgen library instead.Edit: Also AIs, I believe they layout their buildings in the same direction. Quote Link to comment Share on other sites More sharing options...
Mythos_Ruler Posted February 28, 2012 Report Share Posted February 28, 2012 It's just the convention to have all the buildings facing in the same direction for aesthetic reasons, in other words facing towards the starting camera which is the same for all players (Mythos_Ruler was very insistent on that ). That constant might be defined in each separate file, but it should be moved to the rmgen library instead.It's also better for gameplay, so that there is a consistent exit point for units and a consistent start point for building rotation if players want units to exit in a different direction. Quote Link to comment Share on other sites More sharing options...
FeXoR Posted February 29, 2012 Author Report Share Posted February 29, 2012 THX for the reply!The problem was within my file and it's fixed now.However, the building orientation IS inside the grid the AI and the start orientation in-game uses, but there are still the 4 possibilities.Well, not a big issue since it works fine now.I did many things very different then it is handled in the other RMGs.Mine is a very early state until now and more for getting to know the functions, but if anyone wants to take a look:fexor_rmg.rar Quote Link to comment Share on other sites More sharing options...
FeXoR Posted February 29, 2012 Author Report Share Posted February 29, 2012 (edited) Oh, and for those preferring .zip:fexor_rmg.zipEDIT: My dear, wrong version, now it should work... [hope] Edited February 29, 2012 by FeXoR Quote Link to comment Share on other sites More sharing options...
FeXoR Posted February 29, 2012 Author Report Share Posted February 29, 2012 (edited) BTW! The mathematical orientation (defined by cos/sin in x/y direction) and the unit/building orientation differs.I think unit orientation is:-(mathematical orientation - PI/2)How did that happen?And why is the second vertical orientation named "z" instead of "y"?I thought "z" would be the hight over ground or to a base hight but in 0ad it's "y"?Sorry, questions and more questions x) Edited February 29, 2012 by FeXoR Quote Link to comment Share on other sites More sharing options...
historic_bruno Posted February 29, 2012 Report Share Posted February 29, 2012 And why is the second vertical orientation named "z" instead of "y"?I thought "z" would be the hight over ground or to a base hight but in 0ad it's "y"?That was just a choice made long ago and unlikely to change I've seen either Y or Z used as height equally in different applications (X could be used, too but that would be weird). Quote Link to comment Share on other sites More sharing options...
FeXoR Posted February 29, 2012 Author Report Share Posted February 29, 2012 Sooo...Here's a function to place civil center and starting units just by giving the location and the player index of the player the units should be placed for.This is the (very) detailed version for (hopefully) good readability, a shorter version will be added:// Funtion to place civil centre and starting units at given location for a given playerfunction placeStartUnits0adAlike(startLocation, playerId)// "startLocation" should be a list of length 2 with floats determining the 2d-point where the starting entities shall be placed.// "startLocation[0]" should be an float determining the x coordinate of the start location.// "startLocation[1]" should be an float determining the z coordinate of the start location. (Should by y in my book though)// "playerId" should be the player number like seen in Atlas or the game settings ingame (Starting with 1 for the first player with default colour blue, 0 is Gaia){ // Some checks. Enhance if needed... // Setting some variables // Setting default building angle var buildingAngle = 3*Math.PI/4; // Getting civilisation string var civ = g_MapSettings.PlayerData[i].Civ; // Getting civilisation dependent default starting entities var civEntities = g_CivData[civ].StartEntities; // Setting start tile. Not needed but done in the other RMGs so.... var startTile = new Array(2) startTile[0]= round(startLocation[0]) startTile[1]= round(startLocation[1]) // Place civil centre on the start tile placeObject(startTile[0], startTile[1], civEntities[0].Template, playerId, buildingAngle); // Place starting units // Minimal distance to start location so that units don't stand in the civil centere var minDistToCC = 4; // Minimal distance between units so they don't overlap var minDist = 1; // Set general orientation of units var angleMain = -(buildingAngle - PI/2); // This is a bug in my book, it should be the same as building orientation... // Set angle width units should be spread over var angleSpread = PI/4; // Preset angle the first unit should be placed, reset in the outer loop var angleStart = angleMain - angleSpread/2; // Preset angle distance between one unit and the next of the same type, reset in the outer loop var angleAdd = 0; // Preset the angle a unit will be placed in comperison to the civil centre, reset inside the inner loop var angleActual = angleStart; // Preset number of units to place by default of the same type, reset in outer loop var numberOfUnitsOfSameType = 1; // Preset unit template, reset in the outer loop var unitTemplate = ''; // Preset postition the unit will be placed, reset inside the inner loop var unitPosition = new Array(2); unitPosition[0] = startTile[0]; unitPosition[1] = startTile[1]; // Preset orientation of placed unit, reset in the inner loop var unitOrientation = 0; // Outer loop for the diffrent unit types to place beside the civil centre (so starting with 1) for (var unitTypeIndex = 1; unitTypeIndex < civEntities.length; ++unitTypeIndex) { // Reset default number of units of that type numberOfUnitsOfSameType = (civEntities[unitTypeIndex].Count !== undefined ? civEntities[unitTypeIndex].Count : 1); // Reset the angle added per unit of that type depending on the number of them, for multiple units of that type only (otherwise 0 devision) if (numberOfUnitsOfSameType > 1) {angleAdd = angleSpread/(numberOfUnitsOfSameType-1)}; // Reset unit tamplate unitTemplate = civEntities[unitTypeIndex].Template; // Inner loop for multiple units of the same type for (var unitIndex = 0; unitIndex < numberOfUnitsOfSameType; unitIndex++) { // Resetting the angle the unit if (numberOfUnitsOfSameType > 1) {angleActual = angleStart + unitIndex*angleAdd} else {angleActual = angleMain}; // Reset the angle the unit will be placed in comperison to the civil centre unitPosition[0] = startTile[0] + (minDistToCC + minDist*unitTypeIndex)*cos(angleActual); unitPosition[1] = startTile[1] + (minDistToCC + minDist*unitTypeIndex)*sin(angleActual); // Reset orientation of placed unit unitOrientation = -(angleActual - PI/2); // Here is the bug again... // Place the unit placeObject(unitPosition[0], unitPosition[1], unitTemplate, playerId, unitOrientation); }; };};Â BTW, this does'nt seam to be a good place to put this, suggestions very welcome.P.S.: Did I mention this game is pure @#$%ing awesomeness?P.P.S.: Oh, I hope I did'nt break any forum rules now ;0| Quote Link to comment Share on other sites More sharing options...
FeXoR Posted February 29, 2012 Author Report Share Posted February 29, 2012 Got some strange formation issues in the post writer tool... well...Here's a more reasonable version.Swapped sin and cos so unit orientation and mathematical point calculation matches.Still I think that's a little strange...Many variables are set in the loop now with var over and over again... is this OK?But it's much shorter now:// Funtion to place civil centre and starting units at given location for a given playerfunction placeStartUnits(startLocation, playerId)// "startLocation" should be a list of length 2 with floats determining the 2d-point where the starting entities shall be placed.// "startLocation[0]" should be an float determining the x coordinate of the start location.// "startLocation[1]" should be an float determining the z coordinate of the start location. (Should by y in my book though)// "playerId" should be the player number like seen in Atlas or the game settings ingame (Starting with 1 for the first player with default colour blue, 0 is Gaia){ // Some checks. Enhance if needed... // Setting some variables // Setting default building angle, can be got from the global "BUILDING_ANGlE" in further versions var buildingOrientation = 3*Math.PI/4; // Getting civilisation dependent default starting entities var civEntities = g_CivData[g_MapSettings.PlayerData[i].Civ].StartEntities; // Place civil centre on the start location placeObject(startLocation[0], startLocation[1], civEntities[0].Template, playerId, buildingOrientation); // Place starting units // Minimal distance to start location so that units don't stand in the civil centere var minDistToCC = 4; // Minimal distance between units so they don't overlap var minDist = 1; // Set angle width units should be spread over var angleSpread = PI/4; // Outer loop for the diffrent unit types to place beside the civil centre (so starting with 1) for (var unitTypeIndex = 1; unitTypeIndex < civEntities.length; ++unitTypeIndex) { // Reset default number of units of that type var unitCount = (civEntities[unitTypeIndex].Count !== undefined ? civEntities[unitTypeIndex].Count : 1); // Reset the angle added per unit of that type depending on the number of them, for multiple units of that type only (otherwise 0 devision) if (unitCount > 1) {var angleAdd = angleSpread/(unitCount-1)}; // Inner loop for multiple units of the same type for (var unitIndex = 0; unitIndex < unitCount; unitIndex++) { // Resetting the angle the unit will be placed in comperison to the city centre if (unitCount > 1) {var angleActual = buildingOrientation - angleSpread/2 + unitIndex*angleAdd} else {var angleActual = buildingOrientation}; // Place the unit placeObject( startLocation[0] + (minDistToCC + minDist*unitTypeIndex)*sin(angleActual), startLocation[1] + (minDistToCC + minDist*unitTypeIndex)*cos(angleActual), civEntities[unitTypeIndex].Template, playerId, angleActual); }; };}; Quote Link to comment Share on other sites More sharing options...
Spahbod Posted February 29, 2012 Report Share Posted February 29, 2012 This function is already present in SVN version of the game. It now looks like this:function createStartingPlayerEntities(fx, fz, playerid, civEntities, BUILDING_ANGlE){ var uDist = 6; var uSpace = 2; placeObject(fx, fz, civEntities[0].Template, playerid, BUILDING_ANGlE); for (var j = 1; j < civEntities.length; ++j) { var uAngle = -BUILDING_ANGlE + PI * (j - 1) / 2; var count = (civEntities[j].Count !== undefined ? civEntities[j].Count : 1); for (var numberofentities = 0; numberofentities < count; numberofentities++) { var ux = fx + uDist * cos(uAngle) + numberofentities * uSpace * cos(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * cos(uAngle + PI/2)); var uz = fz + uDist * sin(uAngle) + numberofentities * uSpace * sin(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * sin(uAngle + PI/2)); placeObject(ux, uz, civEntities[j].Template, playerid, (j % 2 - 1) * PI + uAngle); } }} Quote Link to comment Share on other sites More sharing options...
FeXoR Posted February 29, 2012 Author Report Share Posted February 29, 2012 I think something like that should be added to one of the rmgen .js files to make it easier for random map designers.They still can make there own arrangements of starting units if they like.Perhaps some value checks of function parameters should be added...Perhaps the starting units should be placed right (female peasants), left (male peasants) and in front (Scout) to need less space (smaller maximum distance to start location).Greetings U gorgeous bunch of individuals!Oh, did'nt see this, thx! Quote Link to comment Share on other sites More sharing options...
FeXoR Posted February 29, 2012 Author Report Share Posted February 29, 2012 But you insist of define coordinated one by one.Do you think that is wise?Or tell me a reason?Well, sry, your decision... Quote Link to comment Share on other sites More sharing options...
FeXoR Posted February 29, 2012 Author Report Share Posted February 29, 2012 Hehe, U made the same "mistake" like me.Swap sin and cos ^^ Quote Link to comment Share on other sites More sharing options...
Spahbod Posted February 29, 2012 Report Share Posted February 29, 2012 But you insist of define coordinated one by one.Do you think that is wise?Or tell me a reason?Well, sry, your decision...We want the function to be simple to use for new scripters. Also it is better to have a unified formation for all random maps.Hehe, U made the same "mistake" like me.Swap sin and cos ^^ Quote Link to comment Share on other sites More sharing options...
FeXoR Posted February 29, 2012 Author Report Share Posted February 29, 2012 To adjust the "build in" unit orientation of all (I guess) entity placement functions to the "usually" used determination of the unit position in polar coordinates (by distance and angle to the position of the civil center with cos/sin for x/y) it is adjusted by inverting the angle:var uAngle = -BUILDING_ANGlE + PI * (j - 1) / 2;Note the "-" in front of "BUILDING_ANGlE"....and then adding (or subtract dependent of the braces used) PI/2:var ux = fx + uDist * cos(uAngle) + numberofentities * uSpace * cos(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * cos(uAngle + PI/2)); var uz = fz + uDist * sin(uAngle) + numberofentities * uSpace * sin(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * sin(uAngle + PI/2));Note the "uAngle + PI/2" in cos/sin.But it can be done by switching cos and sin like it's done in my second function.I don't know yet if this is mathematical correct implemented when the 2nd planar axis is indeed z and not y.But at least it's hard to get used to for me (and as it seams to others too ^^)Hope i managed to explain my point. Quote Link to comment Share on other sites More sharing options...
FeXoR Posted February 29, 2012 Author Report Share Posted February 29, 2012 I missed some functions to determine the distance between two points and the angle the vector between them has.So I added some functions to my script:// Function to get the distance between 2 pointsfunction getDistance(point1, point2) {return Math.pow(Math.pow(point1[0] - point2[0], 2) + Math.pow(point1[1] - point2[1], 2), 1/2)};// Function to get the distance between 2 points given in seperate coordinatesfunction getDistanceXZ(x1, z1, x2, z2) {return getDistance([x1, z1], [x2, z2])};// Function to get the direction from one point to anotherfunction getDirection(point1, point2) {return Math.asin((point2[1] - point1[1])/getDistance(point1, point2))};function getDirectionAlternative(point1, point2) {return Math.acos((point2[0] - point1[0])/getDistance(point1, point2))};// Function to get the direction from one point to another given in seperate coordinatesfunction getDirectionXZ(x1, z1, x2, z2) {return getDirection([x1, z1], [x2, z2])}; Quote Link to comment Share on other sites More sharing options...
FeXoR Posted February 29, 2012 Author Report Share Posted February 29, 2012 I HOPE with the exchanged sin/cos everything's in order Quote Link to comment Share on other sites More sharing options...
FeXoR Posted February 29, 2012 Author Report Share Posted February 29, 2012 (edited) Of cause I mixed it up...And forgot the area of definition that is only PI not 2*PI...A function working and consistent to the unit placement orientation for getting the angle of a vector from one point towards another is for example (perhaps not the best):// Function to get the direction from one point to anotherfunction getDirection(point1, point2){ var vector = [point2[0] - point1[0], point2[1] - point1[1]]; var output = Math.acos(vector[0]/getDistance(point1, point2)); if (vector[1] > 0) {output = PI + (PI - Math.acos(vector[0]/getDistance(point1, point2)))}; return (output + PI/2) % (2*PI);};The other functions are correct... Edited February 29, 2012 by FeXoR Quote Link to comment Share on other sites More sharing options...
FeXoR Posted February 29, 2012 Author Report Share Posted February 29, 2012 Opened a new topic:getDistance(point1, point2) and getDirection(point1, point2) from one point to another Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.