#[macro_use]
extern crate glium;
extern crate image;
use glium::{DisplayBuild,Display,IndexBuffer,Program,Surface,VertexBuffer};
use glium::glutin::{Event,WindowBuilder};
use glium::index::PrimitiveType;
use glium::texture::Texture2d;
struct BallState {
pos: (f32, f32),
dpos: (f32, f32),
}
#[derive(Debug,Clone,Copy)]
struct V2D {
pos: [f32;2],
tex: [f32;2],
}
implement_vertex!(V2D, pos, tex);
fn load_texture(d: &Display) -> Texture2d {
use std::io::Cursor;
let img = image::load(
Cursor::new(&include_bytes!("../assets/texture.png")[..]),
image::PNG).unwrap().to_rgba();
let dims = img.dimensions();
let img = glium::texture::RawImage2d::from_raw_rgba_reversed(
img.into_raw(), dims);
Texture2d::new(d, img).unwrap()
}
fn walls(d: &Display) -> (VertexBuffer<V2D>, IndexBuffer<u16>) {
let mut vertices = vec![];
let mut indices = vec![];
let mut i = 0;
for x in -9..10i32 {
for y in -9..10i32 {
if x.abs() == 9 || y.abs() == 9 {
vertices.extend_from_slice(&square_at((x as f32, y as f32), (0.5, 0.0)));
indices.extend_from_slice(
&[i + 2, i + 1, i, i + 3, i + 2, i]);
i += 4;
}
}
}
let vbuf = VertexBuffer::new(d, vertices.as_slice()).unwrap();
let ibuf = IndexBuffer::new(d, PrimitiveType::TrianglesList, indices.as_slice()).unwrap();
(vbuf, ibuf)
}
fn square_at((x, y): (f32, f32), (bu, bv): (f32, f32)) -> [V2D;4] {
[ V2D { pos: [ x - 0.5, y - 0.5 ], tex: [bu,bv] },
V2D { pos: [ x + 0.5, y - 0.5 ], tex: [bu,bv+0.5] },
V2D { pos: [ x + 0.5, y + 0.5 ], tex: [bu+0.5,bv+0.5] },
V2D { pos: [ x - 0.5, y + 0.5 ], tex: [bu,bv+0.5] },
]
}
fn ball(d: &Display, pos: (f32, f32)) -> (VertexBuffer<V2D>, IndexBuffer<u16>) {
let vertices = square_at(pos, (0.0, 0.0));
let indices = [ 2, 1, 0, 3, 2, 0 ];
let vbuf = VertexBuffer::new(d, &vertices).unwrap();
let ibuf = IndexBuffer::new(d, PrimitiveType::TrianglesList, &indices).unwrap();
(vbuf, ibuf)
}
fn main() {
let display = WindowBuilder::new()
.with_title(format!("bouncy"))
.build_glium()
.unwrap();
let program = Program::from_source(
&display,
include_str!("../assets/vertex.glsl"),
include_str!("../assets/fragment.glsl"),
None).unwrap();
let texture = load_texture(&display);
let mut st = BallState {
pos: (0.0, 0.0),
dpos: (0.1, 0.1),
};
let (w_vbuf, w_ibuf) = walls(&display);
loop {
let mut tgt = display.draw();
let params = Default::default();
tgt.clear_color(1.0, 1.0, 1.0, 1.0);
let (width, height) = tgt.get_dimensions();
let aspect_ratio = height as f32 / width as f32;
let (vbuf, ibuf) = ball(&display, st.pos);
tgt.draw(&vbuf, &ibuf, &program,
&uniform! {
texmap: &texture,
ratio: aspect_ratio,
},
¶ms).unwrap();
tgt.draw(&w_vbuf, &w_ibuf, &program,
&uniform! {
texmap: &texture,
ratio: aspect_ratio,
},
¶ms).unwrap();
tgt.finish().unwrap();
for ev in display.poll_events() {
match ev {
Event::Closed => return,
Event::KeyboardInput(_, n, _) =>
match n {
9 => return,
24 => return,
_ => {},
},
_ => {},
}
}
{
let (x, y) = st.pos;
let (mut dx, mut dy) = st.dpos;
if x < -8.0 || x > 8.0 {
dx = -dx;
}
if y < -8.0 || y > 8.0 {
dy = -dy;
}
dy -= 0.01;
st.pos = (x + dx, y + dy);
st.dpos = (dx, dy);
}
}
}