Created
May 29, 2014 12:02
-
-
Save bvssvni/9b980bfe71f00492b180 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 graphics::{ | |
Context, | |
}; | |
use { | |
AssetStore, | |
GameWindow, | |
Gl, | |
}; | |
use keyboard; | |
use mouse; | |
/// Render argument. | |
pub struct RenderArgs<'a> { | |
/// Rust-Graphics context. | |
pub context: &'a Context<'a>, | |
/// OpenGL back-end for Rust-Graphics. | |
pub gl: &'a mut Gl<'a>, | |
} | |
/// Update argument. | |
pub struct UpdateArgs<'a> { | |
/// Delta time in seconds. | |
pub dt: f64, | |
/// Asset store. | |
pub asset_store: &'a mut AssetStore, | |
} | |
/// Load arguments. | |
pub struct LoadArgs<'a> { | |
/// Asset store. | |
pub asset_store: &'a mut AssetStore, | |
} | |
/// Key press arguments. | |
pub struct KeyPressArgs<'a> { | |
/// Keyboard key. | |
pub key: keyboard::Key, | |
/// Asset store. | |
pub asset_store: &'a mut AssetStore, | |
} | |
/// Key release arguments. | |
pub struct KeyReleaseArgs<'a> { | |
/// Keyboard key. | |
pub key: keyboard::Key, | |
/// Asset store. | |
pub asset_store: &'a mut AssetStore, | |
} | |
/// Mouse press arguments. | |
pub struct MousePressArgs<'a> { | |
/// Mouse button. | |
pub button: mouse::Button, | |
/// Asset store. | |
pub asset_store: &'a mut AssetStore, | |
} | |
/// Mouse release arguments. | |
pub struct MouseReleaseArgs<'a> { | |
/// Mouse button. | |
pub button: mouse::Button, | |
/// Asset store. | |
pub asset_store: &'a mut AssetStore, | |
} | |
/// Mouse move arguments. | |
pub struct MouseMoveArgs<'a> { | |
/// y. | |
pub x: f64, | |
/// x. | |
pub y: f64, | |
/// Asset store. | |
pub asset_store: &'a mut AssetStore, | |
} | |
/// Mouse relative move arguments. | |
pub struct MouseRelativeMoveArgs<'a> { | |
/// Delta x. | |
pub dx: f64, | |
/// Delta y. | |
pub dy: f64, | |
/// Asset store. | |
pub asset_store: &'a mut AssetStore, | |
} | |
/// Contains the different game events. | |
pub enum GameEvent<'a> { | |
/// Render graphics. | |
Render(RenderArgs<'a>), | |
/// Update physical state of the game. | |
Update(UpdateArgs<'a>), | |
/// Performs tasks for loading before showing anything. | |
Load(LoadArgs<'a>), | |
/// Pressed a keyboard key. | |
KeyPress(KeyPressArgs<'a>), | |
/// Released a keyboard key. | |
KeyRelease(KeyReleaseArgs<'a>), | |
/// Pressed a mouse button. | |
MousePress(MousePressArgs<'a>), | |
/// Released a mouse button. | |
MouseRelease(MouseReleaseArgs<'a>), | |
/// Moved mouse cursor. | |
MouseMove(MouseMoveArgs<'a>), | |
/// Moved mouse relative, not bounded by cursor. | |
MouseRelativeMove(MouseRelativeMoveArgs<'a>), | |
} | |
enum GameIteratorState { | |
LoadState, | |
} | |
/// A game loop iterator. | |
pub struct GameIterator<'a, W> { | |
game_window: &'a mut W, | |
asset_store: &'a mut AssetStore, | |
state: GameIteratorState, | |
} | |
impl<'a, W: GameWindow> GameIterator<'a, W> { | |
/// Creates a new game iterator. | |
pub fn new(game_window: &'a mut W, asset_store: &'a mut AssetStore) -> GameIterator<'a, W> { | |
GameIterator { | |
game_window: game_window, | |
asset_store: asset_store, | |
state: LoadState, | |
} | |
} | |
} | |
impl<'a, W: GameWindow> Iterator<GameEvent<'a>> for GameIterator<'a, W> { | |
fn next(&mut self) -> Option<GameEvent<'a>> { | |
use std::mem::transmute; | |
match self.state { | |
LoadState => { | |
return Some(Load(LoadArgs { | |
asset_store: unsafe { transmute::<&mut AssetStore, &'a mut AssetStore>(self.asset_store) } | |
})); | |
}, | |
}; | |
/* | |
// copied. | |
self.load(asset_store); | |
let mut gl_data = GlData::new(); | |
let context = Context::new(); | |
let bg = game_window.get_settings().background_color; | |
let bg = context.rgba(bg[0], bg[1], bg[2], bg[3]); | |
let updates_per_second: u64 = 120; | |
let max_frames_per_second: u64 = 60; | |
// You can make this lower if needed | |
let min_updates_per_frame: u64 = updates_per_second / max_frames_per_second; | |
let billion: u64 = 1_000_000_000; | |
let dt: f64 = 1.0 / updates_per_second as f64; | |
let update_time_in_ns: u64 = billion / updates_per_second; | |
let start = time::precise_time_ns(); | |
let min_ns_per_frame = billion / max_frames_per_second; | |
let mut last_update = start; | |
while !self.should_close(game_window) { | |
let start_render = time::precise_time_ns(); | |
// Rendering code | |
let (w, h) = game_window.get_size(); | |
if w != 0 && h != 0 { | |
self.viewport(game_window); | |
let mut gl = Gl::new(&mut gl_data, asset_store); | |
bg.clear(&mut gl); | |
// Extrapolate time forward to allow smooth motion. | |
// 'now' is always bigger than 'last_update'. | |
let ext_dt = (start_render - last_update) as f64 / billion as f64; | |
self.render( | |
ext_dt, | |
&context | |
.trans(-1.0, 1.0) | |
.scale(2.0 / w as f64, -2.0 / h as f64) | |
.store_view(), | |
&mut gl | |
); | |
self.swap_buffers(game_window); | |
} | |
let next_render = start_render + min_ns_per_frame; | |
// Update gamestate | |
let mut updated = 0; | |
while // If we haven't reached the required number of updates yet | |
( updated < min_updates_per_frame || | |
// Or we have the time to update further | |
time::precise_time_ns() < next_render ) && | |
//And we haven't already progressed time to far | |
last_update + update_time_in_ns < next_render { | |
self.handle_events(game_window, asset_store); | |
self.update(dt, asset_store); | |
updated += 1; | |
last_update += update_time_in_ns; | |
} | |
// Wait if possible | |
let t = (next_render - time::precise_time_ns() ) / 1_000_000; | |
if t > 1 && t < 1000000 { // The second half just checks if it overflowed, | |
// which tells us that t should have been negative | |
// and we are running slow and shouldn't sleep. | |
sleep( t ); | |
} | |
} | |
*/ | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment