feat(final-version): final version with all features - embeded in cyberduck.blog
parent
1af96098e3
commit
acd1848687
11
README.md
11
README.md
|
@ -27,14 +27,3 @@ You can now open the `index.html` file built in the `dist` folder in your browse
|
|||
|
||||
<br>
|
||||
|
||||
## TODO
|
||||
### Game
|
||||
toolbar UI with:
|
||||
- choose between known interesting seed or totally random one
|
||||
- only live/dead colors mode or colored birth/death mode
|
||||
|
||||
interactions:
|
||||
...
|
||||
|
||||
### Embedding
|
||||
- embed in cyberduck.blog
|
||||
|
|
43
index.html
43
index.html
|
@ -1,7 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" style="position: absolute; top: 0%; left: 0%; width: 1280px; height: 720px;"></canvas>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<head>
|
||||
<link data-trunk rel="rust" data-wasm-opt="2" />
|
||||
|
||||
<style>
|
||||
html {
|
||||
/* Remove touch delay: */
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
overflow: hidden;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
canvas {
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0%);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<canvas id="canvas"></canvas>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt::{Display, Formatter, Result};
|
|||
|
||||
use eframe::App;
|
||||
use egui::{
|
||||
vec2, CentralPanel, ComboBox, Context, Frame, Pos2, Rect, Sense, Shape, TextStyle,
|
||||
vec2, CentralPanel, ComboBox, Context, Frame, Pos2, Rect, Sense, Shape, Slider, TextStyle,
|
||||
TopBottomPanel,
|
||||
};
|
||||
use strum::IntoEnumIterator;
|
||||
|
@ -73,6 +73,7 @@ pub struct MyEguiApp {
|
|||
cache: Vec<Shape>,
|
||||
paused: bool,
|
||||
click: Option<Pos2>,
|
||||
life_level: i32,
|
||||
}
|
||||
|
||||
impl MyEguiApp {
|
||||
|
@ -82,6 +83,7 @@ impl MyEguiApp {
|
|||
game: Universe::new(
|
||||
CANVAS_WIDTH as u32 / size as u32,
|
||||
CANVAS_HEIGHT as u32 / size as u32,
|
||||
2,
|
||||
),
|
||||
frame_counter: 0,
|
||||
speed: Speed::default(),
|
||||
|
@ -89,6 +91,7 @@ impl MyEguiApp {
|
|||
cache: Vec::new(),
|
||||
paused: false,
|
||||
click: None,
|
||||
life_level: 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,6 +115,7 @@ impl MyEguiApp {
|
|||
self.game = Universe::new(
|
||||
CANVAS_WIDTH as u32 / self.size as u32,
|
||||
CANVAS_HEIGHT as u32 / self.size as u32,
|
||||
self.life_level,
|
||||
);
|
||||
self.cache = Vec::new();
|
||||
self.frame_counter = 0;
|
||||
|
@ -130,6 +134,7 @@ impl MyEguiApp {
|
|||
.get_mut(&TextStyle::Button)
|
||||
.unwrap()
|
||||
.size *= 1.25;
|
||||
ui.add(Slider::new(&mut self.life_level, 0..=20).text("Life level"));
|
||||
if ui.button("Reset").clicked() {
|
||||
self.reset();
|
||||
}
|
||||
|
|
62
src/game.rs
62
src/game.rs
|
@ -17,11 +17,11 @@ pub struct Universe {
|
|||
}
|
||||
|
||||
impl Universe {
|
||||
pub fn new(width: u32, height: u32) -> Universe {
|
||||
pub fn new(width: u32, height: u32, life_level: i32) -> Universe {
|
||||
let mut rng = rand::thread_rng();
|
||||
let cells = (0..width * height)
|
||||
.map(|_| {
|
||||
if rng.gen_range(0..10) > 5 {
|
||||
if rng.gen_range(0..=20) < life_level {
|
||||
Cell::Alive
|
||||
} else {
|
||||
Cell::Dead
|
||||
|
@ -37,11 +37,35 @@ impl Universe {
|
|||
}
|
||||
}
|
||||
|
||||
fn render_rect(
|
||||
canvas_origin: Vec2,
|
||||
y: f32,
|
||||
x: f32,
|
||||
width_counter: u32,
|
||||
cell_side: f32,
|
||||
) -> Shape {
|
||||
const FILL: Color32 = Color32::from_gray(128);
|
||||
const ROUNDING: Rounding = Rounding {
|
||||
nw: 0.0,
|
||||
ne: 0.0,
|
||||
sw: 0.0,
|
||||
se: 0.0,
|
||||
};
|
||||
const STROKE: Stroke = Stroke::NONE;
|
||||
let rect = Rect::from_min_size(
|
||||
pos2(x, y) + canvas_origin,
|
||||
vec2(cell_side * width_counter as f32, cell_side),
|
||||
);
|
||||
Shape::Rect(RectShape {
|
||||
rect,
|
||||
rounding: ROUNDING,
|
||||
fill: FILL,
|
||||
stroke: STROKE,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn render(&self, canvas_origin: Vec2, canvas_size: Vec2) -> Vec<Shape> {
|
||||
let fill = Color32::from_gray(128);
|
||||
let rounding = Rounding::none();
|
||||
let cell_side = canvas_size.x / self.width as f32;
|
||||
let stroke = Stroke::NONE;
|
||||
let mut rectangles_cache = Vec::new();
|
||||
|
||||
let current = match self.age % 2 {
|
||||
|
@ -59,20 +83,26 @@ impl Universe {
|
|||
}
|
||||
width_counter += 1;
|
||||
} else if width_counter != 0 {
|
||||
let y = row as f32 * cell_side;
|
||||
let rect = Rect::from_min_size(
|
||||
pos2(width_origin, y) + canvas_origin,
|
||||
vec2(cell_side * width_counter as f32, cell_side),
|
||||
);
|
||||
rectangles_cache.push(Shape::Rect(RectShape {
|
||||
rect,
|
||||
rounding,
|
||||
fill,
|
||||
stroke,
|
||||
}));
|
||||
rectangles_cache.push(Universe::render_rect(
|
||||
canvas_origin,
|
||||
row as f32 * cell_side,
|
||||
width_origin,
|
||||
width_counter,
|
||||
cell_side,
|
||||
));
|
||||
width_counter = 0;
|
||||
}
|
||||
}
|
||||
if width_counter != 0 {
|
||||
rectangles_cache.push(Universe::render_rect(
|
||||
canvas_origin,
|
||||
row as f32 * cell_side,
|
||||
width_origin,
|
||||
width_counter,
|
||||
cell_side,
|
||||
));
|
||||
width_counter = 0;
|
||||
}
|
||||
}
|
||||
rectangles_cache
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue