Skip to content

Instantly share code, notes, and snippets.

@todays-mitsui
Created September 16, 2023 23:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save todays-mitsui/4704ff51cca49eb03bf6033c967b888c to your computer and use it in GitHub Desktop.
Save todays-mitsui/4704ff51cca49eb03bf6033c967b888c to your computer and use it in GitHub Desktop.
『RustとWebAssemblyによるゲーム開発』1章 シェルピンスキーの三角形
[package]
name = "rust-webpack-template"
description = "My super awesome Rust, WebAssembly, and Webpack project!"
version = "0.1.0"
authors = ["You <you@example.com>"]
categories = ["wasm"]
readme = "README.md"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[profile.release]
lto = true
[features]
# If you uncomment this line, it will enable `wee_alloc`:
#default = ["wee_alloc"]
[dependencies]
wasm-bindgen = "0.2.45"
console_error_panic_hook = "0.1.7"
rand = "0.8.4"
getrandom = { version = "0.2.3", features = ["js"] }
# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
# compared to the default allocator's ~10K. However, it is slower than the default
# allocator, so it's not enabled by default.
wee_alloc = { version = "0.4.2", optional = true }
[dependencies.web-sys]
version = "0.3.55"
features = [
"console",
"Window",
"Document",
"HtmlCanvasElement",
"CanvasRenderingContext2d",
]
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so it's only enabled
# in debug mode.
[target."cfg(debug_assertions)".dependencies]
[dev-dependencies]
wasm-bindgen-test = "0.3.28"
futures = "0.3.18"
js-sys = "0.3.55"
wasm-bindgen-futures = "0.4.28"
use rand::prelude::*;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
#[allow(unused_imports)]
use web_sys::console;
#[wasm_bindgen(start)]
pub fn main_js() -> Result<(), JsValue> {
console_error_panic_hook::set_once();
let window = web_sys::window().unwrap();
let document = window.document().unwrap();
let canvas = document
.get_element_by_id("canvas")
.unwrap()
.dyn_into::<web_sys::HtmlCanvasElement>()
.unwrap();
let context = canvas
.get_context("2d")
.unwrap()
.unwrap()
.dyn_into::<web_sys::CanvasRenderingContext2d>()
.unwrap();
sierpinski(
&context,
[Point(300.0, 40.5), Point(0.0, 559.5), Point(600.0, 559.5)],
&None,
7,
);
Ok(())
}
fn sierpinski(
context: &web_sys::CanvasRenderingContext2d,
points: [Point; 3],
color: &Option<HslColor>,
depth: u8,
) {
let color = color.unwrap_or(HslColor::random());
draw_triangle(&context, points, &color);
let depth = depth - 1;
if depth <= 0 {
return;
}
let next_color = Some(HslColor::random());
let [top, left, right] = points;
let left_middle = midpoint(top, left).to_incomplete();
let right_middle = midpoint(top, right).to_incomplete();
let bottom_middle = midpoint(left, right).to_incomplete();
sierpinski(
&context,
[top, left_middle, right_middle],
&next_color,
depth,
);
sierpinski(
&context,
[left_middle, left, bottom_middle],
&next_color,
depth,
);
sierpinski(
&context,
[right_middle, bottom_middle, right],
&next_color,
depth,
);
}
fn draw_triangle(
context: &web_sys::CanvasRenderingContext2d,
points: [Point; 3],
color: &HslColor,
) {
let [top, left, right] = points;
context.move_to(top.0, top.1);
context.begin_path();
context.line_to(left.0, left.1);
context.line_to(right.0, right.1);
context.line_to(top.0, top.1);
context.close_path();
// context.stroke();
context.set_fill_style(&JsValue::from_str(&color.to_string()));
context.fill();
}
// ========================================================================== //
#[derive(Copy, Clone)]
struct Point(f64, f64);
fn midpoint(point1: Point, point2: Point) -> Point {
Point((point1.0 + point2.0) / 2.0, (point1.1 + point2.1) / 2.0)
}
impl Point {
fn to_incomplete(self) -> Self {
let Point(x, y) = self;
let int_part = y.floor();
let frac_part = y - int_part;
if frac_part < 0.4 || 0.6 < frac_part {
Point(x, int_part + 0.5)
} else {
Point(x, y)
}
}
}
// ========================================================================== //
#[derive(Copy, Clone)]
struct HslColor(u8, f64, f64);
impl HslColor {
fn random() -> Self {
let mut rng = thread_rng();
Self(
rng.gen_range(0..255),
rng.gen_range(0.2..0.8),
rng.gen_range(0.6..0.95),
)
}
fn to_string(&self) -> String {
format!(
"hsl( {}, {}%, {}% )",
self.0,
self.1 * 100.0,
self.2 * 100.0
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment