| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- //
- // GameScene.m
- // danmaku
- //
- // Created by Sam Jaffe on 5/22/19.
- // Copyright © 2019 Sam Jaffe. All rights reserved.
- //
- #import "GameScene.h"
- #include <OpenGL/gl3.h>
- #include "game/engine/events.hpp"
- #include "GameAdaptor.h"
- @implementation GameScene
- - (id)initWithFrame:(NSRect)aRect {
- NSOpenGLPixelFormatAttribute attr[] = {
- NSOpenGLPFADoubleBuffer,
- 0
- };
-
- // create pixel format
- NSOpenGLPixelFormat *nsglFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
-
- // create the context...
- if (!(self = [super initWithFrame:aRect pixelFormat:nsglFormat])) {
- return nil;
- }
-
- // make the context current
- [[self openGLContext] makeCurrentContext];
-
- // rest of your init method ...
- return self;
- }
- - (void)prepareOpenGL {
- init_gl();
- // enable vertical sychronization to refresh rate
- const GLint vals = 0x01;
- [[self openGLContext] setValues:&vals forParameter:NSOpenGLCPSwapInterval];
-
- const GLint opaque = 0;
- [[self openGLContext] setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
- }
- - (void)drawRect:(NSRect)dirtyRect {
- // glClear(GL_COLOR_BUFFER_BIT);
- // glLoadIdentity();
-
- screen_resize((int)dirtyRect.size.width, (int)dirtyRect.size.height);
- draw_screen();
- // glFlush();
- // the correct way to do double buffering on Mac is this:
- [[self openGLContext] flushBuffer];
-
- int err;
- if ((err = glGetError()) != 0)
- NSLog(@"glGetError(): %d", err);
- }
- - (void)reshape {
- NSRect newFrame = {0, 0, [[self window] frame].size.width, [[self window] frame].size.height};
- [self setFrame:newFrame];
-
- // 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
- screen_resize((int)screen_w, (int)screen_h);
- }
- - (BOOL)acceptsFirstResponder {
- return YES;
- }
- void bind_key_up(NSEvent * evt, int ns_key, int key) {
- if ([evt keyCode] == ns_key) { key_up(key); }
- }
- void bind_key_down(NSEvent * evt, int ns_key, int key) {
- if ([evt keyCode] == ns_key) { key_down(key); }
- }
- void bind_key_toggle(NSEvent * evt, int ns_key, int key) {
- NSUInteger flags = [evt modifierFlags] &
- NSEventModifierFlagDeviceIndependentFlagsMask;
- if (flags & ns_key) {
- key_down(key);
- } else {
- key_up(key);
- }
- }
- - (void)keyDown:(NSEvent *)theEvent {
- if ([theEvent isARepeat])
- return;
-
- NSString *str = [theEvent charactersIgnoringModifiers];
- unichar c = [str characterAtIndex:0];
-
- // only ASCII please
- if (c < ' ' || c > '~') {
- c = 0;
- }
-
- //(unsigned long)[theEvent modifierFlags]
- using namespace engine::keys;
- bind_key_toggle(theEvent, NSEventModifierFlagShift, MOD_SHIFT);
- bind_key_toggle(theEvent, NSEventModifierFlagControl, MOD_CONTROL);
- bind_key_toggle(theEvent, NSEventModifierFlagOption, MOD_ALT);
- bind_key_toggle(theEvent, NSEventModifierFlagCommand, MOD_COMMAND);
- bind_key_down(theEvent, 0x007e, UP_ARROW);
- bind_key_down(theEvent, 0x007d, DOWN_ARROW);
- bind_key_down(theEvent, 0x007b, LEFT_ARROW);
- bind_key_down(theEvent, 0x007c, RIGHT_ARROW);
-
- // NSLog(@"keyDown -> { 0x%04x, 0x%08lx, 0x%02x=%c }", [theEvent keyCode], [theEvent modifierFlags], c, c);
- key_down(c);
- }
- - (void)keyUp:(NSEvent *)theEvent {
- // NSLog(@"keyUp -> { 0x%04x, 0x%08lx }", [theEvent keyCode], [theEvent modifierFlags]);
- NSString *str = [theEvent charactersIgnoringModifiers];
- unichar c = [str characterAtIndex:0];
-
- // only ASCII please
- if (c < ' ' || c > '~') {
- c = 0;
- }
-
- using namespace engine::keys;
- bind_key_up(theEvent, 0x007e, UP_ARROW);
- bind_key_up(theEvent, 0x007d, DOWN_ARROW);
- bind_key_up(theEvent, 0x007b, LEFT_ARROW);
- bind_key_up(theEvent, 0x007c, RIGHT_ARROW);
-
- key_up(c);
- }
- static NSTimer *timer = nil;
- static NSTimer *frameTimer = nil;
- static NSTimeInterval const FRAME_INTERVAL = 1.0 / 60.0;
- - (void)windowDidResignMain:(NSNotification *)notification {
- NSLog(@"window did resign main");
- [timer invalidate];
- [frameTimer invalidate];
-
- game_deactivate(); // freeze, pause
- [self setNeedsDisplay:YES];
- }
- - (void)windowDidBecomeMain:(NSNotification *)notification {
- NSLog(@"window did become main");
-
- game_activate();
- [self setNeedsDisplay:YES];
-
- timer = [NSTimer timerWithTimeInterval:FRAME_INTERVAL
- target:self
- selector:@selector(timerEvent:)
- userInfo:nil
- repeats:YES];
-
- frameTimer = [NSTimer timerWithTimeInterval:FRAME_INTERVAL
- target:self
- selector:@selector(renderEvent:)
- userInfo:nil
- repeats:YES];
-
-
- [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
- [[NSRunLoop currentRunLoop] addTimer:frameTimer forMode:NSDefaultRunLoopMode];
- }
- - (void)renderEvent:(NSTimer *)t {
- draw_screen(); // FIXME
- [[self openGLContext] flushBuffer];
- }
- - (void)timerEvent:(NSTimer *)t {
- run_game();
- [self setNeedsDisplay:YES];
- }
- - (void) awakeFromNib
- {
- NSOpenGLPixelFormatAttribute attributes [] = {
- NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)24,
- NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
- (NSOpenGLPixelFormatAttribute)0
- };
-
- NSOpenGLPixelFormat *pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
- [self setPixelFormat:pf];
- }
- @end
|