I am trying to create an app for iPad and it's been fine so far, and now i am trying to make an object jump, so i've made it that it jumps up into the air and then falls down again, and thats working fine. but my problem comes when i want it to stop at the ground again, i thought CGRectIntersectsRect would work but it just doesn't work, i mean the object is clearly overlapping the ground image, but it's not stopping.
Code:
-(void)gameStatePlayNormal{
if(cubeState == CubeIsTouchingGround){
cubeVelocity.y = 0;
}
gravity = CGPointMake(0, kGravity);
cube.center = CGPointMake(cube.center.x, cube.center.y + cubeVelocity.y);
cubeVelocity.y += gravity.y;
if(touchState == Touch){
if(cubeState != CubeIsJumping){
cubeState = CubeIsJumping;
cubeVelocity.y = cubeVelocity.y -10;
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(cubejump) userInfo:nil repeats:NO];
}
}
}
-(void)cubejump{
if(cubeState == CubeIsJumping){
if(CGRectIntersectsRect(cube.frame, ground.frame)){
NSLog(#"Cube is touching the ground.");
cubeState = CubeIsTouchingGround;
cubeVelocity.y = 0;
}
}
}
and the .h file:
UIImageView *cube;
UIImageView *spike;
UIImageView *box;
UIImageView *ground;
}
-(void)gameStatePlayNormal;
#property (nonatomic, retain) IBOutlet UIImageView *cube;
#property (nonatomic, retain) IBOutlet UIImageView *spike;
#property (nonatomic, retain) IBOutlet UIImageView *box;
#property (nonatomic, retain) IBOutlet UIImageView *ground;
and of course everything is linked up in the .xib file, i can manipulate both the ground image and the cube image in other ways so those are linked to the variable in the xib file.
please help, i tried using the self.view.bounds.size.width as well but it didn't work for the lower part of the screen. please help :)
Related
can I loop through variables by it's name??
IBOutlet UIImageView *img1;
IBOutlet UIImageView *img2;
IBOutlet UIImageView *img3;
IBOutlet UIImageView *img4;
IBOutlet UIImageView *img5;
IBOutlet UIImageView *img6;
IBOutlet UIImageView *img7;
IBOutlet UIImageView *img8;
//then
for(int i = 1; i<=8;i++){
img+i = nil;
}
I know how to loop via tag, but is it posible to do it like this in objective C ??
Not directly, but you can add them to a temporary array or use IBOutletCollection
just for the record, you can do this (but dont do it, use the previous answer)
for(int i = 1; i<=8;i++){
SEL sel = NSSelectorFromString([NSString stringWithFormat:#"setImg%d:", i]);
[self performSelector:sel withObject:nil];
}
I got 30 of these codes, with the same implementation:
// .h
#interface ViewController : UIViewController{
IBOutlet UIImageView *circle;
IBOutlet UIImageView *circle2;
}
#property (nonatomic, retain) IBOutlet UIImageView *circle;
#property (nonatomic, retain) IBOutlet UIImageView *circle2;
// .m
#implementation ViewController
#synthesize circle;
#synthesize circle2;
- (void)viewDidLoad
{
circle = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"Circle.png"]];
circle2 = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"Circle.png"]];
}
And somewhere in my code, Im adding it as a subview.
My problem is,Is there a way to make it shorter, for it to be maintainable.
You can use one IBOutletCollection instead of 30 IBOutlets. You probably want to set the tag on each UIImageView though, so you can still tell them apart.
(This answer assumes you use a nib. Remove the lines where you instantiate the UIImageViews in viewDidLoad if so.)
If you use name like - Circle1.png, Circle2.png, then you can go for for loop for creating this in a loop.
Something like -
for (int i = 0; i < imageCount ; i++ ) {
circle = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:[NSString stringWithFormat: #"Circle%d.png" , i]]];
}
Is there a pattern to where you are putting these views in their superview? If so, you could use a for loop that goes to 30 and programmatically create the views and add them to their superview.
So for example:
for (i = 0; i < 100; i++)
{
UIImageView* circle = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"Circle.png"]];
[self.view addSubview:circle];
}
Would add 100 of the image views you would want. Of course you will need to adjust the positions of each of these views in the loop, but this is the general idea.
while creating this viewcontroller pass the frame as a parameter.thats the only thing changing rite??.the image is same and as there are no other properties .. it may work
I added 6 UIImageViews in Interface Builder.
Those are declared.
#property (nonatomic, strong) IBOutlet UIImageView *Image1;
#property (nonatomic, strong) IBOutlet UIImageView *Image2;
#property (nonatomic, strong) IBOutlet UIImageView *Image3;
#property (nonatomic, strong) IBOutlet UIImageView *Image4;
#property (nonatomic, strong) IBOutlet UIImageView *Image5;
#property (nonatomic, strong) IBOutlet UIImageView *Image6;
Those UIImageView' name has a rule - "Image" + number.
I want to select those ImageViews dinamically.
For example,
for (NSInteger i = 0; i < 6 ; i++) {
if(... condition )
{
//new
[[NSString stringWithFormat:#"Image%d", i+1] setHidden:YES]; //--(1)
}
else
{
[[NSString stringWithFormat:#"Image%d", i+1] setHidden:NO]; //--(2)
}
}
But, this code isn't correct.
Please tell me more good way.
jonkroll's suggestion to put your image views in an array is a good way to do it, and generally the highest performance.
Another way is to use key-value coding (KVC) to access your properties by name:
for (int i = 0; i < 6; ++i) {
NSString *key = [NSString stringWithFormat:#"Image%d", i + 1];
UIImageView *imageView = (UIImageView *)[self valueForKey:key];
imageView.hidden = condition;
}
Using the view tag, as Mark suggests, is a third way to do it. His answer is a little short on details, so I will provide some.
You can set the tag in your nib:
So you can set the tag of your Image1 image view to 1, and the tag of your Image2 image view to 2, and so on.
Then you can find an image view by its tag using the viewWithTag: method on your top-level view:
for (int i = 0; i < 6; ++i) {
[self.view viewWithTag:i+1].hidden = condition;
}
Create an array of your imageViews and iterate over them using fast enumeration:
NSArray *imageViewArray = [NSArray arrayWithObjects:self.Image1,self.Image2,self.Image3,self.Image4,self.Image5,self.Image6,nil];
for (UIImageView* imageView in imageViewArray) {
if(... condition ) {
[imageView setHidden:YES]; //--(1)
} else {
[imageView setHidden:NO]; //--(2)
}
}
typically you can use Tag to identify your views, instead of using the name of the view.
#property(nonatomic) NSInteger tag
see here:
https://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIView_Class/UIView/UIView.html
once you've set the tag, you can then do things like
if(uiview.tag == kSomeButtonTag)
I have implemented a custom class of UISlider so the touchable areas are larger
Everything is working great except now I want to change the initial values depending on other factors in the app.
The only code I have gets the slider's ID from (sender)
I need to address the slider like so...
slider.value = 25.0;
But the only code I have is
-(IBAction) slider1Changed:(id) sender{
UISlider *slider = (UISlider *) sender;
int progressAsInt =(int)(slider.value);
NSLog(#"Slider is %#",slider);
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setInteger:progressAsInt forKey:#"SharedSkilledWorkforce"];
}
In the xib #property (nonatomic, retain) UISlider *slider1; doesn't show up as a conncetion
How do I address the custom UISlider?
Have you tried adding IBOutlet to your slider1 property?
This:
#property (nonatomic, retain) UISlider *slider1;
Needs to be:
#property (nonatomic, retain) IBOutlet UISlider *slider1;
in order to show up in IB. IBOutlet is a hint to the designer similar to IBAction.
I am new to iphone and xcode. This may be a very simple question but I could not find an example code in books. I want to do the following:
Have 2 UIView on the screen
Each view will step through the color of the rainbow (red/orange/yellow/green/blue/indigo/violet) using gesture recognizer, e.g., if the current color is green, if the user swipes up the UIView changes to yellow, if the user swipes down the UIView changes to blue.
Hence, each view will need to keep the current color and respond to the swipes accordingly.
I understand how to implement the detection of swipes using gesture recognizer but I don't know how to have each view keep a separate variable for the current color. I want a generic code because there will be more than 2 UIViews in my application once I figure out how it is done.
Thanks in advance.
You can subclass UIView to include any variables that you like:
ColorSwiperView.h
#interface ColorSwiperView : UIView
{
ColorType currentColor;
}
#property (nonatomic, assign) ColorType currentColor;
#end
ColorSwiperView.m
#implementation ColorSwiperView
#synthesize currentColor;
- (id)initWithFrame:(CGRect)frameRect
{
if ((self = [super initWithFrame:frameRect]) == nil) { return nil; }
currentColor = red;
return self;
}
#end
To be used as follows:
#import "ColorSwiperView"
...
ColorSwiperView * cView = [[ColorSwiperView alloc] initWithFrame:...];
cView.currentColor = green;
Note: this assumes that you have defined an enum for the colors:
typedef enum
{
red = 0,
green = 1,
...
}
ColorType;
perhaps defining a subclass of UIView something like:
#interface RainbowView : UIView {
UIColor *currentColor;
}
#property (nonatomic, retain) UIColor *currentColor;
#end
and creating 2 (or more) views of that class in your view controller as outlets (if you're using interface builder):
#class RainbowView;
#interface RainBowViewController : UIViewController {
RainbowView *rainbowView1;
RainbowView *rainbowView2;
}
#property (nonatomic, retain) IBOutlet RainbowView *rainbowView1;
#property (nonatomic, retain) IBOutlet RainbowView *rainbowView2;
#end
Since you are going to maintain an array of colors, say colorsArray, and assign views their color from that selection. You can do this in the swipe handler.
- (void)handleSwipe:(UISwipeGestureRecognizer*)swipeGesture {
UIView *view = swipeGesture.view;
NSInteger currentColorIndex = [colorsArray indexOfObject:view.backgroundColor];
NSInteger nextColorIndex = currentColorIndex + 1;
if ( nextColorIndex == [colorsArray count] ) {
nextColorIndex = 0;
}
view.backgroundColor = [colorsArray objectAtIndex:nextColorIndex];
}
This way you don't need to subclass.
Subclassing
You can subclass UIView and add your own instance variables to it. Say,
#interface RainbowView: UIView {
NSInteger currentColorIndex;
}
#property (nonatomic, assign) NSInteger currentColorIndex;
...
#end
#implementation RainbowView
#synthesize currentColorIndex;
...
#end
In your gesture handling method,
- (void)handleSwipe:(UISwipeGestureRecognizer*)swipeGesture {
RainbowView *aView = (RainbowView*)swipeGesture.view;
// Get the next color index to aView.currentColorIndex;
aView.backgroundColor = [colorsArray objectAtIndex:nextColorIndex];
aView.currentColorIndex = nextColorIndex;
}