Created
September 16, 2023 23:21
-
-
Save todays-mitsui/4704ff51cca49eb03bf6033c967b888c to your computer and use it in GitHub Desktop.
『RustとWebAssemblyによるゲーム開発』1章 シェルピンスキーの三角形
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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