地图生成器
+Space
+Ruin
+Shadow
+Asteroid
+Resource
+Construction
+Wormhole
+Home
+当前:Space
+diff --git a/dependency/MapGenerator/README.md b/dependency/MapGenerator/README.md new file mode 100644 index 00000000..df0bb384 --- /dev/null +++ b/dependency/MapGenerator/README.md @@ -0,0 +1,3 @@ +# THUAI7 随机地图生成器 + +地图生成逻辑极为简单,有待其他大佬进一步改进。 \ No newline at end of file diff --git a/dependency/MapGenerator/assets/css/map.css b/dependency/MapGenerator/assets/css/map.css new file mode 100644 index 00000000..69d1f965 --- /dev/null +++ b/dependency/MapGenerator/assets/css/map.css @@ -0,0 +1,62 @@ +#paint { + float: left; +} + +#paint canvas { + border: 1px solid #333; + border-radius: 10px; + cursor: crosshair; + margin: 0 20px 20px 0; +} + +#color-picker { + float: left; +} + +#color-picker div { + width: 120px; + height: 40px; + text-align: center; + cursor: pointer; + margin: 14px; + border-radius: 10px; + border: 1px solid #000; +} + +#color-picker div:hover { + border: 1px solid #333; + box-shadow: 0 0 5px #333; + text-shadow: 0 0 5px #333; +} + +#color-picker div p { + font-size: 16px; + font-weight: 500; + line-height: 40px; + margin: 0; +} + +#random-settings { + float: left; +} + +#random-settings p { + font-size: 16px; + font-weight: 500; + margin: 0 0 10px; + text-align: right; +} + +#random-settings p:hover { + color: #025b9e; +} + +#random-settings input { + border-radius: 5px; + border: 1px solid #333; + width: 64px; +} + +#operate { + clear: both; +} \ No newline at end of file diff --git a/dependency/MapGenerator/assets/css/style.css b/dependency/MapGenerator/assets/css/style.css new file mode 100644 index 00000000..7b740219 --- /dev/null +++ b/dependency/MapGenerator/assets/css/style.css @@ -0,0 +1,185 @@ +html { + box-sizing: border-box; + font-family: 'Roboto', sans-serif; + background-color: #fff; +} + +header { + background-color: #fff; + border-bottom: 1px solid #eee; + height: 60px; + line-height: 60px; + position: fixed; + top: 0; + width: 100%; + z-index: 999; +} + +header .logo { + float: left; + margin-left: 30px; +} + +header .logo a { + color: #333; + font-size: 20px; + font-weight: 700; + text-decoration: none; +} + +header .logo a:hover { + color: #025b9e; +} + +header .logo img { + height: 40px; + margin-top: 10px; +} + +header .top-nav { + float: right; + margin-right: 30px; +} + +header .top-nav ul { + list-style: none; + margin: 0; + padding: 0; +} + +header .top-nav ul li { + display: inline-block; + margin-left: 20px; + position: relative; +} + +header .top-nav ul li a { + color: #333; + font-size: 16px; + font-weight: 500; + text-decoration: none; +} + +header .top-nav ul li a:hover { + color: #025b9e; +} + +main { + margin-top: 60px; + padding: 30px; +} + +main h1 { + color: #333; + font-size: 24px; + font-weight: 700; + margin: 0 0 20px; +} + +main h2 { + color: #333; + font-size: 20px; + font-weight: 700; + margin: 0 0 20px; +} + +main p { + color: #333; + font-size: 16px; + font-weight: 400; + line-height: 1.5; + margin: 0 0 20px; +} + +main a { + color: #027dcd; + font-size: 16px; + font-weight: 500; + text-decoration: none; +} + +main a:hover { + color: #025b9e; +} + +main ul { + /* list-style: none; */ + margin: 0; + /* padding: 0; */ +} + +main ul li { + margin-bottom: 20px; +} + +main ul li a { + color: #333; + font-size: 16px; + font-weight: 500; + /* text-decoration: none; */ +} + +main ul li a:hover { + color: #025b9e; +} + +main button { + background-color: #027dcd; + border: 0; + border-radius: 10px; + color: #fff; + cursor: pointer; + font-size: 16px; + font-weight: 500; + height: 40px; + margin-bottom: 20px; + padding: 0 20px; +} + +main button:hover { + background-color: #025b9e; + box-shadow: 0 0 5px #333; + text-shadow: 0 0 5px #333; +} + +main fieldset { + border: 1px solid #333; + border-radius: 10px; + margin-bottom: 20px; + padding: 20px; +} + +main fieldset legend { + color: #333; + font-size: 16px; + font-weight: 500; +} + +main fieldset label { + color: #333; + font-size: 16px; + font-weight: 500; +} + +main fieldset input[type="text"], +main fieldset input[type="email"], +main fieldset input[type="password"], +main fieldset select { + border: 1px solid #eee; + border-radius: 10px; + color: #333; + font-size: 16px; + font-weight: 400; + height: 40px; + margin-bottom: 20px; + padding: 0 10px; + width: 100%; +} + +main fieldset input[type="text"]:focus, +main fieldset input[type="email"]:focus, +main fieldset input[type="password"]:focus, +main fieldset select:focus { + border: 1px solid #333; + box-shadow: 0 0 5px #333; +} \ No newline at end of file diff --git a/dependency/MapGenerator/assets/img/favicon.ico b/dependency/MapGenerator/assets/img/favicon.ico new file mode 100644 index 00000000..75325016 Binary files /dev/null and b/dependency/MapGenerator/assets/img/favicon.ico differ diff --git a/dependency/MapGenerator/assets/js/map.js b/dependency/MapGenerator/assets/js/map.js new file mode 100644 index 00000000..e07e3666 --- /dev/null +++ b/dependency/MapGenerator/assets/js/map.js @@ -0,0 +1,333 @@ +var canvas = document.getElementById("map"); +var ctx = canvas.getContext("2d"); +var currentColor = 0; +var map = new Array(50); +for (var i = 0; i < 50; i++) { + map[i] = new Array(50); + for (var j = 0; j < 50; j++) { + map[i][j] = 0; + } +} +var color = [ + "#FFFFFF", // Space + "#B97A57", // Ruin + "#22B14C", // Shadow + "#99D9EA", // Asteroid + "#A349A4", // Resource + "#FF7F27", // Construction + "#880015", // Wormhole + "#ED1C24", // Home +]; + +function draw() { + ctx.clearRect(0, 0, 500, 500); + for (var i = 0; i < 50; i++) { + for (var j = 0; j < 50; j++) { + ctx.fillStyle = color[map[i][j]]; + ctx.fillRect(i * 10, j * 10, 10, 10); + } + } +} + +canvas.onmousedown = function (e) { + var x = Math.floor(e.offsetX / 10); + var y = Math.floor(e.offsetY / 10); + map[x][y] = currentColor; + draw(); +} + +document.getElementById("space").onclick = function () { + currentColor = 0; + document.getElementById("current").innerHTML = "当前:Space"; +} +document.getElementById("ruin").onclick = function () { + currentColor = 1; + document.getElementById("current").innerHTML = "当前:Ruin"; +} +document.getElementById("shadow").onclick = function () { + currentColor = 2; + document.getElementById("current").innerHTML = "当前:Shadow"; +} +document.getElementById("asteroid").onclick = function () { + currentColor = 3; + document.getElementById("current").innerHTML = "当前:Asteroid"; +} +document.getElementById("resource").onclick = function () { + currentColor = 4; + document.getElementById("current").innerHTML = "当前:Resource"; +} +document.getElementById("construction").onclick = function () { + currentColor = 5; + document.getElementById("current").innerHTML = "当前:Construction"; +} +document.getElementById("wormhole").onclick = function () { + currentColor = 6; + document.getElementById("current").innerHTML = "当前:Wormhole"; +} +document.getElementById("home").onclick = function () { + currentColor = 7; + document.getElementById("current").innerHTML = "当前:Home"; +} + +function saveAsTxt() { + var str = ""; + for (var i = 0; i < 50; i++) { + for (var j = 0; j < 50; j++) { + str += map[j][i]; + } + str += "\n"; + } + var a = document.createElement("a"); + a.style.display = "none"; + a.href = "data:text/plain;charset=utf-8," + str; + a.download = "map.txt"; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); +} + +function saveAsCs() { + var str = "public static uint[,] Map = new uint[50, 50] {\n"; + for (var i = 0; i < 50; i++) { + str += " {"; + for (var j = 0; j < 50; j++) { + str += map[j][i]; + if (j != 49) { + str += ", "; + } + } + str += "}"; + if (i != 49) { + str += ","; + } + str += "\n"; + } + str += "};"; + var a = document.createElement("a"); + a.style.display = "none"; + a.href = "data:text/plain;charset=utf-8," + str; + a.download = "map.cs"; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); +} + +function saveAsPng() { + var a = document.createElement("a"); + a.style.display = "none"; + a.href = canvas.toDataURL("image/png"); + a.download = "map.png"; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); +} + +function isEmptyNearby(x, y, radius) { + for (var i = (x - radius >= 0 ? x - radius : 0); i <= (x + radius <= 49 ? x + radius : 49); i++) { + for (var j = (y - radius >= 0 ? y - radius : 0); j <= (y + radius <= 49 ? y + radius : 49); j++) { + if (map[i][j] != 0) { + return false; + } + } + } + return true; +} + +function haveSthNearby(x, y, radius, type) { + var ret = 0; + for (var i = (x - radius >= 0 ? x - radius : 0); i <= (x + radius <= 49 ? x + radius : 49); i++) { + for (var j = (y - radius >= 0 ? y - radius : 0); j <= (y + radius <= 49 ? y + radius : 49); j++) { + if (map[i][j] == type) { + ret++; + } + } + } + return ret; +} + +function haveSthCross(x, y, radius, type) { + var ret = 0; + for (var i = (x - radius >= 0 ? x - radius : 0); i <= (x + radius <= 49 ? x + radius : 49); i++) { + if (map[i][y] == type) { + ret++; + } + } + for (var j = (y - radius >= 0 ? y - radius : 0); j <= (y + radius <= 49 ? y + radius : 49); j++) { + if (map[x][j] == type) { + ret++; + } + } + return ret; +} + +function generateBorderRuin() { + for (var i = 0; i < 50; i++) { + map[i][0] = 1; + map[i][49] = 1; + map[0][i] = 1; + map[49][i] = 1; + } +} + +function generateHome() { + map[3][46] = 7; + map[46][3] = 7; +} + +function generateAsteroid(width = 2) { + for (var i = 1; i < 49; i++) { + for (var j = 24; j > 24 - width; j--) { + map[i][j] = 3; + map[49 - i][49 - j] = 3; + } + } + for (var i = 1; i < 23; i++) { + if (Math.random() < 0.5 && i != 9 && i != 10 && i != 11 && i != 12) { + map[i][24 - width] = 3; + map[i][24 + width] = 0; + map[49 - i][25 + width] = 3; + map[49 - i][25 - width] = 0; + } + } +} + +function generateResource(num = 7) { + for (var i = 0; i < num; i++) { + var x = Math.floor(Math.random() * 48) + 1; + var y = Math.floor(Math.random() * 23) + 1; + if (isEmptyNearby(x, y, 2)) { + map[x][y] = 4; + map[49 - x][49 - y] = 4; + } + else { + i--; + } + } +} + +function generateConstruction(num = 5) { + for (var i = 0; i < num; i++) { + var x = Math.floor(Math.random() * 48) + 1; + var y = Math.floor(Math.random() * 23) + 1; + if (isEmptyNearby(x, y, 1)) { + map[x][y] = 5; + map[49 - x][49 - y] = 5; + } + else { + i--; + } + } +} + +function generateShadow(prob = 0.015, crossBonus = 23) { + for (var i = 0; i < 50; i++) { + for (var j = 0; j < 50; j++) { + if (map[i][j] == 0 && Math.random() < prob * (haveSthCross(i, j, 1, 2) * crossBonus + 1)) { + map[i][j] = 2; + map[49 - i][49 - j] = 2; + } + } + } +} + +function generateRuin(prob = 0.01, crossBonus = 40) { + for (var i = 2; i < 48; i++) { + for (var j = 2; j < 48; j++) { + if ((map[i][j] == 0 || map[i][j] == 2) && !haveSthNearby(i, j, 1, 3) && !haveSthNearby(i, j, 1, 7) && Math.random() < prob * (haveSthCross(i, j, 1, 1) * (haveSthCross(i, j, 1, 1) > 1 ? 0 : crossBonus) + 1)) { + map[i][j] = 1; + map[49 - i][49 - j] = 1; + } + } + } +} + +function generateWormhole() { + for (var i = 1; i < 49; i++) { + if (map[10][i] == 3) { + map[10][i] = 6; + map[39][49 - i] = 6; + } + if (map[11][i] == 3) { + map[11][i] = 6; + map[38][49 - i] = 6; + } + if (map[24][i] == 3) { + map[24][i] = 6; + map[25][49 - i] = 6; + } + } +} + +function clearCanvas() { + for (var i = 0; i < 50; i++) { + map[i] = new Array(50); + for (var j = 0; j < 50; j++) { + map[i][j] = 0; + } + } + // generateBorderRuin(); + // generateHome(); + draw(); +} + +function random() { + for (var i = 0; i < 50; i++) { + map[i] = new Array(50); + for (var j = 0; j < 50; j++) { + map[i][j] = 0; + } + } + var asteroidWidth = parseInt(document.getElementById("asteroid-width").value); + var resourceNum = parseInt(document.getElementById("resource-num").value); + var constructionNum = parseInt(document.getElementById("construction-num").value); + var shadowProb = parseFloat(document.getElementById("shadow-prob").value); + var shadowCrossBonus = parseInt(document.getElementById("shadow-cross-bonus").value); + var ruinProb = parseFloat(document.getElementById("ruin-prob").value); + var ruinCrossBonus = parseInt(document.getElementById("ruin-cross-bonus").value); + if (isNaN(asteroidWidth) || asteroidWidth < 1 || asteroidWidth > 4) { + asteroidWidth = 2; + alert("Asteroid 宽度非法,设置为默认值 2"); + document.getElementById("asteroid-width").value = 2; + } + if (isNaN(resourceNum) || resourceNum < 1 || resourceNum > 10) { + resourceNum = 7; + alert("Resource 数量非法,设置为默认值 7"); + document.getElementById("resource-num").value = 7; + } + if (isNaN(constructionNum) || constructionNum < 1 || constructionNum > 10) { + constructionNum = 5; + alert("Construction 数量非法,设置为默认值 5"); + document.getElementById("construction-num").value = 5; + } + if (isNaN(shadowProb) || shadowProb < 0 || shadowProb > 0.1) { + shadowProb = 0.015; + alert("Shadow 生成概率非法,设置为默认值 0.015"); + document.getElementById("shadow-prob").value = 0.015; + } + if (isNaN(shadowCrossBonus) || shadowCrossBonus < 1 || shadowCrossBonus > 50) { + shadowCrossBonus = 23; + alert("Shadow 蔓延加成非法,设置为默认值 23"); + document.getElementById("shadow-cross-bonus").value = 23; + } + if (isNaN(ruinProb) || ruinProb < 0 || ruinProb > 0.1) { + ruinProb = 0.01; + alert("Ruin 生成概率非法,设置为默认值 0.01"); + document.getElementById("ruin-prob").value = 0.01; + } + if (isNaN(ruinCrossBonus) || ruinCrossBonus < 1 || ruinCrossBonus > 50) { + ruinCrossBonus = 40; + alert("Ruin 蔓延加成非法,设置为默认值 40"); + document.getElementById("ruin-cross-bonus").value = 40; + } + generateBorderRuin(); + generateHome(); + generateAsteroid(asteroidWidth); + generateResource(resourceNum); + generateConstruction(constructionNum); + generateShadow(shadowProb, shadowCrossBonus); + generateRuin(ruinProb, ruinCrossBonus); + generateWormhole(); + draw(); +} + +clearCanvas(); diff --git a/dependency/MapGenerator/index.html b/dependency/MapGenerator/index.html new file mode 100644 index 00000000..8e8e44c1 --- /dev/null +++ b/dependency/MapGenerator/index.html @@ -0,0 +1,80 @@ + + + +
+ +Space
+Ruin
+Shadow
+Asteroid
+Resource
+Construction
+Wormhole
+Home
+当前:Space
+