317 lines
9.0 KiB
Rust
317 lines
9.0 KiB
Rust
extern crate sdl2;
|
|
|
|
use std::num::Float;
|
|
use std::iter::range_step;
|
|
|
|
use sdl2::video::{Window, WindowPos, OPENGL};
|
|
use sdl2::event::{poll_event, Event};
|
|
use sdl2::timer::{get_ticks, delay};
|
|
use sdl2::rect::{Point, Rect};
|
|
use sdl2::keycode::KeyCode;
|
|
use sdl2::pixels::Color;
|
|
|
|
use tile::Layer;
|
|
use camera::Camera;
|
|
use player::Player;
|
|
use keyboard::KeyboardHandler;
|
|
|
|
mod tile;
|
|
mod camera;
|
|
mod player;
|
|
mod keyboard;
|
|
|
|
|
|
const SCREEN_WIDTH : i32 = 960;
|
|
const SCREEN_HEIGHT : i32 = 640;
|
|
|
|
const TILE_WIDTH : i32 = 32;
|
|
const TILE_HEIGHT : i32 = 32;
|
|
|
|
const MS_PER_UPDATE : usize = 10;
|
|
|
|
|
|
#[derive(Clone)]
|
|
enum Tile {
|
|
Empty,
|
|
Floor(Color)
|
|
}
|
|
|
|
|
|
fn main() {
|
|
sdl2::init(sdl2::INIT_EVERYTHING);
|
|
|
|
let window = match Window::new("Super Matte Bros", WindowPos::PosCentered, WindowPos::PosCentered, SCREEN_WIDTH as isize, SCREEN_HEIGHT as isize, OPENGL) {
|
|
Ok(window) => window,
|
|
Err(err) => panic!("failed to create window: {}", err)
|
|
};
|
|
|
|
let renderer = match sdl2::render::Renderer::from_window(window, sdl2::render::RenderDriverIndex::Auto, sdl2::render::ACCELERATED) {
|
|
Ok(renderer) => renderer,
|
|
Err(err) => panic!("failed to create renderer: {}", err)
|
|
};
|
|
|
|
let mut keyboard = KeyboardHandler::new();
|
|
|
|
let mut layer = Layer::new(120, 20, TILE_WIDTH, TILE_HEIGHT, Tile::Empty);
|
|
|
|
let colors = vec![Color::RGB(0, 0, 255), Color::RGB(0, 128, 255)];
|
|
|
|
for x in range(5, 120) {
|
|
layer.set_tile(x, 14, Tile::Floor(colors[(x % 2) as usize]));
|
|
}
|
|
for x in range(11, 20) {
|
|
layer.set_tile(x, 13, Tile::Floor(colors[(x % 2) as usize]));
|
|
}
|
|
for x in range(14, 20) {
|
|
layer.set_tile(x, 11, Tile::Floor(colors[(x % 2) as usize]));
|
|
}
|
|
|
|
let mut camera = Camera::new(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, layer.to_rect());
|
|
|
|
let mut player = Player::new(290.0, 390.0);
|
|
|
|
let mut current : usize;
|
|
let mut elapsed : usize;
|
|
let mut previous : usize = get_ticks();
|
|
let mut lag : usize = 0;
|
|
|
|
'main : loop {
|
|
current = get_ticks();
|
|
elapsed = current - previous;
|
|
previous = current;
|
|
lag += elapsed;
|
|
|
|
keyboard.clear();
|
|
|
|
'event : loop {
|
|
match poll_event() {
|
|
Event::Quit(_) => break 'main,
|
|
Event::KeyDown(_, _, key, _, _, repeat) => {
|
|
if repeat == false {
|
|
keyboard.key_down(key);
|
|
}
|
|
},
|
|
Event::KeyUp(_, _, key, _, _, _) => {
|
|
keyboard.key_up(key);
|
|
},
|
|
Event::None => break 'event,
|
|
_ => (),
|
|
}
|
|
}
|
|
|
|
if keyboard.was_pressed(KeyCode::Escape) {
|
|
break 'main;
|
|
}
|
|
|
|
if keyboard.is_held(KeyCode::Right) {
|
|
player.dx = 4.0;
|
|
}
|
|
|
|
if keyboard.is_held(KeyCode::Left) {
|
|
player.dx = -4.0;
|
|
}
|
|
|
|
if keyboard.was_pressed(KeyCode::Up) {
|
|
if player.on_ground {
|
|
player.dy = -12.0;
|
|
|
|
player.on_ground = false;
|
|
}
|
|
}
|
|
|
|
if keyboard.was_released(KeyCode::Right) {
|
|
if player.dx > 0.0 {
|
|
player.dx = 0.0;
|
|
}
|
|
}
|
|
|
|
if keyboard.was_released(KeyCode::Left) {
|
|
if player.dx < 0.0 {
|
|
player.dx = 0.0;
|
|
}
|
|
}
|
|
|
|
if keyboard.was_released(KeyCode::Up) {
|
|
if player.dy < -6.0 {
|
|
player.dy = -6.0;
|
|
}
|
|
}
|
|
|
|
while lag >= MS_PER_UPDATE {
|
|
player.update();
|
|
|
|
player.on_ground = false;
|
|
|
|
if let Some(intersect) = layer.find_intersecting(&player.to_rect()) {
|
|
if player.dx > 0.0 {
|
|
let p = player.x + player.w as f32;
|
|
let mut d = player.dx;
|
|
|
|
for y in range(intersect.y, intersect.y + intersect.h + 1) {
|
|
let mut x = intersect.x;
|
|
|
|
loop {
|
|
let t = (x * TILE_WIDTH) as f32 - p;
|
|
|
|
if t > d {
|
|
break;
|
|
}
|
|
|
|
if let Some(tile) = layer.get_tile(x, y) {
|
|
d = match *tile {
|
|
Tile::Empty => d,
|
|
Tile::Floor(_) => d.min(t)
|
|
};
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
x += 1;
|
|
}
|
|
}
|
|
|
|
if d > 0.0 {
|
|
player.x += d;
|
|
} else {
|
|
player.dx = 0.0;
|
|
}
|
|
} else if player.dx < 0.0 {
|
|
let p = player.x;
|
|
let mut d = player.dx;
|
|
|
|
for y in range(intersect.y, intersect.y + intersect.h + 1) {
|
|
let mut x = intersect.x;
|
|
|
|
loop {
|
|
let t = (x * TILE_WIDTH + TILE_WIDTH) as f32 - p;
|
|
|
|
if t < d {
|
|
break;
|
|
}
|
|
|
|
if let Some(tile) = layer.get_tile(x, y) {
|
|
d = match *tile {
|
|
Tile::Empty => d,
|
|
Tile::Floor(_) => d.max(t)
|
|
};
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
x -= 1;
|
|
}
|
|
}
|
|
|
|
if d < 0.0 {
|
|
player.x += d;
|
|
} else {
|
|
player.dx = 0.0;
|
|
}
|
|
}
|
|
|
|
if player.dy > 0.0 {
|
|
let p = player.y + player.h as f32;
|
|
let mut d = player.dy;
|
|
|
|
for x in range(intersect.x, intersect.x + intersect.w + 1) {
|
|
let mut y = intersect.y;
|
|
|
|
loop {
|
|
let t = (y * TILE_HEIGHT) as f32 - p;
|
|
|
|
if t > d {
|
|
break;
|
|
}
|
|
|
|
if let Some(tile) = layer.get_tile(x, y) {
|
|
d = match *tile {
|
|
Tile::Empty => d,
|
|
Tile::Floor(_) => d.min(t)
|
|
};
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
y += 1;
|
|
}
|
|
}
|
|
|
|
if d > 0.0 {
|
|
player.y += d;
|
|
} else {
|
|
player.dy = 0.0;
|
|
|
|
player.on_ground = true;
|
|
}
|
|
} else if player.dy < 0.0 {
|
|
let p = player.y;
|
|
let mut d = player.dy;
|
|
|
|
for x in range(intersect.x, intersect.x + intersect.w + 1) {
|
|
let mut y = intersect.y;
|
|
|
|
loop {
|
|
let t = (y * TILE_HEIGHT + TILE_HEIGHT) as f32 - p;
|
|
|
|
if t < d {
|
|
break;
|
|
}
|
|
|
|
if let Some(tile) = layer.get_tile(x, y) {
|
|
d = match *tile {
|
|
Tile::Empty => d,
|
|
Tile::Floor(_) => d.max(t)
|
|
};
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
y -= 1;
|
|
}
|
|
}
|
|
|
|
if d < 0.0 {
|
|
player.y += d;
|
|
} else {
|
|
player.dy = 0.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
camera.center(&player.to_rect());
|
|
|
|
lag -= MS_PER_UPDATE;
|
|
}
|
|
|
|
let _ = renderer.set_draw_color(Color::RGB(0, 0, 0));
|
|
let _ = renderer.clear();
|
|
|
|
layer.for_each_intersecting(&camera.to_rect(), |tile: &Tile, position: &Rect| {
|
|
let object = camera_relative_rect(&camera.to_rect(), position);
|
|
|
|
match *tile {
|
|
Tile::Empty => (),
|
|
Tile::Floor(color) => {
|
|
let _ = renderer.set_draw_color(color);
|
|
let _ = renderer.fill_rect(&object);
|
|
}
|
|
}
|
|
});
|
|
|
|
let player_rect = camera_relative_rect(&camera.to_rect(), &player.to_rect());
|
|
|
|
let _ = renderer.set_draw_color(Color::RGB(0, 255, 0));
|
|
let _ = renderer.fill_rect(&player_rect);
|
|
|
|
renderer.present();
|
|
|
|
delay(5);
|
|
}
|
|
|
|
sdl2::quit();
|
|
}
|
|
|
|
fn camera_relative_rect(camera: &Rect, other: &Rect) -> Rect {
|
|
Rect::new(other.x - camera.x, other.y - camera.y, other.w, other.h)
|
|
}
|