Initial commit
authorTomas Wenström <tomas.wenstrom@gmail.com>
Thu, 7 Feb 2019 16:30:02 +0000 (17:30 +0100)
committerTomas Wenström <tomas.wenstrom@gmail.com>
Thu, 7 Feb 2019 16:30:02 +0000 (17:30 +0100)
.gitignore [new file with mode: 0644]
Cargo.lock [new file with mode: 0644]
Cargo.toml [new file with mode: 0644]
res/block.bmp [new file with mode: 0644]
res/mario-trans.png [new file with mode: 0644]
res/mario.png [new file with mode: 0644]
src/boll.rs [new file with mode: 0644]
src/common.rs [new file with mode: 0644]
src/main.rs [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..332008f
--- /dev/null
@@ -0,0 +1,3 @@
+/target
+**/*.rs.bk
+.idea/
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644 (file)
index 0000000..61c7454
--- /dev/null
@@ -0,0 +1,299 @@
+[[package]]
+name = "autocfg"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "bitflags"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "c_vec"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cloudabi"
+version = "0.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fuchsia-cprng"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "lazy_static"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libc"
+version = "0.2.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "num"
+version = "0.1.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-iter"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rand"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_jitter 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rand_hc"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_isaac"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_jitter"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_os"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_pcg"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_xorshift"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rdrand"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.1.51"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustc_version"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "sdl-test"
+version = "0.1.0"
+dependencies = [
+ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "sdl2"
+version = "0.32.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "c_vec 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "sdl2-sys"
+version = "0.32.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "time"
+version = "0.1.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
+"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
+"checksum c_vec 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c32b15e95ce816aaf991a41420854e6ba772a2679a9296d906eab1114f1b4e9"
+"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
+"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
+"checksum fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81f7f8eb465745ea9b02e2704612a9946a59fa40572086c6fd49d6ddcf30bf31"
+"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
+"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047"
+"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e"
+"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
+"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124"
+"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
+"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
+"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
+"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
+"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
+"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
+"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
+"checksum rand_jitter 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "080723c6145e37503a2224f801f252e14ac5531cb450f4502698542d188cb3c0"
+"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d"
+"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05"
+"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
+"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
+"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85"
+"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+"checksum sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebf85f207d42e4da59fa31fff977be5ff0b224873506c4bd70cc1c94b331593"
+"checksum sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e82803e85c2e6178d28886cef25b2c53afc2eecaeff739f2247f23ed3352e6c1"
+"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
+"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
+"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644 (file)
index 0000000..ce2f5ee
--- /dev/null
@@ -0,0 +1,12 @@
+[package]
+name = "sdl-test"
+version = "0.1.0"
+authors = ["Tomas Wenström <tomas.wenstrom@gmail.com>"]
+
+[dependencies]
+rand = "0.6.5"
+time = "0.1.42"
+
+[dependencies.sdl2]
+version = "0.32.1"
+features = ["gfx", "image"]
diff --git a/res/block.bmp b/res/block.bmp
new file mode 100644 (file)
index 0000000..a2bfde4
Binary files /dev/null and b/res/block.bmp differ
diff --git a/res/mario-trans.png b/res/mario-trans.png
new file mode 100644 (file)
index 0000000..3f4ae2c
Binary files /dev/null and b/res/mario-trans.png differ
diff --git a/res/mario.png b/res/mario.png
new file mode 100644 (file)
index 0000000..1ceb7e2
Binary files /dev/null and b/res/mario.png differ
diff --git a/src/boll.rs b/src/boll.rs
new file mode 100644 (file)
index 0000000..b273f1d
--- /dev/null
@@ -0,0 +1,48 @@
+use sdl2::pixels::Color;
+use sdl2::rect::Point;
+use sdl2::rect::Rect;
+use sdl2::render::Canvas;
+use sdl2::video::Window;
+
+use {SCREEN_HEIGHT, SCREEN_WIDTH};
+use common::Point2D;
+
+pub struct Boll {
+    pub pos: Point2D<f64>,
+    pub vel: Point2D<f64>,
+}
+
+impl Boll {
+    pub fn update(&mut self) {
+        self.vel.y += 0.1;
+        self.pos += self.vel;
+
+        if self.pos.x < 0.0 {
+            self.pos.x = -self.pos.x;
+            self.vel.x = -self.vel.x;
+        }
+        if self.pos.x > SCREEN_WIDTH as f64 {
+            self.pos.x = SCREEN_WIDTH as f64 - (self.pos.x - SCREEN_WIDTH as f64);
+            self.vel.x = -self.vel.x;
+        }
+        if self.pos.y < 0.0 {
+            self.pos.y = -self.pos.y;
+            self.vel.y = -self.vel.y;
+        }
+        if self.pos.y > SCREEN_HEIGHT as f64 {
+            self.pos.y = SCREEN_HEIGHT as f64 - (self.pos.y - SCREEN_HEIGHT as f64);
+            self.vel.y = -self.vel.y;
+        }
+    }
+
+    pub fn draw(&mut self,canvas: &mut Canvas<Window>, size: u32) {
+        canvas.set_draw_color(Color::RGBA(
+            255 - std::cmp::min(255, (self.vel.length() * 25.0) as u8),
+            (255.0 * (self.pos.x / SCREEN_WIDTH as f64)) as u8,
+            (255.0 * (self.pos.y / SCREEN_HEIGHT as f64)) as u8, 128
+        ));
+        let mut r = Rect::new(0, 0, size, size);
+        r.center_on(Point::new(self.pos.x as i32, self.pos.y as i32));
+        canvas.fill_rect(r).unwrap();
+    }
+}
diff --git a/src/common.rs b/src/common.rs
new file mode 100644 (file)
index 0000000..f3b3373
--- /dev/null
@@ -0,0 +1,54 @@
+use std::ops::{Add, AddAssign};
+
+macro_rules! point {
+    ( $x:expr, $y:expr ) => { Point2D { x:$x, y:$y } };
+}
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub struct Point2D<T> {
+    pub x: T,
+    pub y: T,
+}
+
+impl Point2D<f64> {
+    pub fn length(self) -> f64 {
+        ((self.x * self.x) + (self.y * self.y)).sqrt()
+    }
+}
+
+impl<T: Add<Output=T>> Add for Point2D<T> {
+    type Output = Point2D<T>;
+
+    fn add(self, rhs: Point2D<T>) -> Self::Output {
+        Point2D { x: self.x + rhs.x, y: self.y + rhs.y }
+    }
+}
+
+impl<T: AddAssign> AddAssign for Point2D<T> {
+    fn add_assign(&mut self, rhs: Point2D<T>) {
+        self.x += rhs.x;
+        self.y += rhs.y;
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn immutable_copy_of_point() {
+        let a = point!(0, 0);
+        let mut b = a; // Copy
+        assert_eq!(a, b); // PartialEq
+        b.x = 1;
+        assert_ne!(a, b); // PartialEq
+    }
+
+    #[test]
+    fn add_points() {
+        let mut a = point!(1, 0);
+        assert_eq!(a + point!(2, 2), point!(3, 2)); // Add
+        a += point!(2, 2); // AddAssign
+        assert_eq!(a, point!(3, 2));
+    }
+}
diff --git a/src/main.rs b/src/main.rs
new file mode 100644 (file)
index 0000000..7182836
--- /dev/null
@@ -0,0 +1,171 @@
+extern crate rand;
+extern crate sdl2;
+extern crate time;
+
+use std::collections::hash_map::RandomState;
+use std::collections::HashMap;
+use std::f32::consts::PI;
+
+use rand::Rng;
+use sdl2::event::Event;
+use sdl2::EventPump;
+use sdl2::gfx::primitives::DrawRenderer;
+use sdl2::image::LoadTexture;
+use sdl2::keyboard::Keycode;
+use sdl2::pixels::Color;
+use sdl2::rect::Rect;
+use sdl2::render::BlendMode;
+use sdl2::render::Canvas;
+use sdl2::render::Texture;
+use sdl2::render::TextureCreator;
+use sdl2::video::Window;
+use sdl2::video::WindowContext;
+use time::PreciseTime;
+
+use boll::Boll;
+use common::Point2D;
+
+#[macro_use] mod common;
+mod boll;
+
+const SCREEN_WIDTH: u32 = 1280;
+const SCREEN_HEIGHT: u32 = (SCREEN_WIDTH as f64 * (1440.0 / 2560.0)) as u32;
+const FPS: u32 = 60;
+const NS_PER_FRAME: u32 = 1_000_000_000 / FPS;
+
+fn init() -> (Canvas<Window>, EventPump) {
+    let context = sdl2::init().unwrap();
+    let video = context.video().unwrap();
+    let _image_context = sdl2::image::init(sdl2::image::InitFlag::PNG).unwrap();
+    let window = video.window("SDL test", SCREEN_WIDTH, SCREEN_HEIGHT)
+        .position_centered()
+        .opengl()
+        .build()
+        .unwrap();
+    context.mouse().show_cursor(false);
+    let mut canvas = window.into_canvas().build().unwrap();
+    canvas.set_blend_mode(BlendMode::Add);
+    canvas.set_draw_color(Color::RGB(0, 0, 0));
+    canvas.clear();
+    canvas.present();
+    let event_pump = context.event_pump().unwrap();
+    (canvas, event_pump)
+}
+
+fn load_textures(texture_creator: &TextureCreator<WindowContext>) -> HashMap<&str, Texture, RandomState> {
+    let mut textures = HashMap::new();
+    textures.insert("block", texture_creator.load_texture("res/block.bmp").unwrap());
+    textures.insert("mario", texture_creator.load_texture("res/mario-trans.png").unwrap());
+    textures
+}
+
+fn main() {
+    println!("starting...");
+    let (mut canvas, mut event_pump) = init();
+
+    let mut frame_count: u64 = 0;
+    let mut fps_time = PreciseTime::now();
+
+    let mut bolls: Vec<Boll> = Vec::new();
+    let mut boll_size = 1;
+
+    let texture_creator = canvas.texture_creator();
+    let textures = load_textures(&texture_creator);
+    let mut mario_angle = 0.0;
+
+    'running: loop {
+        let loop_start = PreciseTime::now();
+        canvas.set_draw_color(Color::RGB(0, 0, 0));
+        canvas.clear();
+        {
+            let blocks = 20;
+            let size = 32;
+            let offset = point!((SCREEN_WIDTH as i32 - (blocks + 1) * size) / 2, (SCREEN_HEIGHT as i32 - (blocks + 1) * size) / 2);
+            for i in 0..blocks {
+                canvas.copy(&(textures.get("block").unwrap()), None, Rect::new((i) * size + offset.x, (0) * size + offset.y, size as u32, size as u32)).unwrap();
+                canvas.copy(&(textures.get("block").unwrap()), None, Rect::new((blocks - i) * size + offset.x, (blocks) * size + offset.y, size as u32, size as u32)).unwrap();
+                canvas.copy(&(textures.get("block").unwrap()), None, Rect::new((0) * size + offset.x, (blocks - i) * size + offset.y, size as u32, size as u32)).unwrap();
+                canvas.copy(&(textures.get("block").unwrap()), None, Rect::new((blocks) * size + offset.x, (i) * size + offset.y, size as u32, size as u32)).unwrap();
+            }
+        }
+        {
+            let size = 64;
+            let offset = point!((SCREEN_WIDTH as i32 - size) / 2, (SCREEN_HEIGHT as i32 - size) / 2);
+            let radius = 110.0 + size as f32 * 0.5;
+            let angle = (mario_angle as f32 - 90.0) * PI / 180.0;
+            let offset2 = point!((angle.cos() * radius) as i32, (angle.sin() * radius) as i32);
+            canvas.copy_ex(&(textures.get("mario").unwrap()), None, Rect::new(offset.x + offset2.x, offset.y + offset2.y, size as u32, size as u32), mario_angle, sdl2::rect::Point::new(size / 2, size / 2), false, false).unwrap();
+            mario_angle += 1.0;
+            if mario_angle >= 360.0 { mario_angle -= 360.0 }
+        }
+        {
+            let p = point!((SCREEN_WIDTH / 2) as i16, (SCREEN_HEIGHT / 2) as i16);
+            canvas.circle(p.x, p.y, 100, Color::RGB(255, 255, 255)).unwrap();
+            canvas.aa_circle(p.x, p.y, 110, Color::RGB(255, 255, 255)).unwrap();
+            canvas.ellipse(p.x, p.y, 50, 100, Color::RGB(255, 255, 255)).unwrap();
+            canvas.aa_ellipse(p.x, p.y, 110, 55, Color::RGB(255, 255, 255)).unwrap();
+        }
+
+        for b in &mut bolls {
+            b.update();
+            b.draw(&mut canvas, boll_size);
+        }
+
+//        window.gl_swap_window();
+        for event in event_pump.poll_iter() {
+            match event {
+                Event::Quit { .. } | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
+                    break 'running;
+                }
+                Event::KeyDown { keycode: Some(Keycode::F11), .. } => {
+                    canvas.window_mut()
+                        .set_fullscreen(sdl2::video::FullscreenType::True).unwrap();
+                }
+                Event::KeyDown { keycode: Some(Keycode::KpPlus), .. } => { boll_size = std::cmp::min(boll_size + 1, 32) }
+                Event::KeyDown { keycode: Some(Keycode::KpMinus), .. } => { boll_size = std::cmp::max(boll_size - 1, 1) }
+                Event::MouseMotion { x, y, .. } => { bolls.push(Boll {
+                    pos: point!(x as f64, y as f64),
+                    vel: point!(0.0, 0.0),
+                }) }
+                _ => {}
+            }
+        }
+        canvas.present();
+
+        match loop_start.to(PreciseTime::now()).num_nanoseconds() {
+            Some(ns) if ns < (NS_PER_FRAME - 50_0000) as i64 => { change_boll_count(&mut bolls, 100) }
+            Some(ns) if ns > (NS_PER_FRAME + 50_0000) as i64 => { change_boll_count(&mut bolls, -100) }
+            _ => {}
+        }
+
+        frame_count += 1;
+        if frame_count == FPS as u64 {
+            let duration = fps_time.to(PreciseTime::now()).num_nanoseconds().unwrap() as f64 / 1_000_000_000.0;
+            println!("fps: {}", frame_count as f64 / duration);
+            frame_count = 0;
+            fps_time = PreciseTime::now();
+        }
+    }
+
+    println!("number of bolls: {}", bolls.len());
+}
+
+fn change_boll_count(mut bolls: &mut Vec<Boll>, delta: i32) {
+    if delta > 0 {
+        for _i in 0..delta {
+            add_boll(&mut bolls);
+        }
+    } else if delta < 0 {
+        for _i in 0..delta {
+            bolls.pop();
+        }
+    }
+}
+
+fn add_boll(bolls: &mut Vec<Boll>) {
+    let mut rng = rand::thread_rng();
+    bolls.push(Boll {
+        pos: point!(rng.gen_range(0, SCREEN_WIDTH) as f64, rng.gen_range(0, SCREEN_HEIGHT) as f64),
+        vel: point!(rng.gen_range(-2.0, 2.0), rng.gen_range(-2.0, 2.0)),
+    });
+}