Browse Source

Failure: Move stateful content into a bridge object.

Sam Jaffe 6 years ago
parent
commit
f538bbe19e

+ 6 - 0
danmaku.xcodeproj/project.pbxproj

@@ -30,6 +30,7 @@
 		CD49F794229C22A800EB8926 /* serial.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD49F793229C22A800EB8926 /* serial.cxx */; };
 		CD49F7B3229C530A00EB8926 /* world.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD49F7B2229C530A00EB8926 /* world.cxx */; };
 		CD7E87A52295FCED00D877FE /* danmakuUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = CD7E87A42295FCED00D877FE /* danmakuUITests.m */; };
+		CDC2CDAE229D56B6000A9E09 /* GameBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDC2CDAD229D56B6000A9E09 /* GameBridge.mm */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -108,6 +109,8 @@
 		CD7E881D22960D9C00D877FE /* gameutils.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = gameutils.xcodeproj; path = ../game/util/gameutils.xcodeproj; sourceTree = "<group>"; };
 		CD7E882922960DBB00D877FE /* math.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = math.xcodeproj; path = ../game/math/math.xcodeproj; sourceTree = "<group>"; };
 		CD7E883322960DBF00D877FE /* graphics.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = graphics.xcodeproj; path = ../game/graphics/graphics.xcodeproj; sourceTree = "<group>"; };
+		CDC2CDAD229D56B6000A9E09 /* GameBridge.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = GameBridge.mm; sourceTree = "<group>"; };
+		CDC2CDB5229D56E9000A9E09 /* GameBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameBridge.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -199,6 +202,8 @@
 				CD7E87872295FCEA00D877FE /* AppDelegate.m */,
 				CD7E878D2295FCEA00D877FE /* GameView.h */,
 				CD7E878E2295FCEA00D877FE /* GameView.mm */,
+				CDC2CDB5229D56E9000A9E09 /* GameBridge.h */,
+				CDC2CDAD229D56B6000A9E09 /* GameBridge.mm */,
 				CD7E87932295FCEC00D877FE /* Assets.xcassets */,
 				CD1C83422298A9F500825C4E /* MainMenu.xib */,
 				CD7E87982295FCED00D877FE /* Info.plist */,
@@ -430,6 +435,7 @@
 				CD49F767229B0A3000EB8926 /* player.cxx in Sources */,
 				CD49F794229C22A800EB8926 /* serial.cxx in Sources */,
 				CD49F783229B194C00EB8926 /* burstshot_pattern.cxx in Sources */,
+				CDC2CDAE229D56B6000A9E09 /* GameBridge.mm in Sources */,
 				CD49F762229B0A0500EB8926 /* enemy.cxx in Sources */,
 				CD49F76A229B0A6C00EB8926 /* bullet.cxx in Sources */,
 				CD49F75F229B09F800EB8926 /* level.cxx in Sources */,

+ 5 - 3
danmaku/AppDelegate.h

@@ -6,15 +6,17 @@
 //  Copyright © 2019 Sam Jaffe. All rights reserved.
 //
 
+#import "GameBridge.h"
 #import "GameView.h"
 
 @interface GameWindow : NSWindow
-
+@property(retain) IBOutlet GameBridge * gamebridge;
 @end
 
 @interface AppDelegate : NSObject <NSApplicationDelegate>
 
-@property (assign) IBOutlet GameWindow *window;
-@property (retain) IBOutlet GameView *gameview;
+@property(assign) IBOutlet GameWindow * window;
+@property(retain) IBOutlet GameView * gameview;
+@property(retain) IBOutlet GameBridge * gamebridge;
 
 @end

+ 8 - 1
danmaku/AppDelegate.m

@@ -10,6 +10,7 @@
 
 @implementation AppDelegate
 
+@synthesize gamebridge;
 @synthesize gameview;
 
 NSWindowStyleMask const resizable = NSWindowStyleMaskResizable;
@@ -17,11 +18,17 @@ NSWindowStyleMask const borderless = NSWindowStyleMaskBorderless;
 
 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
   gameview = [[GameView alloc] initWithFrame:[[self window] frame]];
-  
+
   // Insert code here to initialize your application
   [[self window] setStyleMask:[[self window] styleMask] & ~resizable];
   [[self window] setDelegate:[self gameview]];
   [[self window] makeMainWindow];
