add navbar + mapbuilder
This commit is contained in:
parent
486612cf88
commit
f5fd91008c
13 changed files with 678 additions and 61 deletions
|
@ -40,7 +40,6 @@ use rocket_contrib::templates::{Template, Engines};
|
||||||
use rocket_contrib::templates::tera::{self, Value};
|
use rocket_contrib::templates::tera::{self, Value};
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::cmp::Ordering::Equal;
|
|
||||||
|
|
||||||
const COLOURS: [&'static str; 9] = ["grey", "blue", "cyan", "green", "yellow", "orange", "red", "pink", "purple"];
|
const COLOURS: [&'static str; 9] = ["grey", "blue", "cyan", "green", "yellow", "orange", "red", "pink", "purple"];
|
||||||
|
|
||||||
|
|
|
@ -23,15 +23,7 @@ async fn files(file: PathBuf) -> Option<NamedFile> {
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
async fn index() -> Template {
|
async fn index() -> Template {
|
||||||
// let context = context();
|
// let context = context();
|
||||||
let context = Context { name: "Arthur".into(), maps: None };
|
let context = Context::new("Home", None);
|
||||||
// context.insert("name".to_string(), "Arthur".to_string());
|
|
||||||
Template::render("index", &context)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/status")]
|
|
||||||
async fn status() -> Template {
|
|
||||||
// let context = context();
|
|
||||||
let context = Context { name: "Arthur".into(), maps: None };
|
|
||||||
// context.insert("name".to_string(), "Arthur".to_string());
|
// context.insert("name".to_string(), "Arthur".to_string());
|
||||||
Template::render("index", &context)
|
Template::render("index", &context)
|
||||||
}
|
}
|
||||||
|
@ -59,14 +51,19 @@ async fn map_post(map_req: Json<MapReq>) -> Result<String, String> {
|
||||||
Ok("ok".into())
|
Ok("ok".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/maps")]
|
#[get("/lobby")]
|
||||||
async fn maps_get() -> Result<Template, String> {
|
async fn maps_get() -> Result<Template, String> {
|
||||||
let maps = get_maps().await?;
|
let maps = get_maps().await?;
|
||||||
|
let context = Context::new("Lobby", Some(maps));
|
||||||
let context = Context { name: "Arthur".into(), maps: Some(maps) };
|
|
||||||
Ok(Template::render("lobby", &context))
|
Ok(Template::render("lobby", &context))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/mapbuilder")]
|
||||||
|
async fn builder_get() -> Result<Template, String> {
|
||||||
|
let context = Context::new("Map Builder", None);
|
||||||
|
Ok(Template::render("mapbuilder", &context))
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/maps/<file>")]
|
#[get("/maps/<file>")]
|
||||||
async fn map_get(file: String) -> Result<Template, String> {
|
async fn map_get(file: String) -> Result<Template, String> {
|
||||||
let mut content = String::new();
|
let mut content = String::new();
|
||||||
|
@ -77,5 +74,5 @@ async fn map_get(file: String) -> Result<Template, String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fuel(routes: &mut Vec<Route>) {
|
pub fn fuel(routes: &mut Vec<Route>) {
|
||||||
routes.extend(routes![files, status, index, map_post, map_get, maps_get]);
|
routes.extend(routes![files, index, map_post, map_get, maps_get, builder_get]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,38 @@
|
||||||
use async_std::prelude::*;
|
use async_std::prelude::*;
|
||||||
use async_std::fs;
|
use async_std::fs;
|
||||||
|
|
||||||
|
static NAV: [(&'static str, &'static str); 3] = [("/", "Home"), ("/lobby", "Lobby"), ("/mapbuilder", "Map Builder")];
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct Map {
|
pub struct Map {
|
||||||
name: String,
|
name: String,
|
||||||
url: String,
|
url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct Link {
|
||||||
|
name: String,
|
||||||
|
href: String,
|
||||||
|
active: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
nav: Vec<Link>,
|
||||||
pub maps: Option<Vec<Map>>,
|
pub maps: Option<Vec<Map>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Context {
|
||||||
|
pub fn new(active: &str, maps: Option<Vec<Map>>) -> Self {
|
||||||
|
let nav = NAV.iter().map(|(href, name)| Link { name: name.to_string(), href: href.to_string(), active: *name == active }).collect();
|
||||||
|
|
||||||
|
Context {
|
||||||
|
nav, name: String::from(""), maps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_maps() -> Result<Vec<Map>, String> {
|
pub async fn get_maps() -> Result<Vec<Map>, String> {
|
||||||
let mut maps = Vec::new();
|
let mut maps = Vec::new();
|
||||||
let mut entries = fs::read_dir("maps").await.map_err(|_| "IO error".to_string())?;
|
let mut entries = fs::read_dir("maps").await.map_err(|_| "IO error".to_string())?;
|
||||||
|
|
211
backend/static/script/mapbuilder.js
Normal file
211
backend/static/script/mapbuilder.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,5 @@
|
||||||
const ids = {};
|
const ids = {};
|
||||||
["map_holder"].forEach(id => ids[id] = document.getElementById(id));
|
["map_holder", "name", "turns", "nop"].forEach(id => ids[id] = document.getElementById(id));
|
||||||
|
|
||||||
var last_map;
|
var last_map;
|
||||||
|
|
||||||
|
@ -12,3 +12,7 @@ async function handle_map_click(url, event) {
|
||||||
const c = await fetch(url);
|
const c = await fetch(url);
|
||||||
ids["map_holder"].innerHTML = await c.text();
|
ids["map_holder"].innerHTML = await c.text();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function start_game() {
|
||||||
|
|
||||||
|
}
|
46
backend/static/style/base.css
Normal file
46
backend/static/style/base.css
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
.nav ul {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav li {
|
||||||
|
float: left;
|
||||||
|
border-right: 1px solid #bbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav li:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav li a {
|
||||||
|
display: block;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
padding: 14px 16px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav .active {
|
||||||
|
color: #ff7f00;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Change the link color to #111 (black) on hover */
|
||||||
|
|
||||||
|
.nav li a:hover {
|
||||||
|
filter: brightness(80%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
273
backend/static/style/mapbuilder.css
Normal file
273
backend/static/style/mapbuilder.css
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
.content {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
background: black;
|
||||||
|
color: #ff7f00;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
overflow: hidden;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
width: 120vh;
|
||||||
|
height: 95vh;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
padding-left: 3rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.boxed {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
width: 100%;
|
||||||
|
height: 4.75%;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row:nth-child(even) {
|
||||||
|
position: relative;
|
||||||
|
margin-left: 2.5%;
|
||||||
|
margin-right: -2.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row:nth-child(even) .square:nth-child(even) {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row:nth-child(even) .square:nth-child(odd) {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row:nth-child(odd) .square:nth-child(even) {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row:nth-child(odd) .square:nth-child(odd) {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.square {
|
||||||
|
clip-path: polygon( 50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
|
||||||
|
background: #804000;
|
||||||
|
width: calc(4.75% - 2px);
|
||||||
|
height: 130%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.square:hover {
|
||||||
|
filter: brightness(80%);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Customize the label (the container) */
|
||||||
|
|
||||||
|
.colourButtonContainer {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Hide the browser's default radio button */
|
||||||
|
|
||||||
|
.colourButtonContainer input {
|
||||||
|
opacity: 0;
|
||||||
|
height: 0;
|
||||||
|
width: 0;
|
||||||
|
margin: 1rem 0rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Create a custom radio button */
|
||||||
|
|
||||||
|
.colourButtonCheckmark {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 25px;
|
||||||
|
width: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colourButton_gray {
|
||||||
|
background-color: lightgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colourButton_blue {
|
||||||
|
background-color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colourButton_cyan {
|
||||||
|
background-color: cyan;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colourButton_green {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colourButton_yellow {
|
||||||
|
background-color: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colourButton_orange {
|
||||||
|
background-color: orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colourButton_red {
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colourButton_pink {
|
||||||
|
background-color: pink;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colourButton_purple {
|
||||||
|
background-color: purple;
|
||||||
|
}
|
||||||
|
|
||||||
|
.planet_gray {
|
||||||
|
background-color: lightgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.planet_blue {
|
||||||
|
background-color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.planet_cyan {
|
||||||
|
background-color: cyan;
|
||||||
|
}
|
||||||
|
|
||||||
|
.planet_green {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.planet_yellow {
|
||||||
|
background-color: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.planet_orange {
|
||||||
|
background-color: orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
.planet_red {
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.planet_pink {
|
||||||
|
background-color: pink;
|
||||||
|
}
|
||||||
|
|
||||||
|
.planet_purple {
|
||||||
|
background-color: purple;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* On mouse-over, add a gray background color */
|
||||||
|
|
||||||
|
.colourButtonContainer:hover input~.colourButtonCheckmark {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* When the radio button is checked, add a blue background */
|
||||||
|
|
||||||
|
.colourButtonContainer input:checked~.colourButtonCheckmark {
|
||||||
|
border: 1px solid blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Create the indicator (the dot/circle - hidden when not checked) */
|
||||||
|
|
||||||
|
.colourButtonCheckmark:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Show the indicator (dot/circle) when checked */
|
||||||
|
|
||||||
|
.colourButtonContainer input:checked~.colourButtonCheckmark:after {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Style the indicator (dot/circle) */
|
||||||
|
|
||||||
|
.colourButtonContainer .colourButtonCheckmark:after {
|
||||||
|
top: 9px;
|
||||||
|
left: 9px;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
textarea {
|
||||||
|
border: 1px solid #804000;
|
||||||
|
color: #804000;
|
||||||
|
padding: 0.5rem;
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
background: black;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input_container {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input_container label {
|
||||||
|
width: 140px;
|
||||||
|
font-size: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input_container input {
|
||||||
|
width: 100%;
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
|
.output {
|
||||||
|
height: 100%;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color: #E67300;
|
||||||
|
/* Green */
|
||||||
|
border: none;
|
||||||
|
color: black;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 5px;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 16px;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
|
@ -71,7 +71,7 @@ body {
|
||||||
background-color: #333;
|
background-color: #333;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100vh;
|
height: 100%;
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
/* width: 25%; */
|
/* width: 25%; */
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
|
@ -2,10 +2,21 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>Tera Demo</title>
|
<title>Planetwars</title>
|
||||||
|
<link rel="stylesheet" href="style/base.css">
|
||||||
<link rel="stylesheet" href="style/style.css">
|
<link rel="stylesheet" href="style/style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div class="nav">
|
||||||
|
<ul>
|
||||||
|
{% for link in nav %}
|
||||||
|
<li><a {% if link.active %}class="active"{% endif %} href="{{ link.href }}">{{ link.name }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
{% block content %}{% endblock content %}
|
{% block content %}{% endblock content %}
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -4,8 +4,4 @@
|
||||||
|
|
||||||
<h1>Hello {{ name }}!</h1>
|
<h1>Hello {{ name }}!</h1>
|
||||||
|
|
||||||
{% if maps %}
|
|
||||||
{% include "maps" %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<label for="nop">Number of players:</label>
|
<label for="nop">Number of players:</label>
|
||||||
<input id="nop" type="number" value=2></input>
|
<input id="nop" type="number" value=2></input>
|
||||||
</div>
|
</div>
|
||||||
<button>
|
<button onclick="start_game()">
|
||||||
Start
|
Start
|
||||||
</button>
|
</button>
|
||||||
<div id="map_holder">
|
<div id="map_holder">
|
||||||
|
|
57
backend/templates/mapbuilder.html.tera
Normal file
57
backend/templates/mapbuilder.html.tera
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
{% extends "base" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="style/mapbuilder.css">
|
||||||
|
|
||||||
|
<div class="grid"></div>
|
||||||
|
<div class="controls">
|
||||||
|
{# <h2>Controls</h2> #}
|
||||||
|
<div class="boxed">
|
||||||
|
<label>How many squares (this will remove your map)</label>
|
||||||
|
<input class="amountOfSquares" type="number" min="10" max="50" value="20"></input>
|
||||||
|
<div class="colourButtonWrapper"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxed">
|
||||||
|
<label for="currentName">Setting parameters</label>
|
||||||
|
<div class="input_container">
|
||||||
|
<label for="currentName">Name:</label>
|
||||||
|
<input id="currentName" type="text" placeholder="name"></input>
|
||||||
|
</div>
|
||||||
|
<div class="input_container">
|
||||||
|
<label for="currentShipCount">Ship count:</label>
|
||||||
|
<input id="currentShipCount" type="number" value=20></input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxed">
|
||||||
|
<label>Hovered planet parameters</label>
|
||||||
|
<div class="input_container">
|
||||||
|
<label for="name">Name:</label>
|
||||||
|
<input id="name" type="text" disabled></input>
|
||||||
|
</div>
|
||||||
|
<div class="input_container">
|
||||||
|
<label class="small_label" for="shipCount">Ship count:</label>
|
||||||
|
<input id="shipCount" type="number" disabled></input>
|
||||||
|
</div>
|
||||||
|
<div class="input_container">
|
||||||
|
<label class="small_label" for="owner">Owner:</label>
|
||||||
|
<input id="owner" type="number" disabled></input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxed">
|
||||||
|
<label>Name for map</label>
|
||||||
|
<input id="mapName" type="text" placeholder="name"></input>
|
||||||
|
<div class="buttons">
|
||||||
|
<button class="confirm">Send Map</button>
|
||||||
|
<button class="clear">Clear Map</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p id="error_field" class="hidden">
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<script src="script/mapbuilder.js"></script>
|
||||||
|
{% endblock %}
|
|
@ -1,6 +1,8 @@
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="style.css">
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="grid"></div>
|
<div class="grid"></div>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
|
@ -41,4 +43,5 @@
|
||||||
<textarea id="mapOutput" class="output hidden"></textarea>
|
<textarea id="mapOutput" class="output hidden"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<script src="script.js"></script>
|
<script src="script.js"></script>
|
||||||
|
|
||||||
<body>
|
<body>
|
Loading…
Reference in a new issue