Accelerometer Coding Within One Class?

Discussion in 'iOS Programming' started by peacetrain67, Aug 30, 2009.

  1. peacetrain67 macrumors member

    Joined:
    Dec 20, 2007
    #1
    Here is my situation:
    I have followed a simple guide from the book 'Beginning iPhone Development' but would like to tweak one major aspect (I have tweaked a few things: adding a 'response' when the sprite hits the wall instead of just stopping the velocity, sped up the sprite, etc. = basic tweaks). What I want to do is use the sprite's animation (based off the accelerometer's orienation) on top of another ImageView that will be playng an animation in the background. The way the code is currently set up just loads everything without any user interaction. I would like the sprite, etc. to only show up after an action is called. Preferably, I would like to keep all the code within the same class as well, making the exit simpler as well. Thanks in advance: here is my current code:
    BallViewController.h
    Code:
    #define kUpdateInterval (1.0f/60.0f)
    #import <UIKit/UIKit.h>
    
    @interface BallViewController : UIViewController <UIAccelerometerDelegate> {
    }
    @end
    
    BallViewController.m
    Code:
    #import "BallViewController.h"
    #import "BallView.h"
    
    @implementation BallViewController
    
    - (void)viewDidLoad {
    	UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];
    	accelerometer.delegate = self;
    	accelerometer.updateInterval = kUpdateInterval;
        [super viewDidLoad];
    }
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
    }
    
    
    - (void)didReceiveMemoryWarning {
    	// Releases the view if it doesn't have a superview.
        [super didReceiveMemoryWarning];	
    	// Release any cached data, images, etc that aren't in use.
    }
    
    - (void)viewDidUnload {
    	// Release any retained subviews of the main view.
    	// e.g. self.myOutlet = nil;
    }
    
    
    - (void)dealloc {
        [super dealloc];
    }
    #pragma mark -
    - (void)accelerometer:(UIAccelerometer *)accelerometer
    		didAccelerate:(UIAcceleration *)acceleration {
    	[(BallView *)self.view setAcceleration:acceleration];
    	[(BallView *)self.view draw];
    }
    
    @end
    BallView.h
    Code:
    #define kVelocityMultiplier 1000
    #import <UIKit/UIKit.h>
    
    
    @interface BallView : UIView {
    	UIImage *image;
    	CGPoint currentPoint;
    	CGPoint previousPoint;
    	
    	UIAcceleration *acceleration;
    	CGFloat ballXVelocity;
    	CGFloat ballYVelocity;
    }
    @property (nonatomic, retain) UIImage *image;
    @property CGPoint currentPoint;
    @property CGPoint previousPoint;
    @property (nonatomic, retain) UIAcceleration *acceleration;
    @property CGFloat ballXVelocity;
    @property CGFloat ballYVelocity;
    
    -(void)draw;
    @end
    
    BallView.m
    Code:
    #import "BallView.h"
    
    @implementation BallView
    
    @synthesize image;
    @synthesize currentPoint;
    @synthesize previousPoint;
    @synthesize acceleration;
    @synthesize ballXVelocity;
    @synthesize ballYVelocity;
    
    -(id)initWithCoder:(NSCoder *)coder {
    	if (self = [super initWithCoder:coder]) {
    		self.image = [UIImage imageNamed:@"TealBall.png"];
    		self.currentPoint = CGPointMake((self.bounds.size.width / 2.0f) + (image.size.width /2.0f), (self.bounds.size.height / 2.0f) + (image.size.height / 2.0f));
    		
    		ballXVelocity = 0.0f;
    		ballYVelocity = 0.0f;
    	}
    	return self;
    }
    
    -(id)initWithFrame:(CGRect)frame {
    	if (self = [super initWithFrame:frame]) {
    		//Initialization code
    	}
    	return self;
    }
    
    -(void)drawRect:(CGRect)rect {
    	[image drawAtPoint:currentPoint];
    }
    
    -(CGPoint)currentPoint {
    	return currentPoint;
    }
    -(void)setCurrentPoint:(CGPoint)newPoint {
    	previousPoint = currentPoint;
    	currentPoint = newPoint;
    	
    	if (currentPoint.x < 0) {
    		currentPoint.x = 0;
    		ballXVelocity = - (ballXVelocity *.75);
    	}
    	if (currentPoint. y < 0) {
    		currentPoint.y = 0;
    		ballYVelocity = - (ballYVelocity *.75);
    	}
    	if (currentPoint.x > self.bounds.size.width - image.size.width) {
    		currentPoint.x = self.bounds.size.width - image.size.width;
    		ballXVelocity = - (ballXVelocity *.75);
    	}
    	if (currentPoint.y > self.bounds.size.height - image.size.height) {
    		currentPoint.y = self.bounds.size.height - image.size.height;
    		ballYVelocity = - (ballYVelocity *.75);
    	}
    	CGRect currentImageRect = CGRectMake(currentPoint.x, currentPoint.y, currentPoint.x + image.size.width, currentPoint.y + image.size.height);
    	CGRect previousImageRect = CGRectMake(previousPoint.x, previousPoint.y, previousPoint.x + image.size.width, currentPoint.y + image.size.width);
    	[self setNeedsDisplayInRect:CGRectUnion(currentImageRect, previousImageRect)];
    }
    
    -(void)draw {
    	static NSDate *lastDrawTime;
    	if (lastDrawTime != nil) {
    		NSTimeInterval secondsSinceLastDraw = 
    		-([lastDrawTime timeIntervalSinceNow]);
    		
    		ballYVelocity = ballYVelocity + -(acceleration.y * secondsSinceLastDraw);
    		ballXVelocity = ballXVelocity + acceleration.x * secondsSinceLastDraw;
    		
    		CGFloat xAcceleration = secondsSinceLastDraw *ballXVelocity * 1000;
    		CGFloat yAcceleration = secondsSinceLastDraw *ballYVelocity * 1000;
    		
    		self.currentPoint = CGPointMake(self.currentPoint.x + xAcceleration, self.currentPoint.y +yAcceleration);
    	}
    	[lastDrawTime release];
    	lastDrawTime = [[NSDate alloc] init];
    }
    
    - (void)dealloc {
    	[image release];
    	[acceleration release];
        [super dealloc];
    }
    
    @end 
    *All this code works on it's own, but I want to use it on top of a imageView within the first class (that code isn't included). I have all that stuff figured out easily and pretty much understand this code, but the pragma mark is tripping me up a little bit, as well as some of the calls from the first class. Once again, thanks in advance.
     
  2. Kingbombs macrumors member

    Joined:
    Jun 24, 2009
    #2
    Pragma mark isn't anything really code related
    When you click to view all your methods in that class it just puts a line there or says a title (it allows a class with lots of methods to be split up into sections so you can easily work out what each set of methods do in the program)
     
  3. peacetrain67 thread starter macrumors member

    Joined:
    Dec 20, 2007
    #3
    ya i just red into that a little more and realized that. I will look more into that later because the class I have does have a lot of methods (it's well over 2000 lines of code and will probably finish around 3000 lines of code). that was a dead end for how to make this work for me tho. I would be fine with calling the other class if I could tell be specific when to call. using a simple example:
    Code:
    //calls the imageview and the photos i am using
    myimageview.animationImages = [NSArray arrayWithObjects:
    	[UIImage imageNamed: @"MyBackground1.png"],
    	[UIImage imageNamed: @"MyBackground2.png"],
    	[UIImage imageNamed: @"MyBackground3.png"],
    	[UIImage imageNamed: @"MyBackground4.png"],
    	[UIImage imageNamed: @"MyBackground5.png"], nil];
    //sets the basic prefs for the imageview: repeatcount and duration
    	[myimageview setAnimationRepeatCount:0];
    	myimageview.animationDuration = 1;
    //starts the animation
    	myimageview startAnimating];
    //starts an animation to load the view that has the imageview
    	[UIView beginAnimations:nil context:nil];
    	[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
    	[UIView setAnimationDuration:.7];
    //loading the view which contains the imageview
    	imageviewcontainer.alpha = 1;
    	[UIView commitAnimations];
    what else would i need to add to call the ballview - in the code i showed earlier it is called from the viewDidLoad
    Code:
    	UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];
    	accelerometer.delegate = self;
    	accelerometer.updateInterval = kUpdateInterval;
        [super viewDidLoad];
    im going to throw that in my method (with the animation) and see what i can do... anybody else know how to handle this to shorten this XCode adventure...
     
  4. peacetrain67 thread starter macrumors member

    Joined:
    Dec 20, 2007
    #4
    Ive spent 2 days on this, posted to 2 threads, and I think I am close. I feel like I am close...
    *This is not my actual code, it skims out parts that are not needed to save you time... Everything involving the accelerometer is included, though...
    Here is where I am currently:
    BasicViewController.m
    Code:
    -(IBAction)startimageview:(id)sender
    {
    	NSLog(@"startimageview called");
    	//identifies the imageview and the images for it's animation
    	imageview.animationImages = [NSArray arrayWithObjects:
    	[UIImage imageNamed: @"MyBackground1.png"],
    	[UIImage imageNamed: @"MyBackground2.png"],
    	[UIImage imageNamed: @"MyBackground3.png"],
    	[UIImage imageNamed: @"MyBackground4.png"],
    	[UIImage imageNamed: @"MyBackground5.png"], nil];
    	//identifies the imageview repeatcount and duration
    	[imageview setAnimationRepeatCount:0];
    	imageview.animationDuration = 1;
    	//starts the imageview animation
    	[imageview startAnimating];
    	//identifies the fading transition of the view with the imageview
    	[UIView beginAnimations:nil context:nil];
    	[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
    	[UIView setAnimationDuration:.7];
    	imageviewcontainer.alpha = 1;
    	//starts that fading transition i just mentioned
    	[UIView commitAnimations];
    	//bunch of uninvolved code including a timer, another ball, etc.
    	NSLog(@"Accelerometer-Ball Called");
    	//accelerometer-calling code
    	UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];
    	accelerometer.delegate = self;
    	accelerometer.updateInterval = kUpdateInterval;
    }
    //1 gazillion more methods...
    - (void)accelerometer:(UIAccelerometer *)accelerometer
    		didAccelerate:(UIAcceleration *)acceleration {
    	//didAccelerate being called... [U][B][I]APP CRASHES HERE![/I][/B][/U]
    	NSLog(@"DidAccelerate Called");
    	[(AccelBall *)self.view setAcceleration:acceleration];
    	[(AccelBall *)self.view draw];
    }
    
    the app crashes where i implied that it crashed... now for the AccelBall code
    AccelBall.h
    Code:
    @interface AccelBall : UIView {
    	UIImage *BALLimage;
    	CGPoint BALLcurrentpoint;
    	CGPoint BALLpastpoint;	
    	UIAcceleration *acceleration;
    	CGFloat BALLxvelocity;
    	CGFloat BALLyvelocity;
    }
    @property (nonatomic, retain) UIImage *BALLimage;
    @property CGPoint BALLcurrentpoint;
    @property CGPoint BALLpastpoint;
    @property (nonatomic, retain) UIAcceleration *acceleration;
    @property CGFloat BALLxvelocity;
    @property CGFloat BALLyvelocity;
    
    -(void)draw;
    @end 
    AccelBall.m
    Code:
    #import "AccelBall.h"
    
    @implementation AccelBall
    
    @synthesize BALLimage;
    @synthesize BALLcurrentpoint;
    @synthesize BALLpastpoint;
    @synthesize acceleration;
    @synthesize BALLxvelocity;
    @synthesize BALLyvelocity;
    
    -(id)initWithCoder:(NSCoder *)coder {
    	//Never reaches here
    	NSLog(@"initWithCoder: coder");
    	//If anybody could elaborate on initWithCoder for me, that would be appreciated
    	if (self = [super initWithCoder:coder]) {
    	//Identifies my image "RedBall" as the BALLimage
    		self.BALLimage = [UIImage imageNamed:@"RedBall.png"];
    	//sets the current/starting point for the BALLimage
    		self.BALLcurrentpoint = CGPointMake((self.bounds.size.width / 2.0f) + (BALLimage.size.width / 2.0f),
    											(self.bounds.size.height / 2.0f) + (BALLimage.size.height / 2.0f));
    	//Sets the (0) velocity for the BALLimage
    		BALLxvelocity = 0.0f;
    		BALLyvelocity = 0.0f;
    	}
    	return self;
    }
    - (id)initWithFrame:(CGRect)frame {
        if (self = [super initWithFrame:frame]) {
            // Initialization code
        }
        return self;
    }
    - (void)drawRect:(CGRect)rect {
        [BALLimage drawAtPoint:BALLcurrentpoint];
    }
    -(CGPoint)BALLcurrentpoint {
    	return BALLcurrentpoint;
    }
    -(void)setBALLcurrentpoint:(CGPoint)BALLnewpoint {
    	//Changing the pastpoint to the currentpoint, newpoint to the currentpoint
    	BALLpastpoint = BALLcurrentpoint;
    	BALLcurrentpoint = BALLnewpoint;
    	//Sets up walls and wall response (bouncing off of the wall)
    	if (BALLcurrentpoint.x < 0) {
    		BALLcurrentpoint.x = 0;
    		BALLxvelocity = - (BALLxvelocity *.7);
    	}
    	if (BALLcurrentpoint.y < 0) {
    		BALLcurrentpoint.y = 0;
    		BALLyvelocity = - (BALLyvelocity *.7);
    	}
    	if (BALLcurrentpoint.x > self.bounds.size.width - BALLimage.size.width) {
    		BALLcurrentpoint.x = self.bounds.size.width - BALLimage.size.width;
    		BALLxvelocity = - (BALLxvelocity *.7);
    	}
    	if (BALLcurrentpoint.y > self.bounds.size.height - BALLimage.size.height) {
    		BALLcurrentpoint.y = self.bounds.size.height - BALLimage.size.height;
    		BALLyvelocity = - (BALLyvelocity *.7);
    	}
    	//Not sure exactly what this does? Creates a new position for the ball possibly?
    	CGRect currentImageRect = CGRectMake(BALLcurrentpoint.x, BALLcurrentpoint.y, BALLcurrentpoint.x + BALLimage.size.width, BALLcurrentpoint.y + BALLimage.size.height);
    	CGRect pastImageRect = CGRectMake(BALLpastpoint.x, BALLpastpoint.y, BALLpastpoint.x + BALLimage.size.width, BALLpastpoint.y + BALLimage.size.height);
    	[self setNeedsDisplayInRect:CGRectUnion(currentImageRect, pastImageRect)];
    }
    -(void)draw {
    	//Updating based off the last time the image was updated
    	static NSDate *lastdrawtime;
    	if (lastdrawtime != nil) {
    		NSTimeInterval secondssincelastdraw =
    		-([lastdrawtime timeIntervalSinceNow]);
    	//Setting speed (velocity)				
    		BALLyvelocity = BALLyvelocity + -(acceleration.y * secondssincelastdraw);
    		BALLxvelocity = BALLxvelocity + acceleration.x * secondssincelastdraw;		
    		CGFloat xAcceleration = secondssincelastdraw *BALLxvelocity *1000;
    		CGFloat yAcceleration = secondssincelastdraw *BALLyvelocity *1000;		
    		self.BALLcurrentpoint = CGPointMake(self.BALLcurrentpoint.x + xAcceleration, self.BALLcurrentpoint.y + yAcceleration);
    	}
    	//Releasing and refreshing the lastdrawtime from this method
    	[lastdrawtime release];
    	lastdrawtime = [[NSDate alloc] init];
    }
    
    - (void)dealloc {
    	//Releasing the BallImage and acceleration
    	[BALLimage release];
    	[acceleration release];
        [super dealloc];
    }
    
    @end 
    so, why is it crashing (look at the first class's code to see where it crashes...)
    *also would appreciate elabarotation on the few parts of the code I didn't fully grasp... That could help me find another way to do all this (specifically initWithCoder.. I could only find info on MAC OS when I searched for info on this - i had never previously seen it).
    If this helps:

    The Debugger Console Error:
     

Share This Page