summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--about.html9
-rw-r--r--play.css100
-rw-r--r--play.html68
-rw-r--r--play.js53
4 files changed, 151 insertions, 79 deletions
diff --git a/about.html b/about.html
index ea007f4..e318a3c 100644
--- a/about.html
+++ b/about.html
@@ -3,15 +3,10 @@ Crusader Rex is a wargame of the 3rd Crusade. One player plays the Christian
Franks, the other, the Muslim Saracens. The objective of the game is to control
important Victory Cities such as Jerusalem, Acre, Damascus, and Antioch.
-<br clear="left">
-
<p>
Designer: Jerry Taylor and Tom Dalgliesh.
-
-<p>
-Copyright &copy; 2005-2011
-<a href="https://columbiagames.com/cgi-bin/query/cfg/zoom.cfg?product_id=3151">Columbia Games</a>
-and Jerry Taylor.
+<br> Copyright &copy; 2005-2011 <a href="https://columbiagames.com/cgi-bin/query/cfg/zoom.cfg?product_id=3151">Columbia Games</a> and Jerry Taylor.
+<br> Programming &copy; 2021 Tor Andersson.
<ul>
<li><a href="/crusader-rex/info/rules.html">Rulebook</a>
diff --git a/play.css b/play.css
index fd7dd13..8f77a7c 100644
--- a/play.css
+++ b/play.css
@@ -42,12 +42,20 @@ body.Saracens header.your_turn { background-color: lightgreen; }
}
.hand {
- margin: 25px;
+ margin: 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: center;
min-height: 348px;
gap: 16px;
+ min-width: 750px;
+ padding: 24px;
+}
+
+@media (max-width: 800px) {
+ .hand {
+ min-width: 1275px;
+ }
}
.card {
@@ -81,35 +89,46 @@ body.Saracens header.your_turn { background-color: lightgreen; }
filter: grayscale(100%) contrast(70%) brightness(120%);
}
+
.role_info {
- overflow: clip; /* clip dropshadow from filter:grayscale() stacking context */
- padding-top: 16px;
+ overflow: clip;
+ transition: height 100ms, padding 100ms;
+ height: 84px;
+ padding: 12px 0;
}
.role_info .card {
width: 168px;
height: 261px;
border-radius: 9px;
- margin: 0 auto 16px auto;
+ margin: 0 auto;
}
-.role_info .card:not(:hover) {
- margin: 0 auto;
- height: 96px;
- border-bottom-right-radius: 0;
- border-bottom-left-radius: 0;
+.role:hover .role_info {
+ height: 261px;
+}
+
+@media (max-height: 650px) {
+ .role:not(:hover) .role_info { display: none; }
+}
+
+@media (max-height: 800px) {
+ #turn_info { display: none; }
+ .role_info { height: 60px; padding: 8px 0; }
}
/* MAP */
-#mapwrap {
- background-color: #224467;
- box-shadow: 0px 1px 10px rgba(0,0,0,0.5);
+#padmap {
+ margin: 0 auto;
width: 1275px;
height: 2475px;
+ padding: 0 24px;
}
#map {
+ margin: 0;
+ box-shadow: 0px 1px 10px rgba(0,0,0,0.5);
width: 1275px;
height: 2475px;
background-color: #224467;
@@ -179,13 +198,14 @@ body.shift .block.known:hover {
z-index: 100;
}
-#battle .block { position: relative; }
#map .block { position: absolute; z-index: 2; }
#map .block.highlight { z-index: 3; }
#map .block.selected { z-index: 4; }
#map .block.known { z-index: 5; }
#map .block.known:hover { z-index: 6; }
+#battle .block { position: relative; }
+
.block {
background-repeat: no-repeat;
border-radius: 6px;
@@ -272,33 +292,12 @@ body.shift .block.known:hover {
transition-timing-function: ease;
}
-/* LANDSCAPE MAP */
-
-@media (min-width: 2000px) {
- #mapwrap:not(.fit) {
- box-shadow: 1px 0px 10px rgba(0,0,0,0.5);
- height: 1275px;
- width: 2475px;
- margin-bottom: 40px;
- margin-top: 30px;
- }
- #mapwrap:not(.fit) #map {
- transform: translateY(1275px) rotate(-90deg);
- transform-origin: 0 0;
- }
- body.shift #mapwrap:not(.fit) #map .block.known:hover {
- transform: rotate(90deg) scale(2) !important;
- }
- #mapwrap:not(.fit) #map .block { transform: rotate(90deg); }
- #mapwrap:not(.fit) #map .block.r1 { transform: rotate(0deg); }
- #mapwrap:not(.fit) #map .block.r2 { transform: rotate(-90deg); }
- #mapwrap:not(.fit) #map .block.r3 { transform: rotate(-180deg); }
-}
-
/* BATTLE BOARD */
#battle {
background-color: tan;
+ left: calc(90px + max(0px, calc(50% - (1275px + 48px) / 2)));
+ top: 320px;
}
#battle_message {
background-color: gainsboro;
@@ -350,6 +349,35 @@ body.shift .block.known:hover {
#FC.c3, #EC.c3 { background-image: url('castle_3.svg'); width: 300px; }
#FC.c4, #EC.c4 { background-image: url('castle_4.svg'); width: 380px; }
+/* LANDSCAPE MAP */
+
+@media (min-width: 2000px) {
+ #battle {
+ top: 745px;
+ left: calc(500px + max(0px, calc(50% - 2475px / 2)));
+ }
+ .hand {
+ width: 2475px;
+ }
+ #padmap {
+ height: 1275px;
+ width: 2475px;
+ padding: 24px 0;
+ overflow: clip;
+ }
+ #map {
+ transform: translateY(1275px) rotate(-90deg);
+ transform-origin: 0 0;
+ }
+ body.shift #padmap #map > .block.known:hover {
+ transform: rotate(90deg) scale(2) !important;
+ }
+ #blocks > .block { transform: rotate(90deg); }
+ #blocks > .block.r1 { transform: rotate(0deg); }
+ #blocks > .block.r2 { transform: rotate(-90deg); }
+ #blocks > .block.r3 { transform: rotate(-180deg); }
+}
+
/* CARD AND BLOCK IMAGES */
.card_back{background-image:url('cards/card_back.jpg')}
diff --git a/play.html b/play.html
index 46fc21c..7e68f3e 100644
--- a/play.html
+++ b/play.html
@@ -1,53 +1,39 @@
<!DOCTYPE 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>CRUSADER REX</title>
<link rel="icon" href="Cross_of_the_Knights_Templar.svg">
<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="/common/columbia.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="play.js"></script>
</head>
<body>
-<div id="battle">
-<div id="battle_header"></div>
-<div id="ER"></div>
-<div id="EC"></div>
-<div id="EF"></div>
-<div id="FF"></div>
-<div id="FC"></div>
-<div id="FR"></div>
-<div id="battle_message"></div>
-</div>
-
<header>
<div id="toolbar">
- <div class="menu">
- <div class="menu_title"><img src="/images/cog.svg"></div>
- <div class="menu_popup">
- <div class="menu_item" onclick="set_spread_layout()">Spread blocks</div>
- <div class="menu_item" onclick="set_stack_layout()">Stack blocks</div>
- <div class="menu_separator"></div>
- <a class="menu_item" href="info/notes.html" target="_blank">Notes</a>
- <a class="menu_item" href="info/rules.html" target="_blank">Rules</a>
- <a class="menu_item" href="info/cards.html" target="_blank">Cards</a>
- <a class="menu_item" href="info/blocks.html" target="_blank">Blocks</a>
- <div class="resign menu_separator"></div>
- <div class="resign menu_item" onclick="confirm_resign()">Resign</div>
- </div>
- </div>
- <div class="icon_button" onclick="toggle_blocks()"><img src="/images/earth-africa-europe.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>
+ <details>
+ <summary><img src="/images/cog.svg"></summary>
+ <menu>
+ <li onclick="set_spread_layout()">Spread blocks
+ <li onclick="set_stack_layout()">Stack blocks
+ <li class="separator">
+ <li><a href="info/notes.html" target="_blank">Notes</a>
+ <li><a href="info/rules.html" target="_blank">Rules</a>
+ <li><a href="info/cards.html" target="_blank">Cards</a>
+ <li><a href="info/blocks.html" target="_blank">Blocks</a>
+ <li class="resign separator">
+ <li class="resign" onclick="confirm_resign()">Resign
+ </menu>
+ </details>
+ <div class="icon_button" onclick="toggle_blocks()"><img src="/images/earth-africa-europe.svg"></div>
</div>
- <div id="prompt"></div>
- <div id="actions"></div>
</header>
<aside>
@@ -73,10 +59,22 @@
<div id="log"></div>
</aside>
-<main>
+<main data-min-zoom="1" data-max-zoom="2" data-map-width="1323" data-map-height="1323">
-<div id="mapwrap">
+<div id="battle">
+<div id="battle_header"></div>
+<div id="ER"></div>
+<div id="EC"></div>
+<div id="EF"></div>
+<div id="FF"></div>
+<div id="FC"></div>
+<div id="FR"></div>
+<div id="battle_message"></div>
+</div>
+
+<div id="padmap">
<div id="map">
+
<svg id="svgmap" width="1275px" height="2475px" viewBox="0 0 1275 2475">
<path id="sea" d="M30 1201v1170l2-1c1 0 4-1 5-3 2-1 4-2 5-2 2 0 5-1 7-2 3-2 7-4 11-6 3-2 7-4 8-6 1-1 3-2 3-2 2 0 47-23 54-27 4-2 10-6 14-8 7-3 13-7 27-19 4-3 5-4 5-8l1-4h5c4 0 7-1 12-5 6-4 27-24 41-41 7-8 20-21 23-24 1-1 4-3 5-6l6-6c1-1 3-3 4-5 2-3 3-4 10-12 3-3 6-7 6-9 1-1 2-3 3-4 2-1 5-5 7-9 2-3 4-6 5-6 2 0 5-6 5-9 0-2 2-6 5-10s5-7 5-8 0-1 1-1 1-1 2-3c1-4 3-9 8-14 4-5 7-12 7-14 0-1 2-6 4-10 3-4 5-9 6-10 0-1 1-4 3-5 1-2 2-4 2-5 0 0 1-3 3-5 2-3 3-5 3-10 0-6 1-9 4-14 2-3 3-7 3-8 0-3 4-20 6-22 2-3 4-11 4-17 0-1 0-3 1-3 0 0 2-2 2-5 1-2 3-7 4-9 1-3 2-9 3-15 1-11 1-10 0-18 0-5 0-7 1-9s2-5 2-7c1-3 1-5 2-7 0-1 1-4 1-6v-8c4-22 4-23 3-26-1-2-1-4 0-6s1-8 1-13 1-9 1-10v-5c-1-3-1-8-1-12v-10-36c0-8-1-21-2-23 0-1-1-5-1-10 0-14-1-27-2-35-1-3-1-8-1-11s-2-10-5-17c-1-1-1-2 0-3 1-2 1-2 0-3 0-1-1-2 0-2 0-1 0-2-1-3 0-1 0-4-1-7 0-3-1-6-2-9-1-2-2-4-1-4 0-1-1-2-2-2-1-2-1-2 1-3s2-1 3-8c0-5 0-8-2-11-1-2-1-7-1-11-1-5-1-8-3-12-4-6-3-10 0-13 5-4 18-4 26 0l5 3 3-2c1-2 4-3 6-4 3-1 10-9 15-16 2-3 2-3 1-12-2-13-4-18-9-16-2 0-3 0-2-3 0-2-1-4-3-7-2-4-2-5-3-16 0-22-1-28-2-29s-1-2 0-3c2-1-1-9-3-12-2-1-2-2-1-5 0-4 2-7 8-9 9-5 10-5 10-6s1-3 3-5c1-2 2-5 2-6-1-1-1-2 0-3 1 0 1-2 1-2-1-2 0-2 3-2 2 0 4-1 6-3 3-3 4-9 3-10s0-2 1-3c4-3 3-5 0-16-2-5-3-6-6-8-2-1-6-2-8-2-5 0-5-2-1-2 6-2 7-2 8-4 0-2 1-5 2-8 0-3 1-6 2-7s1-3 1-3c-1-1 0-2 0-3 1 0 1-3 1-6v-13c0-4-1-8-1-9-1-2-1-3 1-4 2-2 2-2 1-5 0-2-1-4 0-4 0-1 1-3 2-5 1-3 1-4-1-5-1-1-1-1 2-3 2-2 3-3 3-4s1-2 3-2c4-2 12-10 16-16 2-2 3-4 4-4 0 0 1-1 2-3 1-1 2-4 4-6s2-3 2-6c-1-2-1-5-1-6s0-3-1-4-1-1 1-3c4-3 6-11 4-14-1-2-1-2 1-4 1-2 1-2 0-6-1-2-2-5-1-6 0 0 0-2-1-2-1-2 0-2 3-4l4-3-2-6c-1-3-2-7-3-7-2-1 1-4 4-4s7-4 7-8c0-1-1-4-2-5-2-3-3-6-2-7 1 0 1-1 1-2s2-6 5-11c4-7 4-9 4-13-1-11-12-33-16-33-2 0-7-3-7-4s5-4 8-5c1 0 7 0 12-1s10-1 11-2c3-2 6-1 7 1 1 3 3 4 3 2 0-3 3-5 7-6 7-2 11-4 13-9 1-2 2-4 2-5v-7c-1-4 0-6 1-7 1 0 2-2 1-4 0-2 0-3 3-4 1 0 3-2 3-3 1-1 2-2 5-2 5-1 8-5 6-8-1-2-6-4-11-4-1 0-3-1-4-1-2-2-1-13 0-16 1-1 2-5 2-9 1-8 1-9-2-12-2-2-4-4-5-4 0 0-2-1-2-3-2-2-3-3-6-4-6-1-7-1-7-3 0-1-1-3-2-5-1-3-2-5-2-7 0-1-1-3-2-4-1-3-1-5 3-7 3-3 6-9 4-11 0-1-1-3 0-4 0-1-1-2-3-4-3-3-3-3-2-4 1-2 1-2-2-3-4-3-4-4 1-8 3-2 3-3 3-6-1-4-1-4 4-6 4-3 5-3 8-2 7 1 14-2 15-6v-5c1-1 0-4 0-7-2-3-2-5-1-5 0-1 1-3 1-4 0-3 0-3 3-5 2 0 5-1 7-1 1 0 3-1 5-2 0-1 2-2 3-2l4-2c1-2 3-3 4-3 0 0 2-1 3-3 1-1 5-3 7-4 4-2 4-3 4-6 0-1-1-3-2-4-2-1-4-3-5-4-1-2-4-3-5-4-5-1-3-2 4-2 6 0 13-1 14-3 1-1 11-5 16-6 2-1 4-2 4-3 0-2 5-4 10-3 3 0 4 0 9-5 3-3 6-6 6-7 0-2 13-13 15-14 2 0 5-1 8-2l5-2v-6c0-5-1-7-4-14-2-4-6-10-8-12-5-6-28-25-36-28-2-1-6-5-9-8-4-3-7-6-8-7-4-1-8-6-11-12-2-5-3-7-7-9-2-2-5-3-5-3-1 0-9-5-10-6-5-5-19-15-22-16-1-1-2-2-2-3l-5-5c-7-5-9-9-9-15-1-4-2-7-5-9 0-1-1-2-1-4s0-3-1-3-1-2-2-4c0-3 0-4 4-8 2-2 4-5 4-5 0-2-12-14-15-16-4-2-5-6-3-9s1-5-3-7c-3-1-4-4-2-5 1-1 1-2 1-3s1-3 3-4c2-2 3-3 3-5 0-1 0-4 2-6 2-3 3-5 1-8s0-5 5-8c5-2 9-6 9-8 0-4-20-18-30-22-8-3-10-6-10-12-1-6-1-7-6-13-2-3-4-6-4-8 0-1-2-5-6-9-7-9-8-11-7-15 0-3 0-3-3-4-1-1-6-2-11-2-11-2-10-2-27-9-4-2-8-3-11-3s-10-1-15-2c-5 0-10-1-11-1-7 0-15 2-19 4s-8 2-9-1c0-1 0-3 1-4 2-3 1-6-1-8-1-1-6-2-13-3-14-2-15-2-13-5 1-2 1-3 0-4s-2-1-6 1c-2 1-4 2-5 2 0-1 4-4 11-8 5-2 7-3 7-5 0-1 1-2 3-3 1 0 2-1 2-3s0-3 1-4c1 0 1-1 1-3s-1-3-4-5c-2-2-5-3-6-4-4-1-5-3-2-7 1-2 3-3 7-4 5-1 5-1 8-7 1-3 3-6 5-7 1-1 3-4 3-7 1-3 3-7 3-8 1-1 1-3 1-4-1-3-11-13-17-16-3-2-7-5-10-8-2-2-5-4-7-4-1 0-2-1-3-2s-2-2-4-3l-3-1 7-2c3 0 9-1 12-2 7-1 12-3 18-7 5-4 7-8 7-15 0-5 1-7 10-14 1-1 2-3 2-4 0-3 5-14 9-18s5-6 4-9c0-2 0-3 4-5 6-2 6-4-1-9-6-4-9-7-14-13-2-1-5-4-7-6-3-2-7-5-8-7-2-1-6-3-9-4-2-1-5-2-6-3-2-1-13-6-15-6s-11-4-11-5c-1-1-9-5-18-10-18-8-30-15-35-18-2-2-12-5-31-10-7-3-12-7-12-11 0-2 1-4 5-7 4-4 6-7 7-10l2-5 9-5c10-4 12-6 12-12s1-7 8-10c10-5 11-7 11-12-1-4-1-5 4-9 4-5 9-8 21-12 4-1 11-4 15-7 9-4 10-5 11-9 2-8 8-13 18-16 8-2 11-6 12-13v-5H30v1171z"/>
</svg>
diff --git a/play.js b/play.js
index a707225..f5422ed 100644
--- a/play.js
+++ b/play.js
@@ -111,6 +111,46 @@ let ui = {
present: new Set(),
}
+function remember_position(e) {
+ if (e.classList.contains("show")) {
+ let rect = e.getBoundingClientRect()
+ e.my_parent = true
+ e.my_x = rect.x
+ e.my_y = rect.y
+ } else {
+ e.my_parent = false
+ e.my_x = 0
+ e.my_y = 0
+ }
+}
+
+function animate_position(e) {
+ if (e.parentElement) {
+ if (e.my_parent) {
+ let rect = e.getBoundingClientRect()
+ let dx = e.my_x - rect.x
+ let dy = e.my_y - rect.y
+ if (dx !== 0 || dy !== 0) {
+ e.animate(
+ [
+ { transform: `translate(${dx}px, ${dy}px)`, },
+ { transform: "translate(0, 0)", },
+ ],
+ { duration: 250, easing: "ease" }
+ )
+ }
+ } else {
+ e.animate(
+ [
+ { opacity: 0 },
+ { opacity: 1 }
+ ],
+ { duration: 250, easing: "ease" }
+ )
+ }
+ }
+}
+
function on_focus_space_tip(x) {
ui.towns[x].classList.add("tip")
}
@@ -869,6 +909,9 @@ function on_update() {
document.getElementById("frank_vp").textContent = view.f_vp
document.getElementById("saracen_vp").textContent = view.s_vp
+ for (let c = 1; c <= 27; ++c)
+ remember_position(ui.cards[c])
+
update_cards()
update_map()
@@ -877,11 +920,19 @@ function on_update() {
document.getElementById("battle_message").textContent = view.battle.flash
if (view.flash_next)
start_flash()
- document.getElementById("battle").classList.add("show")
+ if (!document.getElementById("battle").classList.contains("show")) {
+ document.getElementById("battle").classList.add("show")
+ document.getElementById("battle").scrollIntoView({
+ block:"center", inline:"center", behavior:"smooth"
+ })
+ }
update_battle()
} else {
document.getElementById("battle").classList.remove("show")
}
+
+ for (let c = 1; c <= 27; ++c)
+ animate_position(ui.cards[c])
}
build_map()