1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! # quicksilver
//!
//! [![Code
//! Coverage](https://codecov.io/gh/ryanisaacg/quicksilver/branch/master/graph/badge.svg)](https://codecov.io/gh/ryanisaacg/quicksilver)
//! [![Build
//! Status](https://travis-ci.org/ryanisaacg/quicksilver.svg?branch=asset-rework)](https://travis-ci.org/ryanisaacg/quicksilver)
//! [![License](https://img.shields.io/badge/license-Apache-blue.svg)](https://github.com/ryanisaacg/quicksilver/blob/master/LICENSE)
//! [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/ryanisaacg/quicksilver/blob/master/LICENSE)
//! [![Crates.io](https://img.shields.io/crates/v/quicksilver.svg)](https://crates.io/crates/quicksilver)
//!
//! A 2D game framework written in pure Rust
//!
//! ## What's included?
//!
//! - 2D geometry: Vectors, Transformation matrices, Rectangles, Circles, Line segments, and a
//! generic Shape abstraction
//! - Keyboard and 3-button mouse support
//! - Viewport projection of the mouse to the world space automatically
//! - Zero-cost camera transformations
//! - OpenGL hardware-accelerated graphics
//! - A variety of image formats
//! - Multi-play sound clips
//! - A looping music player
//! - Asynchronous asset loading
//! - Unified codebase across desktop and the web
//!
//! ## Supported Platforms
//!
//! The engine is supported on Windows, macOS, (somewhat) Linux, and the web via WebAssembly. 
//! Linux is supported inasmuch as the libraries used for graphics (glutin, gl) and sound (rodio)
//! work correctly, 
//! but no extra attempts to support exotic setups will be made. 
//! The web is only supported via the `wasm32-unknown-unknown` Rust target, not through emscripten.
//! It might work with emscripten but this is not an ongoing guarantee.
//!
//! It has not been tested extensively on desktop platforms other than x86, but there is no reason
//! it should fail to work. If the dependencies libraries and the Rust compiler support a platform,
//! quicksilver should as well.
//!
//! There are no plans to support mobile / touch-primary platforms, as the paradigms are completely
//! different. UI elements must be created differently, input is one or two points of contact
//! rather than primarily through a keyboard, etc. 
//!
//! ## Compiler versions
//!
//! The desktop targets should always compile and run on the latest stable rust. 
//! Currently the web target is limited to nightly rust, because the WASM target that does not
//! require emscripten is limited to nightly.

#![deny(missing_docs)]

#[cfg(not(target_arch="wasm32"))]
extern crate glutin;
#[cfg(not(target_arch="wasm32"))]
extern crate image;
#[cfg(not(target_arch="wasm32"))]
extern crate rand;
#[cfg(not(target_arch="wasm32"))]
extern crate rodio;

mod gl;
pub mod asset;
pub mod geom;
pub mod graphics;
pub mod input;
pub mod sound;
mod timer;
pub use self::timer::Timer;

#[no_mangle]
#[cfg(target_arch="wasm32")]
#[doc(hidden)]
pub unsafe extern "C" fn deallocate_cstring(string: *mut i8) {
    use std::ffi::CString;
    CString::from_raw(string);
}


#[macro_export]
/// A macro that defines the main functions required for native and web
///
/// It takes a typename where the type has `new`, `update`, `draw`, and `events` functions. The
/// `new` function returns an instance of the type. The `events` function should return a `bool`
/// that indicates if the game loop should continue (`true`) or stop (`false`).
macro_rules! game_loop {
    ($state: tt) => (
        #[no_mangle]
        #[cfg(target_arch="wasm32")]
        pub extern "C" fn init() -> *mut $state {
            Box::into_raw(Box::new($state::new()))
        }

        #[no_mangle]
        #[cfg(target_arch="wasm32")]
        pub extern "C" fn update(state: *mut $state) -> u32 {
            let mut state = unsafe { Box::from_raw(state) };
            state.events();
            let duration = state.update();
            Box::into_raw(state);
            duration.subsec_nanos() / 1000000
        }

        #[no_mangle]
        #[cfg(target_arch="wasm32")]
        pub extern "C" fn draw(state: *mut $state) {
            let mut state = unsafe { Box::from_raw(state) };
            state.draw();
            Box::into_raw(state);
        }
        
        #[cfg(target_arch="wasm32")]
        fn main() {}

        #[cfg(not(target_arch="wasm32"))]
        fn main() {
            let mut timer = quicksilver::Timer::new();
            let mut state = $state::new();
            while state.events() {
                timer.tick(|| state.update());
                state.draw();
            }
        }
    )
}