Cocos2d -- Check if place is free before moving (all objects) - objective-c

Is there a method in Cocos2d like CGRectIntersectsRect, except instead of limiting it to one sprite, it checks for ALL objects?

You can do it in a loop. This example is a method for a sprite instance (i.e. the player) to test against an array of other sprites.
- (BOOL) checkForCollision
{
BOOL didCollide = NO;
CGRect myRect;
CGRect testRect;
// assuming anchor point is in the center
myRect = CGRectMake(self.position.x - self.contentSize.width /2,
self.position.y - self.contentSize.height /2,
self.contentSize.width,
self.contentSize.height);
for (CCSprite * currSprite in listOfWallSprites) {
testRect = CGRectMake(currSprite.position.x - currSprite.contentSize.width /2,
currSprite.position.y - currSprite.contentSize.height /2,
currSprite.contentSize.width,
currSprite.contentSize.height);
if ( CGRectIntersectsRect(myRect, testRect) ) {
didCollide = YES;
return didCollide;
}
}
return didCollide;
}

you can set up a method like this
CGRect sprite1Rect = CGRectMake(
sprite1.position.x - (sprite1.contentSize.width/2),
sprite1.position.y - (sprite1.contentSize.height/2),
sprite1.contentSize.width,
sprite1.contentSize.height);
CGRect somethingRect = CGRectMake(
something.position.x - (something.contentSize.width/2),
something.position.y - (something.contentSize.height/2),
something.contentSize.width,
something.contentSize.height);
CGRect something2Rect = CGRectMake(
something2.position.x - (something2.contentSize.width/2),
something2.position.y - (something2.contentSize.height/2),
something2.contentSize.width,
something2.contentSize.height);
if (CGRectIntersectsRect(sprite1Rect, somethingRect) || CGRectIntersectsRect(sprite1Rect, something2Rect)) {
// do something
}
or
if (CGRectIntersectsRect(sprite1.frame, something.frame) || CGRectIntersectsRect(sprite1Rect, something2Rect)) {
// do something
}
this means that if sprite1 intersects something OR something2 then it will do something

Related

Bindings does not update NSTextField

