extern crate sdl2; mod state; mod player; mod constants; mod gates; use state::Positioned; use state::Drawable; use state::Bullet; enum Result { Win, Loss, Nothing, } struct Textures<'a> { player: sdl2::render::Texture<'a>, enemy: sdl2::render::Texture<'a>, pbullet: sdl2::render::Texture<'a>, ebullet: sdl2::render::Texture<'a>, } fn frame, U: state::Bullet>(canvas: &mut sdl2::render::WindowCanvas, state: &mut state::State, events: &mut sdl2::event::EventPollIterator, textures: &Textures) -> Result { let mut new_bullets = Vec::new(); let count = state.count; for enemy in state.enemies.iter_mut() { new_bullets.append(&mut enemy.act(count)); } for bullet in state.bullets.iter_mut() { bullet.act(); } for bullet in state.player_bullets.iter_mut() { bullet.act(); } state.player.act(events); if count % state.player.fire_rate as u64 == 0 { state.player_bullets.push(state::PBullet::new(state.player.x, 0., state.player.y, -3.)); } if state.bullets.iter().any(|bullet| state.player.overlaps(bullet)) || new_bullets.iter().any(|bullet| state.player.overlaps(bullet)) { return Result::Loss; } for enemy in state.enemies.iter_mut() { for bullet in state.player_bullets.iter_mut() { if enemy.overlaps(bullet) { bullet.delete(); let health = enemy.health(); enemy.set_health(health - state::PBullet::damage()); } } } state.enemies.retain(|enemy| state::Enemy::health(enemy) > 0.); if state.enemies.len() == 0 { return Result::Win; } state.bullets.retain(|bullet| !U::outside(bullet)); state.bullets.append(&mut new_bullets); state.player_bullets.retain(|bullet| !state::PBullet::outside(bullet)); for bullet in state.player_bullets.iter() { bullet.draw(canvas, &textures.pbullet); } for enemy in state.enemies.iter() { enemy.draw(canvas, &textures.enemy); } state.player.draw(canvas, &textures.player); for bullet in state.bullets.iter() { bullet.draw(canvas, &textures.ebullet); } canvas.set_draw_color(sdl2::pixels::Color::RGB(255, 0, 0)); canvas.draw_rect(sdl2::rect::Rect::new(0, 0, (state.enemies[0].health() * constants::X_DIM as f64).round() as u32, 20)).unwrap(); state.count += 1; Result::Nothing } fn main() { let sdl_context = sdl2::init().unwrap(); let video_subsystem = sdl_context.video().unwrap(); let window = video_subsystem.window("rust-sdl2 demo", constants::X_DIM, constants::Y_DIM).position_centered().build().unwrap(); let mut canvas = window.into_canvas().build().unwrap(); canvas.set_draw_color(sdl2::pixels::Color::RGB(255, 255, 255)); canvas.clear(); canvas.present(); let mut event_pump = sdl_context.event_pump().unwrap(); let start = std::time::Instant::now(); let frame_duration = std::time::Duration::new(0, 1_000_000_000u32 / 60); let mut frame_count = 0; let mut state: state::State = state::State::new(); let mut won = false; let player_surface: sdl2::surface::Surface = sdl2::image::LoadSurface::from_file("assets/stallman.png").unwrap(); let enemy_surface: sdl2::surface::Surface = sdl2::image::LoadSurface::from_file("assets/gates.png").unwrap(); let ebullet_surface: sdl2::surface::Surface = sdl2::image::LoadSurface::from_file("assets/binary_blob.png").unwrap(); let pbullet_surface: sdl2::surface::Surface = sdl2::image::LoadSurface::from_file("assets/player_pepp.png").unwrap(); let texture_creator = canvas.texture_creator(); let player_texture = texture_creator.create_texture_from_surface(player_surface).unwrap(); let enemy_texture = texture_creator.create_texture_from_surface(enemy_surface).unwrap(); let ebullet_texture = texture_creator.create_texture_from_surface(ebullet_surface).unwrap(); let pbullet_texture = texture_creator.create_texture_from_surface(pbullet_surface).unwrap(); let surfaces = Textures { player: player_texture, enemy: enemy_texture, pbullet: pbullet_texture, ebullet: ebullet_texture }; 'running: loop { if won { for event in event_pump.poll_iter() { match event { sdl2::event::Event::Quit {..} | sdl2::event::Event::KeyDown { keycode: Some(sdl2::keyboard::Keycode::Escape), .. } => { std::process::exit(0); }, _ => { }, } } } else { canvas.set_draw_color(sdl2::pixels::Color::RGB(255, 255, 255)); canvas.clear(); match frame(&mut canvas, &mut state, &mut event_pump.poll_iter(), &surfaces) { Result::Loss => { break; } Result::Win => { canvas.set_draw_color(sdl2::pixels::Color::RGB(255, 204, 102)); canvas.clear(); canvas.present(); won = true; } _ => { canvas.present(); } } } let calc_time = frame_duration * frame_count; match calc_time.checked_sub(start.elapsed()) { Some(t) => std::thread::sleep(t), None => (), } frame_count += 1; } }