Cocos2d - Начальный слой приложения отображается неправильно при загрузке приложения, отображается соответствующим образом после перезагрузки
Я использую синглтон GameManager для обработки некоторых общих задач, необходимых для моей игры. Одна из таких задач - загрузка отдельных игровых сцен. Когда игра запускается, любая отображаемая комбо сцена / слой отображается неправильно; Похоже, что координаты, относительно которых расположены элементы, неверны.
Неважно, какой слой я выберу - все они отображаются неправильно. Если вы нажмете кнопку и загрузите другую сцену / слой, а затем вернетесь к рассматриваемой сцене / слою, все отобразится правильно. Это происходит только на устройствах отображения сетчатки, поэтому я думаю, что это может быть связано с масштабированием, которое я установил для разных типов отображения в диспетчере игр. Тем не менее, изменение масштаба для Retina-дисплеев ломает вещи еще больше (слои слишком малы).
Вот мой AppDelegate.h
#import <UIKit/UIKit.h>
@class RootViewController;
@interface AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
RootViewController *viewController;
}
@property (nonatomic, retain) UIWindow *window;
@end
AppDelegat.m
#import "cocos2d.h"
#import "AppDelegate.h"
#import "GameConfig.h"
#import "RootViewController.h"
#import "GameplayScene.h"
#import "GameManager.h"
@implementation AppDelegate
@synthesize window;
- (void) removeStartupFlicker
{
#if GAME_AUTOROTATION == kGameAutorotationUIViewController
#endif
}
- (void) applicationDidFinishLaunching:(UIApplication*)application
{
// Init the window
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Try to use CADisplayLink director
// if it fails (SDK < 3.1) use the default director
if( ! [CCDirector setDirectorType:kCCDirectorTypeDisplayLink] )
[CCDirector setDirectorType:kCCDirectorTypeDefault];
CCDirector *director = [CCDirector sharedDirector];
// Init the View Controller
viewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];
viewController.wantsFullScreenLayout = YES;
EAGLView *glView = [EAGLView viewWithFrame:[window bounds]
pixelFormat:kEAGLColorFormatRGB565 // kEAGLColorFormatRGBA8
depthFormat:0 // GL_DEPTH_COMPONENT16_OES
];
// attach the openglView to the director
[director setOpenGLView:glView];
[director setDeviceOrientation:kCCDeviceOrientationPortrait];
[director setAnimationInterval:1.0/60];
[director setDisplayFPS:YES];
// make the OpenGLView a child of the view controller
[viewController setView:glView];
// make the View Controller a child of the main window
[window addSubview: viewController.view];
[window makeKeyAndVisible];
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888];
// Removes the startup flicker
[self removeStartupFlicker];
// Run the intro Scene
//[[CCDirector sharedDirector] runWithScene:[GameplayScene node]];
[[GameManager sharedGameManager] runSceneWithID:kMainMenuScene];
}
- (void)dealloc {
[[CCDirector sharedDirector] end];
[window release];
[super dealloc];
}
GameManager.h
#import <Foundation/Foundation.h>
#import "Constants.h"
#import "CommonProtocols.h"
@interface GameManager : NSObject {
BOOL isMusicON;
BOOL isSoundEffectsON;
BOOL hasPlayerDied;
BOOL newHighScore;
BOOL newBestTime;
BOOL isUiTextLeft;
int currentScore;
int highScore;
int lengthPlayed;
int bestTime;
int randomPurple;
int randomGreen;
int timeBonus;
int timeTillDeath;
int uiBackgroundHeight;
CharacterStates previousPurpleState;
CharacterStates previousGreenState;
SceneTypes currentScene;
}
@property (readwrite) BOOL isMusicON;
@property (readwrite) BOOL isSoundEffectsON;
@property (readwrite) BOOL hasPlayerDied;
@property (readwrite) BOOL newHighScore;
@property (readwrite) BOOL newBestTime;
@property (readwrite) BOOL isUiTextLeft;
@property (readwrite) int currentScore;
@property (readwrite) int highScore;
@property (readwrite) int lengthPlayed;
@property (readwrite) int bestTime;
@property (readwrite) int randomPurple;
@property (readwrite) int randomGreen;
@property (readwrite) int uiBackgroundHeight;
@property (readwrite) CharacterStates previousPurpleState;
@property (readwrite) CharacterStates previousGreenState;
@property (readwrite) int timeBonus;
@property (readwrite) int timeTillDeath;
+(GameManager*)sharedGameManager;
-(void)runSceneWithID:(SceneTypes)sceneID;
-(void)openSiteWithLinkType:(LinkTypes)linkTypeToOpen ;
@end
GameManager.m
#import "GameManager.h"
#import "GameplayScene.h"
#import "MainMenuScene.h"
#import "OptionsScene.h"
#import "CreditsScene.h"
#import "IntroScene.h"
#import "LevelCompleteScene.h"
@implementation GameManager
static GameManager* _sharedGameManager = nil;
@synthesize isMusicON;
@synthesize isSoundEffectsON;
@synthesize hasPlayerDied;
@synthesize newHighScore;
@synthesize newBestTime;
@synthesize isUiTextLeft;
@synthesize currentScore;
@synthesize highScore;
@synthesize lengthPlayed;
@synthesize bestTime;
@synthesize previousPurpleState;
@synthesize previousGreenState;
@synthesize randomPurple;
@synthesize randomGreen;
@synthesize timeBonus;
@synthesize timeTillDeath;
@synthesize uiBackgroundHeight;
+(GameManager*)sharedGameManager {
@synchronized([GameManager class])
{
if(!_sharedGameManager)
[[self alloc] init];
return _sharedGameManager;
}
return nil;
}
+(id)alloc {
@synchronized([GameManager class]){
NSAssert(_sharedGameManager == nil, @"Attempted to allocate a second instance of the Game Manager singleton");
_sharedGameManager = [super alloc];
return _sharedGameManager;
}
return nil;
}
-(id) init {
self = [super init];
if (self != nil) {
// Game manager initialized
CCLOG(@"Game manager singleton, init");
hasPlayerDied = NO;
// DECODING INFO FROM DEFAULTS
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [dirPaths objectAtIndex:0];
NSMutableData *gameData;
NSKeyedUnarchiver *decoder;
NSString *documentPath = [documentsDirectory stringByAppendingPathComponent:@"gameState.dat"];
gameData = [NSData dataWithContentsOfFile:documentPath];
if (gameData) {
decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:gameData];
highScore = [decoder decodeIntForKey:@"highScore"];
bestTime = [decoder decodeIntForKey:@"bestTime"];
isMusicON = [decoder decodeBoolForKey:@"isMusicON"];
isSoundEffectsON = [decoder decodeBoolForKey:@"isSoundEffectsON"];
isUiTextLeft = [decoder decodeBoolForKey:@"isUiTextLeft"];
//currentScore = [decoder decodeIntForKey:@"currentScore"];
[decoder release];
} else {
highScore = 0;
bestTime = 0;
isMusicON = TRUE;
isSoundEffectsON = TRUE;
isUiTextLeft = TRUE;
//currentScore = 0;
}
CCLOG(@"Music - %s", isMusicON ? "true" : "false");
CCLOG(@"Sound - %s", isSoundEffectsON ? "true" : "false");
//****************************
currentScore = 0;
timeBonus = 0;
timeTillDeath = 0;
uiBackgroundHeight = 0;
currentScene = kNoSceneUninitialized;
}
return self;
}
-(void)runSceneWithID:(SceneTypes)sceneID {
SceneTypes oldScene = currentScene;
currentScene = sceneID;
id sceneToRun = nil;
switch (sceneID) {
case kMainMenuScene:
sceneToRun = [MainMenuScene node];
break;
case kOptionsScene:
sceneToRun = [OptionsScene node];
break;
case kCreditsScene:
sceneToRun = [CreditsScene node];
break;
case kIntroScene:
sceneToRun = [IntroScene node];
break;
case kLevelCompleteScene:
sceneToRun = [LevelCompleteScene node];
break;
case kGameplayScene:
sceneToRun = [GameplayScene node];
break;
default:
CCLOG(@"Unknown ID, cannot switch scenes");
return;
break;
}
if (sceneToRun == nil) {
// Revert back, since no new scene was found
currentScene = oldScene;
return;
}
// Menu Scenes have a value of < 100
if (sceneID < 100) {
if ([[CCDirector sharedDirector] enableRetinaDisplay:YES]) {
// iPhone 4 Retina
[sceneToRun setScaleX:1.0f];
[sceneToRun setScaleY:1.0f];
CCLOG(@"GM:Scaling for iPhone 4 (retina)");
} else {
[sceneToRun setScaleX:1.0f];
[sceneToRun setScaleY:1.0f];
CCLOG(@"GM:Scaling for iPhone 3G(non-retina)");
}
}
if ([[CCDirector sharedDirector] runningScene] == nil) {
[[CCDirector sharedDirector] runWithScene:sceneToRun];
} else {
[[CCDirector sharedDirector] replaceScene:sceneToRun];
}
}
2 ответа
Однажды я столкнулся с подобной проблемой, но не могу связать ее напрямую с вашим кодом.
Короче говоря, проблема в том, что пока я строю свой слой / сцену в init
метод, nodeToWorldTransformation
(по крайней мере, возможно, и другие) не установлен. Итак, если вы пытаетесь вычислить мировые координаты (или, возможно, размер в мировых координатах) чего-либо, это не сработает.
Теперь, в каждом случае, я использовал это преобразование для вычисления коэффициента масштабирования во время инициализации, и это было неправильно. Если я отложил расчет до того, как преобразование было установлено, то все было в порядке. Преобразование будет готово только после того, как созданный вами слой будет добавлен к его родительскому элементу, но я не совсем уверен, когда это произойдет. Наконец, в моем случае я просто жестко запрограммировал преобразование, зная все измерения во время инициализации.
Кажется, что ваш случай может быть аналогичным этому, но, как я уже сказал, я не могу связать это с вашим кодом.
Ты звонишь node
с вызовом объектов сцены [MainMenuScene scene];
и попробовать
и сделайте этот метод с типом возврата CCScene* и используйте для получения возврата сцены и записи
[[CCDirector sharedDirector]runWithScene:[obj runSceneWithID:1]];
Редактировать --
-(CCScene*)runSceneWithID:(SceneTypes)sceneID {
SceneTypes oldScene = currentScene;
currentScene = sceneID;
id sceneToRun = nil;
switch (sceneID) {
case kMainMenuScene:
sceneToRun = [MainMenuScene node];
break;
case kOptionsScene:
sceneToRun = [OptionsScene node];
break;
case kCreditsScene:
sceneToRun = [CreditsScene node];
break;
case kIntroScene:
sceneToRun = [IntroScene node];
break;
case kLevelCompleteScene:
sceneToRun = [LevelCompleteScene node];
break;
case kGameplayScene:
sceneToRun = [GameplayScene node];
break;
default:
CCLOG(@"Unknown ID, cannot switch scenes");
return nil;
break;
}
if (sceneToRun == nil) {
// Revert back, since no new scene was found
currentScene = oldScene;
}
return sceneToRun;
}