I use bindings to NSObjectController within XIB. When I set new content object of NSObjectController the only textfield value which doesn't change is the one that has first responder. Model changes without an issue.
If I don't use custom getter/setter the textfield that has firstResponder (isBeingEdited) changes without an issue.
What's wrong with my KVC, KVO?
My custom getter/setter is below pic.
PS: I don't want to make window a first responder before I change content object to make it work.
static const CGFloat MMsInOneInch = 25.4;
static const CGFloat inchesInOneMM = 0.0393700787402;
- (void)setPaperWidth:(CGFloat)paperWidth
{
[self willChange];
CGFloat newWidth = paperWidth * [self conversionKoeficientToDefaultUnitType];
if (!_isChangingPaperSize) {
if (self.paperSize == PPPaperSizeA4 && fabs(newWidth - widthSizeOfA4) > 0.001) {
[self setPaperSize:PPPaperSizeCustom];
}
if (self.paperSize == PPPaperSizeUSLetter && fabs(newWidth - widthSizeOfUSLetter) > 0.001 ) {
[self setPaperSize:PPPaperSizeCustom];
}
}
[self willChangeValueForKey:#"paperWidth"];
_paperWidth = newWidth;
[self didChangeValueForKey:#"paperWidth"];
[self didChange];
}
- (CGFloat)conversionKoeficientToDefaultUnitType
{
if ([self defaultUnitType] == [self unitType]) {
return 1;
}
if ([self defaultUnitType] == PPPrintSettingsUnitTypeMM) {
return MMsInOneInch;
}
if ([self defaultUnitType] == PPPrintSettingsUnitTypeInch) {
return inchesInOneMM;
}
return 1;
}
- (CGFloat)paperWidth
{
return _paperWidth / [self conversionKoeficientToDefaultUnitType];
}
I forgot that I use NSNumberFormatter with min/max value which where blocking NSTextField to update.

What am I missing that prevents me from making a generic NSStackView-like container with Auto Layout?

I am trying to implement a container view with Auto Layout for OS X that operates similarly to NSStackView, but with a few differences that NSStackView does not handle (and I need 10.7 support anyway). My rules are:
The subviews are arranged either horizontally or vertically.
In the primary direction, the subviews by default take their intrinsic size.
If a subview is marked "stretchy", it will take whatever space remains after laying out all non-stretchy subviews. Multiple stretchy subviews get equal distributions of the remaining space.
If no subviews are stretchy, the container can grow in the primary direction, showing empty space after the last subview. Nesting two such stacks with the same orientation prefers the outer one.
Along the secondary direction, subviews clamp to the edges of the container view and grow freely.
I thought this could be done in a simple way, connecting the views in the primary direction one after another and then in the secondary direction using the |[view]| visual format. Lack of a stretchy view is handled with a NSView with intrinsic content size 0x0 as the last view.
This mostly worked. Unfortunately, ambiguity arose with a nested tree of horizontally oriented stacks of the form (represented using HTML for expository purposes)
.box {
display: inline-block;
border: 1px solid black;
padding: 0.5em 0.5em 0.5em 0.5em;
}
.outermost-box {
display: inline-block;
border: 1px solid black;
padding: 0.5em 0.5em 0.5em 0.5em;
width: 100%;
}
<div class="outermost-box">
<div class="box">
<input type="button" value="These">
<input type="button" value="Buttons" disabled>
</div>
<div class="box">
<input type="button" value="are">
<div class="box">
<input type="button" value="in" disabled>
</div>
</div>
<div class="box">
<div class="box">
<input type="button" value="nested">
<div class="box">
<input type="button" value="boxes" disabled>
</div>
</div>
</div>
</div>
where all the stacks have no stretchy subviews. Under my definition, the outermost box stretches, and only that one stretches. However, Auto Layout will randomly assign the extra space to one of the inner boxes:
Changing the extra view to a NSLayoutRelationLessThanOrEqual relation (last view.trailing <= superview.trailing) also did not help. I'm going to keep this model for the rest of this post, though, as my next attempts are based on it.
Then I decided to try having the container ask its superview if it should expand. This fixed the above problem, but introduced another problem with deep chains of containers that alternate between horizontal and vertical:
The buttons labelled "Right Margin Test" should stretch, but they either aren't stretching or are stretching but also clipping the views on the sides (I don't have a screenshot of this right now; sorry).
Then I decided to have both the <= and alternate == constraints on the right edge on at the same time, setting == to a low priority if there should be extra space. This new one mostly works, but now has a weird problem. If I resize the window large enough on the Page 3 shown above, then switch to Page 4, I get
and then if I resize I get
even though Page 4 should have space at the bottom under all conditions. Sometimes the bottom of the button can be seen, and visualizing its vertical constraints show it thinks it wants to be as tall as the matrix of radio buttons (right now a NSMatrix; changing it to a bunch of NSButtons will wait until after I fix all these Auto Layout issues).
I'm really not sure what's going on or how to fix any of this. I tried making the == constraint I mentioned have a settable "real hugging priority" of its own, but that just made things break in more spectacular ways.'
There's also problems with positions of tab views being too low initially and taking a few layout cycles to set properly...
Everything shown is done with these containers, NSBoxes with one subview, and NSTabs with one subview. I'll paste the code for my container as it stands now below.
So what about Auto Layout do I not understand that I can't just make it work right with the obvious code? Or can NSStackView do all of what I want and I should just use it instead? (That assumes alignment takes Width and Height as valid, which Interface Builder does not seem to say it does).
Thanks!
// 15 august 2015
#import "uipriv_darwin.h"
// TODOs:
// - tab on page 2 is glitched initially and doesn't grow
// - page 3 doesn't work right; probably due to our shouldExpand logic being applied incorrectly
// TODOs to confirm
// - 10.8: if we switch to page 4, then switch back to page 1, check Spaced, and go back to page 4, some controls (progress bar, popup button) are clipped on the sides
#interface boxChild : NSObject
#property uiControl *c;
#property BOOL stretchy;
#property NSLayoutPriority oldHorzHuggingPri;
#property NSLayoutPriority oldVertHuggingPri;
- (NSView *)view;
#end
#interface boxView : NSView {
uiBox *b;
NSMutableArray *children;
BOOL vertical;
int padded;
NSLayoutConstraint *first;
NSMutableArray *inBetweens;
NSLayoutConstraint *last, *last2;
NSMutableArray *otherConstraints;
NSLayoutAttribute primaryStart;
NSLayoutAttribute primaryEnd;
NSLayoutAttribute secondaryStart;
NSLayoutAttribute secondaryEnd;
NSLayoutAttribute primarySize;
NSLayoutConstraintOrientation primaryOrientation;
NSLayoutConstraintOrientation secondaryOrientation;
}
- (id)initWithVertical:(BOOL)vert b:(uiBox *)bb;
- (void)onDestroy;
- (void)removeOurConstraints;
- (void)forAll:(void (^)(uintmax_t i, boxChild *b))closure;
- (boxChild *)child:(uintmax_t)i;
- (BOOL)isVertical;
- (void)append:(uiControl *)c stretchy:(int)stretchy;
- (void)delete:(uintmax_t)n;
- (int)isPadded;
- (void)setPadded:(int)p;
#end
struct uiBox {
uiDarwinControl c;
boxView *view;
};
#implementation boxChild
- (NSView *)view
{
return (NSView *) uiControlHandle(self.c);
}
#end
#implementation boxView
- (id)initWithVertical:(BOOL)vert b:(uiBox *)bb
{
self = [super initWithFrame:NSZeroRect];
if (self != nil) {
// the weird names vert and bb are to shut the compiler up about shadowing because implicit this/self is stupid
self->b = bb;
self->vertical = vert;
self->children = [NSMutableArray new];
self->inBetweens = [NSMutableArray new];
self->otherConstraints = [NSMutableArray new];
if (self->vertical) {
self->primaryStart = NSLayoutAttributeTop;
self->primaryEnd = NSLayoutAttributeBottom;
self->secondaryStart = NSLayoutAttributeLeading;
self->secondaryEnd = NSLayoutAttributeTrailing;
self->primarySize = NSLayoutAttributeHeight;
self->primaryOrientation = NSLayoutConstraintOrientationVertical;
self->secondaryOrientation = NSLayoutConstraintOrientationHorizontal;
} else {
self->primaryStart = NSLayoutAttributeLeading;
self->primaryEnd = NSLayoutAttributeTrailing;
self->secondaryStart = NSLayoutAttributeTop;
self->secondaryEnd = NSLayoutAttributeBottom;
self->primarySize = NSLayoutAttributeWidth;
self->primaryOrientation = NSLayoutConstraintOrientationHorizontal;
self->secondaryOrientation = NSLayoutConstraintOrientationVertical;
}
}
return self;
}
- (void)onDestroy
{
boxChild *bc;
uintmax_t i, n;
[self removeOurConstraints];
[self->first release];
[self->inBetweens release];
[self->last release];
[self->last2 release];
[self->otherConstraints release];
n = [self->children count];
for (i = 0; i < n; i++) {
bc = [self child:i];
uiControlSetParent(bc.c, NULL);
uiDarwinControlSetSuperview(uiDarwinControl(bc.c), nil);
uiControlDestroy(bc.c);
}
[self->children release];
}
- (void)removeOurConstraints
{
[self removeConstraint:self->first];
[self removeConstraints:self->inBetweens];
[self removeConstraint:self->last];
[self removeConstraint:self->last2];
[self removeConstraints:self->otherConstraints];
}
- (void)forAll:(void (^)(uintmax_t i, boxChild *b))closure
{
uintmax_t i, n;
n = [self->children count];
for (i = 0; i < n; i++)
closure(i, [self child:i]);
}
- (boxChild *)child:(uintmax_t)i
{
return (boxChild *) [self->children objectAtIndex:i];
}
- (BOOL)isVertical
{
return self->vertical;
}
// TODO something about spinbox hugging
- (void)updateConstraints
{
uintmax_t i, n;
BOOL hasStretchy;
NSView *firstStretchy = nil;
CGFloat padding;
NSView *prev, *next;
NSLayoutConstraint *c;
NSLayoutPriority priority;
[super updateConstraints];
[self removeOurConstraints];
n = [self->children count];
if (n == 0)
return;
padding = 0;
if (self->padded)
padding = 8.0; // TODO named constant
// first, attach the first view to the leading
prev = [[self child:0] view];
self->first = mkConstraint(prev, self->primaryStart,
NSLayoutRelationEqual,
self, self->primaryStart,
1, 0,
#"uiBox first primary constraint");
[self addConstraint:self->first];
[self->first retain];
// next, assemble the views in the primary direction
// they all go in a straight line
// also figure out whether we have stretchy controls, and which is the first
if ([self child:0].stretchy) {
hasStretchy = YES;
firstStretchy = prev;
} else
hasStretchy = NO;
for (i = 1; i < n; i++) {
next = [[self child:i] view];
if (!hasStretchy && [self child:i].stretchy) {
hasStretchy = YES;
firstStretchy = next;
}
c = mkConstraint(next, self->primaryStart,
NSLayoutRelationEqual,
prev, self->primaryEnd,
1, padding,
#"uiBox later primary constraint");
[self addConstraint:c];
[self->inBetweens addObject:c];
prev = next;
}
// and finally end the primary direction
self->last = mkConstraint(prev, self->primaryEnd,
NSLayoutRelationLessThanOrEqual,
self, self->primaryEnd,
1, 0,
#"uiBox last primary constraint");
[self addConstraint:self->last];
[self->last retain];
// if there is a stretchy control, add the no-stretchy view
self->last2 = mkConstraint(prev, self->primaryEnd,
NSLayoutRelationEqual,
self, self->primaryEnd,
1, 0,
#"uiBox last2 primary constraint");
priority = NSLayoutPriorityRequired;
if (!hasStretchy) {
BOOL shouldExpand = NO;
uiControl *parent;
parent = uiControlParent(uiControl(self->b));
if (parent != nil)
if (self->vertical)
shouldExpand = uiDarwinControlChildrenShouldAllowSpaceAtBottom(uiDarwinControl(parent));
else
shouldExpand = uiDarwinControlChildrenShouldAllowSpaceAtTrailingEdge(uiDarwinControl(parent));
if (shouldExpand)
priority = NSLayoutPriorityDefaultLow;
}
[self->last2 setPriority:priority];
[self addConstraint:self->last2];
[self->last2 retain];
// next: assemble the views in the secondary direction
// each of them will span the secondary direction
for (i = 0; i < n; i++) {
prev = [[self child:i] view];
c = mkConstraint(prev, self->secondaryStart,
NSLayoutRelationEqual,
self, self->secondaryStart,
1, 0,
#"uiBox start secondary constraint");
[self addConstraint:c];
[self->otherConstraints addObject:c];
c = mkConstraint(prev, self->secondaryEnd,
NSLayoutRelationEqual,
self, self->secondaryEnd,
1, 0,
#"uiBox end secondary constraint");
[self addConstraint:c];
[self->otherConstraints addObject:c];
}
// finally, set sizes for stretchy controls
if (hasStretchy)
for (i = 0; i < n; i++) {
if (![self child:i].stretchy)
continue;
prev = [[self child:i] view];
if (prev == firstStretchy)
continue;
c = mkConstraint(prev, self->primarySize,
NSLayoutRelationEqual,
firstStretchy, self->primarySize,
1, 0,
#"uiBox stretchy sizing");
[self addConstraint:c];
[self->otherConstraints addObject:c];
}
}
- (void)append:(uiControl *)c stretchy:(int)stretchy
{
boxChild *bc;
NSView *childView;
bc = [boxChild new];
bc.c = c;
bc.stretchy = stretchy;
childView = [bc view];
bc.oldHorzHuggingPri = horzHuggingPri(childView);
bc.oldVertHuggingPri = vertHuggingPri(childView);
uiControlSetParent(bc.c, uiControl(self->b));
uiDarwinControlSetSuperview(uiDarwinControl(bc.c), self);
uiDarwinControlSyncEnableState(uiDarwinControl(bc.c), uiControlEnabledToUser(uiControl(self->b)));
// if a control is stretchy, it should not hug in the primary direction
// otherwise, it should *forcibly* hug
if (stretchy)
setHuggingPri(childView, NSLayoutPriorityDefaultLow, self->primaryOrientation);
else
// TODO will default high work?
setHuggingPri(childView, NSLayoutPriorityRequired, self->primaryOrientation);
// make sure controls don't hug their secondary direction so they fill the width of the view
setHuggingPri(childView, NSLayoutPriorityDefaultLow, self->secondaryOrientation);
[self->children addObject:bc];
[bc release]; // we don't need the initial reference now
[self setNeedsUpdateConstraints:YES];
}
- (void)delete:(uintmax_t)n
{
boxChild *bc;
NSView *removedView;
bc = [self child:n];
removedView = [bc view];
uiControlSetParent(bc.c, NULL);
uiDarwinControlSetSuperview(uiDarwinControl(bc.c), nil);
setHorzHuggingPri(removedView, bc.oldHorzHuggingPri);
setVertHuggingPri(removedView, bc.oldVertHuggingPri);
[self->children removeObjectAtIndex:n];
[self setNeedsUpdateConstraints:YES];
}
- (int)isPadded
{
return self->padded;
}
- (void)setPadded:(int)p
{
CGFloat padding;
uintmax_t i, n;
NSLayoutConstraint *c;
self->padded = p;
// TODO split into method (using above code)
padding = 0;
if (self->padded)
padding = 8.0;
n = [self->inBetweens count];
for (i = 0; i < n; i++) {
c = (NSLayoutConstraint *) [self->inBetweens objectAtIndex:i];
[c setConstant:padding];
}
// TODO call anything?
}
#end
static void uiBoxDestroy(uiControl *c)
{
uiBox *b = uiBox(c);
[b->view onDestroy];
[b->view release];
uiFreeControl(uiControl(b));
}
uiDarwinControlDefaultHandle(uiBox, view)
uiDarwinControlDefaultParent(uiBox, view)
uiDarwinControlDefaultSetParent(uiBox, view)
uiDarwinControlDefaultToplevel(uiBox, view)
uiDarwinControlDefaultVisible(uiBox, view)
uiDarwinControlDefaultShow(uiBox, view)
uiDarwinControlDefaultHide(uiBox, view)
uiDarwinControlDefaultEnabled(uiBox, view)
uiDarwinControlDefaultEnable(uiBox, view)
uiDarwinControlDefaultDisable(uiBox, view)
static void uiBoxSyncEnableState(uiDarwinControl *c, int enabled)
{
uiBox *b = uiBox(c);
if (uiDarwinShouldStopSyncEnableState(uiDarwinControl(b), enabled))
return;
[b->view forAll:^(uintmax_t i, boxChild *bc) {
uiDarwinControlSyncEnableState(uiDarwinControl(bc.c), enabled);
}];
}
uiDarwinControlDefaultSetSuperview(uiBox, view)
static BOOL uiBoxChildrenShouldAllowSpaceAtTrailingEdge(uiDarwinControl *c)
{
uiBox *b = uiBox(c);
// return NO if this box is horizontal so nested horizontal boxes don't lead to ambiguity
return [b->view isVertical];
}
static BOOL uiBoxChildrenShouldAllowSpaceAtBottom(uiDarwinControl *c)
{
uiBox *b = uiBox(c);
// return NO if this box is vertical so nested vertical boxes don't lead to ambiguity
return ![b->view isVertical];
}
void uiBoxAppend(uiBox *b, uiControl *c, int stretchy)
{
[b->view append:c stretchy:stretchy];
}
void uiBoxDelete(uiBox *b, uintmax_t n)
{
[b->view delete:n];
}
int uiBoxPadded(uiBox *b)
{
return [b->view isPadded];
}
void uiBoxSetPadded(uiBox *b, int padded)
{
[b->view setPadded:padded];
}
static uiBox *finishNewBox(BOOL vertical)
{
uiBox *b;
uiDarwinNewControl(uiBox, b);
b->view = [[boxView alloc] initWithVertical:vertical b:b];
return b;
}
uiBox *uiNewHorizontalBox(void)
{
return finishNewBox(NO);
}
uiBox *uiNewVerticalBox(void)
{
return finishNewBox(YES);
}
Solved this myself.
The primary change is that instead of having the has-extra-space-after-it is not done by the constraints on self, but on its superview. The superview asks self if it should take the extra space, and if so, it allocates the extra space (using a >= constraint to the superview edge instead of a == constraint).
A variety of other minor fixes fixes the edge case. In particular, everywhere where I do
relation = NSLayoutRelationSomething;
if (condition)
relation = NSLayoutRelationSomethingElse;
constraint = [NSLayoutConstraint constraintWithArg:arg arg:arg
relation:relation
...]
I change to using two constraints, setting the priority of them both based on the condition. This should probably be an Auto Layout best practice, since it works so well...
Thanks anyway!

Limit the Pan Gesture boundary of a UIImageView inside in a UIView

I'm using the below code
- (void)panGestureDetected:(UIPanGestureRecognizer *)recognizer
{
static CGRect originalFrame;
if (state == UIGestureRecognizerStateBegan)
{
originalFrame = recognizer.view.frame;
}
else if (state == UIGestureRecognizerStateChanged)
{
CGPoint translate = [recognizer translationInView:recognizer.view.superview];
CGRect newFrame = CGRectMake(fmin(recognizer.view.superview.frame.size.width - originalFrame.size.width, fmax(originalFrame.origin.x + translate.x,0.0)),
fmin(recognizer.view.superview.size.height - originalFrame.size.height, fmax(originalFrame.origin.y + translate.y, 0.0)),
originalFrame.size.width,
originalFrame.size.height);
recognizer.view.frame = newFrame;
}else if (state == UIGestureRecognizerStateEnded)
{
[self performSelectorInBackground:#selector(ChangeViewAlphaTo1) withObject:nil];
}
}
The main problem is that you are trying to solve two constraints in one line.
Try to break things down when you have an issue. Massive statements are hard to read and even harder to debug.
CGRect newFrame = CGRectMake(fmin(recognizer.view.superview.frame.size.width - originalFrame.size.width, fmax(originalFrame.origin.x + translate.x,0.0)),
fmin(recognizer.view.superview.size.height - originalFrame.size.height, fmax(originalFrame.origin.y + translate.y, 0.0)),
originalFrame.size.width,
originalFrame.size.height);
is barely readable and when you revisit this in 6 months time you or another coder will not be able to tell what you were trying to do.
try replacing that monster with…
[self translateView:recognizer.view limitedBySuperViewBounds:translate];
all of a sudden the method tells you what you are doing.
-(void)translateView:(UIView *)aview limitedBySuperViewBounds:(CGPoint)translate
{
CGRect frameToTranslate = aview.frame;
CGRect superviewBounds= aview.superview.bounds;
frameToTranslate.origin.x = frameToTranslate.origin.x + translate.x;
frameToTranslate.origin.y = frameToTranslate.origin.y + translate.y;
if (translate.x < 0) {
frameToTranslate.origin.x = 0;
}
else if (CGRectGetMaxX(frameToTranslate) > CGRectGetWidth(superviewBounds)){
frameToTranslate.origin.x = CGRectGetWidth(superviewBounds) - CGRectGetWidth(frameToTranslate);
}
if (translate.y < 0) {
frameToTranslate.origin.y = 0;
}
else if (CGRectGetMaxY(frameToTranslate) > CGRectGetHeight(superviewBounds)){
frameToTranslate.origin.y = CGRectGetHeight(superviewBounds) - CGRectGetHeight(frameToTranslate);
}
aview.frame = frameToTranslate;
}
This isn't just my opinion , this is Clean Code

Sparrow - how to fix SIGABRT error, Game initwithwitdth

I've just started with the sparrow framework, and have been following "The Big Sparrow Tutorial" by Gamua themselves. I'm on the first part of the tutorial, using the AppScaffold 1.3 but when I try to compile my basic code it hangs at the loading screen and gives me a SIGABRT error.
I put an exception breakpoint, and it stopped here, in GameController.m (seen at bottom) of the AppScaffold:
mGame = [[Game alloc] initWithWidth:gameWidth height:gameHeight];
This was also my only output:
2012-07-30 07:19:54.787 AppScaffold[1682:10a03] -[Game initWithWidth:height:]: unrecognized selector sent to instance 0x7553980
(lldb)
I am using the stock AppScaffold, the only thing I changed was the Game.m.
This is my Game.m:
#interface Game : SPSprite
#end
#implementation Game
{
#private
SPImage *mBackground;
SPImage *mBasket;
NSMutableArray *mEggs;
}
- (id)init
{
if((self = [super init]))
{
//load the background image first, add it to the display tree
//and keep it for later use
mBackground = [[SPImage alloc] initWithContentsOfFile:#"background.png"];
[self addChild:mBackground];
//load the image of the basket, add it to the display tree
//and keep it for later use
mBasket = [[SPImage alloc] initWithContentsOfFile:#"basket.png"];
[self addChild:mBasket];
//create a list that will hold the eggs,
//which we will add and remove repeatedly during the game
mEggs = [[NSMutableArray alloc] init];
}
return self;
}
- (void)dealloc
{
[mBackground release];
[mBasket release];
[mEggs release];
[super dealloc];
}
#end
I've tried my best to use my basic troubleshooting tactics, but I'm very new to Obj-C and Sparrow and could use a hand :)
Thanks
EDIT: I've addded the GameController.m contents here for clarity:
//
// GameController.m
// AppScaffold
//
#import <OpenGLES/ES1/gl.h>
#import "GameController.h"
#interface GameController ()
- (UIInterfaceOrientation)initialInterfaceOrientation;
#end
#implementation GameController
- (id)initWithWidth:(float)width height:(float)height
{
if ((self = [super initWithWidth:width height:height]))
{
float gameWidth = width;
float gameHeight = height;
// if we start up in landscape mode, width and height are swapped.
UIInterfaceOrientation orientation = [self initialInterfaceOrientation];
if (UIInterfaceOrientationIsLandscape(orientation)) SP_SWAP(gameWidth, gameHeight, float);
mGame = [[Game alloc] initWithWidth:gameWidth height:gameHeight];
mGame.pivotX = gameWidth / 2;
mGame.pivotY = gameHeight / 2;
mGame.x = width / 2;
mGame.y = height / 2;
[self rotateToInterfaceOrientation:orientation animationTime:0];
[self addChild:mGame];
}
return self;
}
- (void)dealloc
{
[mGame release];
[super dealloc];
}
- (UIInterfaceOrientation)initialInterfaceOrientation
{
// In an iPhone app, the 'statusBarOrientation' has the correct value on Startup;
// unfortunately, that's not the case for an iPad app (for whatever reason). Thus, we read the
// value from the app's plist file.
NSDictionary *bundleInfo = [[NSBundle mainBundle] infoDictionary];
NSString *initialOrientation = [bundleInfo objectForKey:#"UIInterfaceOrientation"];
if (initialOrientation)
{
if ([initialOrientation isEqualToString:#"UIInterfaceOrientationPortrait"])
return UIInterfaceOrientationPortrait;
else if ([initialOrientation isEqualToString:#"UIInterfaceOrientationPortraitUpsideDown"])
return UIInterfaceOrientationPortraitUpsideDown;
else if ([initialOrientation isEqualToString:#"UIInterfaceOrientationLandscapeLeft"])
return UIInterfaceOrientationLandscapeLeft;
else
return UIInterfaceOrientationLandscapeRight;
}
else
{
return [[UIApplication sharedApplication] statusBarOrientation];
}
}
- (void)rotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
animationTime:(double)animationTime
{
float angles[] = {0.0f, 0.0f, -PI, PI_HALF, -PI_HALF};
float oldAngle = mGame.rotation;
float newAngle = angles[(int)interfaceOrientation];
// make sure that rotation is always carried out via the minimal angle
while (oldAngle - newAngle > PI) newAngle += TWO_PI;
while (oldAngle - newAngle < -PI) newAngle -= TWO_PI;
// rotate game
if (animationTime)
{
SPTween *tween = [SPTween tweenWithTarget:mGame time:animationTime
transition:SP_TRANSITION_EASE_IN_OUT];
[tween animateProperty:#"rotation" targetValue:newAngle];
[[SPStage mainStage].juggler removeObjectsWithTarget:mGame];
[[SPStage mainStage].juggler addObject:tween];
}
else
{
mGame.rotation = newAngle;
}
// inform all display objects about the new game size
BOOL isPortrait = UIInterfaceOrientationIsPortrait(interfaceOrientation);
float newWidth = isPortrait ? MIN(mGame.gameWidth, mGame.gameHeight) :
MAX(mGame.gameWidth, mGame.gameHeight);
float newHeight = isPortrait ? MAX(mGame.gameWidth, mGame.gameHeight) :
MIN(mGame.gameWidth, mGame.gameHeight);
if (newWidth != mGame.gameWidth)
{
mGame.gameWidth = newWidth;
mGame.gameHeight = newHeight;
SPEvent *resizeEvent = [[SPResizeEvent alloc] initWithType:SP_EVENT_TYPE_RESIZE
width:newWidth height:newHeight animationTime:animationTime];
[mGame broadcastEvent:resizeEvent];
[resizeEvent release];
}
}
// Enable this method for the simplest possible universal app support: it will display a black
// border around the iPhone (640x960) game when it is started on the iPad (768x1024); no need to
// modify any coordinates.
/*
- (void)render:(SPRenderSupport *)support
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
glEnable(GL_SCISSOR_TEST);
glScissor(64, 32, 640, 960);
[super render:support];
glDisable(GL_SCISSOR_TEST);
}
else
[super render:support];
}
*/
#end
Here is my Xcode project: http://cl.ly/2e3g02260N47
You are calling a
initWithWidth:height:
method, while none is defined in your class.
From your edit, it seems that the initWithWidth method is declared in the class GameController, not in Game.
So, it seems that the
In which context are you calling initWithWidth:height: method is declared in Game.h but you define it in GameController.m.
This explains both why you get the SIGABRT and the errors when compiling.
The fix is calling
mGame = [[GameController alloc] init];
from GameController initWithWidth...
- (id)initWithWidth:(float)width height:(float)height
{
if ((self = [super initWithWidth:width height:height]))
{
float gameWidth = width;
float gameHeight = height;
// if we start up in landscape mode, width and height are swapped.
UIInterfaceOrientation orientation = [self initialInterfaceOrientation];
if (UIInterfaceOrientationIsLandscape(orientation)) SP_SWAP(gameWidth, gameHeight, float);
mGame = [[Game alloc] init];
mGame.pivotX = gameWidth / 2;
mGame.pivotY = gameHeight / 2;
mGame.x = width / 2;
mGame.y = height / 2;
[self rotateToInterfaceOrientation:orientation animationTime:0];
[self addChild:mGame];
}
return self;
}
The tutorial was very old and was incompatible with the latest scaffold;
I did this:
- (id)init
{
if((self = [super init]))
{
when I should've done this:
- (id)initWithWidth:(float)width height:(float)height
{
if ((self = [super initWithWidth:width height:height]))
{
thanks, though sergio!
(There are much better sparrow tutorials and I'm even making my own video tutorials :P)

Objective-C: Get closest NSView to dragged NSView

If I have a NSView with 10 subviews, and I drag one of the subviews, what is the easiest way to determine which of the remaining views is closes to the dragged one? My code is working but I somehow feel I'm using a monkey wrench to fine tune a violin. Is there a more elegant way?
subviews is an array of the subviews of the parent view of this view (so it includes this view)
the toolTip of the sub views contain their page # formatted like "Page_#"
- (void) mouseUp: (NSEvent* ) e {
//set up a ridiclous # for current distance
float mtDistance = 12000000.0;
//get this page number
selfPageNum = [[[self toolTip] substringFromIndex:5] intValue];
//set up pageViews array
pageViews = [[NSMutableArray alloc] init];
//loop through the subviews
for (int i=0; i<[subviews count]; i++) {
//set up the view
thisView = [subviews objectAtIndex:i];
//filter for view classes
NSString* thisViewClass = [NSString stringWithFormat:#"%#", [thisView className]];
if ( [thisViewClass isEqual:#"Page"]) {
//add to the pageViews array
[pageViews addObject:thisView];
if (self != thisView) {
//get the view and self frame
NSRect movedViewFrame = [self frame];
NSRect thisViewFrame = [thisView frame];
//get the location area (x*y)
float movedViewLoc = movedViewFrame.origin.x * (movedViewFrame.origin.y * -1);
float thisViewLoc = thisViewFrame.origin.x * (thisViewFrame.origin.y * -1);
//get the difference between x locations
float mtDifference = movedViewLoc - thisViewLoc;
if (mtDifference < 0) {
mtDifference = mtDifference * -1;
}
if (mtDifference < mtDistance) {
mtDistance = mtDifference;
closesView = thisView;
}
}
}//end class check
}//end loop
//....more stuff
}
http://en.wikipedia.org/wiki/Distance
sqrt(pow((x2 - x1), 2) + pow((y2 - y1), 2)))
Edit: Since you only need to find the shortest distance, not exact distances, you don't need to take the square root. Thanks for the insight Abizern
pow((x2 - x1), 2) + pow((y2 - y1), 2)