mirror of https://github.com/LIJI32/SameBoy.git
Implement controls
This commit is contained in:
parent
7624688e3b
commit
3e75016fe0
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue