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
//! The core 2D game engine built from scratch using SDL for graphics and windowing
//!
//! What the engine does (or should do):
//! Abstracts the event loop
//! Reads keyboard mappings from files
//! Handles keyboard inputs based on the mapping
//! Handles sprite and view rendering
//! Includes a renderer interface to render sprites and backgrounds
//! Uses a grid based map system with scrolling support
//! Loads level maps from text files
//! A point system
//! A main menu rendering system
//!
//! Notes: The coordinate system is so that up is a negative change in the
//! y axis, down is a positive change in the y axis, left is a negative
//! change in the x axis, and right is a positive change in the x axis.

extern crate libc;
extern crate sdl2;
extern crate sdl2_image;
extern crate sdl2_ttf;

#[macro_use]
pub mod block;

pub mod actor_manager;
pub mod cache;
pub mod collision;
pub mod context;
pub mod event_loop;
pub mod events;
pub mod font;
pub mod level;
pub mod quadtree;
pub mod raycast;
pub mod score;
pub mod sprite;
pub mod vector;
pub mod viewport;

pub use actor_manager::{ActorFromToken, ActorManager};
pub use collision::{BoundingBox, Collision, CollisionSide};
pub use context::{Context, Window};
pub use events::Events;
pub use quadtree::Quadtree;
pub use raycast::{Polygon, Segment};
pub use score::Score;
pub use sprite::{AnimatedSprite, Animations, Direction, Renderable, Sprite, Spritesheet,
                 SpritesheetConfig, SpriteRectangle};
pub use vector::{PositionChange, Vector2D};
pub use viewport::Viewport;

use sdl2::rect::Rect;

/// Handler for a view to deal with actor messages
pub type MessageHandler<Type, Message> = Box<Fn(&mut Box<Actor<Type, Message>>,
                                                &mut ActorManager<Type, Message>,
                                                &mut Viewport,
                                                &mut Context,
                                                &Message)>;

/// Actions that the view would want the event loop to do
pub enum ViewAction {
    /// Quit the game
    Quit,
    /// Switch to a different view
    ChangeView(Box<View>),
}

pub trait View {
    /// Called every frame to render a view
    fn render(&mut self, context: &mut Context, elapsed: f64);

    /// Called every frame to update a view
    fn update(&mut self, context: &mut Context, elapsed: f64) -> Option<ViewAction>;
}

/// The data contained in an actor
#[derive(Clone, PartialEq)]
pub struct ActorData<Type> {
    /// The id of the actor given by the actor manager
    pub id: i32,
    /// The current state of the actor as a number
    pub state: u32,
    /// The damage that the actor has taken so far
    pub damage: i32,
    /// A byte that contains the sides that
    /// other actors can collide into
    pub collision_filter: u8,
    /// If true, on collision the actor would be
    /// moved away from the collision
    pub resolves_collisions: bool,
    /// The sprite rectangle
    pub rect: Rect,
    /// The current bounding box for the actor
    pub bounding_box: Option<BoundingBox>,
    /// The type of the actor
    pub actor_type: Type,
}

/// A game object that supports sending and receiving messages
pub trait Actor<Type, Message> {
    /// Called every frame to render an actor
    fn render(&mut self, context: &mut Context, viewport: &mut Viewport, elapsed: f64);

    /// Handle a message sent by another actor
    fn handle_message(&mut self, message: &Message) -> Message;

    /// Returns the side of the collision if actor collides with another actor
    fn collides_with(&mut self, other_actor: &ActorData<Type>) -> Option<CollisionSide>;

    /// Called every frame to update an actor
    fn update(&mut self, context: &mut Context, elapsed: f64) -> PositionChange;

    /// Gets the actor data
    fn data(&mut self) -> ActorData<Type>;
}