Implement controls

This commit is contained in:
Lior Halphon 2023-01-14 15:02:34 +02:00
parent 7624688e3b
commit 3e75016fe0
3 changed files with 182 additions and 56 deletions

8
iOS/GBBackgroundView.h Normal file
View File

@ -0,0 +1,8 @@
#import <UIKit/UIKit.h>
#import "GBLayout.h"
#import "GBView.h"
@interface GBBackgroundView : UIImageView
@property (readonly) GBView *gbView;
@property (nonatomic) GBLayout *layout;
@end

165
iOS/GBBackgroundView.m Normal file
View File

@ -0,0 +1,165 @@
#import "GBBackgroundView.h"
#import "GBViewMetal.h"
double CGPointSquaredDistance(CGPoint a, CGPoint b)
{
double deltaX = a.x - b.x;
double deltaY = a.y - b.y;
return deltaX * deltaX + deltaY * deltaY;
}
double CGPointAngle(CGPoint a, CGPoint b)
{
double deltaX = a.x - b.x;
double deltaY = a.y - b.y;
return atan2(deltaY, deltaX);
}
static void positionView(UIImageView *view, CGPoint position)
{
double center = view.image.size.width / 2 * [UIScreen mainScreen].scale;
view.frame = (CGRect){
{
round(position.x - center) / [UIScreen mainScreen].scale,
round(position.y - center) / [UIScreen mainScreen].scale
},
view.image.size
};
}
@implementation GBBackgroundView
{
NSMutableSet<UITouch *> *_touches;
UIImageView *_dpadView;
UIImageView *_aButtonView;
UIImageView *_bButtonView;
UIImageView *_startButtonView;
UIImageView *_selectButtonView;
}
- (instancetype)init
{
self = [super initWithImage:nil];
if (!self) return nil;
_touches = [NSMutableSet set];
_dpadView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"dpad"]];
_aButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button"]];
_bButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button"]];
_startButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button2"]];
_selectButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button2"]];
_gbView = [[GBViewMetal alloc] initWithFrame:CGRectZero];
[self addSubview:_dpadView];
[self addSubview:_aButtonView];
[self addSubview:_bButtonView];
[self addSubview:_startButtonView];
[self addSubview:_selectButtonView];
[self addSubview:_gbView];
return self;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[_touches unionSet:touches];
[self touchesChanged];
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[_touches minusSet:touches];
[self touchesChanged];
}
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[_touches minusSet:touches];
[self touchesChanged];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self touchesChanged];
}
- (void)touchesChanged
{
if (!GB_is_inited(_gbView.gb)) return;
GB_key_mask_t mask = 0;
double factor = [UIScreen mainScreen].scale;
double buttonRadiusSquared = 36 * 36 * factor * factor;
double dpadRadiusSquared = 75 * 75 * factor * factor;
for (UITouch *touch in _touches) {
CGPoint point = [touch locationInView:self];
point.x *= factor;
point.y *= factor;
if (CGPointSquaredDistance(point, _layout.aLocation) <= buttonRadiusSquared) {
mask |= GB_KEY_A_MASK;
}
else if (CGPointSquaredDistance(point, _layout.bLocation) <= buttonRadiusSquared) {
mask |= GB_KEY_B_MASK;
}
else if (CGPointSquaredDistance(point, _layout.startLocation) <= buttonRadiusSquared) {
mask |= GB_KEY_START_MASK;
}
else if (CGPointSquaredDistance(point, _layout.selectLocation) <= buttonRadiusSquared) {
mask |= GB_KEY_SELECT_MASK;
}
else if (CGPointSquaredDistance(point, _layout.dpadLocation) <= dpadRadiusSquared) {
double angle = CGPointAngle(point, _layout.dpadLocation);
signed quantizedAngle = round(angle / M_PI * 6);
if (quantizedAngle < 0) {
quantizedAngle += 12;
}
switch (quantizedAngle) {
case 0 : mask |= GB_KEY_RIGHT_MASK; break;
case 1 : mask |= GB_KEY_RIGHT_MASK | GB_KEY_DOWN_MASK; break;
case 2 : mask |= GB_KEY_DOWN_MASK; break;
case 3 : mask |= GB_KEY_DOWN_MASK; break;
case 4 : mask |= GB_KEY_LEFT_MASK | GB_KEY_DOWN_MASK; break;
case 6 : mask |= GB_KEY_LEFT_MASK; break;
case 7 : mask |= GB_KEY_LEFT_MASK; break;
case 8 : mask |= GB_KEY_LEFT_MASK | GB_KEY_UP_MASK; break;
case 9 : mask |= GB_KEY_UP_MASK; break;
case 10: mask |= GB_KEY_UP_MASK; break;
case 11: mask |= GB_KEY_RIGHT_MASK | GB_KEY_UP_MASK; break;
case 12: mask |= GB_KEY_RIGHT_MASK; break;
}
}
}
GB_set_key_mask(_gbView.gb, mask);
}
- (BOOL)isMultipleTouchEnabled
{
return true;
}
- (BOOL)isUserInteractionEnabled
{
return true;
}
- (void)setLayout:(GBLayout *)layout
{
_layout = layout;
self.image = layout.background;
positionView(_dpadView, layout.dpadLocation);
positionView(_aButtonView, layout.aLocation);
positionView(_bButtonView, layout.bLocation);
positionView(_startButtonView, layout.startLocation);
positionView(_selectButtonView, layout.selectLocation);
CGRect screenFrame = layout.screenRect;
screenFrame.origin.x /= [UIScreen mainScreen].scale;
screenFrame.origin.y /= [UIScreen mainScreen].scale;
screenFrame.size.width /= [UIScreen mainScreen].scale;
screenFrame.size.height /= [UIScreen mainScreen].scale;
_gbView.frame = screenFrame;
}
@end

