|
|
|
@@ -2,161 +2,329 @@ Engine.LoadLibrary("rmgen");
|
|
|
|
|
|
|
|
|
|
InitMap();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Demonstration code for wall placement.
|
|
|
|
|
*
|
|
|
|
|
* Some notes/reminders:
|
|
|
|
|
* - All angles (orientation) are in radians.
|
|
|
|
|
* - When looking at the map, with the x-axis being horizontal and the y-axis vertical:
|
|
|
|
|
* -- The origin point (0,0) of the map is in the bottom-left corner,
|
|
|
|
|
* -- A wall orientated at 0 has its "outside" facing right and its "inside" facing left.
|
|
|
|
|
* -- A wall orientated at Pi is reversed (obviously).
|
|
|
|
|
* -- A wall orientated at Pi/2 has its "outside" facing down and its "inside" facing up.
|
|
|
|
|
* - As a general rule, walls are drawn in a anti-clockwise direction.
|
|
|
|
|
*
|
|
|
|
|
* Some general notes concerning the arguments:
|
|
|
|
|
*
|
|
|
|
|
* - The first two arguments for most placement functions are x/y co-ordinates needed to position the wall. These are received via separate arguments, like in placeObject(), and their exact meaning differs between methods, but should be mostly self explanatory. The exception to this is placeLinearWall(), where the first four arguments are co-ordinates. However, whether two argument or four, the initial x/y co-ordinates are required parameters.
|
|
|
|
|
*
|
|
|
|
|
* - For some functions, the next argument is radius, indicating how far from a central point the wall should be drawn. The functions that use this are marked as doing so below.
|
|
|
|
|
*
|
|
|
|
|
* - The next argument is usually an array containing wall element type strings. (See the block comment for getWallElement() for a list of accepted type strings.) The exception to this is placeFortress(), which accepts a string here instead, identifying which of the predefined fortresses designs you wish to use. (See the example provided below for details.)
|
|
|
|
|
*
|
|
|
|
|
* Most functions will ask that you do not include "bending" wall elements in your array ("cornerIn", "cornerOut", "turn_{x}") and will complain if you attempt to do so. The ones that do this are clearly marked below.
|
|
|
|
|
*
|
|
|
|
|
* The array will generally look like:
|
|
|
|
|
* ["start", "medium", "tower", "gate", "tower", "medium", "end"]
|
|
|
|
|
*
|
|
|
|
|
* Remember that walls are drawn in an anti-clockwise direction. Thus, when looking at a wall element in-game, with the "outside" facing up, then the *next* wall element will be drawn to the left of *this* element.
|
|
|
|
|
*
|
|
|
|
|
* This argument is optional, and each function has a different default value.
|
|
|
|
|
*
|
|
|
|
|
* - The next argument is a string denoting the style of the wall. These are derived from the names of wallsets defined in 0ad: for example "athen_wallset_stone" becomes "athen_stone", and "rome_wallset_seige" becomes "rome_seige". (A full list can be found stored as the keys of the global constant g_WallStyles.) This argument is optional, and if not set, the civ's basic stone wallset will be used.
|
|
|
|
|
*
|
|
|
|
|
* - The next argument is the player-id of the player that is to own the wall. This argument is optional, and defaults to 0 (gaia).
|
|
|
|
|
*
|
|
|
|
|
* - The next argument is an angle defining the angle of orientation of the wall. The exact use differs slightly between functions, but hopefully the comments on the examples below should help. Also see the notes above about wall orientation. This argument is optional, and defaults to 0.
|
|
|
|
|
*
|
|
|
|
|
* - Any remaining arguments differ from function to function, but are all optional. Please read the comments below, and also the block comment of the function in wall_builder.js for further details.
|
|
|
|
|
*
|
|
|
|
|
* And have fun!
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
var mapSize = getMapSize();
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////
|
|
|
|
|
// Demonstration code for wall placement
|
|
|
|
|
////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
// Some general notes to the arguments:
|
|
|
|
|
|
|
|
|
|
// First all the place functions take the coordinates needed to place the wall
|
|
|
|
|
// X and Y coordinate are taken in seperate arguments like in placeObject
|
|
|
|
|
// Their meaning differs for different placement methods but are mainly self explanatory
|
|
|
|
|
// placeLinearWall takes 4 arguments here (2 coordinates) for startX, startY, targetX and targetY
|
|
|
|
|
|
|
|
|
|
// The next argument is always the 'wall' definition, an array of wall element type strings in most cases
|
|
|
|
|
// That looks like ['endLeft', 'wall', 'tower', 'wall', 'endRight', 'entry', 'endLeft', 'wall', 'tower', 'wall', 'endRight']
|
|
|
|
|
// For placeCircularWall and placeLinearWall only wall parts are needed like: ['tower', 'wall']
|
|
|
|
|
// They will automatically end with the first wall element if that makes sense (e.g. the wall is not closed)
|
|
|
|
|
// NOTE: They take further optional arguments to adjust this behaviour (See the wall_builder.js for that)
|
|
|
|
|
// placeFortress just takes a fortress type string that includes the wall definition
|
|
|
|
|
// The default fortress type strings are made for easy placement of predefined fortresses
|
|
|
|
|
// They are chosen like map sizes: 'tiny', 'small', 'medium', 'normal', 'large', 'veryLarge' and 'giant'
|
|
|
|
|
// NOTE: To place a custom fortress use placeCustomFortress instead
|
|
|
|
|
// It takes an instance of the Fortress class instead of the default fortress type strings
|
|
|
|
|
|
|
|
|
|
// The next argument is always the wall style string
|
|
|
|
|
// Wall styles are chosen by strings so the civ strings got by getCivCode() can be used
|
|
|
|
|
// Other styles may be present as well but besides the civ styles only 'palisades' includes all wall element types (yet)
|
|
|
|
|
|
|
|
|
|
// The next argument is always the index of the player that owns the wall.
|
|
|
|
|
// 0 is Gaia, 1 is Player 1 (default color blue), 2 is Player 2 (default color red), ...
|
|
|
|
|
|
|
|
|
|
// The next argument is an angle defining the orientation of the wall
|
|
|
|
|
// placeLinearWall does not need an angle since it's defined by startX/Y and targetX/Y
|
|
|
|
|
// Orientation works like the angle argument in placeObject
|
|
|
|
|
// 0 is always right (towards positive X)
|
|
|
|
|
// Raising the angle will rotate the wall counter-clockwise (mathmatical positive in default 2D)
|
|
|
|
|
// PI/2 faces top (positive Y)
|
|
|
|
|
// Orientation might be a little confusing for placeWall since it defines where the wall has its 'front' or 'outside' not the direction it will be build to.
|
|
|
|
|
// It's because all other methods work like that and it's intuitive there
|
|
|
|
|
// That means the walls outside by default (orientation = 0) faces positive X and (without bending wall elements) will be build towards positive Y
|
|
|
|
|
|
|
|
|
|
// Some other arguments are taken but all of them are optional and in most cases not needed
|
|
|
|
|
// One example is maxAngle for placeCircularWall that defines how far the wall will circumvent the center. Default is 2*PI which makes a full circle
|
|
|
|
|
|
|
|
|
|
// General wall placement setup
|
|
|
|
|
/**
|
|
|
|
|
* General wall placement setup
|
|
|
|
|
*/
|
|
|
|
|
const distToMapBorder = 5;
|
|
|
|
|
const distToOtherWalls = 10;
|
|
|
|
|
var buildableMapSize = mapSize - 2 * distToMapBorder;
|
|
|
|
|
var actualX = distToMapBorder;
|
|
|
|
|
var actualY = distToMapBorder;
|
|
|
|
|
// Wall styles are chosen by strings so the civ strings got by getCivCode() can be used
|
|
|
|
|
// Other styles may be present as well but besides the civ styles only 'palisades' includes all wall element types (yet)
|
|
|
|
|
const wallStyleList = ["athen", "brit", "cart", "gaul", "iber", "mace", "maur", "pers", "ptol", "rome", "sele", "spart", "rome_siege", "palisades"];
|
|
|
|
|
var playerID = 0;
|
|
|
|
|
const wallStyleList = Object.keys(g_WallStyles);
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////
|
|
|
|
|
// Custom wall placement (element based)
|
|
|
|
|
////////////////////////////////////////
|
|
|
|
|
var wall = ['endLeft', 'wallLong', 'tower', 'wall', 'outpost', 'wall', 'cornerOut', 'wall', 'cornerIn', 'wall', 'house', 'endRight', 'entryTower', 'endLeft', 'wallShort', 'barracks', 'gate', 'tower', 'wall', 'wallFort', 'wall', 'endRight'];
|
|
|
|
|
for (let styleIndex = 0; styleIndex < wallStyleList.length; ++styleIndex)
|
|
|
|
|
/**
|
|
|
|
|
* Custom wall placement (element based).
|
|
|
|
|
*
|
|
|
|
|
* Like most wall placement functions, we have to supply an x/y position.
|
|
|
|
|
* In this case, the x/y position marks the start of the wall.
|
|
|
|
|
*
|
|
|
|
|
* For this function, orientation indicates the angle at which the first
|
|
|
|
|
* wall element should be drawn. (The direction that the outside of the
|
|
|
|
|
* first wall element faces towards.)
|
|
|
|
|
*
|
|
|
|
|
* This function permits bending wall elements.
|
|
|
|
|
*/
|
|
|
|
|
for (let styleIndex in wallStyleList)
|
|
|
|
|
{
|
|
|
|
|
let startX = actualX + styleIndex * buildableMapSize/wallStyleList.length; // X coordinate of the first wall element
|
|
|
|
|
let startY = actualY; // Y coordinate of the first wall element
|
|
|
|
|
let style = wallStyleList[styleIndex]; // // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades'
|
|
|
|
|
let orientation = styleIndex * PI/64; // Orientation of the first wall element. 0 means 'outside' or 'front' is right (positive X, like object placement)
|
|
|
|
|
// That means the wall will be build towards top (positive Y) if no corners are used
|
|
|
|
|
let playerId = 0; // Owner of the wall (like in placeObject). 0 is Gaia, 1 is Player 1 (default color blue), ...
|
|
|
|
|
placeWall(startX, startY, wall, style, playerId, orientation); // Actually placing the wall
|
|
|
|
|
}
|
|
|
|
|
actualX = distToMapBorder; // Reset actualX
|
|
|
|
|
actualY += 80 + distToOtherWalls; // Increase actualY for next wall placement method
|
|
|
|
|
let x = actualX + styleIndex * buildableMapSize / wallStyleList.length;
|
|
|
|
|
let y = actualY;
|
|
|
|
|
let wall = ['start', 'long', 'tower', 'tower', 'tower', 'medium', 'outpost', 'medium', 'cornerOut', 'medium', 'cornerIn', 'medium', 'house', 'end', 'entryTower', 'start', 'short', 'barracks', 'gate', 'tower', 'medium', 'fort', 'medium', 'end'];
|
|
|
|
|
let style = wallStyleList[styleIndex];
|
|
|
|
|
let orientation = Math.PI / 16 * Math.sin(styleIndex * Math.PI / 4);
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
|
// Default fortress placement (chosen by fortress type string)
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
|
var fortressRadius = 15; // The space the fortresses take in average. Just for design of this map
|
|
|
|
|
for (let styleIndex = 0; styleIndex < wallStyleList.length; ++styleIndex)
|
|
|
|
|
placeWall(x, y, wall, style, playerID, orientation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Prep for next set of walls
|
|
|
|
|
actualX = distToMapBorder;
|
|
|
|
|
actualY += 80 + distToOtherWalls;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Default fortress placement (chosen by fortress type string)
|
|
|
|
|
*
|
|
|
|
|
* The x/y position in this case marks the center point of the fortress.
|
|
|
|
|
* To make it clearer, we add an obilisk as a visual marker.
|
|
|
|
|
*
|
|
|
|
|
* This is the only wall placement function that does not take an array
|
|
|
|
|
* of elements as an argument. Instead, we provide a "type" that identifies
|
|
|
|
|
* a predefined design to draw. The list of possible types are: "tiny",
|
|
|
|
|
* "small", "medium", "normal", "large", "veryLarge", and "giant".
|
|
|
|
|
*
|
|
|
|
|
* For this function, orientation is the direction in which the main gate
|
|
|
|
|
* is facing.
|
|
|
|
|
*/
|
|
|
|
|
var fortressRadius = 15; // The space the fortresses take in average. Just for design of this map. Not passed to the function.
|
|
|
|
|
|
|
|
|
|
for (let styleIndex in wallStyleList)
|
|
|
|
|
{
|
|
|
|
|
let centerX = actualX + fortressRadius + styleIndex * buildableMapSize/wallStyleList.length; // X coordinate of the center of the fortress
|
|
|
|
|
let centerY = actualY + fortressRadius; // Y coordinate of the center of the fortress
|
|
|
|
|
let type = 'tiny'; // Default fortress types are like map sizes: 'tiny', 'small', 'medium', 'large', 'veryLarge', 'giant'
|
|
|
|
|
let style = wallStyleList[styleIndex]; // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades'
|
|
|
|
|
let playerId = 0; // Owner of the wall. 0 is Gaia, 1 is Player 1 (default color blue), ...
|
|
|
|
|
let orientation = styleIndex * PI/32; // Where the 'main entrance' of the fortress should face (like in placeObject). All fortresses walls should start with an entrance
|
|
|
|
|
placeFortress(centerX, centerY, type, style, playerId, orientation); // Actually placing the fortress
|
|
|
|
|
placeObject(centerX, centerY, 'other/obelisk', 0, 0*PI); // Place visual marker to see the center of the fortress
|
|
|
|
|
}
|
|
|
|
|
actualX = distToMapBorder; // Reset actualX
|
|
|
|
|
actualY += 2 * fortressRadius + 2 * distToOtherWalls; // Increase actualY for next wall placement method
|
|
|
|
|
let x = actualX + fortressRadius + styleIndex * buildableMapSize / wallStyleList.length;
|
|
|
|
|
let y = actualY + fortressRadius;
|
|
|
|
|
let type = "tiny";
|
|
|
|
|
let style = wallStyleList[styleIndex];
|
|
|
|
|
let orientation = styleIndex * Math.PI / 32;
|
|
|
|
|
|
|
|
|
|
//////////////////////////
|
|
|
|
|
// Circular wall placement
|
|
|
|
|
//////////////////////////
|
|
|
|
|
// NOTE: Don't use bending wall elements like corners here!
|
|
|
|
|
var radius = min((mapSize - actualY - distToOtherWalls) / 3, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); // The radius of wall circle
|
|
|
|
|
var centerY = actualY + radius; // Y coordinate of the center of the wall circle
|
|
|
|
|
var orientation = 0; // Where the wall circle will be open if maxAngle < 2*PI, see below. Otherwise where the first wall element will be placed
|
|
|
|
|
for (let styleIndex = 0; styleIndex < wallStyleList.length; ++styleIndex)
|
|
|
|
|
placeObject(x, y, "other/obelisk", playerID, orientation);
|
|
|
|
|
placeFortress(x, y, type, style, playerID, orientation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Prep for next set of walls
|
|
|
|
|
actualX = distToMapBorder;
|
|
|
|
|
actualY += 2 * fortressRadius + distToOtherWalls;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 'Generic' fortress placement (iberian wall circuit code)
|
|
|
|
|
*
|
|
|
|
|
* The function used here is unusual in that the owner and style arguments
|
|
|
|
|
* are swapped. It is also unusual in that we do not supply an orientation.
|
|
|
|
|
*
|
|
|
|
|
* The x/y position in this case marks the center point of the fortress.
|
|
|
|
|
* To make it clearer, we add an obilisk as a visual marker.
|
|
|
|
|
*
|
|
|
|
|
* We also supply a radius value to dictate how wide the circuit of walls should be.
|
|
|
|
|
*/
|
|
|
|
|
var radius = Math.min((mapSize - actualY - distToOtherWalls) / 3, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2);
|
|
|
|
|
for (let styleIndex in wallStyleList)
|
|
|
|
|
{
|
|
|
|
|
let centerX = actualX + radius + styleIndex * buildableMapSize/wallStyleList.length; // X coordinate of the center of the wall circle
|
|
|
|
|
let playerId = 0; // Player ID of the player owning the wall, 0 is Gaia, 1 is the first player (default blue), ...
|
|
|
|
|
let wallPart = ['tower', 'wall', 'house']; // List of wall elements the wall will be build of. Optional, default id ['wall']
|
|
|
|
|
let style = wallStyleList[styleIndex]; // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades'
|
|
|
|
|
let maxAngle = PI/2 * (styleIndex%3 + 2); // How far the wall should circumvent the center
|
|
|
|
|
placeCircularWall(centerX, centerY, radius, wallPart, style, playerId, orientation, maxAngle); // Actually placing the wall
|
|
|
|
|
placeObject(centerX, centerY, 'other/obelisk', 0, 0*PI); // Place visual marker to see the center of the wall circle
|
|
|
|
|
orientation += PI/16; // Increasing orientation to see how rotation works (like for object placement)
|
|
|
|
|
}
|
|
|
|
|
actualX = distToMapBorder; // Reset actualX
|
|
|
|
|
actualY += 2 * radius + distToOtherWalls; // Increase actualY for next wall placement method
|
|
|
|
|
let centerX = actualX + radius + styleIndex * buildableMapSize / wallStyleList.length;
|
|
|
|
|
let centerY = actualY + radius;
|
|
|
|
|
let style = wallStyleList[styleIndex];
|
|
|
|
|
|
|
|
|
|
///////////////////////////
|
|
|
|
|
// Polygonal wall placement
|
|
|
|
|
///////////////////////////
|
|
|
|
|
// NOTE: Don't use bending wall elements like corners here!
|
|
|
|
|
var radius = min((mapSize - actualY - distToOtherWalls) / 2, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); // The radius of wall polygons
|
|
|
|
|
var centerY = actualY + radius; // Y coordinate of the center of the wall polygon
|
|
|
|
|
var orientation = 0; // Where the wall circle will be open if ???, see below. Otherwise where the first wall will be placed
|
|
|
|
|
for (let styleIndex = 0; styleIndex < wallStyleList.length; ++styleIndex)
|
|
|
|
|
placeObject(centerX, centerY, 'other/obelisk', playerID, 0);
|
|
|
|
|
placeGenericFortress(centerX, centerY, radius, playerID, style);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Prep for next set of walls
|
|
|
|
|
actualX = distToMapBorder;
|
|
|
|
|
actualY += 2 * radius + distToOtherWalls;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Circular wall placement
|
|
|
|
|
*
|
|
|
|
|
* It is possible with this function to draw complete circles, or arcs.
|
|
|
|
|
* Each side of the wall consists of the contents of the provided wall
|
|
|
|
|
* array, with the code calculating the number and angle of turns and
|
|
|
|
|
* sides automatically based on the calculated length of each side and
|
|
|
|
|
* the given radius.
|
|
|
|
|
*
|
|
|
|
|
* This function does not permit the use of bending wall elements.
|
|
|
|
|
*
|
|
|
|
|
* In this case, the x/y co-ordinates are the center point around which
|
|
|
|
|
* to draw the walls. To make this clearer, we add an obelisk as a visual
|
|
|
|
|
* marker.
|
|
|
|
|
*
|
|
|
|
|
* We also provide a radius to define the distance between the center
|
|
|
|
|
* point and the walls.
|
|
|
|
|
*
|
|
|
|
|
* For this function, orientation is the direction that the opening of an
|
|
|
|
|
* arc faces. If the wall is to be a complete circle, then this is used as
|
|
|
|
|
* the orientation of the first wall piece.
|
|
|
|
|
*/
|
|
|
|
|
radius = Math.min((mapSize - actualY - distToOtherWalls) / 3, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2);
|
|
|
|
|
for (let styleIndex in wallStyleList)
|
|
|
|
|
{
|
|
|
|
|
let centerX = actualX + radius + styleIndex * buildableMapSize/wallStyleList.length; // X coordinate of the center of the wall circle
|
|
|
|
|
let playerId = 0; // Player ID of the player owning the wall, 0 is Gaia, 1 is the first player (default blue), ...
|
|
|
|
|
let cornerWallElement = 'tower'; // With wall element type will be uset for the corners of the polygon
|
|
|
|
|
let wallPart = ['wall', 'tower']; // List of wall elements the wall will be build of. Optional, default id ['wall']
|
|
|
|
|
let style = wallStyleList[styleIndex]; // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades'
|
|
|
|
|
let numCorners = (styleIndex)%6 + 3; // How many corners the plogon will have
|
|
|
|
|
let skipFirstWall = true; // If the wall should be open towards orientation
|
|
|
|
|
placePolygonalWall(centerX, centerY, radius, wallPart, cornerWallElement, style, playerId, orientation, numCorners, skipFirstWall);
|
|
|
|
|
placeObject(centerX, centerY, 'other/obelisk', 0, 0*PI); // Place visual marker to see the center of the wall circle
|
|
|
|
|
orientation += PI/16; // Increasing orientation to see how rotation works (like for object placement)
|
|
|
|
|
}
|
|
|
|
|
actualX = distToMapBorder; // Reset actualX
|
|
|
|
|
actualY += 2 * radius + distToOtherWalls; // Increase actualY for next wall placement method
|
|
|
|
|
let centerX = actualX + radius + styleIndex * buildableMapSize / wallStyleList.length;
|
|
|
|
|
let centerY = actualY + radius;
|
|
|
|
|
let wallPart = ['tower', 'medium', 'house'];
|
|
|
|
|
let style = wallStyleList[styleIndex];
|
|
|
|
|
let orientation = styleIndex * Math.PI / 16;
|
|
|
|
|
|
|
|
|
|
////////////////////////
|
|
|
|
|
// Linear wall placement
|
|
|
|
|
////////////////////////
|
|
|
|
|
// NOTE: Don't use bending wall elements like corners here!
|
|
|
|
|
var maxWallLength = (mapSize - actualY - distToMapBorder - distToOtherWalls); // Just for this maps design. How long the longest wall will be
|
|
|
|
|
var numWallsPerStyle = floor(buildableMapSize / distToOtherWalls / wallStyleList.length); // Just for this maps design. How many walls of the same style will be placed
|
|
|
|
|
for (let styleIndex = 0; styleIndex < wallStyleList.length; ++styleIndex)
|
|
|
|
|
// maxAngle is how far the wall should circumscribe the center.
|
|
|
|
|
// If equal to Pi * 2, then the wall will be a full circle.
|
|
|
|
|
// If less than Pi * 2, then the wall will be an arc.
|
|
|
|
|
let maxAngle = Math.PI / 2 * (styleIndex % 3 + 2);
|
|
|
|
|
|
|
|
|
|
placeObject(centerX, centerY, 'other/obelisk', playerID, orientation);
|
|
|
|
|
placeCircularWall(centerX, centerY, radius, wallPart, style, playerID, orientation, maxAngle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Prep for next set of walls.
|
|
|
|
|
actualX = distToMapBorder;
|
|
|
|
|
actualY += 2 * radius + distToOtherWalls;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Regular Polygonal wall placement
|
|
|
|
|
*
|
|
|
|
|
* This function draws a regular polygonal wall around a given point. All
|
|
|
|
|
* the sides follow the same pattern, and the (automatically calculated)
|
|
|
|
|
* angles at the corners are identical. We define how many corners we want.
|
|
|
|
|
*
|
|
|
|
|
* This function does not permit the use of bending wall elements.
|
|
|
|
|
*
|
|
|
|
|
* In this case, the x/y co-ordinates are the center point around which
|
|
|
|
|
* to draw the walls. To make this clearer, we add an obelisk as a visual
|
|
|
|
|
* marker.
|
|
|
|
|
*
|
|
|
|
|
* We also provide a radius to define the distance between the center
|
|
|
|
|
* point and the walls.
|
|
|
|
|
*
|
|
|
|
|
* After the usual array of wall elements to use, and before the style
|
|
|
|
|
* argument, we provide the name of a single wall element to use as a
|
|
|
|
|
* corner piece.
|
|
|
|
|
*
|
|
|
|
|
* In this function, orientation is the direction the first wall has its
|
|
|
|
|
* outward side facing or, if the `skipFirstWall` argument is true, the
|
|
|
|
|
* opening in the wall.
|
|
|
|
|
*/
|
|
|
|
|
radius = Math.min((mapSize - actualY - distToOtherWalls) / 2, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2);
|
|
|
|
|
for (let styleIndex in wallStyleList)
|
|
|
|
|
{
|
|
|
|
|
let centerX = actualX + radius + styleIndex * buildableMapSize / wallStyleList.length;
|
|
|
|
|
let centerY = actualY + radius;
|
|
|
|
|
let wallParts = ['medium', 'tower']; // Function default: ['long', 'tower']
|
|
|
|
|
|
|
|
|
|
// Which wall element to use for the corners of the polygon
|
|
|
|
|
let cornerWallElement = 'tower';
|
|
|
|
|
|
|
|
|
|
let style = wallStyleList[styleIndex];
|
|
|
|
|
let orientation = styleIndex * Math.PI / 16;
|
|
|
|
|
|
|
|
|
|
// How many corners the polygon should have:
|
|
|
|
|
let numCorners = styleIndex % 6 + 3;
|
|
|
|
|
|
|
|
|
|
// If true, the first side will not be drawn, leaving the wall open.
|
|
|
|
|
let skipFirstWall = true;
|
|
|
|
|
|
|
|
|
|
placeObject(centerX, centerY, 'other/obelisk', playerID, orientation);
|
|
|
|
|
placePolygonalWall(centerX, centerY, radius, wallParts, cornerWallElement, style, playerID, orientation, numCorners, skipFirstWall);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Prep for next set of walls.
|
|
|
|
|
actualX = distToMapBorder;
|
|
|
|
|
actualY += 2 * radius + distToOtherWalls;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Irregular Polygonal wall placement
|
|
|
|
|
*
|
|
|
|
|
* This function draws an irregular polygonal wall around a given point.
|
|
|
|
|
* Each side of the wall is different, each element used selected at
|
|
|
|
|
* pesudo-random from an assortment. The angles at the corners also differ.
|
|
|
|
|
* We can control this randomness by changing the irregularity argument.
|
|
|
|
|
*
|
|
|
|
|
* This function does not permit the use of bending wall elements.
|
|
|
|
|
*
|
|
|
|
|
* In this case, the x/y co-ordinates are the center point around which
|
|
|
|
|
* to draw the walls. To make this clearer, we add an obelisk as a visual
|
|
|
|
|
* marker.
|
|
|
|
|
*
|
|
|
|
|
* We also provide a radius to define the distance between the center
|
|
|
|
|
* point and the walls.
|
|
|
|
|
*
|
|
|
|
|
* The usual array of wall elements is left out here, instead we provide
|
|
|
|
|
* the name of a single wall element to use as a corner piece.
|
|
|
|
|
*
|
|
|
|
|
* In this function, orientation is the direction the first wall has its
|
|
|
|
|
* outward side facing or, if the `skipFirstWall` argument is true, the
|
|
|
|
|
* opening in the wall.
|
|
|
|
|
*
|
|
|
|
|
* The very last argument is the collection of wallparts used to build
|
|
|
|
|
* the wall. It is not defined in this example (so as to use the defaults)
|
|
|
|
|
* as it is not easy to comprehend.
|
|
|
|
|
*/
|
|
|
|
|
radius = Math.min((mapSize - actualY - distToOtherWalls) / 2, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); // The radius of wall polygons
|
|
|
|
|
for (let styleIndex in wallStyleList)
|
|
|
|
|
{
|
|
|
|
|
let centerX = actualX + radius + styleIndex * buildableMapSize / wallStyleList.length;
|
|
|
|
|
let centerY = actualY + radius;
|
|
|
|
|
|
|
|
|
|
// Which wall element type will be used for the corners of the polygon.
|
|
|
|
|
let cornerWallElement = 'tower';
|
|
|
|
|
|
|
|
|
|
let style = wallStyleList[styleIndex];
|
|
|
|
|
let orientation = styleIndex * Math.PI / 16;
|
|
|
|
|
|
|
|
|
|
// How many corners the polygon will have
|
|
|
|
|
let numCorners = styleIndex % 6 + 3;
|
|
|
|
|
|
|
|
|
|
// Irregularity of the polygon.
|
|
|
|
|
let irregularity = 0.5;
|
|
|
|
|
|
|
|
|
|
// If true, the first side will not be drawn, leaving the wall open.
|
|
|
|
|
let skipFirstWall = true;
|
|
|
|
|
|
|
|
|
|
placeObject(centerX, centerY, 'other/obelisk', playerID, orientation);
|
|
|
|
|
placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement, style, playerID, orientation, numCorners, irregularity, skipFirstWall);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Prep for next set of walls.
|
|
|
|
|
actualX = distToMapBorder;
|
|
|
|
|
actualY += 2 * radius + distToOtherWalls;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Linear wall placement
|
|
|
|
|
*
|
|
|
|
|
* This function draws a straight wall between two given points.
|
|
|
|
|
*
|
|
|
|
|
* This function does not permit the use of bending wall elements.
|
|
|
|
|
*
|
|
|
|
|
* This function has no orientation parameter, the wall pieces are angled
|
|
|
|
|
* automatically. Remember: each piece is placed to the left of the
|
|
|
|
|
* previous piece. Thus, if the start point is at the right-hand side of
|
|
|
|
|
* the screen and the end point is at the left-hand side, the "outside"
|
|
|
|
|
* of the walls is facing the top of the screen.
|
|
|
|
|
*/
|
|
|
|
|
// Two vars, just for this map; firstly how long the longest wall will be.
|
|
|
|
|
var maxWallLength = (mapSize - actualY - distToMapBorder - distToOtherWalls);
|
|
|
|
|
// And secondly, how many walls of the same style will be placed.
|
|
|
|
|
var numWallsPerStyle = Math.floor(buildableMapSize / distToOtherWalls / wallStyleList.length);
|
|
|
|
|
|
|
|
|
|
for (let styleIndex in wallStyleList)
|
|
|
|
|
for (let wallIndex = 0; wallIndex < numWallsPerStyle; ++wallIndex)
|
|
|
|
|
{
|
|
|
|
|
let startX = actualX + (styleIndex * numWallsPerStyle + wallIndex) * distToOtherWalls; // X coordinate the wall will start from
|
|
|
|
|
let startY = actualY; // Y coordinate the wall will start from
|
|
|
|
|
let endX = startX; // X coordinate the wall will end
|
|
|
|
|
let endY = actualY + (wallIndex + 1) * maxWallLength/numWallsPerStyle; // Y coordinate the wall will end
|
|
|
|
|
let playerId = 0; // Player ID of the player owning the wall, 0 is Gaia, 1 is the first player (default blue), ...
|
|
|
|
|
let wallPart = ['tower', 'wall']; // List of wall elements the wall will be build of
|
|
|
|
|
let style = wallStyleList[styleIndex]; // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades'
|
|
|
|
|
placeLinearWall(startX, startY, endX, endY, wallPart, style, playerId); // Actually placing the wall
|
|
|
|
|
// placeObject(startX, startY, 'other/obelisk', 0, 0*PI); // Place visual marker to see where exsactly the wall begins
|
|
|
|
|
// placeObject(endX, endY, 'other/obelisk', 0, 0*PI); // Place visual marker to see where exsactly the wall ends
|
|
|
|
|
// Start point.
|
|
|
|
|
let startX = actualX + (styleIndex * numWallsPerStyle + wallIndex) * buildableMapSize / wallStyleList.length / numWallsPerStyle;
|
|
|
|
|
let startY = actualY;
|
|
|
|
|
|
|
|
|
|
// End point.
|
|
|
|
|
let endX = startX;
|
|
|
|
|
let endY = actualY + (wallIndex + 1) * maxWallLength / numWallsPerStyle;
|
|
|
|
|
|
|
|
|
|
let wallPart = ['tower', 'medium'];
|
|
|
|
|
let style = wallStyleList[styleIndex];
|
|
|
|
|
|
|
|
|
|
placeLinearWall(startX, startY, endX, endY, wallPart, style, playerID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actualX = distToMapBorder; // Reset actualX
|
|
|
|
|
actualY += maxWallLength + distToOtherWalls; // Increase actualY for next wall placement method
|
|
|
|
|
|
|
|
|
|
ExportMap();
|
|
|
|
|