Disable accelerometer for a period of time then enable it - objective-c

I have an app where u can move a man with the accelerometer. There is a ready set go sequence and then using pop Animation the guy appears. Although even when the man is not visible and the ready set go words appear the accelerometer is still usable and u can move the guy and accidentally touch the obstacle which then using cgrectintersectsrect changes to An end game screen. So in that ready set go sequence how can I disable the accelerometer then reenable it when the go word appears?
.h:
#interface GameScreen : UIViewController <UIAccelerometerDelegate> {
IBOutlet UIImageView *image1;
IBOutlet UIImageView *image2;
UIImageView *ball;
CGPoint delta;
IBOutlet UIImageView *man;
IBOutlet UIImageView *fang;
IBOutlet UIImageView* hiddenView;
IBOutlet UILabel* ready;
IBOutlet UILabel* set;
IBOutlet UILabel* go;
IBOutlet UILabel* endScreen;
IBOutlet UIImageView* guy;
CAKeyframeAnimation *popAnimation;
}
#property (nonatomic, retain)UIImageView *image1;
#property (nonatomic, retain)UIImageView *image2;
-(void)checkCollision;
#property (nonatomic, retain)IBOutlet UIImageView *ball;
#property CGPoint delta;
#end
.m:
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
NSLog(#"x : %g", acceleration.x);
NSLog(#"y : %g", acceleration.y);
NSLog(#"z : %g", acceleration.z);
delta.y = acceleration.y * 50;
delta.x = acceleration.x * 50;
ball.center = CGPointMake(ball.center.x + delta.x, ball.center.y + delta.y);
// Right
if(ball.center.x < 0) {
ball.center = CGPointMake(320, ball.center.y);
}
// Left
if(ball.center.x > 320) {
ball.center = CGPointMake(0, ball.center.y);
}
// Top
if(ball.center.y < 0) {
ball.center = CGPointMake(ball.center.x, 460);
}
// Bottom
if(ball.center.y > 460){
ball.center = CGPointMake(ball.center.x, 0);
}
[self checkCollision];
}

You really should be reading a good book on coding and doing some tutorials to get an idea of how to do this, but the concept of a flag is simple.
In the class where your man is moved have a bool called bCanMove or similar, and set that to false when the class is initialised.
Once your "ready, steady, go" sequence finishes you set that to true.
The next step is check this flag in the code where you perform your movement, obviously I can't see your code but I expect you've got a method with a name similar to didAccelerate — in there just check to see if the boolean is true or not, and don't do anything if it isn't, for example:
if(!bCanMove)
{
return;
}
As I can't see your code I don't know whether you're relying on inbuilt mechanisms etc., but as other people have stated (and myself) you shouldn't really be asking these kinds of questions on here — not because you're new to coding but more the way you've phrased the question, nobody can really help without any details and it's something you would't need to ask if you did a little more reading ;)
At a bare minimum you should read this: http://cocoadevcentral.com/d/learn_objectivec/ but that's not going to help you if you don't understand some basic programming concepts (and it would appear you don't) — for that there is no substitute for a good book/tutorial.

Related

How can I rotate a UIImageView?

i'm pretty new to Xcode, and i was wondering how to rotate a uiimage on touch down, this is what i have currently:
#implementation secondViewController
int degrees;
UIImageView *gliderImageView;
bool continueSpinning;
-(void)startSpinning {
degrees = 0;
continueSpinning = true;
[self continueSpinning];
}
-(void)continueSpinning {
degrees = (degrees + 1) %360;
CGAffineTransform rotate = CGAffineTransformMakeRotation( degrees / 180.0 * 3.14);
[gliderImageView setTransform:rotate];
if(!continueSpinning) return;
else [self performSelector:#selector(continueSpinning) withObject:nil afterDelay:0.1f];
}
-(void)stopSpinning {
continueSpinning = false;
}
so does anyone know
how to link the button to the image
how to set a boolean with a button
if this code will work in the first place?
You can find an example of rotating a UIImage here.
So just in your .h write this:
(in the #interface)
IBOutlet UIImage *myImage;
IBOutlet UIButton *myButton;
(after the #interface closing bracket)
#property (nonatomic, retain) IBOutlet UIImage *myImage;
#property (nonatomic, retain) IBOutlet UIButton *myButton
-(IBAction) spinIt:(id)sender;
Then in your .m write:
Under the #implementation:
#synthesize myImage, myButton;
Then below the end of the viewDidLoad write something like this:
-(IBAction)spinIt:(id)sender {
myImage.image = image;
[self addSubview:imageView];
CGAffineTransform rotate = CGAffineTransformMakeRotation( 1.0 / 20.0 * M_PI );
[imageView setTransform:rotate];
}
The above code is from here.
After that add an image and a button to your view in the Storyboard and set up the references by control dragging from the button to the responder and clicking the spinIt method and by control dragging from the outlet names on the far right in the connections tab under the little arrow icon to their respective connections.
The above code rotates 90 degrees so you may want to change it to fit your needs. Also, this is a duplicate question, so in the future please search before posting. Good luck!
EDIT- If you want the image to spin while the button is being pressed I recommend making an array of images of it at different intervals in the spin and playing the images like a stop motion animation. Instructions on that can be found [here]3.

GPUImage animated gaussian blur filter

I was using the GPUImage gaussian blur filter to blur a still image. I want to tie the blur size to an UI element and as the element is changed by the user I blur the picture. The way I am doing it right now is to change the blurSize when there has been a significant (> 0.25) change, reapply the filter and animate the new image into the imageView.
Is there a more efficient way for me to be doing this?
On the iPhone 5, while performance is not laggy, it is not super smooth either (but perhaps that is because this operation is simply too expensive to be super smooth).
interesting question. Your best bet is to pre-compute and render CGImages at a couple of blur scales in your range, then use two stacked UIImageViews, with the one on top showing the blurrier copy but partially transparent. For example, if you rendered blurred at radiuses 1,2,3,…,10, and you wanted to show 3.7, you'd show image 3 on the bottom and image 4 on the top, at 70% opacity.
// Created in answer to Nikhil Varma's question at http://stackoverflow.com/questions/18804668/gpuimage-animated-gaussian-blur-filter
#import "GPUImage.h"
#define BLUR_STEP 2.
#interface AHViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIImageView *imageView2;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (nonatomic) CGFloat blurRadius;
#property (nonatomic, strong) UIImage *image;
#property (nonatomic, strong) GPUImageGaussianBlurFilter *blurFilter;
#property (nonatomic, strong) NSCache *blurredImageCache;
#property (nonatomic, strong) dispatch_queue_t blurQueue;
#property (nonatomic, strong) NSMutableSet *blurAmountsBeingRendered;
#end
#implementation AHViewController
-(void)viewDidLoad {
[super viewDidLoad];
self.image = [UIImage imageNamed:#"ph.jpg"];
self.blurFilter = [GPUImageGaussianBlurFilter new];
self.blurredImageCache = [NSCache new];
self.blurQueue = dispatch_queue_create("Image Blur Queue", DISPATCH_QUEUE_SERIAL);
self.blurAmountsBeingRendered = [NSMutableSet set];
self.blurRadius = 1.0;
}
- (IBAction)sliderDidMove:(UISlider *)sender {
self.blurRadius = 10 * sender.value;
}
-(void)setBlurRadius:(CGFloat)blurRadius {
_blurRadius = blurRadius;
CGFloat smaller = self.blurRadius - fmodf(self.blurRadius, BLUR_STEP);
[self asyncGenerateImageWithBlurAmount:smaller];
CGFloat larger = smaller + BLUR_STEP;
[self asyncGenerateImageWithBlurAmount:larger];
}
-(UIImage *)cachedImageWithBlurAmount:(CGFloat)blur {
return [self.blurredImageCache objectForKey:#(blur)];
}
-(void)asyncGenerateImageWithBlurAmount:(CGFloat)blur {
// This image is already available.
if([self.blurredImageCache objectForKey:#(blur)]) {
[self imageIsAvailableWithBlur:blur];
return;
}
// There's already a render going on for this. Just return.
if([self.blurAmountsBeingRendered containsObject:#(blur)])
return;
// Start a render
[self.blurAmountsBeingRendered addObject:#(blur)];
dispatch_async(self.blurQueue, ^{
self.blurFilter.blurSize = blur;
UIImage *result = [self.blurFilter imageByFilteringImage:self.image];
[self.blurredImageCache setObject:result forKey:#(blur)];
[self.blurAmountsBeingRendered removeObject:#(blur)];
dispatch_async(dispatch_get_main_queue(), ^{
[self imageIsAvailableWithBlur:blur];
});
});
}
-(void)imageIsAvailableWithBlur:(CGFloat)blurAmount {
CGFloat smaller = self.blurRadius - fmodf(self.blurRadius, BLUR_STEP);
CGFloat larger = smaller + BLUR_STEP;
UIImage *sharperImage = [self cachedImageWithBlurAmount:smaller];
UIImage *blurrier = [self cachedImageWithBlurAmount:larger];
if(sharperImage && blurrier) {
if(![self.imageView.image isEqual:sharperImage])
self.imageView.image = sharperImage;
if(![self.imageView2.image isEqual:blurrier]) {
self.imageView2.image = blurrier;
}
self.imageView2.alpha = (self.blurRadius - smaller) / BLUR_STEP;
}
}
#end

NSMutableArray not letting me access object?

I am extremely new to objective-c and iPhone programming (although, i have a little more background with C#), and I am learning by doing.
I am currently trying to make a mini platform game and instead of checking each platform on its own to see if my player intersects with it, I want to make an array and a for statement which will take care of that. (Correct me if i am wrong but NSMutableArray seems a lot like the List feature in C#)
I typed what i think would work but it hasn't, any ideas why? In my #interface I have:
#interface ViewController : UIViewController
{
NSMutableArray *platforms;
UIImageView *platform1;
UIImageView *platform2;
UIImageView *platform3;
UIImageView *platform4;
UIImageView *platform5;
UIImageView *player;
}
#property (nonatomic) NSInteger GameState;
#property IBOutlet UIImageView *player;
#property IBOutlet UIImageView *platform1;
#property IBOutlet UIImageView *platform2;
#property IBOutlet UIImageView *platform3;
#property IBOutlet UIImageView *platform4;
#property IBOutlet UIImageView *platform5;
And in my #implementation i have:
- (void)viewDidLoad
{
[super viewDidLoad];
[NSTimer scheduledTimerWithTimeInterval:1.0/60 target:self selector:#selector(gameLoop) userInfo:nil repeats:YES];
gravity = CGPointMake(0,0.195);
[platforms addObject:platform1];
[platforms addObject:platform2];
[platforms addObject:platform3];
[platforms addObject:platform4];
[platforms addObject:platform5];
}
- (void)gameLoop
{
playerVelocity = CGPointMake(playerVelocity.x,playerVelocity.y + gravity.y);
player.center = CGPointMake(player.center.x + playerVelocity.x,player.center.y + playerVelocity.y);
for(UIImageView *platform in platforms)
{
if(CGRectIntersectsRect(platform.frame,player.frame))
{
BOOL check = YES; //break point here to check if it reaches this point
}
}
}
Also, when i simply type:
if(CGRectIntersectsRect(platform1.frame,player.frame))
{
BOOL doubleCHECK = YES;
}
It works.
You failed to allocate your platforms array. All objects in objective-c are pointers, therefore, probably in your viewDidLoad method, you need a line of code like this:
platforms = [[NSMutableArray alloc] init];
If you check platforms before the loop, I believe you will find that it is nil. You need to create it before you use it (viewDidLoad is probably the best place, unless you need it before the view is loaded) - and unlike some languages, operating on a null object will silently return 0, not throw an exception.

pass slider value to subview

I have a UISlider placed in my main view and I have added a subview UIView (via interface builder) that I have associated with its own class SecondView. I need to pass the value of the slider to my sub view to move a point in the sub view when the slider changes.
I have made changes to the original code and the the below paragraph no longer is accurate. I used used the suggested changes offered by #MatthiasBauch.
I thought it would be simple a matter of sharing an iVar between the two. I created an iVar myPoint using #property (if this is still considered an iVar) in my ViewController interface, set myPoint = sliderValue.value in my ViewController implementation in the IBAction for when the slider value changes. Then in my SecondView implementation I #import "ViewController.h" then call my call my iVar in my SecondView implementation but the way I have done it it only returns nil or 0 instead of the slider value.
I don't want to use global variables.
I have looked at other post that seem to be asking a similar question but I'm still missing the concept, I guess. My code is below.
ViewController.h
#import <UIKit/UIKit.h>
#import "SecondView.h"
#interface ViewController : UIViewController
{
SecondView *secondView; // Do I need this with secondView declared as a #property below?
}
#property (nonatomic, retain) SecondView *secondView;
- (IBAction)sliderChanged:(id)sender;
#property (weak, nonatomic) IBOutlet UISlider *sliderValue;
#property (weak, nonatomic) IBOutlet UILabel *myLabel;
#property (weak, nonatomic) IBOutlet UIView *myView;
#end
ViewController.m
#import "ViewController.h"
#import "SecondView.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize sliderValue, myLabel, myView, secondView;
- (void)viewDidLoad
{
[super viewDidLoad];
secondView.thePoint = 50;
NSLog(#"%f", secondView.thePoint); // This is retuning a zero
}
- (IBAction)sliderChanged:(id)sender
{
secondView.thePoint = sliderValue.value;
myLabel.text = [NSString stringWithFormat:#"%.2f", sliderValue.value];
[secondView setNeedsDisplay];
}
#end
SecondView.h
#import <UIKit/UIKit.h>
#interface SecondView : UIView
#property (assign, nonatomic) CGFloat thePoint;
#end
SecondView.m
#import "SecondView.h"
#implementation SecondView
#synthesize thePoint;
- (void)drawRect:(CGRect)rect
{
float aPoint = thePoint;
NSLog(#"%f", aPoint); // this is retuning 0.000000
UIBezierPath *point = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(aPoint, 100, 4, 4)];
[point fill];
}
#end
Tell the view where to draw and don't ask the (newly allocated) viewController where to draw.
You are allocating a new viewController, this viewController of course does not know the value you set in the viewController where you actually changed the slider.
This won't work. Those two viewControllers are not the same instance. They share the same class, but that's it. Values from one viewController instance don't magically appear in a second instance.
Instead you should set a point property of the secondary view in your slider action.
Something like this:
Add a float #property to your view
#interface SecondView : UIView
#property (assign, nonatomic) CGFloat point;
#end
to draw use that point and not the initial value from a new ViewController instance.
- (void)drawRect:(CGRect)rect
{
float aPoint = self.point;
UIBezierPath *point = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(aPoint, 100, 4, 4)];
[point fill];
}
and set the point property of the secondary view in the slider action
- (IBAction)sliderChanged:(id)sender
{
secondView.point = sliderValue.value;
[secondView setNeedsDisplay]; // you might be able to omit that
myLabel.text = [NSString stringWithFormat:#"%.2f", myPoint];
}
Your ViewController has a property called #myView which points to the instance of SecondView created by the runtime.
So, your ViewController's implementation could call the drawRect: method on myView and pass in the relevant coordinates.
Here's some pseudo code for your ViewController.
- (IBAction)sliderChanged:(id)sender
{
myPoint = sliderValue.value;
myLabel.text = [NSString stringWithFormat:#"%.2f", myPoint];
[myView drawRect:CGRectMake(myPoint, 100, 4, 4)];
}
Note however that in your ViewController, myView is just a UIView, not a SecondView. You have a few choices on how to resolve this. The cleanest way is probably to remove the #import ViewController.h from SecondView and instead do the opposite. That is, have ViewController do an #import SecondView.h, then promote myView to a SecondView.
If that doesn't work for some reason (for example, if XCode demands that it remain strictly a UIView), you can still upcast the myView property at runtime like this:
[(*SecondView)myView drawRect:CGRectMake(myPoint, 100, 4, 4)];
Alternatively, you could point your slider's action at myView like the answer to this question does for a button: subclass UIView actions in viewcontroller
As usual in programming, there are several possible solutions. It's up to you to pick the best one for you. Good luck!

Clickable search icon in NSSearchField and fading background

I would like to make an NSSearchField, just like the one in Ecoute 3.0.
The search icon in the search field should be clickable and expand and collapse if you click it.
How can you achieve this?
I have searched the documentation, but didn't come up with anything useful.
I could implement the expanding with the animator proxy, so that is clear.
Another thing is that the background fades in/fades out as it expands/collapses.
How can I achieve this?
I would be thankful for any advices, sample code, etc.
EDIT
Ok I found the first part out myself.
- (void) resetSearchButtonCell {
NSButtonCell *c= [[NSButtonCell alloc] init];
[c setButtonType:NSMomentaryChangeButton]; // configure the button
[c setBezelStyle:NSRegularSquareBezelStyle]; // configure the button
[c setBordered:NO];
[c setBezeled:NO];
[c setEditable:NO];
[c setImagePosition:NSImageOnly];
[c setImage:[NSImage imageNamed:#"search"]];
[c setAlternateImage:[NSImage imageNamed:#"search-pushed"]];
[c setTarget:self];
[c setAction:#selector(_search:)];
[self setSearchButtonCell:c];
}
Now, I have made a property isCollapsed, which I toggle in _search:.
And in the setIsCollapsed: setter method I do the following:
NSRect newRect = self.frame;
if (_isCollapsed) {
newRect.size.width = kCollapsedWidth;
} else {
newRect.size.width = kEXpandedWidth;
}
[[self animator] setFrameSize:newRect.size];
But for some reason the frame is being reset to the initial size, the one set in Interface Builder, when the NSSearchField gets or looses focus.
Can anyone tell me why?
EDIT
I have solved that problem too. It was auto-layout, which messed up the animation.
Now, the only thing remaining is the background-alpha, which should change.
I could redraw the entire thing, but is there another solution where I could just modify the alpha of only the background and the cancel-button?
I wanted to do something similar. ITSearchField is very solid and nice. However, I desired to expand the search field once it gained focus. As one might find out quickly the NSSearchfield is comprised of many components and layers.
Here is what I wrote to get it to work...
Note: It works on 10.7 or greater. Also you must hook-up the layout constraint of the search field control's width in IB to the outlet.
.h
#interface MySearchField : NSSearchField
#end
.m
#pragma mark - Implementation: Search Field Control
#interface MySearchField()
#property (readwrite, nonatomic, getter=isExpanded) BOOL expand;
#property (readwrite, nonatomic, getter=hasFocusRing) BOOL focusRing;
#property (readwrite, strong, nonatomic) NSTimer *expandTimer;
#property (readwrite, strong, nonatomic) IBOutlet NSLayoutConstraint *widthConstraint;
#property (readwrite, nonatomic) CGFloat searchWidth;
#end
static NSTimeInterval const kSearchFieldTime = 0.5;
#implementation MySearchField
#synthesize expand, focusRing;
#synthesize expandTimer, searchWidth;
#synthesize widthConstraint;
#pragma mark Timer Methods:
- (void) resizeSearchField {
if ( self.hasFocusRing ) {
if ( !self.isExpanded ) {
self.searchWidth = self.widthConstraint.constant;
[[self.widthConstraint animator] setConstant:(self.searchWidth * 2)];
self.expand = YES;
} } else {
if ( (self.isExpanded) &&
((!self.stringValue) || ([self.stringValue isEqualToString:#""])) ) {
[[self.widthConstraint animator] setConstant:self.searchWidth];
self.expand = NO;
} }
}
- (void) stopTimer {
if ( self.expandTimer )
[self.expandTimer invalidate];
self.expandTimer = nil;
}
- (void) startTimer {
[self stopTimer];
SEL resizeSelector = #selector(resizeSearchField);
NSMethodSignature *expandSignature = [MySearchField instanceMethodSignatureForSelector:resizeSelector];
NSInvocation *expandInvocation = [NSInvocation invocationWithMethodSignature:expandSignature];
[expandInvocation setSelector:resizeSelector];
[expandInvocation setTarget:self];
self.expandTimer = [NSTimer scheduledTimerWithTimeInterval:kSearchFieldTime invocation:expandInvocation repeats:NO];
}
#pragma mark Override Methods:
- (void) noteFocusRingMaskChanged {
self.focusRing = !NSEqualRects(NSZeroRect, self.focusRingMaskBounds);
[self startTimer];
[super noteFocusRingMaskChanged];
}
#end
Ok that's it really.
You get notified when the focus ring changes and start a quick timer method.
The timer is necessary for when you click the search field's cancel button which resets the control.
The only thing the timer does is fire the resizeSearchField method.
Update: Oh yeah, don't forget to set the class of your Search Field control in IB to MySearchField or whatever you want to call it.
Enjoy!
I ended up redrawing the background. Like this I was able to set the alpha of it.
The source code is available on Github:
https://github.com/iluuu1994/ITSearchField