I created an Xcode Project, where I use cocos2d as a static library (I don't use the template).
To incorporate cocos2d in my storyboard, I followed the tutorial here: cocos2d & storyboards
As a result I setup CCDirector by using the CCViewController class described in the tutorial.
Everything works fine, except every now and then the console spits out a number of OpenGL errors like:
OpenGL error 0x0506 in DrawSegment 190
My CCGLView is created like this in viewDidLoad:
CGRect rect = self.view.frame;
CGFloat width;
CGFloat height;
if (rect.size.width > rect.size.height)
{
width = rect.size.width;
height = rect.size.height;
}
else
{
width = rect.size.height;
height = rect.size.width;
}
CCGLView *glView = [CCGLView viewWithFrame:CGRectMake(0, 0, width, height)
pixelFormat:kEAGLColorFormatRGB565
depthFormat:0
preserveBackbuffer:NO
sharegroup:nil
multiSampling:NO
numberOfSamples:0];
What are these OpenGL errors, and how can I fix them? If I use the template I don't have these problems.
Related
I am writing a GUI, with a main menu, a second screen and a back button to the main menu. From the initial main menu I use the following lines of code:
midScreenX = [UIScreen mainScreen].bounds.size.width/2;
midScreenY = [UIScreen mainScreen].bounds.size.height/2;
WarScene *battle = [[WarScene alloc] initWithSize: CGSizeMake(midScreenX*2, midScreenY*2)];
SKTransition *reveal = [SKTransition revealWithDirection:SKTransitionDirectionDown duration:1.0];
SKView * skView = (SKView *)self.view;
UIView *viewToRemove = [self.view viewWithTag:101];
[viewToRemove removeFromSuperview];
[skView presentScene:battle transition:reveal];
This works... I think. I open up a new scene, my second scene is the correct size and at least fills the screen. There is a node in that scene which is too big for the screen, and I am working on changing that, but I don't think that that would actually effect the UIScreen's bounds.
The problem arises when I return to the main menu with the following code:
midScreenX = [UIScreen mainScreen].bounds.size.width/2;
midScreenY = [UIScreen mainScreen].bounds.size.height/2;
GameScene *map = [[GameScene alloc] initWithSize: CGSizeMake(midScreenX*2 ,midScreenY*2)];
SKTransition *reveal = [SKTransition revealWithDirection:SKTransitionDirectionDown duration:1.0];
SKView * skView = (SKView *)self.view;
UIView *viewToRemove = [self.view viewWithTag:3];
[viewToRemove removeFromSuperview];
[skView presentScene:map transition:reveal];
As far as I can work out, the values being passed through should be exactly the same as the values initially sent for [UIScreen mainScreen].bounds.size and yet the scene which is initialised is far too big.
Is there anything that I could be doing which might affect [UIScreen mainScreen].bounds.size? Or have I misunderstood what init and .bounds actually do?
In terms of what I have already done to try and solve this problem myself, I have looked at examples of how scenes are normally initialised. I see that often values are used in place of .bounds for example :
initWithSize: CGSizeMake(1024,768)
However, wouldn't that mean that on different devices the scene wouldn't be shown properly/fully?
if you are using iOS 6 or iOS 7,
both [UIScreen mainScreen].bounds.size.width and [UIScreen mainScreen].bounds.size.height is same in all orientation..
but in iOS 8 it give one value in landscape and give another value in portrait mode
NSLog(#"width %f",[[UIScreen mainScreen] bounds].size.width); //portrait ios7 or 6 = 320 , landscape ios7 or 6 = 320
NSLog(#"height %f",[[UIScreen mainScreen] bounds].size.height); //portrait ios7 or 6 = 568 , landscape ios7 or 6 = 568
NSLog(#"width %f",[[UIScreen mainScreen] bounds].size.width); //portrait ios8 = 320 , landscape ios8 = 568
NSLog(#"height %f",[[UIScreen mainScreen] bounds].size.height); //portrait ios8 = 568 , landscape ios8 = 320
so we can check conditions like this,
CGFloat midScreenX,midScreenY;
if (UIDeviceOrientationIsLandscape((UIDeviceOrientation)[[UIApplication sharedApplication] statusBarOrientation]))
{
//landscape mode
midScreenX = ([[UIScreen mainScreen]bounds].size.width>[[UIScreen mainScreen]bounds].size.height?[[UIScreen mainScreen]bounds].size.width:[[UIScreen mainScreen]bounds].size.height)/2;
midScreenY = ([[UIScreen mainScreen]bounds].size.width<[[UIScreen mainScreen]bounds].size.height?[[UIScreen mainScreen]bounds].size.width:[[UIScreen mainScreen]bounds].size.height)/2;
}
else
{
//portrait mode
midScreenX = [[UIScreen mainScreen]bounds].size.width/2;
midScreenY = [[UIScreen mainScreen]bounds].size.height/2;
}
I hope you warScene and gameScene are subclass of SKScene. The method initWithSize returns, A newly initialized scene object. and parameter 'size' is The size of the scene in points.
For more information refer https://developer.apple.com/library/prerelease/ios/documentation/SpriteKit/Reference/SKScene_Ref/index.html#//apple_ref/occ/instm/SKScene/initWithSize:
I am trying to essentially split the screen into four different parts with four different rects like so:
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.width;
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.height;
CGRect jumpleftRect = CGRectMake(0, screenHeight/2, screenWidth/2, screenHeight/2); //1
CGRect runleftRect = CGRectMake(0, 0, screenWidth/2, screenHeight/2); //2
CGRect jumprightRect = CGRectMake(screenWidth/2, screenHeight/2, screenWidth/2, screenHeight/2); //3
CGRect runrightRect = CGRectMake(screenWidth/2, 0, screenWidth/2, screenHeight/2); //4
And then I am cycling through a touchArray and checking if the touch location was within, lets say for example for this question, the first rect:
NSArray *touchArray = [NSMutableArray arrayWithArray:touchArray];
for (UITouch *touchInArray in touchArray) {
CGPoint toucharrayPosition = [touchInArray locationInNode:self];
if (CGRectContainsPoint(jumpleftRect, toucharrayPosition)) { //1st rect }
However it seems like the rect is in the completely wrong spot. This never gets called even though my finger is clearly on the top left part of the screen. My anchorPoints are untouched and normal so I am not sure why this isn't working. Is there some specific reason why the touches aren't registering as in the rects even though in retrospect they should be?
Here are somethings to look into -
Are the values you getting from UIScreen correct? Is there a reason you are using UIScreen and not CCDirector's viewSize property (if using v3, winSize if using v2)?
Did you enable touches and is this code that you have inside a touch began or ended method? If so then when you debugged, did you get the correct screen position from locationInNode? Also during debugging are the rects still correct?
Not sure if this was new behavior in iOS 8 but I just reversed my screenWidth and screenHeight to this:
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
Now things are working very smoothly and nicely.
I'm getting in a bit of a muddle trying to draw some paintcode graphics code in the middle of the screen horizontally.
I'm really not sure if scale or landscape orientation affects this.
I've created a UIView subclass and addSubview in viewDidLoad like so...
MenuTitleView *fancyView = [[MenuTitleView alloc] initWithFrame:self.view.bounds];
[[self view] addSubview:fancyView];
Rather than the size PaintCode gave me...
CGRect textRect = CGRectMake(0, 0, 418, 129);
I'm trying to determine the screen / view width and the size of the canvas width.
I've tried various things without success.
CGRect screenRect = [[UIScreen mainScreen] applicationFrame];
CGFloat w = screenRect.size.width;
CGFloat width = 500;
CGFloat height = 200;
CGFloat x = (w - width) * 0.5f;
CGFloat y = 20;
CGRect textRect = CGRectMake(x, y, width, height);
Scale is not an issue, because Quartz and UIKit now work in 'points' rather than in pixels, so that's already accounted for. However orientation is not, [UIScreen mainScreen] will return the same rect either for applicationFrame or bounds etc, it's oblivious to orientation.
I like to put a solution in a category on UIView or UIViewController, because you'll reuse it plenty. something like this...
-(CGRect )workingCanvas{
CGRect screenRect = [UIScreen mainScreen].bounds;
BOOL landscape = UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]);
CGRect result = CGRectZero;
CGFloat lesserDimension = (screenRect.size.width < screenRect.size.height) ? screenRect.size.width : screenRect.size.height;
CGFloat greaterDimension = (screenRect.size.width > screenRect.size.height) ? screenRect.size.width : screenRect.size.height;
result.size.width = (landscape) ? greaterDimension : lesserDimension;
result.size.height = (landscape) ? lesserDimension : greaterDimension;
if ([[UIApplication sharedApplication]isStatusBarVisible]){
result.size.height -= [[UIApplication sharedApplication]statusBarFrame].size.height;
}
return result;
}
if you want to position your view just in the middle of the screen try this
CGRect screenRect = [[UIScreen mainScreen] applicationFrame];
CGFloat width = 500;
CGFloat height = 200;
CGFloat x = CGRectGetMidX(screenRect);
CGFloat y = 20;
CGRect textRect = CGRectMake(x, y, width, height);
already tested is working
Good Luck!!
I have to implement the rotate works like the photo app. Having the UIImageView inside a UIScrollView. and when device rotate, I want the image to rotate to landscape like Photo's. If the image is landscape-one, then it will fill the whole UIScrollView's width with the rotation animation. When the following code
[UIView animateWithDuration:0.36
animations:^(void){
[_imageView setTransform:CGAffineTransformMakeRotation(M_PI*90/180)];
_imageView.frame = CGRectMake(0, 0, 480, 320); //set the frame after the rotate
self.contentSize = CGSizeMake(480, 320); //set the content-size of the scrollview
}
completion:^(BOOL complete){
}];
But this does not work. rotate happens, but the position of the _imageView is not correct, or the image did not fill the width. Even I change the order frame and content-size before transform, still not correct.
What will be the correct approach to have this?
The WWDC 2010 Video: Designing Apps with Scrolls Views shows you exactly how to do this.
The correct answer, in my opinion, is to not animate the rotation yourself at all.
If you work according to the latest iOS 6 guidelines, then you just rearrange your views in the ViewController its layoutSubviews() method.
The source code that #CoDEFRo refers to is similar to the following, but here I've put it into the UIScrollView's delegate method scrollViewDidScroll:.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGSize boundsSize = scrollView.bounds.size;
CGRect frameToCenter = self.imageView.frame;
if (frameToCenter.size.width < boundsSize.width)
frameToCenter.origin.x = (boundsSize.width - frameToCenter.size.width) / 2;
else
frameToCenter.origin.x = 0;
if (frameToCenter.size.height < boundsSize.height)
frameToCenter.origin.y = (boundsSize.height - frameToCenter.size.height) / 2;
else
frameToCenter.origin.y = 0;
self.imageView.frame = frameToCenter;
}
In my iOS project, glView ends up with height=0 and width=0 even though CGRect frame correctly gets the screen's dimensions in the previous line.
- (void) applicationDidFinishLaunching:(UIApplication*)application {
CGRect frame = [[UIScreen mainScreen] bounds];
EAGLView *glView = [EAGLView viewWithFrame:frame
pixelFormat:kEAGLColorFormatRGB565
depthFormat:0
preserveBackbuffer:NO
sharegroup:nil
multiSampling:NO
numberOfSamples:0
];
}
Is there some other way I need to create my EAGLView *glView in order for it to be init'ed properly?
You will have to add the glView to a UIWindow. Check out the app delegate code in the Cocos2D project templates.