Detalles del tutorial
- Tecnología: iOS
- Dificultad: Nivel medio
- Tiempo de realización: 45 - 60 minutos
Modelo de sonidos SaberSoundsModel
Creamos una nueva clase Objetive-C que sea subclase de NSObject y la llamamos SaberSoundsModel. Aquí creamos 2 Arrays, uno con los nombres de los ficheros de audio, filesArray, que recorreremos para llenar saberSoundsArray con los objetos de sonido. Como vereis saberSoundsArray es una property para poder acceder posteriormente. No se te olvide importar AVFoundation/AVFoundation para manejar los objetos de audio.
#import <Foundation/Foundation.h> @interface SaberSoundsModel : NSObject{ NSMutableArray *saberSoundsArray; NSArray *filesArray; } @property (nonatomic, strong) NSMutableArray *saberSoundsArray; @end
#import "SaberSoundsModel.h" #import <AVFoundation/AVFoundation.h> @implementation SaberSoundsModel @synthesize saberSoundsArray=_saberSoundsArray; -(id)init { if ((self = [super init])) { //array con todos los nombres de los archivos de sonido filesArray = [NSArray arrayWithObjects:@"sabramb1.wav", @"ltsaberon01.wav", @"ltsaberoff01.wav", @"sabrswg1.wav", @"sabrswg2.wav", @"sabrswg6.mp3", @"sabrswg4.mp3", @"sabhit1.WAV", @"sabhit2.WAV", @"sabhit3.WAV", @"ltsaberhit15.wav", @"espadazo1.wav", @"espadazo2.wav", @"espadazo3.wav", nil]; //array que contendrá los objetos de sonidos self.saberSoundsArray = [NSMutableArray arrayWithObjects: nil]; for (int i=0; i<[filesArray count]; i++) { NSString *file = [NSString stringWithFormat:@"%@", [[filesArray objectAtIndex:i] description] ]; NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] resourcePath],file]]; AVAudioPlayer *sound = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil] ; [_saberSoundsArray addObject:sound]; } //NSLog(@"saberSoundsArray: %@",[_saberSoundsArray description]); } return self; } @end
Ahora vamos a AppDelegate para inicializar el modelo de sonidos y pasarlo a ViewController ya inicializado. Crearemos en ViewController una property llamada saberSoundsArray para darle valor desde AppDelegate.
#import <UIKit/UIKit.h> @class SaberSoundsModel; @interface AppDelegate : UIResponder <UIApplicationDelegate>{ SaberSoundsModel *saberSoundsModel; } @property (strong, nonatomic) UIWindow *window; @end
#import "AppDelegate.h" #import "SaberSoundsModel.h" #import "ViewController.h" @implementation AppDelegate @synthesize window = _window; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. //inicializamos modelo saberSoundsModel = [[SaberSoundsModel alloc] init]; //sacamos viewController desde la jerarquía de window ViewController *viewController=(ViewController *)self.window.rootViewController; //pasamos a saberSoundsArray el modelo inicializado anteriormente [viewController setSaberSoundsArray: [saberSoundsModel saberSoundsArray ]]; return YES; } //el resto de código generado por Xcode lo dejamos tal cual
#import <UIKit/UIKit.h> @interface ViewController : UIViewController{ NSMutableArray *saberSoundsArray; } //creamos la property @property (nonatomic, strong) NSMutableArray *saberSoundsArray; - (IBAction)startLaser:(id)sender; @end
//sintetizamos la property @synthesize saberSoundsArray=_saberSoundsArray; - (void)viewDidUnload { [super viewDidUnload]; //liberamos saberSoundsArray self.saberSoundsArray = nil; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; }
Clase SaberOnViewController
SaberOnViewController será la clase encargada de controlar la vista que hará posible visualizar el sable láser. Creamos de la manera habitual una nueva clase que sea subclase de UIViewController, le añadimos una property llamada saberSoundsArray y la sintetizamos.
#import <UIKit/UIKit.h> @interface SaberOnViewController : UIViewController{ NSMutableArray *saberSoundsArray; } @property (nonatomic, strong) NSMutableArray *saberSoundsArray; @end
@synthesize saberSoundsArray = _saberSoundsArray; - (void)viewDidUnload { [super viewDidUnload]; self.saberSoundsArray=nil; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; }
Clase ViewController
Ahora vamos a añadir el código necesario a la función startLaser de ViewController para que tome el control la clase SaberOnViewController de manera modal con presentModalViewController. Primero importamos SaberOnViewController y AudioToolbox/AudioToolbox para la vibración.
#import "SaberOnViewController.h" //añadimos este framework para que se pueda acceder a la vibración #import <AudioToolbox/AudioToolbox.h>
Después vamos a ViewController.m y metemos código en la función startLaser. A este controlador le pasamos el modelo saberSoundsArray.
- (IBAction)startLaser:(id)sender { //vibración AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); //inicializo SaberOnViewController de nombre controller SaberOnViewController *controller = [[SaberOnViewController alloc] init]; //pasamos el modelo a controller [controller setSaberSoundsArray: _saberSoundsArray]; //presentamos controller de manera modal [self presentModalViewController:controller animated:YES]; }
Vista SaberOnView
Vamos a crear una vista mediante código exclusivamente que contendrá la imagen del sable láser, para lo cual creamos una nueva clase que sea subclase de UIView.
En el código de esta clase/vista tendremos una property xShift que será para indicar el desplazamiento horizontal que se aplicará dependiendo del acelerómetro. (El sable se mueve en el eje x de la pantalla dependiendo del movimiento aplicado al iPhone). También tendremos la imagen del fondo y la del sable, siendo esta última la que se va a desplazar manteniendo la otra estática. Para salir del modo láser bastará con tocar la pantalla por lo que canBecomeFirstResponder debe de responder YES.
#import <UIKit/UIKit.h> @interface SaberOnView : UIView { float xShift; CGImageRef image; } @property (nonatomic, assign) float xShift; @end
#import "SaberOnView.h" @implementation SaberOnView @synthesize xShift; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code //fdo******************************** UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"fdo_Saber.png"]]; self.backgroundColor = background; //sable***************************** NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"sable.png" ofType:nil]; UIImage *img = [UIImage imageWithContentsOfFile:imagePath]; image = CGImageRetain(img.CGImage); } return self; } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code // What rectangle am I filling? CGRect bounds = [self bounds]; // Where is its center? CGPoint center; center.x = bounds.origin.x + bounds.size.width / 2.0; center.y = bounds.origin.y + bounds.size.height / 2.0; // Get the context being draw upon CGContextRef context = UIGraphicsGetCurrentContext(); center.x += xShift; CGRect imageRect; imageRect.origin = CGPointMake(center.x - 71, center.y -240); imageRect.size = CGSizeMake(143.0, 480.0); // Draw the image CGContextDrawImage(context, imageRect, image); } - (BOOL)canBecomeFirstResponder { return YES; } @end
Te animo a continuar con la 3ª y última parte de este tutorial en la que nos meteremos con el acelerómetro para disparar sonidos, vibración y mover el sable láser por el eje x de la pantalla.
Deja una respuesta