explosion, fix server linking on restart

This commit is contained in:
Theis Pieter Hollebeek 2026-04-28 16:42:59 +02:00
parent 197693c71f
commit c0f97dd83d
21 changed files with 62 additions and 14 deletions

10
game/Cargo.lock generated
View File

@ -22,10 +22,20 @@ checksum = "96e613fca5924ccab8ab8369ab292a1b4720b125e98007fbda163f4ce7176472"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"libc", "libc",
"sdl3-image-sys",
"sdl3-sys", "sdl3-sys",
"sdl3-ttf-sys", "sdl3-ttf-sys",
] ]
[[package]]
name = "sdl3-image-sys"
version = "0.6.2+SDL-image-3.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64a0c5e6f5874aef7cdc76ff36855bffd98f52feb9df3f5b7f443e0beb4472fe"
dependencies = [
"sdl3-sys",
]
[[package]] [[package]]
name = "sdl3-sys" name = "sdl3-sys"
version = "0.6.3+SDL-3.4.4" version = "0.6.3+SDL-3.4.4"

View File

@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
sdl3 = { version = "0.18.0", features = ["ttf"] } sdl3 = { version = "0.18.0", features = ["ttf", "image"] }

BIN
game/assets/explosion/0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
game/assets/explosion/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
game/assets/explosion/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
game/assets/explosion/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
game/assets/explosion/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
game/assets/explosion/5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
game/assets/explosion/6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
game/assets/explosion/7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
game/assets/explosion/8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
game/assets/explosion/9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -12,6 +12,7 @@ pub trait Io<R: Renderer, G: Game<R>> {
pub trait Renderer { pub trait Renderer {
fn load_text(&mut self, text: &str, size: f64, color: Color) -> u32; fn load_text(&mut self, text: &str, size: f64, color: Color) -> u32;
fn load_image(&mut self, path: &str) -> u32;
fn draw_texture(&mut self, id: u32, pos: V2); fn draw_texture(&mut self, id: u32, pos: V2);
fn query_texture(&mut self, id: u32) -> V2; fn query_texture(&mut self, id: u32) -> V2;
fn draw_rect(&mut self, pos: V2, size: V2, color: Color); fn draw_rect(&mut self, pos: V2, size: V2, color: Color);

View File

@ -33,6 +33,7 @@ mod textures {
use std::collections::HashMap; use std::collections::HashMap;
use sdl3::{ use sdl3::{
image::LoadTexture,
render::{Texture, TextureCreator}, render::{Texture, TextureCreator},
ttf::Font, ttf::Font,
video::WindowContext, video::WindowContext,
@ -54,6 +55,19 @@ mod textures {
id_counter: 0, id_counter: 0,
} }
} }
pub fn render_image(&mut self, path: &str) -> u32 {
let texture = unsafe {
let static_texture_creator: *const TextureCreator<WindowContext> =
&self.texture_creator as *const _;
let texture = (&*static_texture_creator).load_texture(path).unwrap();
texture
};
let id = self.id_counter;
self.textures.insert(id, texture);
self.id_counter += 1;
id
}
pub fn render_font(&mut self, font: Font, text: &str, color: Color) -> u32 { pub fn render_font(&mut self, font: Font, text: &str, color: Color) -> u32 {
let surface = font.render(text).blended(color).unwrap(); let surface = font.render(text).blended(color).unwrap();
let texture = unsafe { let texture = unsafe {
@ -276,6 +290,11 @@ impl Renderer for SdlIo<'_> {
let (_, size) = self.canvas.window().size(); let (_, size) = self.canvas.window().size();
size as f64 size as f64
} }
fn load_image(&mut self, path: &str) -> u32 {
let id = self.texture_handler.render_image(path);
id
}
} }
impl From<V2> for FPoint { impl From<V2> for FPoint {

View File

@ -375,10 +375,11 @@ struct Game {
keys_pressed: HashSet<Key>, keys_pressed: HashSet<Key>,
event_queue: Arc<Mutex<VecDeque<f64>>>, event_queue: Arc<Mutex<VecDeque<f64>>>,
ground: GroundManager, ground: GroundManager,
joever_timer: Option<f64>, game_over_timer: Option<Duration>,
} }
impl Game { impl Game {
const RESTART_TIMER: Duration = Duration::from_secs(5);
fn new() -> Self { fn new() -> Self {
Self { Self {
skateboard: Skateboard { skateboard: Skateboard {
@ -395,27 +396,28 @@ impl Game {
segment_manager: SegmentManager::new(V3(0.0, -0.24, 1.6), 4, 2.0, 1.0), segment_manager: SegmentManager::new(V3(0.0, -0.24, 1.6), 4, 2.0, 1.0),
keys_pressed: HashSet::new(), keys_pressed: HashSet::new(),
ground: GroundManager::new(V3(0.0, -0.25, -0.4), 0.1, 10, 20, 4), ground: GroundManager::new(V3(0.0, -0.25, -0.4), 0.1, 10, 20, 4),
joever_timer: None, game_over_timer: None,
} }
} }
fn restart(&mut self) { fn restart(&mut self) {
*self = Self::new(); let mut new = Self::new();
std::mem::swap(&mut new.event_queue, &mut self.event_queue);
*self = new;
} }
} }
impl<R: Renderer> engine::Game<R> for Game { impl<R: Renderer> engine::Game<R> for Game {
fn update(&mut self, delta_time: Duration) { fn update(&mut self, delta_time: Duration) {
if let Some(joever_timer) = self.joever_timer.as_mut() { if let Some(timer) = self.game_over_timer.as_mut() {
*joever_timer -= delta_time.as_secs_f64(); match timer.checked_sub(delta_time) {
if *joever_timer <= 0.0 { Some(result) => *timer = result,
self.restart(); None => self.restart(),
} }
return; return;
} }
if let UpdateResult::GameOver = self.skateboard.update(delta_time) { if let UpdateResult::GameOver = self.skateboard.update(delta_time) {
self.joever_timer = Some(5.0); self.game_over_timer = Some(Self::RESTART_TIMER);
return;
} }
self.camera_pos = V3( self.camera_pos = V3(
self.skateboard.pos.0, self.skateboard.pos.0,
@ -457,8 +459,7 @@ impl<R: Renderer> engine::Game<R> for Game {
}; };
if let UpdateResult::GameOver = self.segment_manager.update(&mut cx, delta_time) { if let UpdateResult::GameOver = self.segment_manager.update(&mut cx, delta_time) {
self.joever_timer = Some(5.0); self.game_over_timer = Some(Self::RESTART_TIMER);
return;
} }
if self if self
@ -485,9 +486,26 @@ impl<R: Renderer> engine::Game<R> for Game {
let V2(width, _height) = r.query_texture(id); let V2(width, _height) = r.query_texture(id);
r.draw_texture(id, V2(r.screen_width() / 2.0 - width / 2.0, 50.0)); r.draw_texture(id, V2(r.screen_width() / 2.0 - width / 2.0, 50.0));
} }
if let Some(joever_timer) = self.joever_timer { if let Some(timer) = self.game_over_timer {
{
let percentage =
(Self::RESTART_TIMER - timer).as_secs_f64() / Self::RESTART_TIMER.as_secs_f64();
let percentage = percentage * 4.0;
if percentage < 1.0 {
let picked_texture = (percentage * 16.0).floor() as u32;
let id = r.load_image(&format!("assets/explosion/{picked_texture}.png"));
let V2(width, height) = r.query_texture(id);
r.draw_texture(
id,
V2(
r.screen_width() / 2.0 - width / 2.0,
r.screen_height() * 0.8 - height / 2.0,
),
);
}
}
let id = r.load_text( let id = r.load_text(
&format!("{}", joever_timer.ceil() as u32), &format!("{}", timer.as_secs_f64().ceil() as u32),
96.0, 96.0,
Color::Green, Color::Green,
); );