Browse Source

Fixing .gitignore
Adding engine module for engine dispatching.
Current features:
- Runs up to a certain framerate (doing nothing)
- Defines mouse/keyboard events (need mouse_drag, mouse_move?)
- Defines a mapping scheme between raw keyboard input and an enumeration of key identities
- Discards any unmapped keyboard input
- Abstract scene type, represents an interactable system.
- Typedefs/bindings for time points. Including FPS literals
- game_dispatch provides the following features
- Maps mouse/keyboard into local-world in order to abstract the bindings/screen size away
- throttles framerate with sleep if it goes faster than the 'minimum_frame_duration' variable.

Samuel Jaffe 9 years ago
parent
commit
aa050792b9

+ 1 - 1
.gitignore

@@ -1 +1 @@
-.*_tc.cpp
+*_tc.cpp

+ 289 - 0
engine/engine.xcodeproj/project.pbxproj

@@ -0,0 +1,289 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		CD2973951D7B117E00E37217 /* time.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD2973931D7B117E00E37217 /* time.cpp */; };
+		CD2973961D7B117E00E37217 /* time.hpp in Headers */ = {isa = PBXBuildFile; fileRef = CD2973941D7B117E00E37217 /* time.hpp */; };
+		CDB1F8C81D7A312B00700C6B /* game_dispatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDB1F8C61D7A312B00700C6B /* game_dispatch.cpp */; };
+		CDB1F8C91D7A312B00700C6B /* game_dispatch.hpp in Headers */ = {isa = PBXBuildFile; fileRef = CDB1F8C71D7A312B00700C6B /* game_dispatch.hpp */; };
+		CDB1F8CC1D7A319A00700C6B /* scene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDB1F8CA1D7A319A00700C6B /* scene.cpp */; };
+		CDB1F8CD1D7A319A00700C6B /* scene.hpp in Headers */ = {isa = PBXBuildFile; fileRef = CDB1F8CB1D7A319A00700C6B /* scene.hpp */; };
+		CDB1F8D21D7A32A300700C6B /* events.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDB1F8D01D7A32A300700C6B /* events.cpp */; };
+		CDB1F8D31D7A32A300700C6B /* events.hpp in Headers */ = {isa = PBXBuildFile; fileRef = CDB1F8D11D7A32A300700C6B /* events.hpp */; };
+		CDB1F8D51D7A32F800700C6B /* engine_fwd.hpp in Headers */ = {isa = PBXBuildFile; fileRef = CDB1F8D41D7A32F800700C6B /* engine_fwd.hpp */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		CD2973931D7B117E00E37217 /* time.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = time.cpp; sourceTree = "<group>"; };
+		CD2973941D7B117E00E37217 /* time.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = time.hpp; sourceTree = "<group>"; };
+		CDB1F8AE1D7A30CD00700C6B /* libengine.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libengine.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		CDB1F8C61D7A312B00700C6B /* game_dispatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = game_dispatch.cpp; sourceTree = "<group>"; };
+		CDB1F8C71D7A312B00700C6B /* game_dispatch.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = game_dispatch.hpp; sourceTree = "<group>"; };
+		CDB1F8CA1D7A319A00700C6B /* scene.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scene.cpp; sourceTree = "<group>"; };
+		CDB1F8CB1D7A319A00700C6B /* scene.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = scene.hpp; sourceTree = "<group>"; };
+		CDB1F8D01D7A32A300700C6B /* events.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = events.cpp; sourceTree = "<group>"; };
+		CDB1F8D11D7A32A300700C6B /* events.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = events.hpp; sourceTree = "<group>"; };
+		CDB1F8D41D7A32F800700C6B /* engine_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = engine_fwd.hpp; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		CDB1F8AB1D7A30CD00700C6B /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		CDB1F8A51D7A30CD00700C6B = {
+			isa = PBXGroup;
+			children = (
+				CDB1F8B01D7A30CD00700C6B /* src */,
+				CDB1F8AF1D7A30CD00700C6B /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		CDB1F8AF1D7A30CD00700C6B /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				CDB1F8AE1D7A30CD00700C6B /* libengine.dylib */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		CDB1F8B01D7A30CD00700C6B /* src */ = {
+			isa = PBXGroup;
+			children = (
+				CDB1F8D41D7A32F800700C6B /* engine_fwd.hpp */,
+				CDB1F8C61D7A312B00700C6B /* game_dispatch.cpp */,
+				CDB1F8C71D7A312B00700C6B /* game_dispatch.hpp */,
+				CDB1F8CA1D7A319A00700C6B /* scene.cpp */,
+				CDB1F8CB1D7A319A00700C6B /* scene.hpp */,
+				CDB1F8D01D7A32A300700C6B /* events.cpp */,
+				CDB1F8D11D7A32A300700C6B /* events.hpp */,
+				CD2973931D7B117E00E37217 /* time.cpp */,
+				CD2973941D7B117E00E37217 /* time.hpp */,
+			);
+			name = src;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		CDB1F8AC1D7A30CD00700C6B /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CDB1F8C91D7A312B00700C6B /* game_dispatch.hpp in Headers */,
+				CDB1F8D31D7A32A300700C6B /* events.hpp in Headers */,
+				CDB1F8D51D7A32F800700C6B /* engine_fwd.hpp in Headers */,
+				CD2973961D7B117E00E37217 /* time.hpp in Headers */,
+				CDB1F8CD1D7A319A00700C6B /* scene.hpp in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		CDB1F8AD1D7A30CD00700C6B /* engine */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CDB1F8B91D7A30CD00700C6B /* Build configuration list for PBXNativeTarget "engine" */;
+			buildPhases = (
+				CDB1F8AA1D7A30CD00700C6B /* Sources */,
+				CDB1F8AB1D7A30CD00700C6B /* Frameworks */,
+				CDB1F8AC1D7A30CD00700C6B /* Headers */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = engine;
+			productName = engine;
+			productReference = CDB1F8AE1D7A30CD00700C6B /* libengine.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		CDB1F8A61D7A30CD00700C6B /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0720;
+				ORGANIZATIONNAME = "Sam Jaffe";
+				TargetAttributes = {
+					CDB1F8AD1D7A30CD00700C6B = {
+						CreatedOnToolsVersion = 7.2.1;
+					};
+				};
+			};
+			buildConfigurationList = CDB1F8A91D7A30CD00700C6B /* Build configuration list for PBXProject "engine" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = CDB1F8A51D7A30CD00700C6B;
+			productRefGroup = CDB1F8AF1D7A30CD00700C6B /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				CDB1F8AD1D7A30CD00700C6B /* engine */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+		CDB1F8AA1D7A30CD00700C6B /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CD2973951D7B117E00E37217 /* time.cpp in Sources */,
+				CDB1F8D21D7A32A300700C6B /* events.cpp in Sources */,
+				CDB1F8CC1D7A319A00700C6B /* scene.cpp in Sources */,
+				CDB1F8C81D7A312B00700C6B /* game_dispatch.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		CDB1F8B71D7A30CD00700C6B /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		CDB1F8B81D7A30CD00700C6B /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		CDB1F8BA1D7A30CD00700C6B /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				EXECUTABLE_PREFIX = lib;
+				GCC_ENABLE_CPP_EXCEPTIONS = YES;
+				GCC_ENABLE_CPP_RTTI = YES;
+				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				USER_HEADER_SEARCH_PATHS = ".. ../include";
+			};
+			name = Debug;
+		};
+		CDB1F8BB1D7A30CD00700C6B /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				EXECUTABLE_PREFIX = lib;
+				GCC_ENABLE_CPP_EXCEPTIONS = YES;
+				GCC_ENABLE_CPP_RTTI = YES;
+				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				USER_HEADER_SEARCH_PATHS = ".. ../include";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		CDB1F8A91D7A30CD00700C6B /* Build configuration list for PBXProject "engine" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CDB1F8B71D7A30CD00700C6B /* Debug */,
+				CDB1F8B81D7A30CD00700C6B /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		CDB1F8B91D7A30CD00700C6B /* Build configuration list for PBXNativeTarget "engine" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CDB1F8BA1D7A30CD00700C6B /* Debug */,
+				CDB1F8BB1D7A30CD00700C6B /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = CDB1F8A61D7A30CD00700C6B /* Project object */;
+}

+ 29 - 0
engine/engine_fwd.hpp

@@ -0,0 +1,29 @@
+//
+//  engine_fwd.hpp
+//  engine
+//
+//  Created by Sam Jaffe on 9/2/16.
+//
+
+#pragma once
+
+#include <string>
+#include <unordered_map>
+
+namespace engine {
+  using raw_key_t = int;
+  using key_enum_t = int;
+  using scene_id_t = std::string;
+  
+  using key_binding = std::unordered_map<raw_key_t, key_enum_t>;
+
+  class game_dispatch;
+  class scene;
+  
+  namespace event {
+    struct key_event;
+    struct mouse_event;
+  }
+  
+  struct tick;
+}

+ 8 - 0
engine/events.cpp

@@ -0,0 +1,8 @@
+//
+//  events.cpp
+//  engine
+//
+//  Created by Sam Jaffe on 9/2/16.
+//
+
+#include "events.hpp"

+ 50 - 0
engine/events.hpp

@@ -0,0 +1,50 @@
+//
+//  events.hpp
+//  engine
+//
+//  Created by Sam Jaffe on 9/2/16.
+//
+
+#pragma once
+
+#include "engine_fwd.hpp"
+#include "math/math_fwd.hpp"
+#include "math/vector.hpp"
+
+namespace engine {
+  namespace key {
+    enum default_keys : key_enum_t {
+      FORWARD,
+      LEFT,
+      BACKWARD,
+      RIGHT,
+      JUMP,
+      CROUCH,
+      INTERACT,
+      QUIT
+    };
+  }
+  
+  namespace event {
+    enum event_type {
+      PRESSED_MASK   = 0x1,
+      RELEASED_MASK  = 0x2,
+      KEY_MASK       = 0x4,
+      MOUSE_MASK     = 0x8,
+      KEY_PRESSED    = KEY_MASK   | PRESSED_MASK ,
+      KEY_RELEASED   = KEY_MASK   | RELEASED_MASK,
+      MOUSE_PRESSED  = MOUSE_MASK | PRESSED_MASK ,
+      MOUSE_RELEASED = MOUSE_MASK | RELEASED_MASK
+    };
+    
+    struct key_event {
+      key_enum_t key;
+      event_type type;
+    };
+    
+    struct mouse_event {
+      math::vec2 current_mouse_position;
+      event_type type;
+    };
+  }
+}

+ 93 - 0
engine/game_dispatch.cpp

@@ -0,0 +1,93 @@
+//
+//  game_dispatch.cpp
+//  gameutils
+//
+//  Created by Sam Jaffe on 9/2/16.
+//
+
+#include <thread>
+
+#include "game_dispatch.hpp"
+
+#include "events.hpp"
+#include "scene.hpp"
+
+namespace engine {
+  namespace {
+    event::event_type mask( event::event_type t, bool pressed ) {
+      return static_cast<event::event_type>( t | ( pressed ? event::PRESSED_MASK : event::RELEASED_MASK ) );
+    }
+  }
+  
+  game_dispatch::game_dispatch( )
+  : screen_size( { 1920.f, 1080.f } )
+  , minimum_frame_duration( engine::FPS60 )
+  , scenes( )
+  , current_timestamp( clock::now( ) )
+  , curr_scene( ) {
+    
+  }
+  
+  game_dispatch::current_scene_info::current_scene_info( ) {
+    
+  }
+  
+  game_dispatch::current_scene_info::current_scene_info( scene * curr )
+  : ptr( curr )
+  , current_scene_id( ptr->id )
+  , local_size( ptr->get_size( ) ) {
+    
+  }
+  
+  void game_dispatch::process_key_event( raw_key_t key, bool press ) {
+    if ( ! curr_scene.is_keyboard_event ) return;
+    auto const & binding = curr_scene.ptr->get_binding( );
+    auto it = binding.find( key );
+    if ( it == binding.end( ) ) return;
+
+    curr_scene.ptr->handle_key_event( {
+      it->second,
+      mask( event::KEY_MASK, press )
+    } );
+  }
+  
+  void game_dispatch::process_mouse_event( math::vec2 mouse_pos, bool press ) {
+    if ( ! curr_scene.is_mouse_event ) return;
+    math::vec2 local_scene_position = mouse_pos * curr_scene.local_size / screen_size;
+
+    curr_scene.ptr->handle_mouse_event( {
+      local_scene_position,
+      mask( event::MOUSE_MASK, press )
+    } );
+  }
+  
+  tick game_dispatch::get_tick( ) {
+    timestamp now = clock::now( );
+    return { now, now - current_timestamp };
+  }
+  
+  tick game_dispatch::next_frame( ) {
+    tick t = get_tick( );
+    
+    while ( t.since < minimum_frame_duration ) {
+      std::this_thread::sleep_for( minimum_frame_duration - t.since );
+      t = get_tick( );
+    }
+    
+    current_timestamp = t.now;
+    return t;
+  }
+  
+  void game_dispatch::gameloop( ) try {
+    while ( running ) { single_frame( next_frame( ) ); }
+    cleanup_resources( );
+    exit( EXIT_SUCCESS );
+  } catch ( std::exception const & ex ) {
+    // todo: logging
+    exit( EXIT_FAILURE );
+  }
+  
+  void game_dispatch::quit( ) {
+    running = false;
+  }
+}

+ 56 - 0
engine/game_dispatch.hpp

@@ -0,0 +1,56 @@
+//
+//  game_dispatch.hpp
+//  gameutils
+//
+//  Created by Sam Jaffe on 9/2/16.
+//
+
+#pragma once
+
+#include <chrono>
+#include <memory>
+#include <unordered_map>
+
+#include "time.hpp"
+#include "engine_fwd.hpp"
+#include "events.hpp"
+#include "math/math_fwd.hpp"
+#include "math/vector.hpp"
+
+namespace engine {
+  class game_dispatch {
+  public:
+    game_dispatch( );
+    
+    void process_key_event( raw_key_t key, bool press );
+    void process_mouse_event( math::vec2 click, bool press );
+    
+    [[noreturn]] void gameloop( );
+    void quit( );
+  private:
+    void single_frame( tick t ) { }
+    tick get_tick( );
+    tick next_frame( );
+    void cleanup_resources( ) { } // TODO ???
+  private:
+    math::vec2 screen_size;
+    duration minimum_frame_duration;
+
+    using scene_t = std::unique_ptr<scene>;
+    std::unordered_map<scene_id_t, scene_t> scenes;
+    
+    bool running = true;
+    timestamp current_timestamp;
+    struct current_scene_info {
+      current_scene_info( );
+      current_scene_info( scene * );
+      
+      scene * ptr; // weak
+      
+      std::string current_scene_id; // metadata
+      math::vec2 local_size; // metadata
+      bool is_mouse_event;
+      bool is_keyboard_event;
+    } curr_scene;
+  };
+}

+ 44 - 0
engine/scene.cpp

@@ -0,0 +1,44 @@
+//
+//  scene.cpp
+//  engine
+//
+//  Created by Sam Jaffe on 9/2/16.
+//
+
+#include "scene.hpp"
+
+#include "events.hpp"
+#include "game_dispatch.hpp"
+
+namespace engine {
+  
+  
+  scene::~scene( ) { }
+  
+  void scene::update( tick ) {
+    
+  }
+  
+  void scene::render( ) {
+    
+  }
+  
+  void scene::handle_key_event( event::key_event evt ) {
+    if ( evt.type & event::PRESSED_MASK &&
+        evt.key == key::QUIT ) {
+      dispatch.lock()->quit( );
+    }
+  }
+  
+  void scene::handle_mouse_event( event::mouse_event evt ) {
+    
+  }
+  
+  math::vec2 scene::get_size( ) const {
+    return local_scene_dimension;
+  }
+  
+  key_binding const & scene::get_binding( ) const {
+    return keys;
+  }
+}

+ 37 - 0
engine/scene.hpp

@@ -0,0 +1,37 @@
+//
+//  scene.hpp
+//  engine
+//
+//  Created by Sam Jaffe on 9/2/16.
+//
+
+#pragma once
+
+#include <memory>
+
+#include "engine_fwd.hpp"
+#include "math/math_fwd.hpp"
+#include "math/vector.hpp"
+#include "util/identity.hpp"
+
+namespace engine {  
+  class scene : public identity<scene, std::string> {
+  public:
+    using identity<scene, std::string>::identity;
+    virtual ~scene( );
+    
+    virtual void update( tick );
+    virtual void render( );
+    virtual void handle_key_event( event::key_event evt );
+    virtual void handle_mouse_event( event::mouse_event evt );
+    
+    math::vec2 get_size( ) const;
+    key_binding const & get_binding( ) const;
+  protected:
+    void change_scene( std::string const & scene_id );
+  private:
+    math::vec2 local_scene_dimension;
+    key_binding keys;
+    std::weak_ptr<game_dispatch> dispatch;
+  };
+}

+ 18 - 0
engine/time.cpp

@@ -0,0 +1,18 @@
+//
+//  time.cpp
+//  engine
+//
+//  Created by Sam Jaffe on 9/3/16.
+//
+
+#include "time.hpp"
+
+namespace engine {
+  using std::chrono::duration_cast;
+  using std::chrono::nanoseconds;
+  
+  duration const FPS30 { nanoseconds{ 33333333 } };
+  duration const FPS60 { nanoseconds{ 16666666 } };
+  duration const FPS120{ nanoseconds{  8333333 } };
+  duration const FPS144{ nanoseconds{  6944444 } };
+}

+ 26 - 0
engine/time.hpp

@@ -0,0 +1,26 @@
+//
+//  time.hpp
+//  engine
+//
+//  Created by Sam Jaffe on 9/3/16.
+//
+
+#pragma once
+
+#include <chrono>
+
+namespace engine {
+  using clock = std::chrono::steady_clock;
+  using timestamp = std::chrono::time_point<clock>;
+  using duration = clock::duration;
+  
+  extern duration const FPS30;
+  extern duration const FPS60;
+  extern duration const FPS120;
+  extern duration const FPS144;
+  
+  struct tick {
+    timestamp now;
+    duration since;
+  };  
+}

+ 3 - 0
game.xcworkspace/contents.xcworkspacedata

@@ -1,6 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Workspace
    version = "1.0">
+   <FileRef
+      location = "group:engine/engine.xcodeproj">
+   </FileRef>
    <FileRef
       location = "group:util/gameutils.xcodeproj">
    </FileRef>