如何在 SpriteKit 中使用 UITextView?
How can I use a UITextView in SpriteKit?
所以我在我的游戏中有这个 UITextView,我想通过添加 SKAction 动画 并让它互动来让它更有活力物理学。前者我做的有点 hacky 我不太满意的方式,后者我没做过,因为我不知道怎么做。
这就是我执行 SKActions 的方式:
我做了几个伊娃:
-textViewContent (NSString)
-textViewSize (CGRect)
-textView(UITextView)
-fakeTextView (SKSpriteNode)
由 didMoveToView 调用:
-(void)createTextView {
textViewContent = @"foo";
textViewSize = CGRectMake(CGRectGetMidX(self.frame)-(self.frame.size.width/4),
CGRectGetMidY(self.frame)-(self.frame.size.height/4), self.frame.size.width/2, self.frame.size.height/2);
textView = [[UITextView alloc]initWithFrame:textViewSize];
textView.backgroundColor = [SKColor orangeColor];
textView.text = textViewContent;
textView.textColor = [SKColor whiteColor];
textView.textAlignment = NSTextAlignmentLeft;
textView.font = [UIFont fontWithName:@"Code-Pro-Demo" size:25];
textView.layer.zPosition = -1;
textView.alpha = 0;
textView.editable = NO;
fakeTextView = [SKSpriteNode spriteNodeWithColor:[SKColor orangeColor] size:CGSizeMake(self.frame.size.width/2, self.frame.size.height/2)];
fakeTextView.position = CGPointMake((self.frame.size.width*1.5),CGRectGetMidY(self.frame));
[self addChild:fakeTextView];
[self textViewEntersScene];
}
-(void)textViewEntersScene{
SKAction *wait = [SKAction waitForDuration:0.5];
SKAction *moveIn = [SKAction moveToX:(self.frame.size.width/2) - 100 duration:0.3];
SKAction *moveBackSlightly = [SKAction moveToX:self.frame.size.width/2 duration:0.2];
SKAction *displayTextView = [SKAction runBlock:^{
textView.alpha = 1;
}];
SKAction *hideFakeTextView = [SKAction runBlock:^{
fakeTextView.hidden = YES;
}];
[fakeTextView runAction:[SKAction sequence:@[wait,moveIn,moveBackSlightly,displayTextView,hideFakeTextView]]];
}
如您所知,可能性非常有限。有没有更好的方法来实现这个或类似的东西?
我创建了一个 class 来显示和滚动文本。创建新的 SKNode class.
后,您可以直接复制和粘贴 .h 和 .m 文件
基本上 class 显示 SKLabelNodes 并在超过 1 行时向上滚动它们。线条出现一段时间,如果添加额外的线条则向上移动然后淡出。
它是非常通用的东西,因此您可以在任何项目中随意使用和修改代码。
要使用 class,请导入 header 并使用此代码(示例):
TextBubble *myBubble = [[TextBubble alloc] init];
[myBubble createBubbleWithText:@"Hello this is a very nice day to go fishing and have a cold beer." textSize:24 maxLineLength:20];
myBubble.position = CGPointMake(300, 300);
[self addChild:myBubble];
TextBubble Header 文件
#import <SpriteKit/SpriteKit.h>
@interface TextBubble : SKNode
-(instancetype)init;
-(void)createBubbleWithText:(NSString *)textString textSize:(int)textSize maxLineLength:(int)maxLineLength;
@end
TextBubble 实现文件
#import "TextBubble.h"
@implementation TextBubble {
NSMutableArray *linesArray;
}
- (instancetype)init {
self = [super init];
if (self) {
linesArray = [[NSMutableArray alloc] init];
}
return self;
}
-(void)createBubbleWithText:(NSString *)textString textSize:(int)textSize maxLineLength:(int)maxLineLength {
NSMutableString *passedText = [[NSMutableString alloc] initWithString:textString];
NSMutableString *currentLine = [[NSMutableString alloc] init];
unsigned long characterCounter = 0;
BOOL keepGoing = true;
while (keepGoing) {
NSRange whiteSpaceRange = [passedText rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet]];
if(whiteSpaceRange.location != NSNotFound) {
characterCounter += whiteSpaceRange.location+1;
if(characterCounter <= maxLineLength) {
[currentLine appendString:[passedText substringWithRange:NSMakeRange(0, whiteSpaceRange.location+1)]];
[passedText setString:[passedText substringWithRange:NSMakeRange(whiteSpaceRange.location+1, [passedText length]-whiteSpaceRange.location-1)]];
} else {
[currentLine setString:[currentLine substringWithRange:NSMakeRange(0, [currentLine length]-1)]];
SKLabelNode *myNode = [SKLabelNode labelNodeWithFontNamed:@"Arial-BoldMT"];
myNode.text = [NSString stringWithString:currentLine];
myNode.fontSize = textSize;
myNode.fontColor = [SKColor blueColor];
myNode.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;
myNode.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
myNode.zPosition = 0;
[linesArray addObject:myNode];
characterCounter = 0;
[currentLine setString:@""];
}
} else {
[currentLine appendString:passedText];
SKLabelNode *myNode = [SKLabelNode labelNodeWithFontNamed:@"Arial-BoldMT"];
myNode.text = [NSString stringWithString:currentLine];
myNode.fontSize = textSize;
myNode.fontColor = [SKColor blueColor];
myNode.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;
myNode.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
myNode.zPosition = 0;
[linesArray addObject:myNode];
keepGoing = false;
}
}
if([linesArray count] == 1) {
SKAction *block0 = [SKAction runBlock:^{
SKLabelNode *myNode = [linesArray objectAtIndex:0];
myNode.alpha = 0.0;
[self addChild:myNode];
[myNode runAction:[SKAction fadeAlphaTo:1.0 duration:0.5]];
}];
SKAction *wait1 = [SKAction waitForDuration:2.5];
SKAction *block1 = [SKAction runBlock:^{
SKLabelNode *myNode = [linesArray objectAtIndex:0];
[myNode runAction:[SKAction fadeAlphaTo:0.0 duration:0.5]];
}];
SKAction *wait2 = [SKAction waitForDuration:0.5];
SKAction *block2 = [SKAction runBlock:^{
[[linesArray objectAtIndex:0] removeFromParent];
}];
[self runAction:[SKAction sequence:@[block0, wait1, block1, wait2, block2]]];
}
if([linesArray count] == 2) {
float heightCounter = 0.0;
for (int i = 0; i<[linesArray count]; i++) {
SKAction *wait0 = [SKAction waitForDuration:(2.0 * i)];
SKAction *block0 = [SKAction runBlock:^{
SKLabelNode *myNode = [linesArray objectAtIndex:i];
myNode.alpha = 0.0;
myNode.position = CGPointMake(0, 0);
[self addChild:myNode];
[[linesArray objectAtIndex:i] runAction:[SKAction fadeAlphaTo:1.0 duration:0.5]];
}];
SKAction *wait1 = [SKAction waitForDuration:1.5];
heightCounter += 30;
SKAction *block1 = [SKAction runBlock:^{
[[linesArray objectAtIndex:i] runAction:[SKAction moveToY:heightCounter duration:0.5]];
}];
SKAction *block2 = [SKAction runBlock:^{
[[linesArray objectAtIndex:i] runAction:[SKAction fadeAlphaTo:0.0 duration:0.5]];
}];
SKAction *wait2 = [SKAction waitForDuration:0.5];
SKAction *block3 = [SKAction runBlock:^{
[[linesArray objectAtIndex:i] removeFromParent];
}];
[self runAction:[SKAction sequence:@[wait0, block0, wait1, block1, wait1, block2, wait2, block3]]];
heightCounter = 0;
}
}
if([linesArray count] >= 3) {
float heightCounter = 0.0;
for (int i = 0; i<[linesArray count]; i++) {
SKAction *wait0 = [SKAction waitForDuration:(1.5 * i)];
SKAction *block0 = [SKAction runBlock:^{
SKLabelNode *myNode = [linesArray objectAtIndex:i];
myNode.alpha = 0.0;
myNode.position = CGPointMake(0, 0);
[self addChild:myNode];
[[linesArray objectAtIndex:i] runAction:[SKAction fadeAlphaTo:1.0 duration:0.5]];
}];
SKAction *wait1 = [SKAction waitForDuration:1.5];
heightCounter += 30;
SKAction *block1 = [SKAction runBlock:^{
[[linesArray objectAtIndex:i] runAction:[SKAction moveToY:heightCounter duration:0.5]];
}];
heightCounter += 30;
SKAction *block5 = [SKAction runBlock:^{
[[linesArray objectAtIndex:i] runAction:[SKAction moveToY:heightCounter duration:0.5]];
}];
SKAction *block2 = [SKAction runBlock:^{
[[linesArray objectAtIndex:i] runAction:[SKAction fadeAlphaTo:0.0 duration:0.5]];
}];
SKAction *wait2 = [SKAction waitForDuration:0.5];
SKAction *block3 = [SKAction runBlock:^{
[[linesArray objectAtIndex:i] removeFromParent];
}];
[self runAction:[SKAction sequence:@[wait0, block0, wait1, block1, wait1, block5, wait1, block2, wait2, block3]]];
heightCounter = 0;
}
}
}
@end
所以我在我的游戏中有这个 UITextView,我想通过添加 SKAction 动画 并让它互动来让它更有活力物理学。前者我做的有点 hacky 我不太满意的方式,后者我没做过,因为我不知道怎么做。
这就是我执行 SKActions 的方式:
我做了几个伊娃:
-textViewContent (NSString)
-textViewSize (CGRect)
-textView(UITextView)
-fakeTextView (SKSpriteNode)
由 didMoveToView 调用:
-(void)createTextView {
textViewContent = @"foo";
textViewSize = CGRectMake(CGRectGetMidX(self.frame)-(self.frame.size.width/4),
CGRectGetMidY(self.frame)-(self.frame.size.height/4), self.frame.size.width/2, self.frame.size.height/2);
textView = [[UITextView alloc]initWithFrame:textViewSize];
textView.backgroundColor = [SKColor orangeColor];
textView.text = textViewContent;
textView.textColor = [SKColor whiteColor];
textView.textAlignment = NSTextAlignmentLeft;
textView.font = [UIFont fontWithName:@"Code-Pro-Demo" size:25];
textView.layer.zPosition = -1;
textView.alpha = 0;
textView.editable = NO;
fakeTextView = [SKSpriteNode spriteNodeWithColor:[SKColor orangeColor] size:CGSizeMake(self.frame.size.width/2, self.frame.size.height/2)];
fakeTextView.position = CGPointMake((self.frame.size.width*1.5),CGRectGetMidY(self.frame));
[self addChild:fakeTextView];
[self textViewEntersScene];
}
-(void)textViewEntersScene{
SKAction *wait = [SKAction waitForDuration:0.5];
SKAction *moveIn = [SKAction moveToX:(self.frame.size.width/2) - 100 duration:0.3];
SKAction *moveBackSlightly = [SKAction moveToX:self.frame.size.width/2 duration:0.2];
SKAction *displayTextView = [SKAction runBlock:^{
textView.alpha = 1;
}];
SKAction *hideFakeTextView = [SKAction runBlock:^{
fakeTextView.hidden = YES;
}];
[fakeTextView runAction:[SKAction sequence:@[wait,moveIn,moveBackSlightly,displayTextView,hideFakeTextView]]];
}
如您所知,可能性非常有限。有没有更好的方法来实现这个或类似的东西?
我创建了一个 class 来显示和滚动文本。创建新的 SKNode class.
后,您可以直接复制和粘贴 .h 和 .m 文件基本上 class 显示 SKLabelNodes 并在超过 1 行时向上滚动它们。线条出现一段时间,如果添加额外的线条则向上移动然后淡出。
它是非常通用的东西,因此您可以在任何项目中随意使用和修改代码。
要使用 class,请导入 header 并使用此代码(示例):
TextBubble *myBubble = [[TextBubble alloc] init];
[myBubble createBubbleWithText:@"Hello this is a very nice day to go fishing and have a cold beer." textSize:24 maxLineLength:20];
myBubble.position = CGPointMake(300, 300);
[self addChild:myBubble];
TextBubble Header 文件
#import <SpriteKit/SpriteKit.h>
@interface TextBubble : SKNode
-(instancetype)init;
-(void)createBubbleWithText:(NSString *)textString textSize:(int)textSize maxLineLength:(int)maxLineLength;
@end
TextBubble 实现文件
#import "TextBubble.h"
@implementation TextBubble {
NSMutableArray *linesArray;
}
- (instancetype)init {
self = [super init];
if (self) {
linesArray = [[NSMutableArray alloc] init];
}
return self;
}
-(void)createBubbleWithText:(NSString *)textString textSize:(int)textSize maxLineLength:(int)maxLineLength {
NSMutableString *passedText = [[NSMutableString alloc] initWithString:textString];
NSMutableString *currentLine = [[NSMutableString alloc] init];
unsigned long characterCounter = 0;
BOOL keepGoing = true;
while (keepGoing) {
NSRange whiteSpaceRange = [passedText rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet]];
if(whiteSpaceRange.location != NSNotFound) {
characterCounter += whiteSpaceRange.location+1;
if(characterCounter <= maxLineLength) {
[currentLine appendString:[passedText substringWithRange:NSMakeRange(0, whiteSpaceRange.location+1)]];
[passedText setString:[passedText substringWithRange:NSMakeRange(whiteSpaceRange.location+1, [passedText length]-whiteSpaceRange.location-1)]];
} else {
[currentLine setString:[currentLine substringWithRange:NSMakeRange(0, [currentLine length]-1)]];
SKLabelNode *myNode = [SKLabelNode labelNodeWithFontNamed:@"Arial-BoldMT"];
myNode.text = [NSString stringWithString:currentLine];
myNode.fontSize = textSize;
myNode.fontColor = [SKColor blueColor];
myNode.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;
myNode.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
myNode.zPosition = 0;
[linesArray addObject:myNode];
characterCounter = 0;
[currentLine setString:@""];
}
} else {
[currentLine appendString:passedText];
SKLabelNode *myNode = [SKLabelNode labelNodeWithFontNamed:@"Arial-BoldMT"];
myNode.text = [NSString stringWithString:currentLine];
myNode.fontSize = textSize;
myNode.fontColor = [SKColor blueColor];
myNode.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;
myNode.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
myNode.zPosition = 0;
[linesArray addObject:myNode];
keepGoing = false;
}
}
if([linesArray count] == 1) {
SKAction *block0 = [SKAction runBlock:^{
SKLabelNode *myNode = [linesArray objectAtIndex:0];
myNode.alpha = 0.0;
[self addChild:myNode];
[myNode runAction:[SKAction fadeAlphaTo:1.0 duration:0.5]];
}];
SKAction *wait1 = [SKAction waitForDuration:2.5];
SKAction *block1 = [SKAction runBlock:^{
SKLabelNode *myNode = [linesArray objectAtIndex:0];
[myNode runAction:[SKAction fadeAlphaTo:0.0 duration:0.5]];
}];
SKAction *wait2 = [SKAction waitForDuration:0.5];
SKAction *block2 = [SKAction runBlock:^{
[[linesArray objectAtIndex:0] removeFromParent];
}];
[self runAction:[SKAction sequence:@[block0, wait1, block1, wait2, block2]]];
}
if([linesArray count] == 2) {
float heightCounter = 0.0;
for (int i = 0; i<[linesArray count]; i++) {
SKAction *wait0 = [SKAction waitForDuration:(2.0 * i)];
SKAction *block0 = [SKAction runBlock:^{
SKLabelNode *myNode = [linesArray objectAtIndex:i];
myNode.alpha = 0.0;
myNode.position = CGPointMake(0, 0);
[self addChild:myNode];
[[linesArray objectAtIndex:i] runAction:[SKAction fadeAlphaTo:1.0 duration:0.5]];
}];
SKAction *wait1 = [SKAction waitForDuration:1.5];
heightCounter += 30;
SKAction *block1 = [SKAction runBlock:^{
[[linesArray objectAtIndex:i] runAction:[SKAction moveToY:heightCounter duration:0.5]];
}];
SKAction *block2 = [SKAction runBlock:^{
[[linesArray objectAtIndex:i] runAction:[SKAction fadeAlphaTo:0.0 duration:0.5]];
}];
SKAction *wait2 = [SKAction waitForDuration:0.5];
SKAction *block3 = [SKAction runBlock:^{
[[linesArray objectAtIndex:i] removeFromParent];
}];
[self runAction:[SKAction sequence:@[wait0, block0, wait1, block1, wait1, block2, wait2, block3]]];
heightCounter = 0;
}
}
if([linesArray count] >= 3) {
float heightCounter = 0.0;
for (int i = 0; i<[linesArray count]; i++) {
SKAction *wait0 = [SKAction waitForDuration:(1.5 * i)];
SKAction *block0 = [SKAction runBlock:^{
SKLabelNode *myNode = [linesArray objectAtIndex:i];
myNode.alpha = 0.0;
myNode.position = CGPointMake(0, 0);
[self addChild:myNode];
[[linesArray objectAtIndex:i] runAction:[SKAction fadeAlphaTo:1.0 duration:0.5]];
}];
SKAction *wait1 = [SKAction waitForDuration:1.5];
heightCounter += 30;
SKAction *block1 = [SKAction runBlock:^{
[[linesArray objectAtIndex:i] runAction:[SKAction moveToY:heightCounter duration:0.5]];
}];
heightCounter += 30;
SKAction *block5 = [SKAction runBlock:^{
[[linesArray objectAtIndex:i] runAction:[SKAction moveToY:heightCounter duration:0.5]];
}];
SKAction *block2 = [SKAction runBlock:^{
[[linesArray objectAtIndex:i] runAction:[SKAction fadeAlphaTo:0.0 duration:0.5]];
}];
SKAction *wait2 = [SKAction waitForDuration:0.5];
SKAction *block3 = [SKAction runBlock:^{
[[linesArray objectAtIndex:i] removeFromParent];
}];
[self runAction:[SKAction sequence:@[wait0, block0, wait1, block1, wait1, block5, wait1, block2, wait2, block3]]];
heightCounter = 0;
}
}
}
@end