From: xangelo Date: Fri, 13 May 2022 04:44:33 +0000 (-0400) Subject: UI update for map with sector selector X-Git-Url: https://git.xangelo.ca/?a=commitdiff_plain;h=aa9d5e6223a080da56cef99693e13c4f7f840da7;p=browser-rts.git UI update for map with sector selector Capitol Ships are now automatically placed into "sectors" (hard-coded for now) that allow smaller map sizes, while still keeping density. This included a large visual update to the map overview that includes images for the different sectors, a proper overlaid grid, and per city icons. --- diff --git a/dump.sql b/dump.sql index 9cd3202..9330aa6 100644 --- a/dump.sql +++ b/dump.sql @@ -8,6 +8,7 @@ CREATE TABLE IF NOT EXISTS "accounts" ( CREATE TABLE IF NOT EXISTS "cities" ( "id" string, "owner" string, + "icon" string, "totalSpace" int, "usedSpace" int, "gold" int, @@ -118,4 +119,4 @@ INSERT INTO "units" VALUES ('soldiers','Soldiers',2,1,1,0,0,0,2,2.1,1); INSERT INTO "units" VALUES ('attackers','Attackers',5,2,0,1,0,0,3,4,1); INSERT INTO "units" VALUES ('defenders','Defenders',4,2,0,1,0,0,5,1,4); INSERT INTO "units" VALUES ('sp_attackers','Sp. Attacker',9,4,0,0,1,0,7,7,3); -INSERT INTO "units" VALUES ('sp_defenders','Sp. Defender',11,5,0,0,0,1,10,2,9); \ No newline at end of file +INSERT INTO "units" VALUES ('sp_defenders','Sp. Defender',11,5,0,0,0,1,10,2,9); diff --git a/package.json b/package.json index 25f5e4a..7deac18 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "dev": "npx nodemon src/api.ts", "setup:rebels": "npx ts-node scripts/generate-cities.ts", "setup:database": "npx ts-node scripts/setup.ts", - "setup": "npm run setup:database && npm run setup:rebels" + "setup": "npm run setup:rebels" }, "dependencies": { "@bull-board/api": "^3.11.0", diff --git a/public/assets/bg/mapoverview_1.png b/public/assets/bg/mapoverview_1.png new file mode 100644 index 0000000..edc5ab2 Binary files /dev/null and b/public/assets/bg/mapoverview_1.png differ diff --git a/public/assets/bg/mapoverview_2.png b/public/assets/bg/mapoverview_2.png new file mode 100644 index 0000000..fcaedf7 Binary files /dev/null and b/public/assets/bg/mapoverview_2.png differ diff --git a/public/assets/colony-ships/01.png b/public/assets/colony-ships/01.png new file mode 100644 index 0000000..3a638a7 Binary files /dev/null and b/public/assets/colony-ships/01.png differ diff --git a/public/assets/colony-ships/rebels/1.png b/public/assets/colony-ships/rebels/1.png new file mode 100644 index 0000000..cfda262 Binary files /dev/null and b/public/assets/colony-ships/rebels/1.png differ diff --git a/public/assets/colony-ships/rebels/2.png b/public/assets/colony-ships/rebels/2.png new file mode 100644 index 0000000..98109df Binary files /dev/null and b/public/assets/colony-ships/rebels/2.png differ diff --git a/public/assets/colony-ships/rebels/3.png b/public/assets/colony-ships/rebels/3.png new file mode 100644 index 0000000..52c7aec Binary files /dev/null and b/public/assets/colony-ships/rebels/3.png differ diff --git a/public/assets/colony-ships/rebels/4.png b/public/assets/colony-ships/rebels/4.png new file mode 100644 index 0000000..ded5e31 Binary files /dev/null and b/public/assets/colony-ships/rebels/4.png differ diff --git a/public/assets/colony-ships/rebels/5.png b/public/assets/colony-ships/rebels/5.png new file mode 100644 index 0000000..eb5be25 Binary files /dev/null and b/public/assets/colony-ships/rebels/5.png differ diff --git a/public/assets/colony-ships/rebels/6.png b/public/assets/colony-ships/rebels/6.png new file mode 100644 index 0000000..3f26045 Binary files /dev/null and b/public/assets/colony-ships/rebels/6.png differ diff --git a/public/game.html b/public/game.html index dedfa56..3596ad2 100644 --- a/public/game.html +++ b/public/game.html @@ -34,7 +34,7 @@ Unit Training
  • - Map + Map
  • Mail @@ -64,4 +64,4 @@ A project by xangelo - \ No newline at end of file + diff --git a/public/scifi.css b/public/scifi.css index 2aa0485..c9e6da2 100644 --- a/public/scifi.css +++ b/public/scifi.css @@ -4,6 +4,7 @@ --page-bg: #061619; --green-bg: #193818; --green-border: #32821c; + --red-border: #821c1c; } input { @@ -89,7 +90,7 @@ button::after, .btn::after { } .danger { background-color: #381818; - border-color: #821c1c; + border-color: var(--red-border); } .danger::after { color: #821c1c @@ -249,4 +250,48 @@ form > div { padding: 10px 25px; background-color: var(--page-bg); justify-content: space-evenly; -} \ No newline at end of file +} + +#overworld-map { + width: auto; + margin: 0 auto; +} +#overworld-map td { + overflow: hidden; + padding: 0; + background: transparent; + border: solid 1px #000; +} +#overworld-map td div { + width: 32px; + height: 32px; + overflow: hidden; +} + +#overworld-map td div.city { + cursor: pointer; +} +#overworld-map td div.city.yours { + border: solid 1px var(--green-border); +} +#overworld-map td div.city.yours img { + width: 100%; +} +#overworld-map td div.city.others { + border: solid 1px var(--red-border); +} +#overworld-map td div.city.others img { + width: 100%; +} + +#overworld-map .grid-numbers { + color: #7b7b7b; + text-align: center; +} + +#sector-selector { + margin: 20px 50px; +} +#sector-selector select { + margin-left: 20px; +} diff --git a/public/stylesheet.css b/public/stylesheet.css index 4541f8e..609d28e 100644 --- a/public/stylesheet.css +++ b/public/stylesheet.css @@ -1,6 +1,3 @@ -#home form > div { - line-height: 3rem; -} table form { margin-bottom: 0; @@ -15,29 +12,6 @@ table form input { color: #fff; width: 100%; } - -#overworld-map td { - overflow: hidden; - padding: 0; -} - -#overworld-map td div { - width: 5px; - height: 8px; - overflow: hidden; -} - -#overworld-map td div.city { - cursor: pointer; -} - -#overworld-map td div.city.yours { - background-color: #eee; -} -#overworld-map td div.city.others { - background-color: #a00; -} - .unread td{ background-color: #373737; -} \ No newline at end of file +} diff --git a/scripts/generate-cities.ts b/scripts/generate-cities.ts index 5583b86..43b2f39 100644 --- a/scripts/generate-cities.ts +++ b/scripts/generate-cities.ts @@ -5,10 +5,10 @@ const cityRepo = new CityRepository(); (async () => { for(let i = 0; i < 100; ++i) { - await cityRepo.create(uuid()); + await cityRepo.create(uuid(), true); } console.log('Created 100 cities'); process.exit(0); -})(); \ No newline at end of file +})(); diff --git a/src/api.ts b/src/api.ts index 5f48de4..aba677b 100644 --- a/src/api.ts +++ b/src/api.ts @@ -11,7 +11,7 @@ import { construction } from './tasks/construction'; import { unitTraining } from './tasks/unit-training'; import { fight } from './tasks/fight'; import { renderUnitTraining } from './render/unit-training'; -import { launchOffensive, listOperations, renderOverworldMap } from './render/fight'; +import { launchOffensive, listOperations, renderOverworldMap } from './render/map'; import { createBullBoard } from '@bull-board/api'; import { BullAdapter } from '@bull-board/api/bullAdapter'; import _ from 'lodash'; @@ -117,11 +117,23 @@ server.get<{}, string>('/poll/unit-training', async req => { return renderUnitTraining(city, units, unitTrainingQueues); }); -server.get<{}, string>('/poll/map', async req => { +server.post<{body: {sector: string}}, string>('/poll/map', async req => { const account = await accountRepo.validate(req.authInfo.accountId, req.authInfo.token); const city = await cityRepo.getUsersCity(account.id); - return renderOverworldMap(await cityRepo.findAllInSector(city.sector_id), city); + let sector = city.sector_id; + if(req.body.sector) { + try { + sector = parseInt(req.body.sector); + } + catch(e) { + sector = city.sector_id; + } + } + + console.log('Checking cities in sector', sector); + + return renderOverworldMap(await cityRepo.findAllInSector(sector), city, sector); }); server.get<{}, string>('/poll/mailroom', async req => { @@ -285,4 +297,4 @@ server.get('/attacks/outgoing', async req => { }); -server.start(); \ No newline at end of file +server.start(); diff --git a/src/config.ts b/src/config.ts index ad7a3c5..ba4d32e 100644 --- a/src/config.ts +++ b/src/config.ts @@ -4,4 +4,4 @@ dotenv(); export const TICK_LENGTH = process.env.TICK_LENGTH || 1000 * 60 * 5; export const API_PORT = process.env.API_PORT || 9090; -export const AVAILABLE_SECTORS = 1 +export const AVAILABLE_SECTORS = 2 diff --git a/src/render/fight.ts b/src/render/fight.ts deleted file mode 100644 index ee3fbe4..0000000 --- a/src/render/fight.ts +++ /dev/null @@ -1,151 +0,0 @@ -import _ from "lodash"; -import { DateTime } from "luxon"; -import { Account } from "../repository/accounts"; -import { ArmyQueueWithAttackedOwner } from "../repository/army"; -import { City, CityRepository, CityWithLocation } from "../repository/city"; -import { topbar } from "./topbar"; - -const cityRepo = new CityRepository(); - -export function renderOverworldMap(cities: CityWithLocation[], yourCity: CityWithLocation): string { - let map: CityWithLocation[][] = new Array(25); - for(let i = 0; i < cities.length; ++i) { - if(!map[cities[i].location_y]) { - map[cities[i].location_y] = new Array(25); - } - - map[cities[i].location_y][cities[i].location_x] = cities[i]; - } - - let rows: string[] = []; - for(let y = 0; y < 25; ++y) { - rows[y] = ''; - for(let x = 0; x < 25; ++x) { - if(!map[y] || !map[y][x]) { - rows[y] += '
    ' ; - } - else if(map[y][x]) { - if(map[y][x].id === yourCity.id) - rows[y] += '
    '; - else - rows[y] += `
    `; - } - else { - rows[y] += '
    '; - } - } - rows[y] += ''; - } - let html = ` -

    Map

    -
    -
    - - ${rows.join("\n")} -
    - - `; - - return html; - -} - -export function listOperations(outgoingOps: ArmyQueueWithAttackedOwner[]): string { - let html = ` -

    Outgoing Attacks

    - - - - - - - - - - - - ${outgoingOps.map(op => { - return ` - - - - - - - - - - `; - }).join("\n")} -
    DestinationSol.Atk.Def.Sp. Atk.Sp. Def.Est. Arrival
    ${op.attacked_account} - (${op.location_x},${op.location_y})${op.soldiers.toLocaleString()}${op.attackers.toLocaleString()}${op.defenders.toLocaleString()}${op.sp_attackers.toLocaleString()}${op.sp_defenders.toLocaleString()}${ _.round(DateTime.fromMillis(op.due).diffNow().as('hours'), 2)} hours
    - `; - - return html; -} - -export async function launchOffensive(city: CityWithLocation, owner: Account, yourCity: CityWithLocation, you: Account): Promise { - const distance = cityRepo.distanceInHours(city, yourCity); - const power = await cityRepo.power({ - soldiers: yourCity.soldiers, - attackers: yourCity.attackers, - defenders: yourCity.defenders, - sp_attackers: yourCity.sp_attackers, - sp_defenders: yourCity.sp_defenders - }) - let html = ` -

    Viewing (${city.location_x},${city.location_y}) owned by ${owner.username}

    -

    Report

    -

    This city is ${distance} hours away.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Soldiers - - (${yourCity.soldiers}) -
    Attackers - - (${yourCity.attackers}) -
    Defenders - - (${yourCity.defenders}) -
    Sp. Attack - - (${yourCity.sp_attackers}) -
    Sp. Defenders - - (${yourCity.sp_defenders}) -
    Total Power${power}
    - -
    -
    - `; - - return html + topbar(yourCity); -} \ No newline at end of file diff --git a/src/render/kingdom-overview.ts b/src/render/kingdom-overview.ts index 9fd07ab..c6b5964 100644 --- a/src/render/kingdom-overview.ts +++ b/src/render/kingdom-overview.ts @@ -22,7 +22,7 @@ export function renderKingomOverview(city: CityWithLocation, account: Account): Location - ${city.location_x},${city.location_y} + ${city.sector_id} - (${city.location_x},${city.location_y}) Attackers ${city.attackers.toLocaleString()} @@ -51,4 +51,4 @@ export function renderKingomOverview(city: CityWithLocation, account: Account): ${topbar(city)}`; -} \ No newline at end of file +} diff --git a/src/render/map.ts b/src/render/map.ts new file mode 100644 index 0000000..219103d --- /dev/null +++ b/src/render/map.ts @@ -0,0 +1,185 @@ +import _ from "lodash"; +import { DateTime } from "luxon"; +import { Account } from "../repository/accounts"; +import { ArmyQueueWithAttackedOwner } from "../repository/army"; +import { City, CityRepository, CityWithLocation } from "../repository/city"; +import { topbar } from "./topbar"; +import { AVAILABLE_SECTORS } from '../config'; +import {initArray} from "../lib/util"; + +const cityRepo = new CityRepository(); + +export function renderOverworldMap(cities: CityWithLocation[], yourCity: CityWithLocation, activeSector: number): string { + let map: CityWithLocation[][] = new Array(25); + for(let i = 0; i < cities.length; ++i) { + if(!map[cities[i].location_y]) { + map[cities[i].location_y] = new Array(25); + } + + map[cities[i].location_y][cities[i].location_x] = cities[i]; + } + + let rows: string[] = []; + let headerRow: string[] = []; + for(let y = 0; y <= 25; ++y) { + rows[y] = ''; + if(y === 0) { + // first row! add the X coors + for(let x = 0; x <= 25; ++x) { + headerRow.push(`${x}`); + } + } + else { + for(let x = 0; x <= 25; ++x) { + if(x === 0) { + rows[y] += `${y}`; + } + else { + if(!map[y] || !map[y][x]) { + rows[y] += `
    ` ; + } + else if(map[y][x]) { + if(map[y][x].id === yourCity.id) + rows[y] += `
    `; + else + rows[y] += `
    + +
    `; + } + else { + rows[y] += '
    '; + } + } + } + } + rows[y] += ''; + } + let sectorSwitch: string[] = []; + for(let i = 1; i <= AVAILABLE_SECTORS; ++i) { + sectorSwitch.push( + `` + ); + } + let html = ` +

    Map

    +
    +
    +
    + Switch Scanned Sectors: + +
    + + + ${headerRow.join("\n")} + + ${rows.join("\n")} +
    +
    + `; + + + return html; + +} + +export function listOperations(outgoingOps: ArmyQueueWithAttackedOwner[]): string { + let html = ` +

    Outgoing Attacks

    + + + + + + + + + + + + ${outgoingOps.map(op => { + return ` + + + + + + + + + + `; + }).join("\n")} +
    DestinationSol.Atk.Def.Sp. Atk.Sp. Def.Est. Arrival
    ${op.attacked_account} - (${op.location_x},${op.location_y})${op.soldiers.toLocaleString()}${op.attackers.toLocaleString()}${op.defenders.toLocaleString()}${op.sp_attackers.toLocaleString()}${op.sp_defenders.toLocaleString()}${ _.round(DateTime.fromMillis(op.due).diffNow().as('hours'), 2)} hours
    + `; + + return html; +} + +export async function launchOffensive(city: CityWithLocation, owner: Account, yourCity: CityWithLocation, you: Account): Promise { + const distance = cityRepo.distanceInHours(city, yourCity); + const power = await cityRepo.power({ + soldiers: yourCity.soldiers, + attackers: yourCity.attackers, + defenders: yourCity.defenders, + sp_attackers: yourCity.sp_attackers, + sp_defenders: yourCity.sp_defenders + }) + let html = ` +

    Viewing (${city.location_x},${city.location_y}) owned by ${owner.username}

    +

    Report

    +

    This city is ${distance} hours away.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Soldiers + + (${yourCity.soldiers}) +
    Attackers + + (${yourCity.attackers}) +
    Defenders + + (${yourCity.defenders}) +
    Sp. Attack + + (${yourCity.sp_attackers}) +
    Sp. Defenders + + (${yourCity.sp_defenders}) +
    Total Power${power}
    + +
    +
    + `; + + return html + topbar(yourCity); +} diff --git a/src/repository/city.ts b/src/repository/city.ts index df80878..7b88185 100644 --- a/src/repository/city.ts +++ b/src/repository/city.ts @@ -30,6 +30,7 @@ export type City = { barracks: number; special_attacker_trainer: number; special_defender_trainer: number; + icon: string; } export type CityWithLocation = { @@ -54,7 +55,8 @@ export class CityRepository extends Repository { this.armyRepository = new ArmyRepository(); } - async create(accountId: string): Promise { + async create(accountId: string, rebel: boolean = false): Promise { + const icon = rebel ? `/colony-ships/rebels/${random(1, 6)}.png` : '/colony-ships/01.png'; const info: City = { id: uuid(), owner: accountId, @@ -74,6 +76,7 @@ export class CityRepository extends Repository { barracks: 0, special_attacker_trainer: 0, special_defender_trainer: 0, + icon }; await this.Insert(info); @@ -204,7 +207,10 @@ where l.sector_id = ?`, [sector_id]); Math.pow((city2.location_y - city1.location_y), 2) ); - return _.round(dist/4, 2); + // sectors always add 4 hours + const sector_dist = Math.abs(city1.sector_id - city2.sector_id) * 6; + + return _.round(dist/4, 2) + sector_dist; }