Firstly here is my .h files code where i declared everything...
#interface NextlLevel : UIViewController{
IBOutlet UIImageView *Coin1;
int score;
IBOutlet UILabel *scorelable;
}
#property (nonatomic, assign) int score;
#property (nonatomic, retain) IBOutlet UILabel *scorelable;
#end
I have also synthesised my implementations in my .m file here is the code...
#synthesize score;
#synthesize scorelable;
Secondly I have some code which just checks if my drag-able image has collided with a still image. Here is the code...
-(void) ifCollided {
if(CGRectIntersectsRect(Coin1.frame,MoneyBag.frame)){
Coin1.hidden = YES;
}
}
This code is just a basic way of checking for a collision but once the image has collided I want to add to a int which is displayed in a label.
The only way i thought i could do this was by ...
firstly adding this line of code to 'ifCollided'
[self scorecheck];
So now 'ifCollided' looks something like this:
-(void) ifCollided {
if(CGRectIntersectsRect(Coin1.frame,MoneyBag.frame)){
Coin1.hidden = YES;
[self scorecheck];
}
}
Thirdly I had to make 'scorecheck' I did this by...
-(void)scorecheck{
score++;
scorelable.text = [NSString stringWithFormat:#"%i", score];
}
}
Here is a image to show that the code I'm currently using is not working correctly. And therefore is not just adding just one to the int that i set to 0. I'm displaying the int in the score label (at the top of my screen). Due to the code not correctly working as long as you touch, drag and hold whilst colliding in the boundaries of the image with the collission rule (in this case the moneybag)
Here is to the image i was talking about:
Any help would be very appreciated
Edit:Here is what i was meant to do in the void ifCollided
-(void) ifCollided {
if (!Coin1.hidden)
{
Coin1.hidden = YES;
[self scorecheck];
}
}
Thanks #Elliott Perry
So, to clarify, you would like a mechanism that guarantees that the score will only increment once per each coin colliding with the moneybag?
There are any number of ways to do this but they all require you to keep track of which coins have already been processed in some way. You could give each of your coins a unique reference and store a collection of ids that represent coins that have already been processed, avoiding calling scorecheck if the collection contains the id of the coin in question.
Alternatively, and the method I'd go with, you can mark each coin to let yourself know not to process that coin a second time. Since your hiding the coins on collision, why not use the hidden property to determine whether to increment the score or not:
-(void)ifCollided
{
if(CGRectIntersectsRect(Coin1.frame,MoneyBag.frame))
{
if (!Coin1.hidden)
{
Coin1.hidden = YES;
[self scorecheck];
}
}
}
If for whatever reason that isn't feasible here is an example marking the coins using the tag property:
-(void)ifCollided
{
if(CGRectIntersectsRect(Coin1.frame,MoneyBag.frame))
{
if (Coin1.tag != 1)
{
Coin1.hidden = YES;
[self scorecheck];
Coin1.tag = 1;
}
}
}
Related
I have no idea how I should correctly name the title but I know exactly what my problem is (I will eventually edit the title later).
I am pretty new to Objective-C and I am still learning.
So, I have a class that contains a tableView (I will call it ClassA) and another with a normal UIView (ClassB). What I want to do, is to let a button appear when a row is selected.
I created in my ClassB.h file:
+(id)sharedInstance;
#property (retain, nonatomic) IBOutlet UIButton *btn;
-(void) showBtn :(BOOL) show;
And in my ClassB.m file:
#synthesize btn;
static ClassB *this = nil;
(+id) sharedInstance {
if(!this) {
#synchronized (self) {
this = [[ClassB alloc] init];
}
}
return this;
}
-(void)viewDidLoad {
[self showBtn:NO] //because I only want to let it appear when a row is selected.
[self.view addSubview:btn];
}
-(void) showBtn :(BOOL) show { // I called this method in classA.
if (show == NO) {
btn.hidden = YES;
} else {
btn.hidden = NO;
}
}
So when I launch my app, the button is hidden and stays hidden when I select a row. I debugged, and found that btn is nil when I called the method in ClassA. After some research, I found that the method is called for another instance, so here my question, what can I do, to get it called for the right instance?
EDIT
Here part of my ClassA.m
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSInteger row = [indexPath row];
[[ClassB sharedInstance] showBtn:YES];
}
Observation: The ClassB is a UIViewController which is wrong. UIViewControllers have viewDidLoad.
Implementation Suggestion:
The correct implementation for the requirement would be that you create a custom cell with a button. Hide the button in awakeFromNib method. in didSelectRowAtIndex set the cell.button.isHidden = YES.
This should alone take care of the requirement mentioned above.
Question
I'm developing some poker software ~ purely for fun.
Now when it comes to the chips, I'm having a nightmare. One positioning them, two the denominations and THREE Selecting the ones I'll need! This seems almost impossible with my current design.
Basically, I draw an skshapenode give it the name of the denomination and the player name. However, this chip can be drawn 50 times with the same name.
When I come to animating these chips, I can only see a wall of impossibility..
once I've made a function to choose the right denominations of chips to use for a call or raise etc, how will I even begin to write this pseudo code?
I require 2 large chips, 1 small chip and 2 medium chips {
SKNode *node = [self childnodewithname:denomination, playername];
runaction..
}
Baring in mind, I'll only need to take 2 of the 20 that are there in the chip stack.. As well as change the ownership of the chip..
is this possible? or am I seriously overcomplicating the issue..?
You need to rework your solution a little bit. I would do something like this:
First, subclass a SKSpriteNode (or SK whatever node you like) to make a chip:
Chip.h
#interface Chip : SKSpriteNode
#property (nonatomic, retain) NSString *player;
#property int denomination;
#end
Chip.m
#implementation Chip
- (id)initWithColor:(UIColor *)color size:(CGSize)size
{
if(self = [super initWithColor:color size:size])
{
self.name = #"chip";
}
return self;
}
#end
Now you've got something you can reasonably enumerate and inspect.
Add a bunch of chips to your game scene:
GameScene.m
-(void)didMoveToView:(SKView *)view {
for(int i = 0; i < 50; i++)
{
Chip *chip = [[Chip alloc] initWithColor:[SKColor greenColor]
size:CGSizeMake(100.0, 100.0)];
chip.player = #"some player";
chip.denomination = 10;
[self addChild:chip];
}
}
Then when it's time to pop off a certain number of the chips:
-(void)popChipsFromPlayer:(NSString *)playerName
ofDenomination:(int)denomination
numberOfChips:(int)numChips
{
__block int i;
[self enumerateChildNodesWithName:#"chip"
usingBlock:^(SKNode *node, BOOL *stop) {
Chip *chip = (Chip *)node;
if(chip.denomination == denomination &&
[playerName isEqualToString:chip.player])
{
if(i==numChips)
return;
SKAction *moveUp = [SKAction moveByX:0.0
y:200.0
duration:3];
[chip runAction:moveUp];
i++;
}
}];
}
Call the method:
[self popChipsFromPlayer:#"some player"
ofDenomination:10
numberOfChips:3];
I have a screen, which contains multiple UIImages (their amount and size are known only at runtime, so i add them programmatically) and some fixed buttons below these UIImages.
How to make buttons display certainly under all Images?
I've tried
1.) Put Buttons and Images into 2 separate views, and then add constraint between them. No result, buttons are hidden behind images.
2.) Put buttons into separate view and set constraint in code, (tried both viewDidLoad and viewDidAppear). Constraint is set between container view and top of the screen, depending on size and amount of images.
Example of code:
-(void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSInteger totalImages = [self.object.fullphotos count];
self.labelsTopConstraint.constant = totalImages*(imageHeight + 20) + 10;
}
In case 2 buttons are positioned right, but don't respond to touches.
How should I layout everything correctly?
Thanks in advance!
Take a Tableview for those images and add buttons in a last cell.
The best way is creating a Object with a refresh method that can be called in viewDidAppear
MyObject.h
#interface MyObject : UIViewController
#property (nonatomic,strong) UIImageview *img;
#property (nonatomic,strong) UIButton *btn;
- (void) refresh;
in MyObject.m
- (void)viewDidLoad {
[self.btn addTarget:self action:#selector(myMethod:) forControlEvents:UIControlEventTouchUpInside];
}
- (void) refresh {
//make your settings here
}
-(void)myMethod {
//your button action here
}
Then in your controller if you have your objects in an NSArray:
-(void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
for (MyObject *myObj in objectsArray) {
#autoreleasePool {
[myObj refresh];
}
}
}
I'm using a IBAction button to turn a map layer on. This code turns it on when the button is tapped.
- (IBAction)lightingLayer:(id)sender {
[_mapView addTileSource:[[RMMapBoxSource alloc] initWithMapID:#"MapID"]];
}
Now I'd like to adjust it so when the user taps it once, the layers turns on. And when it's tapped again, it turns on and so forth. I took a stab at it by borrowing code from a similar example but it doesn't work.
- (IBAction)lightingLayer:(id)sender {
_Bool *isON = NULL;
isON = !isON;
if(isON) {
[_mapView addTileSource:[[RMMapBoxSource alloc] initWithMapID:#"MapID"]];
} else {
[_mapView removeTileSource:[[RMMapBoxSource alloc] initWithMapID:#"MapID"]];
}
This flags, incompatible integer to pointer conversion assigning bool from int. Can someone provide some simple code to help me achieve my goal. Thanks in advance for your time.
This error it's because you are assigning a bool value to a pointer. A pointer is nothing but a integer value, which holds a memory position as a hexadecimal number.
But actually, to accomplish what you want, you don't need a pointer, just use a property to store this bool and create a toggle funcionality.
declare this private property:
#property (strong, assign) BOOL isChecked;
And in your action:
- (IBAction)lightingLayer:(id)sender {
self.isChecked = !self.isChecked;
if(self.isChecked) {
[_mapView addTileSource:[[RMMapBoxSource alloc] initWithMapID:#"MapID"]];
} else {
[_mapView removeTileSource:[[RMMapBoxSource alloc] initWithMapID:#"MapID"]];
}
}
Ps: I only focused here in explain the error you are getting now. This add/remove tile logic is probably wrong too. I think you still would have to save the same reference to be added and later removed.
Do this way
BOOL isON;
- (IBAction)lightingLayer:(id)sender {
if(isON) {
[_mapView addTileSource:[[RMMapBoxSource alloc] initWithMapID:#"MapID"]];
isON=NO;
} else {
[_mapView removeTileSource:[[RMMapBoxSource alloc] initWithMapID:#"MapID"]];
isON=YES;
}
This is what I went with. It's a slight adjustment from Lucas' answer. This will alternate turning the map on an off. Thanks for the responses.
//.h
#property BOOL *isChecked;
//.m
self.isChecked = !self.isChecked;
if((self.isChecked)) {
[_mapView addTileSource:onlineSource atIndex:1];
} else {
[_mapView setHidden:YES forTileSourceAtIndex:1 ];
I have about 10 draggable objects in my game that need to be removed entirely from the game at certain points, no use of these objects is required until a new game is started...
currently i say self.imageView = nil
However, the more images i discard this way, the slower the game becomes. I believe it is because the images are not completely gone and they are all being put at (0, 0) even though they are out of the view.
How else can i get rid of these image views in order to increase my performance?
Here is how I add the images to my view:
#interface GameView : UIView
{
UIImage *ball;
}
#property UIImageView *redBall;
-(id)initWithBallImage:(UIImageView *)ball;
#implementation GameView
-(id)initWithBallImage:(UIImageView *)ball
{
self = [super init]
if (self)
{
_redBall = ball;
return self;
}
return nil;
}
-(void)spawnBallWithColor:(BallColor)ballColor intoArray:(NSMutableArray *)array atPoint:(CGPoint)point
{
switch (ballColor) {
case kRedBall:
ball = [UIImage imageNamed:#"redBall.png"];
self.redBall = [[UIImageView alloc] initWithImage:ball];
self.redBall.center = point;
[array addObject:self.redBall];
[self addSubview:self.redBall];
break;
}
//I use the above method in an initWithLevel: method...
Then to remove the object from the view...
[self.redBall removeFromSuperview];
[self.redBall removeFromSuperview];
You also need
self.redBall = nil;
And you need to remove it from that array you added it to.
Additionally
self.redBall = [[UIImageView alloc] initWithImage:ball];
Is leaking memory if you aren't using automatic reference counting.