+
+  gamebridge = [[GameBridge alloc] init];
+  [[self gameview] setGamebridge:[self gamebridge]];
+  [[self window] setGamebridge:[self gamebridge]];
+
+  [[self gamebridge] refresh];
 }
 
 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app {

+ 21 - 0
danmaku/GameBridge.h

@@ -0,0 +1,21 @@
+//
+//  GameBridge.h
+//  danmaku
+//
+//  Created by Sam Jaffe on 5/28/19.
+//  Copyright © 2019 Sam Jaffe. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+@interface GameBridge : NSObject
+- (id) init;
+
+- (void) pause;
+- (void) unpause;
+- (void) update;
+- (void) render;
+- (void) refresh;
+
+- (void) keyEvent:(int)key down:(BOOL)pressed;
+@end

+ 62 - 0
danmaku/GameBridge.mm

@@ -0,0 +1,62 @@
+//
+//  GameBridge.m
+//  danmaku
+//
+//  Created by Sam Jaffe on 5/28/19.
+//  Copyright © 2019 Sam Jaffe. All rights reserved.
+//
+
+#import "GameBridge.h"
+
+#import <memory>
+
+#include "danmaku/world.hpp"
+#include "game/engine/game_dispatch.hpp"
+#include "game/graphics/renderer.hpp"
+
+@implementation GameBridge {
+  std::shared_ptr<graphics::direct_renderer> renderer;
+  std::shared_ptr<engine::game_dispatch> game;
+}
+
+- (id)init {
+  if (!(self = [super init])) {
+    return nil;
+  }
+  
+  using namespace graphics;
+  renderer = std::make_shared<direct_renderer>(driver::openGL);
+  game = std::make_shared<engine::game_dispatch>(renderer);
+  auto world = danmaku::world::load_world("scripts/level/world.json", game);
+  game->register_scene(world);
+  game->activate_scene("light-1");
+  
+  return self;
+}
+
+- (void) pause {
+  // env::pause_clock();
+}
+
+- (void) unpause {
+  // env::resume_clock();
+}
+
+- (void) update {
+  game->update();
+}
+
+- (void) render {
+  game->render();
+}
+
+- (void) refresh {
+  renderer->clear();
+  game->render();
+}
+
+- (void) keyEvent:(int)key down:(BOOL)pressed {
+  game->process_key_event(key, pressed);
+}
+
+@end

+ 5 - 0
danmaku/GameView.h

@@ -8,7 +8,12 @@
 
 #import <Cocoa/Cocoa.h>
 
+#import "GameBridge.h"
+
 @interface GameView : NSOpenGLView<NSWindowDelegate>
+
+@property (retain) IBOutlet GameBridge *gamebridge;
+
 - (void) press_key:(int)key forEvent:(NSEvent *)evt ns_key:(int)local
               down:(BOOL)pressed;
 - (void) toggle_key:(int)key forEvent:(NSEvent *)evt ns_key:(int)local;

+ 28 - 33
danmaku/GameView.mm

@@ -8,22 +8,20 @@
 
 #import "GameView.h"
 
-#include <memory>
-#include <OpenGL/gl3.h>
+#import "AppDelegate.h"
+#import "GameBridge.h"
 
-#include "danmaku/world.hpp"
+#include <OpenGL/gl3.h>
 #include "game/engine/events.hpp"
-#include "game/engine/game_dispatch.hpp"
-#include "game/graphics/renderer.hpp"
+#include "vector/vector.hpp"
 
 namespace env { namespace detail {
   extern void resize_screen(math::vec2i const&);
 }}
 
-@implementation GameView {
-  std::shared_ptr<graphics::direct_renderer> renderer;
-  std::shared_ptr<engine::game_dispatch> game;
-}
+@implementation GameView
+
+@synthesize gamebridge;
 
 - (id)initWithFrame:(NSRect)aRect {
   NSOpenGLPixelFormatAttribute attr[] = {
@@ -42,14 +40,6 @@ namespace env { namespace detail {
     return nil;
   }
 
-  using graphics::direct_renderer;
-  using graphics::driver;
-  renderer = std::make_shared<direct_renderer>(driver::openGL);
-  game = std::make_shared<engine::game_dispatch>(renderer);
-  auto world = danmaku::world::load_world("scripts/level/world.json", game);
-  game->register_scene(world);
-  game->activate_scene("light-1");
-
   // make the context current
   NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat:nsglFormat
                                                         shareContext:nil];
@@ -70,20 +60,26 @@ namespace env { namespace detail {
                      forParameter:NSOpenGLCPSurfaceOpacity];
 }
 
+
+- (void) setScreenSize:(CGSize)dims {
+  [self setScreenWidth:dims.width andHeight:dims.height];
+}
+
+- (void) setScreenWidth:(int)width andHeight:(int)height {
+  env::detail::resize_screen(make_vector(width, height));
+}
+
 - (void)drawRect:(NSRect)dirtyRect {
   //  glClear(GL_COLOR_BUFFER_BIT);
   //  glLoadIdentity();
   
-  env::detail::resize_screen({{(int)dirtyRect.size.width,
-                               (int)dirtyRect.size.height}});
-  if (game) {
-    renderer->clear();
-    game->render();
-  }
+  [self setScreenSize:dirtyRect.size];
+  
   //  glFlush();
   // the correct way to do double buffering on Mac is this:
   [[self openGLContext] flushBuffer];
-  
+  [[self gamebridge] refresh];
+
   int err;
   if ((err = glGetError()) != 0) {
     NSLog(@"glGetError(): %d", err);
@@ -97,13 +93,11 @@ namespace env { namespace detail {
   
   // window resize; width and height are in pixel coordinates
   // but they are floats
-  float screen_w = [self frame].size.width;
-  float screen_h = [self frame].size.height;
   
   //  glViewport(0,0, screen_w, screen_h);
   
   // here I cast floats to ints; most systems use integer coordinate systems
-  env::detail::resize_screen({{(int)screen_w, (int)screen_h}});
+  [self setScreenSize:[self frame].size];
 }
 
 - (BOOL)acceptsFirstResponder {
@@ -113,14 +107,14 @@ namespace env { namespace detail {
 - (void) press_key:(int)key forEvent:(NSEvent *)evt ns_key:(int)local
               down:(BOOL)pressed {
   if ([evt keyCode] == local) {
-    game->process_key_event(key, pressed);
+    [[self gamebridge] keyEvent:key down:pressed];
   }
 }
 
 - (void) toggle_key:(int)key forEvent:(NSEvent *)evt ns_key:(int)local {
   NSUInteger flags = [evt modifierFlags] &
       NSEventModifierFlagDeviceIndependentFlagsMask;
-  game->process_key_event(key, flags & local);
+  [[self gamebridge] keyEvent:key down:(flags & local)];
 }
 
 - (void)keyDown:(NSEvent *)theEvent {
@@ -152,7 +146,7 @@ namespace env { namespace detail {
 
   NSLog(@"keyDown -> { 0x%04x, 0x%08lx, 0x%02x=%c }", [theEvent keyCode],
         [theEvent modifierFlags], c, c);
-  game->process_key_event(c, true);
+  [[self gamebridge] keyEvent:c down:YES];
 }
 
 - (void)keyUp:(NSEvent *)theEvent {
@@ -172,7 +166,7 @@ namespace env { namespace detail {
   [self press_key:LEFT_ARROW forEvent:theEvent ns_key:0x007b down:NO];
   [self press_key:RIGHT_ARROW forEvent:theEvent ns_key:0x007c down:NO];
   
-  game->process_key_event(c, false);
+  [[self gamebridge] keyEvent:c down:NO];
 }
 
 static NSTimer *timer = nil;
@@ -214,18 +208,19 @@ static NSTimeInterval const FRAME_INTERVAL = 1.0 / 60.0;
 }
 
 - (void)renderEvent:(NSTimer *)t {
-  game->render();
+  [[self gamebridge] render];
   [[self openGLContext] flushBuffer];
 }
 
 - (void)timerEvent:(NSTimer *)t {
-  game->update();
+  [[self gamebridge] update];
   [self setNeedsDisplay:YES];
 }
 
 - (void) awakeFromNib
 {
   NSOpenGLPixelFormatAttribute attributes [] = {
+    NSOpenGLPFADoubleBuffer,
     NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)24,
     NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
     (NSOpenGLPixelFormatAttribute)0