diff options
author | Tor Andersson <tor@ccxvii.net> | 2023-10-19 02:14:04 +0200 |
---|---|---|
committer | Tor Andersson <tor@ccxvii.net> | 2023-10-21 18:32:29 +0200 |
commit | d2ff4e66e48d78bef4970c584bdcacedbcc05aef (patch) | |
tree | be8a3cf023f89e246cc7aee3517b86f21e04598e | |
parent | f6c6cfa47e922907aa80bd892308e1aec10e9954 (diff) | |
download | washingtons-war-d2ff4e66e48d78bef4970c584bdcacedbcc05aef.tar.gz |
Mobile layout.
-rw-r--r-- | about.html | 1 | ||||
-rw-r--r-- | cover.1x.jpg | bin | 27012 -> 27980 bytes | |||
-rw-r--r-- | cover.2x.jpg | bin | 57726 -> 86219 bytes | |||
-rw-r--r-- | play.css | 21 | ||||
-rw-r--r-- | play.html | 86 | ||||
-rw-r--r-- | play.js | 120 | ||||
-rw-r--r-- | rules.js | 70 |
7 files changed, 137 insertions, 161 deletions
@@ -1,7 +1,6 @@ <p> Unlicensed game prototype! -<br clear=left> <ul> <li><a href="/washingtons-war/info/rulebook.html">Rulebook</a> diff --git a/cover.1x.jpg b/cover.1x.jpg Binary files differindex 7889c4d..dfdc372 100644 --- a/cover.1x.jpg +++ b/cover.1x.jpg diff --git a/cover.2x.jpg b/cover.2x.jpg Binary files differindex 09dc03e..a96ff62 100644 --- a/cover.2x.jpg +++ b/cover.2x.jpg @@ -56,20 +56,9 @@ aside { /* CARD ACTION POPUP MENU */ -#popup { - position: absolute; - user-select: none; - background-color: #ddd; - left: 10px; - top: 100px; - box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.3); - z-index: 100; - min-width: 20ex; - white-space: nowrap; -} -#popup div { padding: 3pt 8pt; display: none; } -#popup div.enabled { padding: 3pt 8pt; display: block; } -#popup div:hover { background-color: teal; color: white; } +#popup { max-width: 250px; } +#popup li.title { text-align: center } +#popup li.disabled { display: none } /* MAP WITH MARKERS, CUs, LEADERS, AND SPACES */ @@ -172,7 +161,6 @@ aside { line-height: 50px; padding-left: 6px; font-size: 30px; - user-select: none; color: white; text-shadow: 0px 0px 3px black; font-weight: bold; @@ -269,7 +257,8 @@ aside { .hand .card.enabled:hover, .hand .card.selected { Xtransform: scale(1.5) translate(0,-30px); - transform: scale(1.1); + Xtransform: scale(1.1); + transform: translate(0,-10px); z-index: 10; } @@ -1,14 +1,15 @@ <!DOCTYPE html> -<html> +<html lang="en"> <head> -<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1"> +<meta name="viewport" content="width=device-width, height=device-height, user-scalable=no, interactive-widget=resizes-content, viewport-fit=cover"> +<meta name="theme-color" content="#444"> <meta charset="utf-8"> <title>WASHINGTON'S WAR</title> <link rel="icon" href="favicon.png"> <link rel="stylesheet" href="/fonts/fonts.css"> -<link rel="stylesheet" href="/common/play.css"> +<link rel="stylesheet" href="/common/client.css"> <link rel="stylesheet" href="play.css"> -<script defer src="/common/play.js"></script> +<script defer src="/common/client.js"></script> <script defer src="data.js"></script> <script defer src="cards.js"></script> <script defer src="play.js"></script> @@ -16,60 +17,33 @@ </head> <body> -<div id="popup" onmouseleave="hide_popup_menu()"> - <div id="menu_card_play_event" onclick="on_card_play_event()"> - Play Event - </div> - <div id="menu_card_discard_event" onclick="on_card_discard_event()"> - Discard for PC action - </div> - <div id="menu_card_campaign" onclick="on_card_campaign()"> - Play Campaign - </div> - <div id="menu_card_ops_general" onclick="on_card_ops_general()"> - Activate a General - </div> - <div id="menu_card_ops_pc" onclick="on_card_ops_pc()"> - Place PC markers - </div> - <div id="menu_card_ops_reinforcements" onclick="on_card_ops_reinforcements()"> - Bring on Reinforcements - </div> - <div id="menu_card_ops_queue" onclick="on_card_ops_queue()"> - Place into Operations Queue - </div> - <div id="menu_card_battle_play" onclick="on_card_battle_play()"> - Play for +2 DRM - </div> - <div id="menu_card_battle_discard" onclick="on_card_battle_discard()"> - Discard for +1 DRM - </div> - <div id="menu_exchange_for_discard" onclick="on_exchange_for_discard()"> - Exchange for Discarded Event - </div> -</div> +<menu id="popup"> + <li class="title">CARD + <li class="separator"> + <li data-action="card_play_event"> Play Event + <li data-action="card_discard_event"> Discard for PC action + <li data-action="card_campaign"> Play Campaign + <li data-action="card_ops_general"> Activate a General + <li data-action="card_ops_pc"> Place PC markers + <li data-action="card_ops_reinforcements"> Bring on Reinforcements + <li data-action="card_ops_queue"> Place into Operations Queue + <li data-action="card_battle_play"> Play for +2 DRM + <li data-action="card_battle_discard"> Discard for +1 DRM + <li data-action="exchange_for_discard"> Exchange for Discarded Event +</menu> <header> - <div class="menu"> - <div class="menu_title"><img src="/images/cog.svg"></div> - <div class="menu_popup"> - <div class="menu_item" onclick="window.open('info/playbook.html', '_blank')">Playbook</div> - <div class="menu_item" onclick="window.open('info/rulebook.html', '_blank')">Rulebook</div> - <div class="menu_item" onclick="window.open('cards.html', '_blank')">Cards</div> - <div class="menu_separator"></div> - <div class="menu_item" onclick="send_save()">🐞 Save</div> - <div class="menu_item" onclick="send_restore()">🐞 Restore</div> - <div class="menu_separator"></div> - <div class="menu_item" onclick="send_restart()">⚠ Restart</div> - </div> + <div id="toolbar"> + <details> + <summary><img src="/images/cog.svg"></summary> + <menu> + <li><a href="info/playbook.html" target="blank">Playbook</a> + <li><a href="info/rulebook.html" target="blank">Rulebook</a> + <li><a href="cards.html" target="blank">Cards</a> + </menu> + </details> + <button onclick="toggle_markers()"><img src="/images/earth-america.svg"></button> </div> - - <div class="icon_button" onclick="toggle_markers()"><img src="/images/earth-america.svg"></div> - <div class="icon_button" onclick="toggle_zoom()"><img src="/images/magnifying-glass.svg"></div> - <div class="icon_button" onclick="toggle_log()"><img src="/images/scroll-quill.svg"></div> - - <div id="prompt"></div> - <div id="actions"></div> </header> <aside> @@ -95,7 +69,7 @@ <div id="log"></div> </aside> -<main> +<main onclick="hide_popup_menu()"> <div id="mapwrap"> <div id="map"> @@ -419,86 +419,67 @@ function on_update() { } } -let current_popup_card = 0; +function is_action(action, card) { + return view.actions && view.actions[action] && view.actions[action].includes(card) +} -function show_popup_menu(evt, list) { - document.querySelectorAll("#popup div").forEach(e => e.classList.remove('enabled')); - for (let item of list) { - let e = document.getElementById("menu_" + item); - e.classList.add('enabled'); +function show_popup_menu(evt, menu_id, target_id, title) { + let menu = document.getElementById(menu_id) + + let show = false + for (let item of menu.querySelectorAll("li")) { + let action = item.dataset.action + if (action) { + if (is_action(action, target_id)) { + show = true + item.classList.add("action") + item.classList.remove("disabled") + item.onclick = function () { + send_action(action, target_id) + hide_popup_menu() + evt.stopPropagation() + } + } else { + item.classList.remove("action") + item.classList.add("disabled") + item.onclick = null + } + } } - let popup = document.getElementById("popup"); - popup.style.display = 'block'; - popup.style.left = (evt.clientX-50) + "px"; - popup.style.top = (evt.clientY-12) + "px"; - ui.cards[current_popup_card].classList.add("selected"); -} -function hide_popup_menu() { - let popup = document.getElementById("popup"); - popup.style.display = 'none'; - if (current_popup_card) { - ui.cards[current_popup_card].classList.remove("selected"); - current_popup_card = 0; + if (show) { + menu.onmouseleave = hide_popup_menu + menu.style.display = "block" + if (title) { + let item = menu.querySelector("li.title") + if (item) { + item.onclick = hide_popup_menu + item.textContent = title + } + } + + let w = menu.clientWidth + let h = menu.clientHeight + let x = Math.max(5, Math.min(evt.clientX - w / 2, window.innerWidth - w - 5)) + let y = Math.max(5, Math.min(evt.clientY - 12, window.innerHeight - h - 40)) + menu.style.left = x + "px" + menu.style.top = y + "px" + + return true } -} -function on_card_play_event() { - send_action('card_play_event', current_popup_card); - hide_popup_menu(); -} -function on_card_discard_event() { - send_action('card_discard_event', current_popup_card); - hide_popup_menu(); + return false } -function on_card_campaign() { - send_action('card_campaign', current_popup_card); - hide_popup_menu(); -} -function on_card_ops_general() { - send_action('card_ops_general', current_popup_card); - hide_popup_menu(); -} -function on_card_ops_pc() { - send_action('card_ops_pc', current_popup_card); - hide_popup_menu(); -} -function on_card_ops_reinforcements() { - send_action('card_ops_reinforcements', current_popup_card); - hide_popup_menu(); -} -function on_card_ops_queue() { - send_action('card_ops_queue', current_popup_card); - hide_popup_menu(); -} -function on_card_ops_queue() { - send_action('card_ops_queue', current_popup_card); - hide_popup_menu(); -} -function on_card_battle_play() { - send_action('card_battle_play', current_popup_card); - hide_popup_menu(); -} -function on_card_battle_discard() { - send_action('card_battle_discard', current_popup_card); - hide_popup_menu(); -} -function on_exchange_for_discard() { - send_action('exchange_for_discard', current_popup_card); - hide_popup_menu(); + +function hide_popup_menu() { + document.getElementById("popup").style.display = "none" } function on_card(evt) { if (view.actions) { let c = evt.target.id.split("+")[1] | 0; - let menu = []; - for (let action in view.actions) - if (Array.isArray(view.actions[action]) && view.actions[action].includes(c)) - menu.push(action); - if (menu.length > 0) { - current_popup_card = c; - show_popup_menu(evt, menu); - } + show_popup_menu(evt, "popup", c, CARDS[c].title) + evt.stopPropagation() } } @@ -533,4 +514,3 @@ function toggle_markers() { document.querySelector("#map").classList.toggle("hide_markers"); } -scroll_with_middle_mouse("main", 2); @@ -71,7 +71,7 @@ let game; let view; function random(n) { - return ((game.seed = game.seed * 69621 % 0x7fffffff) / 0x7fffffff) * n | 0; + return (game.seed = game.seed * 200105 % 34359738337) % n } function logbr() { @@ -87,25 +87,63 @@ function logp(s) { game.log.push(game.active[0] + " " + s); } +function object_copy(original) { + if (Array.isArray(original)) { + let n = original.length + let copy = new Array(n) + for (let i = 0; i < n; ++i) { + let v = original[i] + if (typeof v === "object" && v !== null) + copy[i] = object_copy(v) + else + copy[i] = v + } + return copy + } else { + let copy = {} + for (let i in original) { + let v = original[i] + if (typeof v === "object" && v !== null) + copy[i] = object_copy(v) + else + copy[i] = v + } + return copy + } +} + function clear_undo() { - game.undo = []; + if (game.undo) { + game.undo.length = 0 + } } function push_undo() { - game.undo.push(JSON.stringify(game, (k,v) => { - if (k === 'undo') return 0; - if (k === 'log') return v.length; - return v; - })); + if (game.undo) { + let copy = {} + for (let k in game) { + let v = game[k] + if (k === "undo") + continue + else if (k === "log") + v = v.length + else if (typeof v === "object" && v !== null) + v = object_copy(v) + copy[k] = v + } + game.undo.push(copy) + } } function pop_undo() { - let save_undo = game.undo; - let save_log = game.log; - game = JSON.parse(save_undo.pop()); - game.undo = save_undo; - save_log.length = game.log; - game.log = save_log; + if (game.undo) { + let save_log = game.log + let save_undo = game.undo + game = save_undo.pop() + save_log.length = game.log + game.log = save_log + game.undo = save_undo + } } function remove_from_array(array, item) { @@ -3444,11 +3482,7 @@ states.game_over = { /* CLIENT/SERVER COMMS */ -exports.ready = function (scenario, options, players) { - return players.length === 2; -} - -exports.setup = function (seed, scenario, players) { +exports.setup = function (seed, scenario, options) { setup_game(seed); return game; } |