View File

@ -5,6 +5,7 @@
#import "GBAudioClient.h"
#import "GBROMManager.h"
#import "GBLoadROMTableViewController.h"
#import "GBBackgroundView.h"
#include <Core/gb.h>
@implementation GBViewController
@ -14,15 +15,9 @@
volatile bool _running;
volatile bool _stopping;
bool _romLoaded;
GBLayout *_currentLayout;
GBHorizontalLayout *_horizontalLayout;
GBVerticalLayout *_verticalLayout;
UIImageView *_backgroundView;
UIImageView *_dpadView;
UIImageView *_aButtonView;
UIImageView *_bButtonView;
UIImageView *_startButtonView;
UIImageView *_selectButtonView;
GBBackgroundView *_backgroundView;
NSCondition *_audioLock;
GB_sample_t *_audioBuffer;
size_t _audioBufferSize;
@ -31,19 +26,6 @@
GBAudioClient *_audioClient;
}
static void positionView(UIImageView *view, CGPoint position)
{
double center = view.image.size.width / 2 * [UIScreen mainScreen].scale;
view.frame = (CGRect){
{
round(position.x - center) / [UIScreen mainScreen].scale,
round(position.y - center) / [UIScreen mainScreen].scale
},
view.image.size
};
}
static void loadBootROM(GB_gameboy_t *gb, GB_boot_rom_t type)
{
GBViewController *self = (__bridge GBViewController *)GB_get_user_data(gb);
@ -114,30 +96,19 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp)
_horizontalLayout = [[GBHorizontalLayout alloc] init];
_verticalLayout = [[GBVerticalLayout alloc] init];
_backgroundView = [[UIImageView alloc] initWithImage:nil];
_backgroundView = [[GBBackgroundView alloc] init];
[_window addSubview:_backgroundView];
self.view = _backgroundView;
_dpadView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"dpad"]];
_aButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button"]];
_bButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button"]];
_startButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button2"]];
_selectButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button2"]];
_gbView = [[GBViewMetal alloc] initWithFrame:CGRectZero];
[self initGameBoy];
_gbView = _backgroundView.gbView;
_gbView.gb = &_gb;
[_gbView screenSizeChanged];
[self willRotateToInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation
duration:0];
[_backgroundView addSubview:_dpadView];
[_backgroundView addSubview:_aButtonView];
[_backgroundView addSubview:_bButtonView];
[_backgroundView addSubview:_startButtonView];
[_backgroundView addSubview:_selectButtonView];
[_backgroundView addSubview:_gbView];
_audioLock = [[NSCondition alloc] init];
@ -179,30 +150,12 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp)
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration
{
GBLayout *layout = _horizontalLayout;
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
_currentLayout = _verticalLayout;
layout = _verticalLayout;
}
else {
_currentLayout = _horizontalLayout;
}
_backgroundView.image = _currentLayout.background;
_backgroundView.frame = [_currentLayout viewRectForOrientation:[UIApplication sharedApplication].statusBarOrientation];
positionView(_dpadView, _currentLayout.dpadLocation);
positionView(_aButtonView, _currentLayout.aLocation);
positionView(_bButtonView, _currentLayout.bLocation);
positionView(_startButtonView, _currentLayout.startLocation);
positionView(_selectButtonView, _currentLayout.selectLocation);
CGRect screenFrame = _currentLayout.screenRect;
screenFrame.origin.x /= [UIScreen mainScreen].scale;
screenFrame.origin.y /= [UIScreen mainScreen].scale;
screenFrame.size.width /= [UIScreen mainScreen].scale;
screenFrame.size.height /= [UIScreen mainScreen].scale;
_gbView.frame = screenFrame;
[_gbView flip];
_backgroundView.frame = [layout viewRectForOrientation:orientation];
_backgroundView.layout = layout;
}
- (BOOL)prefersHomeIndicatorAutoHidden