use spottedcat::{
Context, DrawOption, DrawOption3D, FogBackgroundSettings, FogSamplingSettings, FogSettings,
Model, Pt, Spot, Text, WindowConfig,
};
use std::time::Duration;
struct FogWorld {
cube: Model,
sphere: Model,
floor: Model,
giant_bg: Model,
time: f32,
fps: f32,
frame_count: u32,
accumulated_time: f32,
fps_text: Text,
}
impl Spot for FogWorld {
fn initialize(ctx: &mut Context) -> Self {
spottedcat::set_camera_pos(ctx, [0.0, 3.6, 14.0]);
spottedcat::set_camera_target(ctx, 0.0, 1.2, -12.0);
spottedcat::set_camera_up(ctx, 0.0, 1.0, 0.0);
spottedcat::set_ambient_light(ctx, [0.16, 0.18, 0.17, 1.0]);
let floor_tex = spottedcat::Image::new(
ctx,
Pt::from(2.0),
Pt::from(2.0),
&[
58, 69, 66, 255, 48, 58, 55, 255, 48, 58, 55, 255, 58, 69, 66, 255,
],
)
.unwrap();
let cube_tex =
spottedcat::Image::new(ctx, Pt::from(1.0), Pt::from(1.0), &[152, 162, 156, 255])
.unwrap();
let sphere_tex =
spottedcat::Image::new(ctx, Pt::from(1.0), Pt::from(1.0), &[225, 232, 228, 255])
.unwrap();
let bg_tex =
spottedcat::Image::new(ctx, Pt::from(1.0), Pt::from(1.0), &[104, 113, 116, 255])
.unwrap();
let floor = spottedcat::model::create_plane(ctx, 1.0, 1.0)
.unwrap()
.with_material(floor_tex);
let cube = spottedcat::model::create_cube(ctx, 1.0)
.unwrap()
.with_material(cube_tex);
let sphere = spottedcat::model::create_sphere(ctx, 1.0)
.unwrap()
.with_material(sphere_tex);
let giant_bg = spottedcat::model::create_sphere(ctx, 1.0)
.unwrap()
.with_material(bg_tex);
const FONT: &[u8] = include_bytes!("../assets/DejaVuSans.ttf");
let font_id = spottedcat::register_font(ctx, FONT.to_vec());
let fps_text = Text::new("FPS: 0", font_id)
.with_font_size(Pt::from(24.0))
.with_color([0.0, 1.0, 0.0, 1.0]);
Self {
cube,
sphere,
floor,
giant_bg,
time: 0.0,
fps: 0.0,
frame_count: 0,
accumulated_time: 0.0,
fps_text,
}
}
fn update(&mut self, _ctx: &mut Context, dt: Duration) {
let dt_secs = dt.as_secs_f32();
self.time += dt_secs;
self.accumulated_time += dt_secs;
self.frame_count += 1;
if self.accumulated_time >= 1.0 {
self.fps = self.frame_count as f32 / self.accumulated_time;
self.fps_text.set_content(format!("FPS: {:.1}", self.fps));
self.accumulated_time = 0.0;
self.frame_count = 0;
}
}
fn draw(&mut self, ctx: &mut Context, screen: spottedcat::Image) {
let fog = FogSettings::default()
.with_color([0.72, 0.79, 0.77, 1.0])
.with_strength(0.26)
.with_background(
FogBackgroundSettings::morning_mist()
.with_horizon_glow(0.035)
.with_blend(0.68, 0.52),
)
.with_sampling(FogSamplingSettings::default().with_height_samples(4, 8))
.with_distance(14.0, 48.0, 0.22, 1.0)
.with_height(-1.0, 9.0, 0.16, 1.0);
spottedcat::set_fog(ctx, fog);
screen.draw(
ctx,
&self.floor,
DrawOption3D::default()
.with_position([0.0, -1.0, -8.0])
.with_rotation([-std::f32::consts::FRAC_PI_2, 0.0, 0.0])
.with_scale([50.0, 50.0, 1.0]),
);
screen.draw(
ctx,
&self.giant_bg,
DrawOption3D::default()
.with_position([0.0, 6.5 + (self.time * 0.18).sin() * 0.4, -70.0])
.with_scale([70.0, 70.0, 70.0])
.with_opacity(0.16),
);
for row in 0..6 {
let z = -4.0 - row as f32 * 4.4;
let sway = (self.time * 0.8 + row as f32 * 0.7).sin() * 0.35;
let lift = (self.time * 1.1 + row as f32 * 0.5).sin() * 0.12;
screen.draw(
ctx,
&self.cube,
DrawOption3D::default()
.with_position([-3.0 + sway, -0.1 + lift, z])
.with_scale([1.1, 1.7, 1.1])
.with_rotation([0.0, self.time * 0.3 + row as f32 * 0.2, 0.0]),
);
screen.draw(
ctx,
&self.cube,
DrawOption3D::default()
.with_position([3.0 - sway, 0.2 - lift * 0.5, z - 1.0])
.with_scale([1.4, 2.2, 1.4])
.with_rotation([0.0, -self.time * 0.25 - row as f32 * 0.18, 0.0]),
);
screen.draw(
ctx,
&self.sphere,
DrawOption3D::default()
.with_position([0.0, 1.0 + row as f32 * 0.18, z - 2.0])
.with_scale([
1.2 + row as f32 * 0.18,
1.2 + row as f32 * 0.18,
1.2 + row as f32 * 0.18,
]),
);
}
spottedcat::clear_fog(ctx);
screen.draw(
ctx,
&self.fps_text,
DrawOption::default().with_position([Pt::from(10.0), Pt::from(10.0)]),
);
}
fn remove(&mut self, ctx: &mut Context) {
spottedcat::clear_fog(ctx);
}
}
fn main() {
spottedcat::run::<FogWorld>(WindowConfig {
title: "Fog World Example".to_string(),
..Default::default()
});
}