Objective C: Code freezes when loading series of images - objective-c

My first post to the forums but I have been using answers posted here for the last several months and find the answers incredibly useful! I'm still learning objective c and still learning some basics.
My code is several hundred lines right so I don't want to the post the whole code. The basic premise of the code is to load a series of random images to random locations on the screen.
When I was trying to figure out how to deal with this idea I made a simple test version that would add one balloon when a button is pressed and then when you hit pop balloons delete all the balloon images that were created.
This balloon code worked just fine, and then I added this same concept into my main code. However now when I use it only a larger scale the code would freeze at 99% cpu usage and 18.5 MB memory. The code never failed but would sit frozen. The larger version is basically just adding multiple balloons when a button is pressed instead of one. Sometimes as many as 15 images.
Is there any reason a code of this style would not work on a larger scale? Or how do you go about problem solving an issue when the code freezes and no error is given.
.h file
#interface ViewController : UIViewController
{
// Holds an array of images of the balloons
NSMutableArray *BalloonArray;
// Holds an array file names of the balloon PNG files
NSMutableArray *BalloonNames;
}
-(void)AddBalloon:(id)sender;
-(void)PopBalloons:(id)sender;
#end
.m file
#interface ViewController ()
#end
#implementation ViewController
-(void)viewDidLoad
{
// Allocates memory for the array
BalloonArray = [[NSMutableArray alloc] init];
// Allocates memory and inputs the names of the images
BalloonNames = [NSMutableArray arrayWithObjects:[UIImage imageNamed:#"pink.png"],[UIImage imageNamed:#"blue.png"],[UIImage imageNamed:#"green.png"], nil];
[super viewDidLoad];
}
-(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(void)AddBalloon:(id)sender
{
int x; // x position of the balloon image created
int y; // y position of the balloon image created
int i; // Random index value to pull a random balloon image out
// Random number generator for the x and y position
x = arc4random_uniform(230) + 30;
y = arc4random_uniform(400) + 150;
// Random index value from 0 to 2
// Random based on how many images there are to chose from
i = arc4random_uniform(3);
// Uses the image from the index value previously randomnized
UIImage *Balloon = [BalloonNames objectAtIndex:i];
// Places the UIImage in a UIImageView
UIImageView *BalloonView = [[UIImageView alloc] initWithImage:Balloon];
// Sizes the image to the correct size
BalloonView.frame = CGRectMake(0, 0, 50, 100);
// Centers the image using the x and y coordinates
BalloonView.center = CGPointMake(x,y);
// Adds the image view to the view
[self.view addSubview:BalloonView];
// Adds the image view to the array
[BalloonArray addObject:BalloonView];
}
-(void)PopBalloons:(id)sender
{
// Removes each image in the array out of the main view
for(UIImageView *Test in BalloonArray)
{
[Test removeFromSuperview];
}
// Removes all object from the array
[BalloonArray removeAllObjects];
}
#end

Make the method -(void)AddBalloon:(id)sender to run on a Separate Thread. Perhaps you can use [NSThread detachNewThreadSelector:#selector(myThreadMainMethod:) toTarget:self withObject:nil];. Have a look at Apple Documentation

Related

Cocos2d - Problems with .pvr.ccz spritesheet (incorrect position, blurry) created with TexturePacker

I have a problem by using the .pvr.ccz format. I have a simple spritesheet with a few sprites on it created by TexturePacker. It's loaded like in my example code below.
#implementation MainScene
- (id)init
{
// Apple recommend assigning self with supers return value
self = [super init];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"spritesheet.plist"];
CCSprite * sprite = [CCSprite spriteWithSpriteFrame:[CCSpriteFrame frameWithImageNamed:#"play-button.png"]];
sprite.position = ccp(0.5, 0.5);
sprite.positionType = CCPositionTypeNormalized;
[self addChild:sprite];
// done
return self;
}
#end
The spritesheet is loaded and I don't get any warnings or errors in the console. But somehow the sprite (play-button.png) is first of all blurry and on the second hand it's the wrong position on the spritesheet (so it's a half of another sprite and not the playbutton).
In TexturePacker I have the following options selected:
I read many articles about the advantages of using pvr.ccz. I use the cocos2d version 3.5. So did I miss something in my code or is there an option in Texturepacker?
At a point in time (memory fails) cocos2d and TP changed the .pvr format (produced and read) to the normal 'flipped' version. Thus, just select the Flip PVR check-box in TP, and the rendering should be fine.

New scene is created from its frame size but it keeps getting smaller each time. Why?

I am writing a game in which the user must prevent falling objects (rocks) to pass the button of the screen using some plates, each click make a plate at that position but he can only have 5 plates at each time and clicking on sixth point vanished the first plate while creating a new one.
That was a brief on how my game mechanics work.
Here is the part of my code that counts falling objects(sprites) using physics and if they became more than 10 a game over message will be shown and the code restarts the game, a new game. to have a new game I need to
-(void)didSimulatePhysics
{
[self enumerateChildNodesWithName:#"rock" usingBlock:^(SKNode *node, BOOL *stop) {
if (node.position.y < 0)
{
ScoreNum++;
[node removeFromParent];
score.text = [NSString stringWithFormat:#"%# %li",ScoreMSG,(long)ScoreNum];
if (ScoreNum > 10)
{
score.fontSize = 40;
score.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
score.text = #"Game Over!";
SKScene *spaceshipScene = [[GameScene alloc] initWithSize:CGRectMake(0, 0,CGRectGetMaxY(self.frame),CGRectGetMaxX(self.frame)).size];
printf("%f %f",CGRectGetMidX(self.frame),CGRectGetMidX(self.frame));
SKTransition *doors = [SKTransition doorsOpenVerticalWithDuration:0.25];
[self.view presentScene:spaceshipScene transition:doors];
ScoreNum = 0;
}
}
}];
}
GameScene is subclassed from SKScene like this
#import <SpriteKit/SpriteKit.h>
#interface GameScene : SKScene
#end
The code works find but the plates (all of the sprites on the screen) gets squeezed from sides
The following picture shows the results, first time, second time and third time, I needed 10 reputation to include 3 pictures so I had to merge them all into one picture, Here it is.
https://www.imageupload.co.uk/images/2015/08/30/123.png
Sorry, looks like I can not embed an image since I have not enough reputation!
Why each my scene squeezes?
Looks like you set a scaleMode in your viewController.viewDidLoad that handles your game scene, nothing wrong with your physics code (in your question).
look for something like this scene.scaleMode = SKSceneScaleModeAspectFill usually SKScenes are automatically scaled based on the screen size of the device and it is upto SKScene to provide you a scene.
Your scenes in your pictures shows that scenes have a complete and full cover but they are scaled.
It is kind of hard to handle sprite size while do not controling scale. I suggest to get ride of every Scale Mode and remark them all and control the scale your self.
if you are not going to zoom in/out as I believe it is the case in your game you just need to reset the scenes scale to 1 each time after each scene transition.

Correctly Load an Image into an Existing storyboard UIImageView?

I am using an array to try to load images into specific UIImageViews. I have 10 UIImageViews set up on my storyboard.
I also have a Game Over method that runs whenever the frame of one UIImageView intersects with another UIImageView. For some reason, whenever I try to use the array to load my UIImageViews, my Game Over method immediately triggers. I can't figure out why. As soon as I remove the initWithImage line, the game runs normally. Any ideas?
- (void)viewDidLoad
{
KanaCharacters = [[NSArray alloc] initWithObjects:[UIImage imageNamed:#"a.png"],...
nil];
int imageDisplay = arc4random_uniform([KanaCharacters count]);
Monster1 = [[UIImageView alloc] initWithImage:[KanaCharacters objectAtIndex:imageDisplay]];
}
-(void) Collision
{
if ((CGRectIntersectsRect(Monster1.frame, Ship.frame)) && (Monster1Hit==NO))
{
[self GameOver];
}
}
-(void)GameOver
{
WinOrLose.hidden=NO;
WinOrLose.text = [NSString stringWithFormat:#"You Lose!"];
}
I suspect that Collision if firing once an image in Monster1 and Ship.frame.
This is because I suspect your Monster is being placed where your ship is?
you may want to move the ship or the monster before you add the image into the view.

app crash after allocation of 10 mb memory

We are facing crash in my app. I check on instrument that after allocation of 10 mb app get crash at any point(not any fix instance).
I am allocating approax 1000 label every time i click on any button in a for loop and release it after work done please help. In instrument there is no memory leaks but still app crash after allocationg 10 mb of memory.
this is a code i am applying on click of a button
is this a right way??????
-(IBACTION) btnShow
{
for (UIView *obj in scrollview.subviews)
{
[obj removeFromSuperview];
}
int x;
int y=0;
for (int j=0; j<12; j++) {
x=0;
// Do any additional setup after loading the view, typically from a nib.
for (int i=0; i<1000; i++) {
UILabel * lblUsage=[[UILabel alloc] initWithFrame:CGRectMake(x, y, 75, 45)];
lblUsage.text=[NSString stringWithFormat:#"%d",i];
lblUsage.textColor=[UIColor lightGrayColor];
lblUsage.numberOfLines=2;
lblUsage.font = [UIFont systemFontOfSize:14.0];
lblUsage.textAlignment=UITextAlignmentCenter;
lblUsage.backgroundColor=[UIColor colorWithPatternImage:
[UIImage imageNamed:#"labelBox.png"]];
lblUsage.layer.borderColor = [UIColor blackColor].CGColor;
lblUsage.layer.borderWidth = 0.5;
[scrollview addSubview:lblUsage];
[lblUsage release];
x+=75;
}
y+=40;
}
scrollview.contentSize=CGSizeMake(x, 1000);
}
you receive memory warning in the above code
memory warning level 1 is first warning where you should remove unnecessary view to clean up memory
memory warning level 2 is the limit.. remove something now or your app will quit within few seconds.
memory warning level 3 is sent when the system has decided to quit your app! due to memory usage
Sorry, but you'll just have to take a completely different aproach - which will
make your code much more complex. There's no way you could get around by creating
12.000 labels with pattern background.
initially you would create only those labels that are shown on screen and one or
two rows (and columns) of those that could soon appear on screen while the user is scrolling
then you'll do most of your work in viewDidScroll by creating and disposing of lables on the fly.
here your code should decide which labels can be disposed of (when they are far enough from visible screen)
and which have to be created because they could appear soon on screen (depends on current location of content.
offset)
Take a look at ScrollViewSuite as example for tiling. It's not exactly what you're looking
for but it should give you a kickstart.

Draw waveform in NSView

I need to draw a waveform in an NSView. (I have all the samples in an array). The drawing must be efficient and really fast without clipping, flickering, etc, it must be smooth. The waveform will be "moving" according to the song position and some changes to the samples (DSP processing) will be shown as visual representation onto NSView in realtime.
I'm familiar drawing lines, arcs, etc onto canvas objects and I have developed apps doing such things but not on Mac OS X ...
I want to ask if anyone can guide me where to start drawing! Core Animation, OpenGL, simple override drawing methods, ??, etc. Which would be the best practice - API to use?
I would keep it simple and create an NSView subclass with an audioData property that uses Cocoa drawing. You could call [view setAudioData:waveArray] which would in turn call [self setNeedsDisplay:YES].
In your drawRect: method you could then iterate through the samples and use NSRectFill() accordingly. Here sample's value is between 0 and 1.
- (void)drawRect:(NSRect)dirtyRect {
[[NSColor blueColor]set];
for (id sample in self.waveArray) {
NSRect drawingRect = NSZeroRect;
drawingRect.origin.x = [self bounds].origin.x;
drawingRect.origin.y = [self bounds].origin.y + ([self.waveArray indexOfObject:sample]/([self.waveArray count] - 1.0));
drawingRect.size.width = [self bounds].size.width/[self.waveArray count];
drawingRect.size.height = [self bounds].size.height * [sample value];
NSRectFill(drawingRect);
}
}
This code isn't exact, and you should be sure to make it more efficent by only drawing samples inside dirtyRect.
I would start with a really long and thin image to represent a single bar/column for the waveform.
My plan would be to have a NSTimer that moves all bars of the wave one to the left every 0.01 seconds.
So something like this in the loop.
for (int x; x < [WaveArray count] ; x++)
{
UIImageView * Bar = [WaveArray ObjectAtIndex: x];
[Bar setCenter:CGPointMake(Bar.center.x-1,Bar.center.y)];
}
Now all you have to do is create the objects at the correct hight and add them to the WaveArray and they all will be moved to the left.