我正在使用Mac OS上的SpriteKit为MIDI击鼓创建一个节奏应用程序。 Note
个对象是下面的绿色和蓝色的对象。音符在屏幕上从右向左移动。随着音符越来越接近红色的“游戏栏”,我想在游戏栏旁边创建音符的轮廓,以向用户表明音符越来越接近游戏栏并且是时候玩了
我需要每个Note
对象在距离播放头一定距离时通知另一个名为Sequencer
的类,以便它可以为最近的音符开始音符轮廓动画。这些音符知道它们距离游戏头有多远,所以这不是问题。 代表团是否会成为这种情况的候选人?我试图了解授权的目的,但我永远无法弄清楚如何将其实施到我与游戏相关的具体情况中。
编辑:已添加代码
GameScene.m
@implementation GameScene
- (void)didMoveToView:(SKView *)view {
...
[self initSequence];
[self initNoteProcessor];
[self initPlayBar];
...
}
...
//keeps track of a collection of notes and vertical line measure markers and
//responsible for drawing them in scene and moving them left
-(void) initSequence {
_sequence = [[Sequencer alloc] initWithWidth:1150];
[_sequence setPosition:CGPointMake(130, 0)];
[self addChild:_sequence];
}
...
//responsible for handling incoming MIDI input from a keyboard and checking to see
//if notes are played on time, early or late
-(void) initNoteProcessor {
_noteProcessor = [[NoteProcessor alloc] initWithSequence:_sequence];
}
...
//creates a vertical line that indicates when notes need to be played
-(void) initPlayBar {
_playBar = (SKSpriteNode*)[self childNodeWithName:@"playBar"];
_playBar.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_playBar.frame.size];
_playBar.physicsBody.affectedByGravity = NO;
[_playBar.physicsBody setDynamic:YES];
[_playBar.physicsBody setAllowsRotation:NO];
[_playBar.physicsBody setCategoryBitMask:kPlayBarCategory];
[_playBar.physicsBody setCollisionBitMask:kNoCategory];
[_playBar.physicsBody setContactTestBitMask:kNoteCategory | kLineCategory];
[[NSUserDefaults standardUserDefaults] setDouble:_playBar.position.x forKey:@"playBarXPosition"];
}
的 NoteProcessor.m
@implementation NoteProcessor
-(instancetype) initWithSequence:(Sequencer*)sequence {
if (self = [super init]) {
_sequence = sequence;
_noteActiveIndex = 0;
[self initActiveNoteIndices];
[self initNoteIndicator];
//when user plays key on keyboard, notify this class
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(midiPlayed:) name:@"MidiPlayedNotificationKey" object:nil];
}
return self;
}
//keeps track of the next note of each pitch that is incoming
-(void) initActiveNoteIndices {
_activeNoteIndicesByPitch = [NSMutableArray array];
for (int i = 0; i < kTotalKeys; i++) {
[_activeNoteIndicesByPitch addObject:[NSNumber numberWithInteger:0]];
}
}
//checks position of note and decides whether they are on time, early or late
-(void) updateCurrentNoteStatus {
...
}
//handles notifications from MIDI keyboard when user plays a key
-(void) midiPlayed:(NSNotification*)notification {
//stuff happens here
}
@end
的 Sequencer.m
@implementation Sequencer
-(instancetype) initWithWidth:(double)width {
if (self = [super init]) {
...
[self drawNotes];
}
return self;
}
//draws all of the notes on screen
-(void) drawNotes {
NSMutableArray *parsedNotes = [_midiParser getNoteData];
float distancePerBeat = [self getGridArea] / [self getMeasuresDisplayed] / 4;
float xPos = 0;
for (int i = 0; i < [parsedNotes count]; i++) {
NSArray *currNote = [parsedNotes objectAtIndex:i];
double location = [[currNote objectAtIndex:0] doubleValue];
double duration = [[currNote objectAtIndex:1] doubleValue];
int midiValue = [[currNote objectAtIndex:2] intValue];
Note *note = [[Note alloc] initWithLocation:location Duration:duration MidiValue:midiValue];
xPos = distancePerBeat * (location - 1);
float yPos = kNoteHeight[note.midiValue - 36];
[note setPosition:CGPointMake(xPos, yPos)];
[note setZPosition:kNoteZPosition];
NSMutableArray *noteList = [_notes objectAtIndex:midiValue-36];
[noteList addObject:note];
[self addChild:note];
}
}
//this method is called 60 times per second
//each call moves 1/60th of the distance it would move in 1/60th of a second
-(void) moveLeftAfterElapsedTime:(double)elapsedTime {
double timePerBeat = 60 / [self getBpm];
double timePerMeasure = timePerBeat * 4;
double lengthPerMeasure = [self getGridArea] / [self getMeasuresDisplayed];
double distancePerFrame = lengthPerMeasure / (timePerMeasure * 60);
double x = elapsedTime * distancePerFrame * 60;
[self moveAllNotesLeftByDistance:x];
}
//actually does all of the moving of the notes
-(void) moveAllNotesLeftByDistance:(double)distance {
for (int i = 0; i < [_notes count]; i++) {
NSMutableArray *noteList = [_notes objectAtIndex:i];
for (int j = 0; j < [noteList count]; j++) {
Note *note = [noteList objectAtIndex:j];
double xPos = note.position.x - distance;
double y = note.position.y;
[note setPosition:CGPointMake(xPos, y)];
}
}
}