iOS: Sable láser con UIAccelerometer y sonido (II)

Detalles del tutorial

  • Tecnología: iOS
  • Dificultad: Nivel medio
  • Tiempo de realización: 45 – 60 minutos

Vamos con la 2ª parte del tutorial del sable láser. Empezamos con la clase modelo de los sonidos del sable que llamaremos SaberSoundsModel. Aquí crearemos un array con todos los sonidos inicializados y listos para su reproducción.

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.

ios sable laser 6

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.

Valora esta entrada:

1 votos. Promedio: 3,00 de 5
1 Estrella2 Estrellas3 Estrellas4 Estrellas5 Estrellas

Entrada archivada en:

Categorías: iOS

Etiquetas:

★ Por Raúl Flores (11 entradas) el

Entradas relacionadas

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

*