Compare commits
30 commits
master
...
frontend/v
Author | SHA1 | Date | |
---|---|---|---|
|
9325b289c4 | ||
|
20a2a9c79e | ||
|
ae5cbdca79 | ||
|
217341e381 | ||
|
f8c86487d5 | ||
|
55dbd5ff2e | ||
|
da4c7b84b7 | ||
|
b1f41d7974 | ||
|
c2365d3668 | ||
|
b8fc4e1710 | ||
|
720520f4b7 | ||
|
68a58e24d7 | ||
|
4645f8d392 | ||
|
dc8df8eb9f | ||
|
2c9dc46b48 | ||
|
ddbf7a026c | ||
|
bebc10a81f | ||
|
8d0144f1ef | ||
|
ef06cf93a3 | ||
|
a1cfa658e9 | ||
|
c8b149f0c4 | ||
|
941dfaf03d | ||
|
da4920014d | ||
|
2431a7f4c7 | ||
|
a0d296e8fb | ||
|
a849ee7356 | ||
|
1fa5390f87 | ||
|
a37405047e | ||
|
0b47ded269 | ||
|
9db1426e15 |
17 changed files with 503 additions and 915 deletions
38
Dockerfile
38
Dockerfile
|
@ -1,38 +0,0 @@
|
||||||
FROM rust:1.44 AS build-env
|
|
||||||
|
|
||||||
|
|
||||||
WORKDIR /sources
|
|
||||||
|
|
||||||
RUN git clone -b wasm32-target-fix https://github.com/drager/wasm-pack.git
|
|
||||||
WORKDIR wasm-pack
|
|
||||||
|
|
||||||
RUN rustup default nightly
|
|
||||||
RUN cargo install --path .
|
|
||||||
|
|
||||||
|
|
||||||
WORKDIR /planetwars
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
WORKDIR backend
|
|
||||||
RUN cargo build --release
|
|
||||||
|
|
||||||
|
|
||||||
WORKDIR ../frontend
|
|
||||||
|
|
||||||
RUN cargo update
|
|
||||||
RUN wasm-pack build
|
|
||||||
|
|
||||||
FROM node:10
|
|
||||||
COPY --from=build-env /planetwars /planetwars
|
|
||||||
WORKDIR /planetwars/frontend/www
|
|
||||||
RUN npm install
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
WORKDIR /planetwars/backend
|
|
||||||
|
|
||||||
EXPOSE 9142
|
|
||||||
EXPOSE 8123
|
|
||||||
EXPOSE 3012
|
|
||||||
|
|
||||||
CMD ["target/release/planetwars"]
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
# Planetwars
|
|
||||||
|
|
||||||
## Docker
|
|
||||||
|
|
||||||
Build: `docker build --tag pw:1.0 .`
|
|
||||||
|
|
||||||
Run: `docker run --rm -p 8123:8123 -p 9142:9142 -p 3012:3012 -v $(pwd)/backend/games:/planetwars/backend/games --name planetwars pw:1.0`
|
|
||||||
|
|
||||||
Add parameter `-e PW_HOST_NAME=<domain>`, for example `-e PW_HOST_NAME=mozaic.zeus.gent`, to set the domain used in the application.
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "planetwars"
|
name = "backend"
|
||||||
version = "0.1.2"
|
version = "0.1.1"
|
||||||
authors = ["ajuvercr <arthur.vercruysse@ugent.be>"]
|
authors = ["ajuvercr <arthur.vercruysse@ugent.be>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
@ -8,20 +8,18 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
mozaic = { git = "https://github.com/ZeusWPI/MOZAICP" }
|
mozaic = { git = "https://github.com/ZeusWPI/MOZAICP" }
|
||||||
rand = { version = "0.8.2", default-features = true }
|
rand = { version = "0.6.5", default-features = true }
|
||||||
|
|
||||||
async-std = { version = "1.9.0", features = ["attributes"] }
|
async-std = { version = "1.5.0", features = ["attributes"] }
|
||||||
futures = { version = "0.3.12", features = ["executor", "thread-pool"] }
|
futures = { version = "0.3.1", features = ["executor", "thread-pool"] }
|
||||||
|
|
||||||
figment = "0.10.2"
|
serde = "1.0.100"
|
||||||
|
serde_derive = "1.0.100"
|
||||||
serde = "1.0.119"
|
|
||||||
serde_derive = "1.0.119"
|
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
tracing = "0.1.22"
|
tracing = "0.1.9"
|
||||||
tracing-futures = "0.2.4"
|
tracing-futures = "0.1.0"
|
||||||
tracing-subscriber = "0.2.15"
|
tracing-subscriber = "0.1.5"
|
||||||
rocket = { git = "https://github.com/SergioBenitez/Rocket", branch = "master" }
|
rocket = { git = "https://github.com/SergioBenitez/Rocket", branch = "async" }
|
||||||
rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket", branch = "master", features = ["handlebars_templates", "tera_templates"] }
|
rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket", branch = "async", features = ["handlebars_templates", "tera_templates"] }
|
||||||
|
|
||||||
educe = { version = "0.4.13", features = ["Debug", "Default", "Hash", "Clone", "Copy"] }
|
educe = { version = "0.4.2", features = ["Debug", "Default", "Hash", "Clone", "Copy"] }
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
# Planetwars backend
|
# Planetwars backend
|
||||||
|
|
||||||
Change hostname in info slides with PW_PORT, PW_HOST_NAME or PW_ADDRESS env variable.
|
|
||||||
|
|
||||||
The main planetwars server that instanciates planetwars matches etc...
|
The main planetwars server that instanciates planetwars matches etc...
|
||||||
|
|
11
backend/Rocket.toml
Normal file
11
backend/Rocket.toml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[development]
|
||||||
|
address = "localhost"
|
||||||
|
port = 8000
|
||||||
|
|
||||||
|
[staging]
|
||||||
|
address = "0.0.0.0"
|
||||||
|
port = 80
|
||||||
|
|
||||||
|
[production]
|
||||||
|
address = "0.0.0.0"
|
||||||
|
port = 8123
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(proc_macro_hygiene, async_closure, decl_macro)]
|
#![feature(proc_macro_hygiene)]
|
||||||
|
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -11,8 +11,6 @@ extern crate futures;
|
||||||
extern crate mozaic;
|
extern crate mozaic;
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
|
|
||||||
extern crate figment;
|
|
||||||
|
|
||||||
extern crate tracing;
|
extern crate tracing;
|
||||||
extern crate tracing_futures;
|
extern crate tracing_futures;
|
||||||
extern crate tracing_subscriber;
|
extern crate tracing_subscriber;
|
||||||
|
@ -24,7 +22,6 @@ extern crate rocket_contrib;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate educe;
|
extern crate educe;
|
||||||
|
|
||||||
use figment::{providers::{Serialized, Env}};
|
|
||||||
use tracing_subscriber::{EnvFilter, FmtSubscriber};
|
use tracing_subscriber::{EnvFilter, FmtSubscriber};
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
@ -43,33 +40,14 @@ mod util;
|
||||||
use util::Games;
|
use util::Games;
|
||||||
use util::COLOURS;
|
use util::COLOURS;
|
||||||
|
|
||||||
use rocket::fairing::AdHoc;
|
|
||||||
use rocket_contrib::templates::tera::{self, Value};
|
use rocket_contrib::templates::tera::{self, Value};
|
||||||
use rocket_contrib::templates::{Engines, Template};
|
use rocket_contrib::templates::{Engines, Template};
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
/// Config for the planetwars server
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub struct PWConfig {
|
|
||||||
host_name: String,
|
|
||||||
address: String,
|
|
||||||
port: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for PWConfig {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
host_name: String::from("localhost"),
|
|
||||||
address: String::from("0.0.0.0"),
|
|
||||||
port: 8000,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Calculate viewbox from array of points (used in map preview), added to Tera engine.
|
/// Calculate viewbox from array of points (used in map preview), added to Tera engine.
|
||||||
/// So this function can be called in template.
|
/// So this function can be called in template.
|
||||||
fn calc_viewbox(value: &Value, _: &HashMap<String, Value>) -> tera::Result<Value> {
|
fn calc_viewbox(value: Value, _: HashMap<String, Value>) -> tera::Result<Value> {
|
||||||
let mut min_x = std::f64::MAX;
|
let mut min_x = std::f64::MAX;
|
||||||
let mut min_y = std::f64::MAX;
|
let mut min_y = std::f64::MAX;
|
||||||
let mut max_x = std::f64::MIN;
|
let mut max_x = std::f64::MIN;
|
||||||
|
@ -101,21 +79,15 @@ fn calc_viewbox(value: &Value, _: &HashMap<String, Value>) -> tera::Result<Value
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get's the right colour for planets
|
/// Get's the right colour for planets
|
||||||
fn get_colour(value: &Value, _: &HashMap<String, Value>) -> tera::Result<Value> {
|
fn get_colour(value: Value, _: HashMap<String, Value>) -> tera::Result<Value> {
|
||||||
return Ok(Value::String(
|
return Ok(Value::String(
|
||||||
COLOURS[value.as_u64().unwrap_or(0) as usize].to_string(),
|
COLOURS[value.as_u64().unwrap_or(0) as usize].to_string(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_host_name(host_name: &str) -> impl Fn(&HashMap<String, Value>) -> tera::Result<Value> + Sync + Send {
|
|
||||||
let host_name = host_name.to_string();
|
|
||||||
|
|
||||||
move |_| Ok(Value::String(host_name.clone()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Async main function, starting logger, graph and rocket
|
/// Async main function, starting logger, graph and rocket
|
||||||
#[rocket::launch]
|
#[async_std::main]
|
||||||
async fn rocket() -> rocket::Rocket {
|
async fn main() {
|
||||||
let fut = graph::set_default();
|
let fut = graph::set_default();
|
||||||
|
|
||||||
let sub = FmtSubscriber::builder()
|
let sub = FmtSubscriber::builder()
|
||||||
|
@ -123,38 +95,26 @@ async fn rocket() -> rocket::Rocket {
|
||||||
.finish();
|
.finish();
|
||||||
tracing::subscriber::set_global_default(sub).unwrap();
|
tracing::subscriber::set_global_default(sub).unwrap();
|
||||||
|
|
||||||
let pool = ThreadPool::builder().create().unwrap();
|
let pool = ThreadPool::new().unwrap();
|
||||||
pool.spawn_ok(fut.map(|_| ()));
|
pool.spawn_ok(fut.map(|_| ()));
|
||||||
let gm = create_game_manager("0.0.0.0:9142", pool.clone()).await;
|
let gm = create_game_manager("0.0.0.0:9142", pool.clone()).await;
|
||||||
|
|
||||||
async_std::task::sleep(std::time::Duration::from_millis(200)).await;
|
|
||||||
|
|
||||||
let mut routes = Vec::new();
|
let mut routes = Vec::new();
|
||||||
routes::fuel(&mut routes);
|
routes::fuel(&mut routes);
|
||||||
|
|
||||||
let figment = rocket::Config::figment()
|
let tera = Template::custom(|engines: &mut Engines| {
|
||||||
.merge(Serialized::defaults(PWConfig::default())) // Extend but not overwrite
|
engines.tera.register_filter("calc_viewbox", calc_viewbox);
|
||||||
.merge(Env::prefixed("PW_")); // Overwrite
|
engines.tera.register_filter("get_colour", get_colour);
|
||||||
|
});
|
||||||
|
|
||||||
rocket::custom(figment)
|
rocket::ignite()
|
||||||
.manage(gm)
|
.manage(gm)
|
||||||
.manage(pool)
|
.manage(pool)
|
||||||
.manage(Games::new())
|
.manage(Games::new())
|
||||||
.attach(AdHoc::config::<PWConfig>()) // Manage the config
|
.attach(tera)
|
||||||
.mount("/", routes)
|
.mount("/", routes)
|
||||||
.attach(AdHoc::on_attach("Assets Config", async move |rocket| {
|
.launch()
|
||||||
let pw_config = rocket.figment().extract::<PWConfig>().unwrap_or_default();
|
.unwrap();
|
||||||
println!("PW Config {:?}", pw_config);
|
|
||||||
let host_name = pw_config.host_name.clone();
|
|
||||||
|
|
||||||
let tera = Template::custom(move |engines: &mut Engines| {
|
|
||||||
engines.tera.register_filter("calc_viewbox", calc_viewbox);
|
|
||||||
engines.tera.register_filter("get_colour", get_colour);
|
|
||||||
engines.tera.register_function("get_host_name", get_host_name(&host_name));
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(rocket.attach(tera))
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates the actual game_manager
|
/// Creates the actual game_manager
|
||||||
|
@ -162,9 +122,9 @@ async fn rocket() -> rocket::Rocket {
|
||||||
async fn create_game_manager(tcp: &str, pool: ThreadPool) -> game::Manager {
|
async fn create_game_manager(tcp: &str, pool: ThreadPool) -> game::Manager {
|
||||||
let addr = tcp.parse::<SocketAddr>().unwrap();
|
let addr = tcp.parse::<SocketAddr>().unwrap();
|
||||||
let (gmb, handle) = game::Manager::builder(pool.clone());
|
let (gmb, handle) = game::Manager::builder(pool.clone());
|
||||||
pool.spawn_ok(handle.map(|_| {println!("I'm done")}));
|
pool.spawn_ok(handle.map(|_| ()));
|
||||||
let ep = TcpEndpoint::new(addr, pool.clone());
|
let ep = TcpEndpoint::new(addr, pool.clone());
|
||||||
|
|
||||||
let gmb = gmb.add_endpoint(ep, "TCP endpoint");
|
let gmb = gmb.add_endpoint(ep, "TCP endpoint");
|
||||||
gmb.build("games/games.json", pool).await.unwrap()
|
gmb.build("games.ini", pool).await.unwrap()
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,11 +36,11 @@ impl PlanetWarsGame {
|
||||||
.map(|p| (p.name.clone(), p.id))
|
.map(|p| (p.name.clone(), p.id))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if let Err(_) = create_dir("games") {
|
if let Err(_) = create_dir("static/games") {
|
||||||
println!("'games' already exists");
|
println!("'static/games' already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
let file = File::create(format!("games/{}", location)).unwrap();
|
let file = File::create(format!("static/games/{}", location)).unwrap();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
state,
|
state,
|
||||||
|
|
|
@ -77,7 +77,7 @@ async fn post_game(
|
||||||
state: State<'_, Games>,
|
state: State<'_, Games>,
|
||||||
) -> Result<Json<GameRes>, String> {
|
) -> Result<Json<GameRes>, String> {
|
||||||
let game = build_builder(
|
let game = build_builder(
|
||||||
tp.inner().clone(),
|
tp.clone(),
|
||||||
game_req.nop,
|
game_req.nop,
|
||||||
game_req.max_turns,
|
game_req.max_turns,
|
||||||
&game_req.map,
|
&game_req.map,
|
||||||
|
@ -108,7 +108,6 @@ fn generate_string_id() -> String {
|
||||||
rand::thread_rng()
|
rand::thread_rng()
|
||||||
.sample_iter(&rand::distributions::Alphanumeric)
|
.sample_iter(&rand::distributions::Alphanumeric)
|
||||||
.take(15)
|
.take(15)
|
||||||
.map(|x| x as char)
|
|
||||||
.collect::<String>()
|
.collect::<String>()
|
||||||
+ ".json"
|
+ ".json"
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,7 @@ mod maps;
|
||||||
/// Handles all files located in the static folder
|
/// Handles all files located in the static folder
|
||||||
#[get("/<file..>", rank = 6)]
|
#[get("/<file..>", rank = 6)]
|
||||||
async fn files(file: PathBuf) -> Option<NamedFile> {
|
async fn files(file: PathBuf) -> Option<NamedFile> {
|
||||||
NamedFile::open(Path::new("static/").join(file)).await.ok()
|
NamedFile::open(Path::new("static/").join(file)).ok()
|
||||||
}
|
|
||||||
|
|
||||||
/// Handles all games files to be served
|
|
||||||
#[get("/games/<loc>")]
|
|
||||||
async fn game_get(loc: String) -> Option<NamedFile> {
|
|
||||||
NamedFile::open(Path::new("games/").join(loc)).await.ok()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Routes the index page, rendering the index Template.
|
/// Routes the index page, rendering the index Template.
|
||||||
|
@ -68,7 +62,6 @@ pub fn fuel(routes: &mut Vec<Route>) {
|
||||||
routes.extend(routes![
|
routes.extend(routes![
|
||||||
files,
|
files,
|
||||||
index,
|
index,
|
||||||
game_get,
|
|
||||||
builder_get,
|
builder_get,
|
||||||
visualizer_get,
|
visualizer_get,
|
||||||
debug_get
|
debug_get
|
||||||
|
@ -78,20 +71,18 @@ pub fn fuel(routes: &mut Vec<Route>) {
|
||||||
info::fuel(routes);
|
info::fuel(routes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads games.json
|
/// Reads games.ini
|
||||||
/// File that represents all played games
|
/// File that represents all played games
|
||||||
/// Ready to be visualized
|
/// Ready to be visualized
|
||||||
async fn get_played_games() -> Vec<GameState> {
|
async fn get_played_games() -> Vec<GameState> {
|
||||||
match fs::File::open("games/games.json").await {
|
match fs::File::open("games.ini").await {
|
||||||
Ok(file) => {
|
Ok(file) => {
|
||||||
let file = BufReader::new(file);
|
let file = BufReader::new(file);
|
||||||
file.lines()
|
file.lines()
|
||||||
.filter_map(move |maybe| {
|
.filter_map(move |maybe| async {
|
||||||
async {
|
|
||||||
maybe
|
maybe
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|line| serde_json::from_str::<FinishedState>(&line).ok())
|
.and_then(|line| serde_json::from_str::<FinishedState>(&line).ok())
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.map(|state| state.into())
|
.map(|state| state.into())
|
||||||
.collect()
|
.collect()
|
||||||
|
|
|
@ -16,9 +16,9 @@ How to connect
|
||||||
|
|
||||||
<pre class="commands">
|
<pre class="commands">
|
||||||
<code>
|
<code>
|
||||||
$ wget {{ get_host_name() }}/bot/runner.py
|
$ wget mozaic.zeus.gent/bot/runner.py
|
||||||
$ wget {{ get_host_name() }}/bot/simple.py
|
$ wget mozaic.zeus.gent/bot/simple.py
|
||||||
$ python3 runner.py -p 9142 --host {{ get_host_name() }}\
|
$ python3 runner.py -p 9142 --host mozaic.zeus.gent \
|
||||||
-n <Your name> -i <Id from the lobby> \
|
-n <Your name> -i <Id from the lobby> \
|
||||||
python3 simple.py
|
python3 simple.py
|
||||||
</code>
|
</code>
|
||||||
|
|
31
build.sh
31
build.sh
|
@ -1,31 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
info() {
|
|
||||||
echo
|
|
||||||
echo ">>>>>>>>>>>>>>>>>>>>>>>>>>> $1"
|
|
||||||
echo
|
|
||||||
}
|
|
||||||
|
|
||||||
source /home/$USER/.cargo/env
|
|
||||||
|
|
||||||
cd "$(dirname "$0")"
|
|
||||||
|
|
||||||
info "Pulling git"
|
|
||||||
git pull
|
|
||||||
|
|
||||||
cd frontend
|
|
||||||
|
|
||||||
info "Building WASM package"
|
|
||||||
cargo update
|
|
||||||
wasm-pack build
|
|
||||||
|
|
||||||
cd www
|
|
||||||
info "Building frontend with npm"
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
cd ../..
|
|
||||||
cd backend
|
|
||||||
|
|
||||||
info "Building backend with cargo --release"
|
|
||||||
cargo update
|
|
||||||
cargo build --release
|
|
|
@ -1,81 +0,0 @@
|
||||||
const fs = require('fs')
|
|
||||||
const readline = require('readline');
|
|
||||||
const rl = readline.createInterface({input: process.stdin, output: process.stdout});
|
|
||||||
|
|
||||||
const MY_PLAYER_NUMBER = 1
|
|
||||||
|
|
||||||
function move(moves) {
|
|
||||||
let record = {'moves': moves}
|
|
||||||
console.error(JSON.stringify(record))
|
|
||||||
console.log(JSON.stringify(record))
|
|
||||||
}
|
|
||||||
|
|
||||||
function find_max_with_key(array, key) {
|
|
||||||
return array.reduce((item1, item2) => {
|
|
||||||
let val1 = item1[key];
|
|
||||||
let val2 = item2[key];
|
|
||||||
return (val1 > val2 ? item1 : item2);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function find_min_with_key(array, key) {
|
|
||||||
return array.reduce((item1, item2) => {
|
|
||||||
let val1 = item1[key];
|
|
||||||
let val2 = item2[key];
|
|
||||||
return (val1 < val2 ? item1 : item2);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* De main code van de bot
|
|
||||||
*/
|
|
||||||
function run_bot(state) {
|
|
||||||
// Maak een lijst van mijn eigen planeten
|
|
||||||
let my_planets = state["planets"].filter((planet) => {
|
|
||||||
return planet['owner'] === MY_PLAYER_NUMBER
|
|
||||||
})
|
|
||||||
|
|
||||||
// Maak een lijst van de planeten van de tegenstander
|
|
||||||
let other_planets = state["planets"].filter((planet) => {
|
|
||||||
return planet['owner'] !== MY_PLAYER_NUMBER
|
|
||||||
})
|
|
||||||
|
|
||||||
if (my_planets.length === 0 || other_planets.length === 0) {
|
|
||||||
// Als er al een speler dood is moet ik niets meer doen
|
|
||||||
move([])
|
|
||||||
} else {
|
|
||||||
// Stuur alle schepen behalve 1 van mijn planeet met meeste schepen
|
|
||||||
// naar die van de andere speler met zijn minste schepen
|
|
||||||
let planet = find_max_with_key(my_planets, 'ship_count');
|
|
||||||
let dest = find_min_with_key(other_planets, 'ship_count');
|
|
||||||
|
|
||||||
if (planet !== undefined && dest !== undefined) {
|
|
||||||
move([{
|
|
||||||
'origin': planet['name'],
|
|
||||||
'destination': dest['name'],
|
|
||||||
'ship_count': planet['ship_count'] - 1
|
|
||||||
}])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
// Je kunt als 2de argument een file meegeven. De bot gaat deze dan gebruiken als input voor de ronde
|
|
||||||
if (process.argv.length > 2) {
|
|
||||||
try {
|
|
||||||
const data = fs.readFileSync(process.argv[2], 'utf8')
|
|
||||||
run_bot(JSON.parse(data))
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Anders gaan we stdin lezen
|
|
||||||
rl.on('line', (data) => {
|
|
||||||
run_bot(JSON.parse(data))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = main();
|
|
||||||
|
|
|
@ -4,9 +4,6 @@ version = "0.1.0"
|
||||||
authors = ["ajuvercr <arthur.vercruysse@ugent.be>"]
|
authors = ["ajuvercr <arthur.vercruysse@ugent.be>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[package.metadata.wasm-pack.profile.release]
|
|
||||||
wasm-opt = ["-Oz", "--enable-mutable-globals"]
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
extern crate octoon_math;
|
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
extern crate octoon_math;
|
||||||
extern crate voronoi;
|
extern crate voronoi;
|
||||||
|
|
||||||
use octoon_math::Mat3;
|
use octoon_math::{Mat3, Vec3, Vec2};
|
||||||
use voronoi::{make_polygons, voronoi, Point};
|
use voronoi::{Point, voronoi, make_polygons};
|
||||||
|
|
||||||
mod types;
|
|
||||||
mod utils;
|
mod utils;
|
||||||
|
mod types;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
@ -38,7 +38,7 @@ pub struct Circle {
|
||||||
|
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
fn spr(from: f32) -> f32 {
|
fn spr(from: f32) -> f32 {
|
||||||
let pi2 = PI * 2.;
|
let pi2 = PI*2.;
|
||||||
((from % pi2) + pi2) % pi2
|
((from % pi2) + pi2) % pi2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,17 +50,17 @@ impl Circle {
|
||||||
let y2 = p2.y;
|
let y2 = p2.y;
|
||||||
|
|
||||||
// Distance between planets
|
// Distance between planets
|
||||||
let q = ((x2 - x1).powi(2) + (y2 - y1).powi(2)).sqrt();
|
let q = ((x2-x1).powi(2) + (y2-y1).powi(2)).sqrt();
|
||||||
// Center of between planets
|
// Center of between planets
|
||||||
let x3 = (x1 + x2) / 2.0;
|
let x3 = (x1+x2)/2.0;
|
||||||
let y3 = (y1 + y2) / 2.0;
|
let y3 = (y1+y2)/2.0;
|
||||||
|
|
||||||
// Radius of circle
|
// Radius of circle
|
||||||
let r = q * 1.0;
|
let r = q * 1.0;
|
||||||
|
|
||||||
// Center of circle
|
// Center of circle
|
||||||
let x = x3 + (r.powi(2) - (q / 2.0).powi(2)).sqrt() * (y1 - y2) / q;
|
let x = x3 + (r.powi(2)-(q/2.0).powi(2)).sqrt() * (y1-y2)/q;
|
||||||
let y = y3 + (r.powi(2) - (q / 2.0).powi(2)).sqrt() * (x2 - x1) / q;
|
let y = y3 + (r.powi(2)-(q/2.0).powi(2)).sqrt() * (x2-x1)/q;
|
||||||
// console_log!("{},{} -> {},{} ({},{} r={})", x1, y1, x2, y2, x, y, r);
|
// console_log!("{},{} -> {},{} ({},{} r={})", x1, y1, x2, y2, x, y, r);
|
||||||
|
|
||||||
let a0 = spr((y - y1).atan2(x - x1));
|
let a0 = spr((y - y1).atan2(x - x1));
|
||||||
|
@ -74,12 +74,7 @@ impl Circle {
|
||||||
|
|
||||||
let distance = q.ceil() as usize + 1;
|
let distance = q.ceil() as usize + 1;
|
||||||
Self {
|
Self {
|
||||||
r,
|
r, x, y, a0, ad, distance
|
||||||
x,
|
|
||||||
y,
|
|
||||||
a0,
|
|
||||||
ad,
|
|
||||||
distance,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,31 +90,19 @@ impl Circle {
|
||||||
|
|
||||||
let cos = alpha.cos();
|
let cos = alpha.cos();
|
||||||
let sin = alpha.sin();
|
let sin = alpha.sin();
|
||||||
(
|
(Mat3::new(
|
||||||
Mat3::new(
|
0.3, 0.0, 0.0,
|
||||||
0.3,
|
0.0, 0.3, 0.0,
|
||||||
0.0,
|
-self.x + cos * self.r, -self.y + sin * self.r, 0.3,
|
||||||
0.0,
|
), alpha)
|
||||||
0.0,
|
|
||||||
0.3,
|
|
||||||
0.0,
|
|
||||||
-self.x + cos * self.r,
|
|
||||||
-self.y + sin * self.r,
|
|
||||||
0.3,
|
|
||||||
),
|
|
||||||
alpha,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_voronoi(planets: &Vec<types::Planet>, bbox: f32) -> (Vec<f32>, Vec<usize>) {
|
fn create_voronoi(planets: &Vec<types::Planet>, bbox: f32) -> (Vec<Vec2<f32>>, Vec<usize>) {
|
||||||
let mut verts: Vec<[f32; 2]> = planets.iter().map(|p| [p.x, p.y]).collect();
|
let mut verts: Vec<Vec2<f32>> = planets.iter().map(|p| Vec2::new(p.x, p.y)).collect();
|
||||||
let mut ids = Vec::new();
|
let mut ids = Vec::new();
|
||||||
|
|
||||||
let vor_points = planets
|
let vor_points = planets.iter().map(|p| Point::new(p.x as f64, p.y as f64)).collect();
|
||||||
.iter()
|
|
||||||
.map(|p| Point::new(p.x as f64, p.y as f64))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let vor = voronoi(vor_points, bbox as f64);
|
let vor = voronoi(vor_points, bbox as f64);
|
||||||
let vor = make_polygons(&vor);
|
let vor = make_polygons(&vor);
|
||||||
|
@ -130,8 +113,9 @@ fn create_voronoi(planets: &Vec<types::Planet>, bbox: f32) -> (Vec<f32>, Vec<usi
|
||||||
|
|
||||||
let mut prev = ids.len() + poly.len() - 1;
|
let mut prev = ids.len() + poly.len() - 1;
|
||||||
for p in poly.iter() {
|
for p in poly.iter() {
|
||||||
|
|
||||||
let now = verts.len();
|
let now = verts.len();
|
||||||
verts.push([p.x.0 as f32, p.y.0 as f32]);
|
verts.push(Vec2::new(p.x.0 as f32, p.y.0 as f32));
|
||||||
|
|
||||||
ids.push(idx);
|
ids.push(idx);
|
||||||
ids.push(now);
|
ids.push(now);
|
||||||
|
@ -140,9 +124,10 @@ fn create_voronoi(planets: &Vec<types::Planet>, bbox: f32) -> (Vec<f32>, Vec<usi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(verts.concat(), ids)
|
(verts, ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub struct Game {
|
pub struct Game {
|
||||||
states: Vec<types::State>,
|
states: Vec<types::State>,
|
||||||
|
@ -153,18 +138,18 @@ pub struct Game {
|
||||||
/* put extra shit here */
|
/* put extra shit here */
|
||||||
view_box: Vec<f32>,
|
view_box: Vec<f32>,
|
||||||
|
|
||||||
planets: Vec<f32>,
|
planets: Vec<Vec3<f32>>,
|
||||||
planet_ships: Vec<usize>,
|
planet_ships: Vec<usize>,
|
||||||
|
|
||||||
ship_locations: Vec<f32>,
|
ship_locations: Vec<[f32;9]>,
|
||||||
ship_label_locations: Vec<f32>,
|
ship_label_locations: Vec<[f32;9]>,
|
||||||
ship_colours: Vec<f32>,
|
ship_colours: Vec<Vec3<f32>>,
|
||||||
ship_counts: Vec<usize>,
|
ship_counts: Vec<usize>,
|
||||||
|
|
||||||
current_planet_colours: Vec<f32>,
|
current_planet_colours: Vec<Vec3<f32>>,
|
||||||
|
|
||||||
voronoi_vertices: Vec<f32>,
|
voronoi_vertices: Vec<Vec2<f32>>,
|
||||||
voronoi_colors: Vec<f32>,
|
voronoi_colors: Vec<Vec3<f32>>,
|
||||||
voronoi_indices: Vec<usize>,
|
voronoi_indices: Vec<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,10 +161,9 @@ impl Game {
|
||||||
console_log!("Rust is busy being awesome!");
|
console_log!("Rust is busy being awesome!");
|
||||||
|
|
||||||
// First line is fucked but we just filter out things that cannot parse
|
// First line is fucked but we just filter out things that cannot parse
|
||||||
let states: Vec<types::State> = file
|
let states: Vec<types::State> = file.split("\n").filter_map(|line|
|
||||||
.split("\n")
|
serde_json::from_str(line).ok()
|
||||||
.filter_map(|line| serde_json::from_str(line).ok())
|
).collect();
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut planet_map = HashMap::new();
|
let mut planet_map = HashMap::new();
|
||||||
|
|
||||||
|
@ -191,14 +175,10 @@ impl Game {
|
||||||
}
|
}
|
||||||
let view_box = utils::caclulate_viewbox(&states[0].planets);
|
let view_box = utils::caclulate_viewbox(&states[0].planets);
|
||||||
|
|
||||||
let (voronoi_vertices, voronoi_indices) =
|
|
||||||
create_voronoi(&states[0].planets, view_box[2].max(view_box[3]));
|
|
||||||
|
|
||||||
let voronoi_colors: Vec<f32> = voronoi_indices
|
let (voronoi_vertices, voronoi_indices) = create_voronoi(&states[0].planets, view_box[2].max(view_box[3]));
|
||||||
.iter()
|
|
||||||
.map(|_| [0.0, 0.0, 0.0])
|
let voronoi_colors = voronoi_indices.iter().map(|_| Vec3::new(0.0, 0.0, 0.0)).collect(); // Init these colours on black
|
||||||
.collect::<Vec<[f32; 3]>>()
|
|
||||||
.concat(); // Init these colours on black
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
planets: utils::get_planets(&states[0].planets, 2.0),
|
planets: utils::get_planets(&states[0].planets, 2.0),
|
||||||
|
@ -220,20 +200,24 @@ impl Game {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_viewbox(&self) -> Vec<f32> {
|
pub fn get_viewbox(&self) -> *const f32 {
|
||||||
self.view_box.clone()
|
self.view_box.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_planets(&self) -> Vec<f32> {
|
pub fn get_planets(&self) -> *const Vec3<f32> {
|
||||||
self.planets.clone()
|
self.planets.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_planet_ships(&self) -> Vec<usize> {
|
pub fn get_planet_ships(&self) -> *const usize {
|
||||||
self.planet_ships.clone()
|
self.planet_ships.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_planet_colors(&self) -> Vec<f32> {
|
pub fn get_planet_colors(&self) -> *const Vec3<f32> {
|
||||||
self.current_planet_colours.clone()
|
self.current_planet_colours.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_planet_count(&self) -> usize {
|
||||||
|
self.planets.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn turn_count(&self) -> usize {
|
pub fn turn_count(&self) -> usize {
|
||||||
|
@ -241,7 +225,7 @@ impl Game {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_turn(&mut self, turn: usize) -> usize {
|
pub fn update_turn(&mut self, turn: usize) -> usize {
|
||||||
self.turn = turn.min(self.states.len() - 1);
|
self.turn = turn.min(self.states.len() -1);
|
||||||
|
|
||||||
self.update_planet_ships();
|
self.update_planet_ships();
|
||||||
self.update_planet_colours();
|
self.update_planet_colours();
|
||||||
|
@ -253,114 +237,105 @@ impl Game {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_planet_ships(&mut self) {
|
fn update_planet_ships(&mut self) {
|
||||||
self.planet_ships = self.states[self.turn]
|
self.planet_ships = self.states[self.turn].planets.iter().map(|p| p.ship_count as usize).collect();
|
||||||
.planets
|
|
||||||
.iter()
|
|
||||||
.map(|p| p.ship_count as usize)
|
|
||||||
.collect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_voronoi_colors(&mut self) {
|
fn update_voronoi_colors(&mut self) {
|
||||||
for (i, p) in self.states[self.turn].planets.iter().enumerate() {
|
for (i, p) in self.states[self.turn].planets.iter().enumerate() {
|
||||||
let color = utils::COLORS[p.owner.unwrap_or(0) as usize % utils::COLORS.len()];
|
self.voronoi_colors[i] = utils::COLORS[p.owner.unwrap_or(0) as usize % utils::COLORS.len()].into()
|
||||||
self.voronoi_colors[i * 3 + 0] = color[0];
|
|
||||||
self.voronoi_colors[i * 3 + 1] = color[1];
|
|
||||||
self.voronoi_colors[i * 3 + 2] = color[2];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_planet_colours(&mut self) {
|
fn update_planet_colours(&mut self) {
|
||||||
let mut new_vec: Vec<[f32; 3]> = Vec::new();
|
let mut new_vec = Vec::new();
|
||||||
let planets_now = self.states[self.turn].planets.iter();
|
let planets_now = self.states[self.turn].planets.iter();
|
||||||
let planets_later = self.states[(self.turn + 1).min(self.states.len() - 1)]
|
let planets_later = self.states[(self.turn + 1).min(self.states.len() - 1)].planets.iter();
|
||||||
.planets
|
|
||||||
.iter();
|
|
||||||
|
|
||||||
for (p1, p2) in planets_now.zip(planets_later) {
|
for (p1, p2) in planets_now.zip(planets_later) {
|
||||||
new_vec
|
new_vec.push(
|
||||||
.push(utils::COLORS[p1.owner.unwrap_or(0) as usize % utils::COLORS.len()].into());
|
utils::COLORS[p1.owner.unwrap_or(0) as usize % utils::COLORS.len()].into()
|
||||||
new_vec
|
);
|
||||||
.push(utils::COLORS[p2.owner.unwrap_or(0) as usize % utils::COLORS.len()].into());
|
new_vec.push(
|
||||||
|
utils::COLORS[p2.owner.unwrap_or(0) as usize % utils::COLORS.len()].into()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.current_planet_colours = new_vec.concat::<f32>();
|
self.current_planet_colours = new_vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_ship_locations(&mut self) {
|
fn update_ship_locations(&mut self) {
|
||||||
let mut new_sl = Vec::new();
|
self.ship_locations = Vec::new();
|
||||||
let mut new_sll = Vec::new();
|
self.ship_label_locations = Vec::new();
|
||||||
|
let t = Mat3::new(0.2, 0., 0.,
|
||||||
let t = Mat3::new(0.2, 0., 0., 0., 0.2, 0.0, 0., -0.5, 0.2);
|
0., 0.2, 0.0,
|
||||||
|
0., -0.5, 0.2);
|
||||||
|
|
||||||
for ship in self.states[self.turn].expeditions.iter() {
|
for ship in self.states[self.turn].expeditions.iter() {
|
||||||
let ((o1, a1), (o2, a2)) = self
|
let ((o1, a1), (o2, a2)) = self.planet_map.get(&(ship.origin.clone(), ship.destination.clone())).unwrap().get_for_remaining(ship.turns_remaining as usize);
|
||||||
.planet_map
|
self.ship_locations.push((o1 * Mat3::rotate_z(a1)).to_array());
|
||||||
.get(&(ship.origin.clone(), ship.destination.clone()))
|
self.ship_locations.push((o2 * Mat3::rotate_z(a2)).to_array());
|
||||||
.unwrap()
|
|
||||||
.get_for_remaining(ship.turns_remaining as usize);
|
|
||||||
new_sl.push((o1 * Mat3::rotate_z(a1)).to_array());
|
|
||||||
new_sl.push((o2 * Mat3::rotate_z(a2)).to_array());
|
|
||||||
|
|
||||||
new_sll.push((o1 + t).to_array());
|
self.ship_label_locations.push((o1 + t).to_array());
|
||||||
new_sll.push((o2 + t).to_array());
|
self.ship_label_locations.push((o2 + t).to_array());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ship_locations = new_sl.concat();
|
self.ship_colours = self.states[self.turn].expeditions.iter().map(|s| {
|
||||||
self.ship_label_locations = new_sll.concat();
|
utils::COLORS[s.owner as usize % utils::COLORS.len()].into()
|
||||||
|
}).collect();
|
||||||
self.ship_colours = self.states[self.turn]
|
|
||||||
.expeditions
|
|
||||||
.iter()
|
|
||||||
.map(|s| utils::COLORS[s.owner as usize % utils::COLORS.len()])
|
|
||||||
.collect::<Vec<[f32; 3]>>()
|
|
||||||
.concat();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_ship_counts(&mut self) {
|
fn update_ship_counts(&mut self) {
|
||||||
self.ship_counts = self.states[self.turn]
|
self.ship_counts = self.states[self.turn].expeditions.iter().map(|s| {
|
||||||
.expeditions
|
s.ship_count as usize
|
||||||
.iter()
|
}).collect();
|
||||||
.map(|s| s.ship_count as usize)
|
|
||||||
.collect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_max_ships(&self) -> usize {
|
pub fn get_max_ships(&self) -> usize {
|
||||||
self.states
|
self.states.iter().map(|s| s.expeditions.len()).max().unwrap()
|
||||||
.iter()
|
|
||||||
.map(|s| s.expeditions.len())
|
|
||||||
.max()
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ship_locations(&self) -> Vec<f32> {
|
pub fn get_ship_count(&self) -> usize {
|
||||||
self.ship_locations.clone()
|
self.states[self.turn].expeditions.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ship_label_locations(&self) -> Vec<f32> {
|
pub fn get_ship_locations(&self) -> *const [f32;9] {
|
||||||
self.ship_label_locations.clone()
|
self.ship_locations.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ship_colours(&self) -> Vec<f32> {
|
pub fn get_ship_label_locations(&self) -> *const [f32;9] {
|
||||||
self.ship_colours.clone()
|
self.ship_label_locations.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ship_counts(&self) -> Vec<usize> {
|
pub fn get_ship_colours(&self) -> *const Vec3<f32> {
|
||||||
self.ship_counts.clone()
|
self.ship_colours.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_voronoi_verts(&self) -> Vec<f32> {
|
pub fn get_ship_counts(&self) -> *const usize {
|
||||||
self.voronoi_vertices.clone()
|
self.ship_counts.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_voronoi_colours(&self) -> Vec<f32> {
|
pub fn get_voronoi_vert_count(&self) -> usize {
|
||||||
self.voronoi_colors.clone()
|
self.voronoi_vertices.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_voronoi_inds(&self) -> Vec<usize> {
|
pub fn get_voronoi_verts(&self) -> *const Vec2<f32> {
|
||||||
self.voronoi_indices.clone()
|
self.voronoi_vertices.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_voronoi_colours(&self) -> *const Vec3<f32> {
|
||||||
|
self.voronoi_colors.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_voronoi_ind_count(&self) -> usize {
|
||||||
|
self.voronoi_indices.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_voronoi_inds(&self) -> *const usize {
|
||||||
|
self.voronoi_indices.as_ptr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn alert(s: &str);
|
fn alert(s: &str);
|
||||||
|
|
|
@ -9,20 +9,22 @@ pub fn set_panic_hook() {
|
||||||
console_error_panic_hook::set_once();
|
console_error_panic_hook::set_once();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use octoon_math::{Vec3};
|
||||||
|
|
||||||
/// this is total extra, so it the planet viewbox is like 100px wide, it will now be in total 110 pixels wide
|
/// this is total extra, so it the planet viewbox is like 100px wide, it will now be in total 110 pixels wide
|
||||||
static VIEWBOX_SCALE: f32 = 0.1;
|
static VIEWBOX_SCALE: f32 = 0.1;
|
||||||
|
|
||||||
pub static COLORS: [[f32; 3]; 10] = [
|
pub static COLORS: [[f32; 3]; 10] = [
|
||||||
[0.5, 0.5, 0.5],
|
[0.5 , 0.5 , 0.5 ],
|
||||||
[1.0, 0.50, 0.0], // #FF8000
|
[1.0 , 0.50, 0.0 ], // #FF8000
|
||||||
[0.0, 0.50, 1.0], // #0080ff
|
[0.0 , 0.50, 1.0 ], // #0080ff
|
||||||
[1.0, 0.4, 0.58], // #FF6693
|
[1.0 , 0.4 , 0.58 ], // #FF6693
|
||||||
[0.24, 0.79, 0.33], // #3fcb55
|
[0.24, 0.79, 0.33 ], // #3fcb55
|
||||||
[0.79, 0.76, 0.24], // #cbc33f
|
[0.79, 0.76, 0.24 ], // #cbc33f
|
||||||
[0.81, 0.25, 0.91], // #cf40e9
|
[0.81, 0.25, 0.91 ], // #cf40e9
|
||||||
[0.94, 0.32, 0.32], // #FF3F0D
|
[0.94, 0.32, 0.32 ], // #FF3F0D
|
||||||
[0.11, 0.93, 0.94], // #1beef0
|
[0.11, 0.93, 0.94 ], // #1beef0
|
||||||
[0.05, 0.77, 1.0], // #0DC5FF
|
[0.05, 0.77, 1.0 ], // #0DC5FF
|
||||||
];
|
];
|
||||||
|
|
||||||
use super::types;
|
use super::types;
|
||||||
|
@ -34,32 +36,16 @@ pub fn caclulate_viewbox(planets: &Vec<types::Planet>) -> Vec<f32> {
|
||||||
Some(p) => (p.x, p.y, p.x, p.y),
|
Some(p) => (p.x, p.y, p.x, p.y),
|
||||||
None => return vec![0.0, 0.0, 0.0, 0.0],
|
None => return vec![0.0, 0.0, 0.0, 0.0],
|
||||||
};
|
};
|
||||||
let (min_x, min_y, max_x, max_y) =
|
let (min_x, min_y, max_x, max_y) = planets
|
||||||
planets
|
|
||||||
.iter()
|
.iter()
|
||||||
.fold(init, |(min_x, min_y, max_x, max_y), p| {
|
.fold(init, |(min_x, min_y, max_x, max_y), p| (min_x.min(p.x), min_y.min(p.y), max_x.max(p.x), max_y.max(p.y)));
|
||||||
(
|
|
||||||
min_x.min(p.x),
|
|
||||||
min_y.min(p.y),
|
|
||||||
max_x.max(p.x),
|
|
||||||
max_y.max(p.y),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
let (width, height) = (max_x - min_x, max_y - min_y);
|
let (width, height) = (max_x - min_x, max_y - min_y);
|
||||||
let (dx, dy) = (
|
let (dx, dy) = ((VIEWBOX_SCALE * width).max(6.0), (VIEWBOX_SCALE * height).max(6.0));
|
||||||
(VIEWBOX_SCALE * width).max(6.0),
|
|
||||||
(VIEWBOX_SCALE * height).max(6.0),
|
|
||||||
);
|
|
||||||
|
|
||||||
vec![min_x - dx / 2.0, min_y - dy / 2.0, width + dx, height + dy]
|
vec![min_x - dx/2.0, min_y - dy/2.0, width + dx, height + dy]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_planets(planets: &Vec<types::Planet>, r: f32) -> Vec<f32> {
|
pub fn get_planets(planets: &Vec<types::Planet>, r: f32) -> Vec<Vec3<f32>> {
|
||||||
planets.iter().fold(Vec::new(), |mut cum, p| {
|
planets.iter().map(|p| Vec3::new(p.x, p.y, r)).collect()
|
||||||
cum.push(p.x);
|
|
||||||
cum.push(p.y);
|
|
||||||
cum.push(r);
|
|
||||||
cum
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,7 @@
|
||||||
import { Game } from "planetwars";
|
import { Game } from "planetwars";
|
||||||
import { memory } from "planetwars/planetwars_bg";
|
import { memory } from "planetwars/planetwars_bg";
|
||||||
import {
|
import { Resizer, resizeCanvasToDisplaySize, FPSCounter, url_to_mesh, Mesh, Dictionary } from "./webgl/util";
|
||||||
Resizer,
|
import { Shader, Uniform4f, Uniform3fv, Uniform1f, Uniform2f, ShaderFactory, Uniform3f, UniformMatrix3fv, UniformBool } from './webgl/shader';
|
||||||
resizeCanvasToDisplaySize,
|
|
||||||
FPSCounter,
|
|
||||||
url_to_mesh,
|
|
||||||
Mesh,
|
|
||||||
Dictionary,
|
|
||||||
} from "./webgl/util";
|
|
||||||
import {
|
|
||||||
Shader,
|
|
||||||
Uniform4f,
|
|
||||||
Uniform3fv,
|
|
||||||
Uniform1f,
|
|
||||||
Uniform2f,
|
|
||||||
ShaderFactory,
|
|
||||||
Uniform3f,
|
|
||||||
UniformMatrix3fv,
|
|
||||||
UniformBool,
|
|
||||||
} from "./webgl/shader";
|
|
||||||
import { Renderer } from "./webgl/renderer";
|
import { Renderer } from "./webgl/renderer";
|
||||||
import { VertexBuffer, IndexBuffer } from "./webgl/buffer";
|
import { VertexBuffer, IndexBuffer } from "./webgl/buffer";
|
||||||
import { VertexBufferLayout, VertexArray } from "./webgl/vertexBufferLayout";
|
import { VertexBufferLayout, VertexArray } from "./webgl/vertexBufferLayout";
|
||||||
|
@ -28,10 +11,8 @@ import { BBox } from "./voronoi/voronoi-core";
|
||||||
|
|
||||||
function to_bbox(box: number[]): BBox {
|
function to_bbox(box: number[]): BBox {
|
||||||
return {
|
return {
|
||||||
xl: box[0],
|
'xl': box[0], 'xr': box[0] + box[2],
|
||||||
xr: box[0] + box[2],
|
'yt': box[1], 'yb': box[1] + box[3]
|
||||||
yt: box[1],
|
|
||||||
yb: box[1] + box[3],
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,26 +39,18 @@ export function set_loading(loading: boolean) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ELEMENTS = {};
|
const ELEMENTS = {};
|
||||||
[
|
["name", "turnCounter", "main", "turnSlider", "fileselect", "speed", "canvas"].forEach(n => ELEMENTS[n] = document.getElementById(n));
|
||||||
"name",
|
|
||||||
"turnCounter",
|
|
||||||
"main",
|
|
||||||
"turnSlider",
|
|
||||||
"fileselect",
|
|
||||||
"speed",
|
|
||||||
"canvas",
|
|
||||||
].forEach((n) => (ELEMENTS[n] = document.getElementById(n)));
|
|
||||||
|
|
||||||
const CANVAS = ELEMENTS["canvas"];
|
const CANVAS = ELEMENTS["canvas"];
|
||||||
const RESOLUTION = [CANVAS.width, CANVAS.height];
|
const RESOLUTION = [CANVAS.width, CANVAS.height];
|
||||||
|
|
||||||
const LAYERS = {
|
const LAYERS = {
|
||||||
vor: -1, // Background
|
'vor': -1, // Background
|
||||||
planet: 1,
|
'planet': 1,
|
||||||
planet_label: 2,
|
'planet_label': 2,
|
||||||
ship: 3,
|
'ship': 3,
|
||||||
ship_label: 4,
|
'ship_label': 4
|
||||||
};
|
}
|
||||||
|
|
||||||
const COUNTER = new FPSCounter();
|
const COUNTER = new FPSCounter();
|
||||||
|
|
||||||
|
@ -117,59 +90,45 @@ class GameInstance {
|
||||||
|
|
||||||
turn_count = 0;
|
turn_count = 0;
|
||||||
|
|
||||||
constructor(
|
constructor(game: Game, meshes: Mesh[], ship_mesh: Mesh, shaders: Dictionary<ShaderFactory>) {
|
||||||
game: Game,
|
|
||||||
meshes: Mesh[],
|
|
||||||
ship_mesh: Mesh,
|
|
||||||
shaders: Dictionary<ShaderFactory>
|
|
||||||
) {
|
|
||||||
this.game = game;
|
this.game = game;
|
||||||
const planets = game.get_planets();
|
this.planet_count = this.game.get_planet_count();
|
||||||
this.planet_count = planets.length;
|
|
||||||
|
|
||||||
this.shader = shaders["normal"].create_shader(GL, {
|
this.shader = shaders["normal"].create_shader(GL, { "MAX_CIRCLES": '' + this.planet_count });
|
||||||
MAX_CIRCLES: "" + planets.length,
|
|
||||||
});
|
|
||||||
this.image_shader = shaders["image"].create_shader(GL);
|
this.image_shader = shaders["image"].create_shader(GL);
|
||||||
this.vor_shader = shaders["vor"].create_shader(GL, {
|
this.vor_shader = shaders["vor"].create_shader(GL, { "PLANETS": '' + this.planet_count });
|
||||||
PLANETS: "" + planets.length,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.text_factory = defaultLabelFactory(GL, this.image_shader);
|
this.text_factory = defaultLabelFactory(GL, this.image_shader);
|
||||||
this.planet_labels = [];
|
this.planet_labels = [];
|
||||||
this.ship_labels = [];
|
this.ship_labels = [];
|
||||||
|
|
||||||
this.resizer = new Resizer(CANVAS, [...game.get_viewbox()], true);
|
this.resizer = new Resizer(CANVAS, [...f32v(game.get_viewbox(), 4)], true);
|
||||||
this.renderer = new Renderer();
|
this.renderer = new Renderer();
|
||||||
this.game.update_turn(0);
|
this.game.update_turn(0);
|
||||||
|
|
||||||
// Setup key handling
|
// Setup key handling
|
||||||
document.addEventListener("keydown", this.handleKey.bind(this));
|
document.addEventListener('keydown', this.handleKey.bind(this));
|
||||||
|
|
||||||
// List of [(x, y, r)] for all planets
|
// List of [(x, y, r)] for all planets
|
||||||
|
const planets = f32v(game.get_planets(), this.planet_count * 3);
|
||||||
this._create_voronoi(planets);
|
this._create_voronoi(planets);
|
||||||
this._create_planets(planets, meshes);
|
this._create_planets(planets, meshes);
|
||||||
this._create_shipes(ship_mesh);
|
this._create_shipes(ship_mesh);
|
||||||
|
|
||||||
// Set slider correctly
|
// Set slider correctly
|
||||||
this.turn_count = game.turn_count();
|
this.turn_count = game.turn_count();
|
||||||
ELEMENTS["turnSlider"].max = this.turn_count - 1 + "";
|
ELEMENTS["turnSlider"].max = this.turn_count - 1 + '';
|
||||||
}
|
}
|
||||||
|
|
||||||
_create_voronoi(planets: Float32Array) {
|
_create_voronoi(planets: Float32Array) {
|
||||||
const planet_points = [];
|
const planet_points = [];
|
||||||
for (let i = 0; i < planets.length; i += 3) {
|
for (let i = 0; i < planets.length; i += 3) {
|
||||||
planet_points.push({ x: -planets[i], y: -planets[i + 1] });
|
planet_points.push({ 'x': -planets[i], 'y': -planets[i + 1] });
|
||||||
}
|
}
|
||||||
|
|
||||||
const bbox = to_bbox(this.resizer.get_viewbox());
|
const bbox = to_bbox(this.resizer.get_viewbox());
|
||||||
|
|
||||||
this.vor_builder = new VoronoiBuilder(
|
this.vor_builder = new VoronoiBuilder(GL, this.vor_shader, planet_points, bbox);
|
||||||
GL,
|
|
||||||
this.vor_shader,
|
|
||||||
planet_points,
|
|
||||||
bbox
|
|
||||||
);
|
|
||||||
this.renderer.addRenderable(this.vor_builder.getRenderable(), LAYERS.vor);
|
this.renderer.addRenderable(this.vor_builder.getRenderable(), LAYERS.vor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,25 +136,13 @@ class GameInstance {
|
||||||
for (let i = 0; i < this.planet_count; i++) {
|
for (let i = 0; i < this.planet_count; i++) {
|
||||||
{
|
{
|
||||||
const transform = new UniformMatrix3fv([
|
const transform = new UniformMatrix3fv([
|
||||||
1,
|
1, 0, 0,
|
||||||
0,
|
0, 1, 0,
|
||||||
0,
|
-planets[i * 3], -planets[i * 3 + 1], 1,
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
-planets[i * 3],
|
|
||||||
-planets[i * 3 + 1],
|
|
||||||
1,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const indexBuffer = new IndexBuffer(
|
const indexBuffer = new IndexBuffer(GL, meshes[i % meshes.length].cells);
|
||||||
GL,
|
const positionBuffer = new VertexBuffer(GL, meshes[i % meshes.length].positions);
|
||||||
meshes[i % meshes.length].cells
|
|
||||||
);
|
|
||||||
const positionBuffer = new VertexBuffer(
|
|
||||||
GL,
|
|
||||||
meshes[i % meshes.length].positions
|
|
||||||
);
|
|
||||||
|
|
||||||
const layout = new VertexBufferLayout();
|
const layout = new VertexBufferLayout();
|
||||||
layout.push(GL.FLOAT, 3, 4, "a_position");
|
layout.push(GL.FLOAT, 3, 4, "a_position");
|
||||||
|
@ -207,8 +154,8 @@ class GameInstance {
|
||||||
vao,
|
vao,
|
||||||
this.shader,
|
this.shader,
|
||||||
{
|
{
|
||||||
u_trans: transform,
|
"u_trans": transform,
|
||||||
u_trans_next: transform,
|
"u_trans_next": transform,
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
LAYERS.planet
|
LAYERS.planet
|
||||||
|
@ -217,15 +164,9 @@ class GameInstance {
|
||||||
|
|
||||||
{
|
{
|
||||||
const transform = new UniformMatrix3fv([
|
const transform = new UniformMatrix3fv([
|
||||||
1,
|
1., 0, 0,
|
||||||
0,
|
0, 1., 0,
|
||||||
0,
|
-planets[i * 3], -planets[i * 3 + 1] - 1.2, 1.,
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
-planets[i * 3],
|
|
||||||
-planets[i * 3 + 1] - 1.2,
|
|
||||||
1,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const label = this.text_factory.build(GL, transform);
|
const label = this.text_factory.build(GL, transform);
|
||||||
|
@ -255,12 +196,12 @@ class GameInstance {
|
||||||
|
|
||||||
const label = this.text_factory.build(GL);
|
const label = this.text_factory.build(GL);
|
||||||
this.ship_labels.push(label);
|
this.ship_labels.push(label);
|
||||||
this.renderer.addRenderable(label.getRenderable(), LAYERS.ship_label);
|
this.renderer.addRenderable(label.getRenderable(), LAYERS.ship_label)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
on_resize() {
|
on_resize() {
|
||||||
this.resizer = new Resizer(CANVAS, [...this.game.get_viewbox()], true);
|
this.resizer = new Resizer(CANVAS, [...f32v(this.game.get_viewbox(), 4)], true);
|
||||||
const bbox = to_bbox(this.resizer.get_viewbox());
|
const bbox = to_bbox(this.resizer.get_viewbox());
|
||||||
this.vor_builder.resize(GL, bbox);
|
this.vor_builder.resize(GL, bbox);
|
||||||
}
|
}
|
||||||
|
@ -271,65 +212,36 @@ class GameInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
_update_planets() {
|
_update_planets() {
|
||||||
const colours = this.game.get_planet_colors();
|
const colours = f32v(this.game.get_planet_colors(), this.planet_count * 6);
|
||||||
const planet_ships = this.game.get_planet_ships();
|
const planet_ships = i32v(this.game.get_planet_ships(), this.planet_count);
|
||||||
|
|
||||||
this.vor_shader.uniform(GL, "u_planet_colours", new Uniform3fv(colours));
|
this.vor_shader.uniform(GL, "u_planet_colours", new Uniform3fv(colours));
|
||||||
|
|
||||||
for (let i = 0; i < this.planet_count; i++) {
|
for (let i = 0; i < this.planet_count; i++) {
|
||||||
const u = new Uniform3f(
|
const u = new Uniform3f(colours[i * 6], colours[i * 6 + 1], colours[i * 6 + 2]);
|
||||||
colours[i * 6],
|
this.renderer.updateUniform(i, (us) => us["u_color"] = u, LAYERS.planet);
|
||||||
colours[i * 6 + 1],
|
const u2 = new Uniform3f(colours[i * 6 + 3], colours[i * 6 + 4], colours[i * 6 + 5]);
|
||||||
colours[i * 6 + 2]
|
this.renderer.updateUniform(i, (us) => us["u_color_next"] = u2, LAYERS.planet);
|
||||||
);
|
|
||||||
this.renderer.updateUniform(
|
|
||||||
i,
|
|
||||||
(us) => (us["u_color"] = u),
|
|
||||||
LAYERS.planet
|
|
||||||
);
|
|
||||||
const u2 = new Uniform3f(
|
|
||||||
colours[i * 6 + 3],
|
|
||||||
colours[i * 6 + 4],
|
|
||||||
colours[i * 6 + 5]
|
|
||||||
);
|
|
||||||
this.renderer.updateUniform(
|
|
||||||
i,
|
|
||||||
(us) => (us["u_color_next"] = u2),
|
|
||||||
LAYERS.planet
|
|
||||||
);
|
|
||||||
|
|
||||||
this.planet_labels[i].setText(
|
this.planet_labels[i].setText(GL, "*" + planet_ships[i], Align.Middle, Align.Begin);
|
||||||
GL,
|
|
||||||
"*" + planet_ships[i],
|
|
||||||
Align.Middle,
|
|
||||||
Align.Begin
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_update_ships() {
|
_update_ships() {
|
||||||
const ships = this.game.get_ship_locations();
|
const ship_count = this.game.get_ship_count();
|
||||||
const labels = this.game.get_ship_label_locations();
|
const ships = f32v(this.game.get_ship_locations(), ship_count * 9 * 2);
|
||||||
const ship_counts = this.game.get_ship_counts();
|
const labels = f32v(this.game.get_ship_label_locations(), ship_count * 9 * 2);
|
||||||
const ship_colours = this.game.get_ship_colours();
|
const ship_counts = i32v(this.game.get_ship_counts(), ship_count);
|
||||||
|
const ship_colours = f32v(this.game.get_ship_colours(), ship_count * 3);
|
||||||
|
|
||||||
for (let i = 0; i < this.game.get_max_ships(); i++) {
|
for (let i = 0; i < this.game.get_max_ships(); i++) {
|
||||||
if (i < ship_counts.length) {
|
if (i < ship_count) {
|
||||||
this.ship_labels[i].setText(
|
this.ship_labels[i].setText(GL, "" + ship_counts[i], Align.Middle, Align.Middle);
|
||||||
GL,
|
|
||||||
"" + ship_counts[i],
|
|
||||||
Align.Middle,
|
|
||||||
Align.Middle
|
|
||||||
);
|
|
||||||
|
|
||||||
this.renderer.enableRenderable(i, LAYERS.ship);
|
this.renderer.enableRenderable(i, LAYERS.ship);
|
||||||
this.renderer.enableRenderable(i, LAYERS.ship_label);
|
this.renderer.enableRenderable(i, LAYERS.ship_label);
|
||||||
|
|
||||||
const u = new Uniform3f(
|
const u = new Uniform3f(ship_colours[i * 3], ship_colours[i * 3 + 1], ship_colours[i * 3 + 2]);
|
||||||
ship_colours[i * 3],
|
|
||||||
ship_colours[i * 3 + 1],
|
|
||||||
ship_colours[i * 3 + 2]
|
|
||||||
);
|
|
||||||
|
|
||||||
const t1 = new UniformMatrix3fv(ships.slice(i * 18, i * 18 + 9));
|
const t1 = new UniformMatrix3fv(ships.slice(i * 18, i * 18 + 9));
|
||||||
const t2 = new UniformMatrix3fv(ships.slice(i * 18 + 9, i * 18 + 18));
|
const t2 = new UniformMatrix3fv(ships.slice(i * 18 + 9, i * 18 + 18));
|
||||||
|
@ -337,25 +249,18 @@ class GameInstance {
|
||||||
const tl1 = new UniformMatrix3fv(labels.slice(i * 18, i * 18 + 9));
|
const tl1 = new UniformMatrix3fv(labels.slice(i * 18, i * 18 + 9));
|
||||||
const tl2 = new UniformMatrix3fv(labels.slice(i * 18 + 9, i * 18 + 18));
|
const tl2 = new UniformMatrix3fv(labels.slice(i * 18 + 9, i * 18 + 18));
|
||||||
|
|
||||||
this.renderer.updateUniform(
|
this.renderer.updateUniform(i, (us) => {
|
||||||
i,
|
|
||||||
(us) => {
|
|
||||||
us["u_color"] = u;
|
us["u_color"] = u;
|
||||||
us["u_color_next"] = u;
|
us["u_color_next"] = u;
|
||||||
us["u_trans"] = t1;
|
us["u_trans"] = t1;
|
||||||
us["u_trans_next"] = t2;
|
us["u_trans_next"] = t2;
|
||||||
},
|
}, LAYERS.ship);
|
||||||
LAYERS.ship
|
|
||||||
);
|
|
||||||
|
|
||||||
this.renderer.updateUniform(
|
this.renderer.updateUniform(i, (us) => {
|
||||||
i,
|
|
||||||
(us) => {
|
|
||||||
us["u_trans"] = tl1;
|
us["u_trans"] = tl1;
|
||||||
us["u_trans_next"] = tl2;
|
us["u_trans_next"] = tl2;
|
||||||
},
|
}, LAYERS.ship_label);
|
||||||
LAYERS.ship_label
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
this.renderer.disableRenderable(i, LAYERS.ship);
|
this.renderer.disableRenderable(i, LAYERS.ship);
|
||||||
this.renderer.disableRenderable(i, LAYERS.ship_label);
|
this.renderer.disableRenderable(i, LAYERS.ship_label);
|
||||||
|
@ -380,21 +285,9 @@ class GameInstance {
|
||||||
if (!this.playing) {
|
if (!this.playing) {
|
||||||
this.last_time = time;
|
this.last_time = time;
|
||||||
|
|
||||||
this.shader.uniform(
|
this.shader.uniform(GL, "u_viewbox", new Uniform4f(this.resizer.get_viewbox()));
|
||||||
GL,
|
this.vor_shader.uniform(GL, "u_viewbox", new Uniform4f(this.resizer.get_viewbox()));
|
||||||
"u_viewbox",
|
this.image_shader.uniform(GL, "u_viewbox", new Uniform4f(this.resizer.get_viewbox()));
|
||||||
new Uniform4f(this.resizer.get_viewbox())
|
|
||||||
);
|
|
||||||
this.vor_shader.uniform(
|
|
||||||
GL,
|
|
||||||
"u_viewbox",
|
|
||||||
new Uniform4f(this.resizer.get_viewbox())
|
|
||||||
);
|
|
||||||
this.image_shader.uniform(
|
|
||||||
GL,
|
|
||||||
"u_viewbox",
|
|
||||||
new Uniform4f(this.resizer.get_viewbox())
|
|
||||||
);
|
|
||||||
|
|
||||||
this.renderer.render(GL);
|
this.renderer.render(GL);
|
||||||
return;
|
return;
|
||||||
|
@ -411,51 +304,19 @@ class GameInstance {
|
||||||
GL.viewport(0, 0, GL.canvas.width, GL.canvas.height);
|
GL.viewport(0, 0, GL.canvas.width, GL.canvas.height);
|
||||||
GL.clear(GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT);
|
GL.clear(GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
this.vor_shader.uniform(
|
this.vor_shader.uniform(GL, "u_time", new Uniform1f((time - this.last_time) / ms_per_frame));
|
||||||
GL,
|
this.vor_shader.uniform(GL, "u_viewbox", new Uniform4f(this.resizer.get_viewbox()));
|
||||||
"u_time",
|
|
||||||
new Uniform1f((time - this.last_time) / ms_per_frame)
|
|
||||||
);
|
|
||||||
this.vor_shader.uniform(
|
|
||||||
GL,
|
|
||||||
"u_viewbox",
|
|
||||||
new Uniform4f(this.resizer.get_viewbox())
|
|
||||||
);
|
|
||||||
this.vor_shader.uniform(GL, "u_resolution", new Uniform2f(RESOLUTION));
|
this.vor_shader.uniform(GL, "u_resolution", new Uniform2f(RESOLUTION));
|
||||||
this.vor_shader.uniform(GL, "u_vor", new UniformBool(this.use_vor));
|
this.vor_shader.uniform(GL, "u_vor", new UniformBool(this.use_vor));
|
||||||
|
|
||||||
this.shader.uniform(
|
this.shader.uniform(GL, "u_time", new Uniform1f((time - this.last_time) / ms_per_frame));
|
||||||
GL,
|
this.shader.uniform(GL, "u_mouse", new Uniform2f(this.resizer.get_mouse_pos()));
|
||||||
"u_time",
|
this.shader.uniform(GL, "u_viewbox", new Uniform4f(this.resizer.get_viewbox()));
|
||||||
new Uniform1f((time - this.last_time) / ms_per_frame)
|
|
||||||
);
|
|
||||||
this.shader.uniform(
|
|
||||||
GL,
|
|
||||||
"u_mouse",
|
|
||||||
new Uniform2f(this.resizer.get_mouse_pos())
|
|
||||||
);
|
|
||||||
this.shader.uniform(
|
|
||||||
GL,
|
|
||||||
"u_viewbox",
|
|
||||||
new Uniform4f(this.resizer.get_viewbox())
|
|
||||||
);
|
|
||||||
this.shader.uniform(GL, "u_resolution", new Uniform2f(RESOLUTION));
|
this.shader.uniform(GL, "u_resolution", new Uniform2f(RESOLUTION));
|
||||||
|
|
||||||
this.image_shader.uniform(
|
this.image_shader.uniform(GL, "u_time", new Uniform1f((time - this.last_time) / ms_per_frame));
|
||||||
GL,
|
this.image_shader.uniform(GL, "u_mouse", new Uniform2f(this.resizer.get_mouse_pos()));
|
||||||
"u_time",
|
this.image_shader.uniform(GL, "u_viewbox", new Uniform4f(this.resizer.get_viewbox()));
|
||||||
new Uniform1f((time - this.last_time) / ms_per_frame)
|
|
||||||
);
|
|
||||||
this.image_shader.uniform(
|
|
||||||
GL,
|
|
||||||
"u_mouse",
|
|
||||||
new Uniform2f(this.resizer.get_mouse_pos())
|
|
||||||
);
|
|
||||||
this.image_shader.uniform(
|
|
||||||
GL,
|
|
||||||
"u_viewbox",
|
|
||||||
new Uniform4f(this.resizer.get_viewbox())
|
|
||||||
);
|
|
||||||
this.image_shader.uniform(GL, "u_resolution", new Uniform2f(RESOLUTION));
|
this.image_shader.uniform(GL, "u_resolution", new Uniform2f(RESOLUTION));
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
|
@ -475,9 +336,8 @@ class GameInstance {
|
||||||
this.playing = true;
|
this.playing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ELEMENTS["turnCounter"].innerHTML =
|
ELEMENTS["turnCounter"].innerHTML = this.frame + " / " + (this.turn_count - 1);
|
||||||
this.frame + " / " + (this.turn_count - 1);
|
ELEMENTS["turnSlider"].value = this.frame + '';
|
||||||
ELEMENTS["turnSlider"].value = this.frame + "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleKey(event: KeyboardEvent) {
|
handleKey(event: KeyboardEvent) {
|
||||||
|
@ -503,13 +363,13 @@ class GameInstance {
|
||||||
|
|
||||||
// d key
|
// d key
|
||||||
if (event.keyCode == 68) {
|
if (event.keyCode == 68) {
|
||||||
ELEMENTS["speed"].value = ms_per_frame + 10 + "";
|
ELEMENTS["speed"].value = ms_per_frame + 10 + '';
|
||||||
ELEMENTS["speed"].onchange(undefined);
|
ELEMENTS["speed"].onchange(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
// a key
|
// a key
|
||||||
if (event.keyCode == 65) {
|
if (event.keyCode == 65) {
|
||||||
ELEMENTS["speed"].value = Math.max(ms_per_frame - 10, 0) + "";
|
ELEMENTS["speed"].value = Math.max(ms_per_frame - 10, 0) + '';
|
||||||
ELEMENTS["speed"].onchange(undefined);
|
ELEMENTS["speed"].onchange(undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -521,79 +381,51 @@ var shaders: Dictionary<ShaderFactory>;
|
||||||
|
|
||||||
export async function set_instance(source: string) {
|
export async function set_instance(source: string) {
|
||||||
if (!meshes || !shaders) {
|
if (!meshes || !shaders) {
|
||||||
const mesh_promises = ["ship.svg", "earth.svg", "mars.svg", "venus.svg"]
|
const mesh_promises = ["ship.svg", "earth.svg", "mars.svg", "venus.svg"].map(
|
||||||
.map((name) => "static/res/assets/" + name)
|
(name) => "static/res/assets/" + name
|
||||||
.map(url_to_mesh);
|
).map(url_to_mesh);
|
||||||
|
|
||||||
const shader_promies = [
|
const shader_promies = [
|
||||||
(async () =>
|
(async () => <[string, ShaderFactory]>["normal", await ShaderFactory.create_factory("static/shaders/frag/simple.glsl", "static/shaders/vert/simple.glsl")])(),
|
||||||
<[string, ShaderFactory]>[
|
(async () => <[string, ShaderFactory]>["vor", await ShaderFactory.create_factory("static/shaders/frag/vor.glsl", "static/shaders/vert/vor.glsl")])(),
|
||||||
"normal",
|
(async () => <[string, ShaderFactory]>["image", await ShaderFactory.create_factory("static/shaders/frag/image.glsl", "static/shaders/vert/simple.glsl")])(),
|
||||||
await ShaderFactory.create_factory(
|
|
||||||
"static/shaders/frag/simple.glsl",
|
|
||||||
"static/shaders/vert/simple.glsl"
|
|
||||||
),
|
|
||||||
])(),
|
|
||||||
(async () =>
|
|
||||||
<[string, ShaderFactory]>[
|
|
||||||
"vor",
|
|
||||||
await ShaderFactory.create_factory(
|
|
||||||
"static/shaders/frag/vor.glsl",
|
|
||||||
"static/shaders/vert/vor.glsl"
|
|
||||||
),
|
|
||||||
])(),
|
|
||||||
(async () =>
|
|
||||||
<[string, ShaderFactory]>[
|
|
||||||
"image",
|
|
||||||
await ShaderFactory.create_factory(
|
|
||||||
"static/shaders/frag/image.glsl",
|
|
||||||
"static/shaders/vert/simple.glsl"
|
|
||||||
),
|
|
||||||
])(),
|
|
||||||
];
|
];
|
||||||
let shaders_array: [string, ShaderFactory][];
|
let shaders_array: [string, ShaderFactory][];
|
||||||
[meshes, shaders_array] = await Promise.all([
|
[meshes, shaders_array] = await Promise.all(
|
||||||
|
[
|
||||||
Promise.all(mesh_promises),
|
Promise.all(mesh_promises),
|
||||||
Promise.all(shader_promies),
|
Promise.all(shader_promies),
|
||||||
]);
|
]
|
||||||
|
);
|
||||||
|
|
||||||
shaders = {};
|
shaders = {};
|
||||||
shaders_array.forEach(([name, fac]) => (shaders[name] = fac));
|
shaders_array.forEach(([name, fac]) => shaders[name] = fac);
|
||||||
}
|
}
|
||||||
|
|
||||||
resizeCanvasToDisplaySize(CANVAS);
|
resizeCanvasToDisplaySize(CANVAS);
|
||||||
|
|
||||||
game_instance = new GameInstance(
|
game_instance = new GameInstance(Game.new(source), meshes.slice(1), meshes[0], shaders);
|
||||||
Game.new(source),
|
|
||||||
meshes.slice(1),
|
|
||||||
meshes[0],
|
|
||||||
shaders
|
|
||||||
);
|
|
||||||
|
|
||||||
set_loading(false);
|
set_loading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener(
|
window.addEventListener('resize', function () {
|
||||||
"resize",
|
|
||||||
function () {
|
|
||||||
resizeCanvasToDisplaySize(CANVAS);
|
resizeCanvasToDisplaySize(CANVAS);
|
||||||
|
|
||||||
if (game_instance) {
|
if (game_instance) {
|
||||||
game_instance.on_resize();
|
game_instance.on_resize();
|
||||||
}
|
}
|
||||||
},
|
}, { capture: false, passive: true })
|
||||||
{ capture: false, passive: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
ELEMENTS["turnSlider"].oninput = function () {
|
ELEMENTS["turnSlider"].oninput = function () {
|
||||||
if (game_instance) {
|
if (game_instance) {
|
||||||
game_instance.updateTurn(parseInt(ELEMENTS["turnSlider"].value));
|
game_instance.updateTurn(parseInt(ELEMENTS["turnSlider"].value));
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
ELEMENTS["speed"].onchange = function () {
|
ELEMENTS["speed"].onchange = function () {
|
||||||
ms_per_frame = parseInt(ELEMENTS["speed"].value);
|
ms_per_frame = parseInt(ELEMENTS["speed"].value);
|
||||||
};
|
}
|
||||||
|
|
||||||
function step(time: number) {
|
function step(time: number) {
|
||||||
if (game_instance) {
|
if (game_instance) {
|
||||||
|
|
Loading…
Reference in a new issue