3 de julio de 2008

Documentación Mp3Player - ActionScript 2.0

Hola !

Les traigo una api que hice hace un tiempo pero se me había pasado compartirlo, es para hacer reproductores mp3 en flash con actionscript 2.0, es muy sencillita de utilizar.

Documentación:

------------------------------------------------------------------------------------------------

Paquete: com.jahepi.mp3player
Clase: public class Track
Herencia: Object

Encapsula las propiedades básicas de una pista.

Propiedades Públicas


url:String
Dirección del mp3.

name:String
Nombre del mp3.

------------------------------------------------------------------------------------------------

Paquete: com.jahepi.mp3player
Clase: public class Player
Herencia: Object

La clase Player te permite crear reproductores flash de manera sencilla, el objetivo de esta clase era el no acoplar los elementos gráficos y así tener la libertad de realizar tus propios diseños de reproductores.

Se emplearon 3 patrones de diseño para la realización, uno de ellos el Singleton, esto quiere decir que solamente se puede obtener una instancia de la clase Player, esto lo hice porque en las aplicaciones se utiliza un solo reproductor por lo general.

Además con Singleton tenemos un acceso global a nuestra instancia.

El siguiente fue el Patrón de Estado, para manejar los diferentes estados en el que puede estar un reproductor como cuando esta en pausa, en reproducción, etc., y por último uno que va de la mano con el Patrón de Estado , una Fábrica-Peso Ligero para no estar creando instancias de nuestros estados cada ves que se requieran.

Propiedades Públicas

stream:Bolean
Valor booleano que indica si la carga del mp3 se hace en modo stream.

volume:Number
Número del 0 al 100 que indica el volumen del track en reproducción.

Métodos Públicos

[Static] getInstance:Player
Con este método estático obtenemos la instancia de nuestro Player.

addTrack(track:Track):Void
Añade un objeto track a la lista de reproducción.

removeTrackAt(index:Number):Track
Remueve un objeto track de la lista de reproducción.

getTrackAt(index:Number):Track
Obtenemos un objeto track de la lista de reproducción de acuerdo al índice pasado como parámetro.

tracksIterator():IIterator
Devuelve un objeto iterador para recorrer la lista de reproducción.

playTrackAt(index:Number):Void
Inicia la reproducción de un track de la lista de reproducción de acuerdo al índice pasado como parámetro.

playNextTrack():Void
Inicia la reproducción del siguiente track en la lista de reproducción.

playPrevTrack():Void
Inicia la reproducción del anterior track en la lista de reproducción.

getCurrentTrack():Track
Obtenemos el track actual de la lista de reproducción.

stop():Void
Cancela la reproducción del track actual en la lista.

play():Void
Inicia la reproducción del track actual de la lista.

pause():Void
Pausa la reproducción del track actual de la lista.

getSeconds():Number
Obtenemos el número de segundos de la reproducción del track actual de la lista.

getTrackLoadPercentage():Number
Obtenemos el porcentaje de carga del track actual de la lista.

getTrackPlayingPercentage():Number
Obtenemos el porcentaje de reproducción del track actual de la lista.

setTrackPosition(percentage:Number):Void
Cambiamos la posición de reproducción del track actual, el parámetro percentage debe se un número entre el 0 y 100, como 10.2, 99, 32.45, etc…, si el player esta en modo stream y se pone un porcentaje mayor al cargado, este se ajustará automáticamente.

Eventos

TRACKLOADINGPROGRESS
Evento que se dispara cada ½ segundo cuando empieza la carga del track hasta finalizar.

TRACKLOADINGSTART
Evento que se dispara cuando la carga del track inicia.

TRACKLOADINGCOMPLETE
Evento que se dispara cuando la carga del track finaliza.

TRACKCOMPLETE
Evento que se dispara cuando finaliza la reproducción total del track.

TRACKPLAYING
Evento que se dispara cada ½ segundo cuando el track esta en reproducción hasta finalizar.

ERROR
Evento que se dispara al ocurrir un error inesperado.

------------------------------------------------------------------------------------------------

Les dejo el archivo junto a un ejemplo para que vean cómo se utiliza, cualquier pregunta no duden en contactarme.

ARCHIVO

Ojalá les sea útil.

Un saludote !

21 de junio de 2008

Librería MaskSquareEffect - ActionScript 2.0

MaskSquareEffect es una librería que te permite realizar varios efectos de mascara con cuadros en flash, aquí hay un panel para que pruebes los distintos efectos que se pueden generar:

Ejemplo

Esta versión utiliza el motor de animaciones TweenLite, el rendimiento ha mejorado muchísimo, en comparación al motor que viene por defecto en flash (Tween).

¿ Cómo la utilizo ?

Bajen primero el archivo

MaskSquareEffect.zip

Primero debemos descomprimir el archivo, vamos a ver una carpeta “com”, esta la extraemos dentro del proyecto donde vamos a aplicar los efectos.

La clase principal es MaskSquareEffect, se encuentra en el paquete com.jahepi.squareeffect.

DOCUMENTACIÓN MASKSQUAREEFFECT

CONSTRUCTOR

1.- MaskSquareEffect(target:MovieClip, rows:Number, columns:Number, fadeIn:Boolean)

Descripción:
Crea un nuevo objeto MaskSquareEffect.

Parámetros:

target: El nombre de instancia del movieclip al cual le queremos dar el efecto.
rows: El número de filas que va a ser dividido el movieclip para hacer el efecto.
columns: El número de columnas que va a ser dividido el movieclip para hacer el efecto.
fadeIn: Indica si el efecto aparece o desaparece el movieclip.

Ejemplo:
var effect:MaskSquareEffect = new MaskSquareEffect(mc, 10, 10, true);

MÉTODOS

1.- play():void

Descripción:
Inicia la ejecución de la animación.

Ejemplo:
effect.play();

2.- isPlaying():Boolean

Descripción:
Retorna verdadero si la animación esta en ejecución y falso en caso contrario.

Ejemplo:
effect.isPlaying();

3.- remove():void

Descripción:
Remueve la máscara que se creo dinámicamente al hacer el efecto, solamente se puede remover si la mascara ha sido creada y si la animación no esta en ejecución.

Ejemplo:
effect.remove();

PROPIEDADES

1.- animationType:Function

Descripción:
Propiedad que lleva como referencia el tipo de animación, las siguientes opciones son las que puedes usar, para utilizarlas tienes que importar el paquete mx.transitions.tween.easing.*

  • Strong.easeIn, Strong.easeOut, Strong.easeInOut
  • Back.easeIn, Back.easeOut, Back.easeInOut
  • Bounce.easeIn, Bounce.easeOut, Bounce.easeInOut
  • Regular.easeIn, Regular.easeOut, Regular.easeInOut
  • Elasctic.easeIn, Elasctic.easeOut, Elasctic.easeInOut
  • None.easeNone
Ejemplo:
effect.animationType = Bounce.easeInOut;

2.- direction:IDirection

Descripción:
Esto es la dirección que va a tomar la animación, por ejemplo, puede ir de izquierda a derecha ó de derecha a izquierda, las siguientes direcciones son las disponibles en el paquete, se tiene que importar el paquete com.jahepi.squareeffect.directions.*:

  • UptoDown
  • DowntoUp
  • LefttoRight
  • RighttoLeft
  • DowntoUpCornerLeft
  • DowntoUpCornerRight
  • UptoDownCornerLeft
  • UptoDownCornerRight
  • ZigZag

Ejemplo:
effect.direction = new UptoDown(1, .2);

Ahora los objetos IDirection como UptoDown reciben 2 parámetros:

Delay: Este es el tiempo en segundos que va a transcurrir para que empiece la animación.

DelayIncrementer: Este es un poco confuso al principio, pero es la espera en segundos que se va a incrementar por cada línea de animación generada por la dirección, hagan la prueba para que vean el efecto.

3.- duration:Number

Descripción:
Es el tiempo en segundos que va a durar la animación en cada división del movieclip.

Ejemplo:
effect.duration = 2;

4.- rows:Number

Descripción:
Número que indica el número de filas que será dividido el movieclip.

Ejemplo:
effect.rows = 13;

5.- columns:Number

Descripción:
Número que indica el número de columnas que será dividido el movieclip.
Ejemplo:
effect.columns = 13;

6.- fadeIn:Boolean

Descripción:
Booleano que indica si el efecto oculta el movieclip o lo muestra.
Ejemplo:
effect.fadeIn = true;

EVENTOS

1.- ON_MOTION_FINISH

Descripción:
Evento que nos notifica cuando la animación ha terminado.

effect.addEventListener(MaskSquareEffect.ON_MOTION_FINISH, onFinish);

function onFinish(evt:Object):Void {
evt.target.remove();
}

El evento nos devuelve un objeto que tiene una propiedad target que hace referencia al objeto MaskSquareEffect.

Ahora veamos un ejemplo completo:

import com.jahepi.squareeffect.MaskSquareEffect;
import mx.transitions.easing.*;
import com.jahepi.squareeffect.directions.*;

var effect:MaskSquareEffect = new MaskSquareEffect(mc, 10, 15, true);
effect.animationType = Elastic.easeOut;
effect.duration = 1;
effect.direction = new ZigZag(1, .05);
effect.addEventListener(MaskSquareEffect.ON_MOTION_FINISH, onFinish);
effect.play();

function onFinish(evt:Object):Void {
evt.target.remove();
}

Sencillo, no ?, si quieren pueden agregarle mas tipos de direcciones para eso métanle mano al paquete com.jahepi.squareeffect.directions, ahí viene la clave.

Dentro del archivo, viene un ejemplo para que vean el funcionamiento.

Sale, cualquier duda, comentario, mejoras, etc., se los agradecería muchísimo.

Un saludote !

16 de junio de 2008

Simulador de Explorador de Carpetas (XML+AS3.0)

Hola !

Traigo un pequeño proyecto que estaba haciendo en mis tiempos libres, es un simple simulador de explorador de carpetas hecho en Flash CS3, utiliza XML y Actionscript 3.0.

Se podría utilizar para hacer catálogos ó portafolios de trabajos, la ventaja es que puedes hacer una estructura anidada de los niveles que gustes, cada carpeta puede contener sus propios archivos, también le incorporé una paginación cuando se despliegan los archivos, ordenamiento por nombre pero se le pueden añadir nuevos filtros de ordenamiento fácilmente como ordenar los archivos por su fecha si es que decides agregarle esa propiedad, el ordenamiento es muy parecido a la arquitectura utilizada en java.

Explico como utilizar el proyecto por defecto.

Descomprime el proyecto, vas a ver una carpeta model, dentro de esta contiene un archivo llamado “categorias.xml”, en esta viene la configuración de las carpetas, veamos el xml:

<?xml version="1.0" encoding="utf-8"?>
<categorias>

<categoria nombre="Carpeta 1" src="model/data/datosCarpeta.xml">
<categoria nombre="SubCarpeta 1-A" src="model/data/datosCarpeta.xml">
<categoria nombre="SubSubCarpeta 1-A-A" src="model/data/datosCarpeta.xml" />
</categoria>
<categoria nombre="SubCarpeta 1-B" src="model/data/datosCarpeta.xml" />
</categoria>

<categoria nombre="Carpeta 2" src="">
<categoria nombre="SubCarpeta 2-A" src="model/data/datosCarpeta.xml" />
</categoria>

</categorias>


Dentro de la etiqueta , se encuentra la estructura general de las carpetas, por ejemplo:

Tengo 2 carpetas en la raíz de mi proyecto,

  • Carpeta 1

  • Carpeta 2


Dentro de Carpeta 1 hay una carpeta llamada SubCarpeta 1-A y Subcarpeta 2-A, dentro de SubCarpeta 1-A encontramos que hay otra carpeta SubSubCarpeta 1-A-A y dentro de SubSubCarpeta 1-A-A ya no hay nada.

Dentro de Carpeta 2 hay una carpeta llamada SubCarpeta 2-A, y esta carpeta ya no contiene otras carpetas.

Así podemos ir anidando las carpetas los niveles que deseemos.

Dentro de cada carpeta podemos tener archivos, y para lograr esto, utilizamos el atributo “src” de la etiqueta , dentro de este atributo ponemos la ruta que contiene los archivos, si esa carpeta no contiene archivos dejamos ese atributo en blanco.

Por ejemplo:

<categoria nombre="Carpeta 1" src="model/data/datosCarpeta.xml">


La Carpeta 1, cuando la abramos cargará los archivos que se encuentran en model/data/datosCarpeta.xml, la estructura de ese archivo debe ser como esta:

<?xml version="1.0" encoding="utf-8"?>
<categoryData>

<data>
<name>Homer Jay</name>
<desc>La voz original en inglés es de Dan Castellaneta. En España fue doblado hasta la undécima temporada por el fallecido Carlos Revilla, a quien sustituye Carlos Ysbert. En Latinoamérica hasta la decimoquinta temporada (incluida) estaba doblado por Humberto Vélez, reemplazado tiempo después por Otto Balbuena.</desc>
<views>
<view>images/homero.gif</view>
</views>
</data>

<data>
<name>Bartholomew</name>
<desc>Bart es decididamente el más rebelde de la familia. Es un muchacho simpático y también muy travieso, que hace muchas bromas con su amigo Milhouse. Sigue los programas de su ídolo Krusty el payaso y de Itchy & Scratchy.</desc>
<views>
<view>images/bart.jpg</view>
</views>
</data>

<categoryData>


Cuando queramos agregar nuevos archivos agregamos un nuevo nodo “data”, algo muy importante es no olvidar poner la etiqueta , dentro de esta van las imágenes por si tu archivo hace referencia a un juego de imágenes, puedes poner swf´s, jpg´s, gif´s ó png´s.

Si no hay imágenes deja la etiqueta views vacía.

Así cada carpeta puede apuntar a un archivo diferente en su atributo src, siempre y cuando respetando la estructura del xml que contiene los archivos.

Sale, dejo el proyecto, para que le metan mano y lo acoplen a sus necesidades.

Cualquier comentarios, sugerencia, mentada de madre :P, es bienvenida.

Les dejo una captura:



Aquí se pueden descargar el proyecto:
PROYECTO

Un Saludote !

6 de junio de 2008

Una nueva forma de ver el paradigma orientado a objetos - Parte 2

Encapsulamiento: la forma tradicional de verlo y la nueva forma de verlo

Mi paraguas orientado a objetos.

En mi clases de diseño de orientado a objetos, frecuentemente pregunto a mis estudiantes, “Quien ha escuchado que encapsulamiento es definido como ocultamiento de datos?”, casi todos levantan la mano.

Entonces procedo a contar una historia de mi paraguas. Ten en mente que vivo en Seatle, la cual tiene una reputación de ser más húmedo de lo que es, pero es aún un lugar muy húmedo en otoño, invierno y primavera. Aquí los paraguas y abrigos son nuestros amigos personales!

Déjame contarte acerca de mi gran paraguas. Es bastante grande para cubrirme!, de hecho, 3 o 4 personas puedes cubrirse conmigo. Mientras estamos cubiertos, manteniéndonos alejados de la lluvia, puedo moverme de un lugar a otro. Tiene un sistema de sonido para mantenerme entretenido mientras me mantengo seco. Sorprendentemente, puede también acondicionar el aire para que este más caliente o más frío. Es un paraguas genial.

Mi paraguas es conveniente. Se queda ahí esperando por mi. Tiene ruedas para que no tenga que estarlo cargando. Ni siquiera lo tengo que empujar porque lo puede hacer por si mismo. Algunas veces, abriré la parte superior de mi paraguas para dejar pasar los rayos solares. (El porque del que este usando mi paraguas cuando esta asoleado afuera esta fuera de mi compresión).

En Seatle, hay cientos de miles de paraguas de todos colores.

La mayoría de las personas les llama autos.

Pero pienso en el mío como un paraguas porque un paraguas es algo usado para mantenernos fuera de la lluvia. Muchas veces, mientras estoy esperando afuera por alguien para conocerlo, me siento en mi “paraguas” para mantenerme seco!

Las definiciones pueden limitarnos

Por supuesto que un carro no es realmente un paraguas. Si, puedes usarlo para mantenerte alejado de la lluvia, pero esa es una visión muy limitada de un auto. De la misma manera, el encapsulamiento es no solamente para el ocultamiento de datos. Esa es una visión muy limitada de encapsulamiento. Pensarlo de esa manera nos limita al hacer nuestros diseños.

Como pensar acerca del encapsulamiento

Encapsulamiento debería ser enseñado como “cualquier tipo de ocultamiento”. En otras palabras, puede ocultar datos. Pero también puede ocultar implementaciones, clases derivadas o cualquier cantidad de cosas. Considera el diagrama monstrado en la figura 8-1.

Multiples niveles de encapsulamiento

Figura 8-1


La figura 8-1 muestra varios tipos de encapsulamiento:

· Encapsulamiento de datos – Los datos en Point, Line, Saquer y Circle están ocultos.

· Encapsulamiento de métodos – Por ejemplo, el método setLocation de Circle.

· Encapsulamiento de Subclases – Los clientes de Shape no ven Points, Lines, Squares o Circles.

· Encapsulamiento de otros objetos: Nadie más que Circle esta enterado de la existencia de xxCircle.

Un tipo de encapsulamiento es alcanzado cuando hay una clase abstracta que se comporta polifórmicamente sin que el cliente se entere de que tipo en concreto es el que está usando. Además, adaptando interfaces oculta lo que esta detrás del objeto adaptado.

La ventaja de esta nueva definición

La ventaje de ver el encapsulamiento de esta manera nos da una mejor manera de separar (descomponer) los programas. Las capas de encapsulamiento llegan a ser las interfaces que debo diseñar. Encapsulando varios tipos de Shapes, puedo añadir nuevos sin cambiar nada del programa del cliente que los usa. Encapsulando XXCircle detrás de Circle, puedo cambiar la implementación en un futuro si lo eligo o es necesario.

Herencia como concepto vs herencia para la reutilización

Cuando el paradigma orientado a objetos fue por primera vez presentado, la reutilización de clases fue promocionada como uno de los más grandes beneficios. La reutilización usualmente era lograda creando clases y luego derivando nuevas clases basadas en las clases base. Por lo tanto el término clases especializadas era para esas subclases que fueron derivadas de otras clases (otras clases se refiere también a un término conocido como clases generalizadas).

No estoy poniendo en duda la importancia de esto, en lugar estoy proponiendo lo que creo es una forma más poderosa de usar la herencia. En el ejemplo de arriba, puedo hacer mis diseños basados en diferentes tipos especiales de Shapes (Estos son, Points, Lines, Squares y Circles). Sin embargo, esto probablemente no oculte los casos especiales cuando yo piense en usar Shapes. Puede que tome ventaja del conocimiento de estas clases concretas.

Si por el contrario, pienso en Shapes como una forma de clasificar Points, Lines Squares y Circles, puedo más fácilmente pensar acerca de estos como un TODO. Esto hará más probable que yo diseñe por interfaz (Shapes). También significa que si obtengo un nuevo tipo de Shape, será poco probable que me vea en una posición de dificultad de mantenimiento. (Porque el código del cliente no conoce con que tipo en concreto de Shape está tratando).

Pronto pondré la tercera parte,

Un saludote !

27 de mayo de 2008

Una nueva forma de ver el paradigma orientado a objetos - Parte 1

Hola !

Les traigo una traducción que aún estoy elaborando de un capítulo del libro Design Patterns Explained, es uno de los capítulos que me ha parecido extraordinario, ire subiendo fragmentos progresivamente, espero que este pequeño tema los anime a conseguir este excelente libro.


Una Nueva Perspectiva

La forma tradicional de ver los objetos, encapsulamiento y herencia es muy limitada. En este capítulo de “Design Patterns Explained”, lo autores describen una nueva forma de ver el diseño orientado a objetos, la cual viene de una perspectiva tomada de los patrones de diseño.

Introducción

En capítulos anteriores, se discutieron 3 conceptos fundamentales del diseño orientado a objetos: objetos, encapsulación, y clases abstractas. Como el diseñador ve estos conceptos es importante. La forma tradicional de verlo es simplemente muy limitada. En este capítulo se da un paso atrás y nos enfocamos en temas discutidos anteriormente en este libro. La intención es describir una nueva forma de ver el diseño orientado a objetos, la cual viene de una perspectiva tomada de los patrones de diseño.

En este capítulo:

· Comparo y contrasto la forma tradicional de ver a los objetos, como un paquete de datos y métodos, con la nueva forma, como cosas con responsabilidades.

· Comparo y contrasto la forma tradicional de ver al encapsulamiento como ocultamiento de datos, con la nueva forma como la habilidad de ocultar cualquier cosa. Es especialmente importante ver que el encapsulamiento puede ser usado para contener variaciones en el comportamiento.

· Comparo y contrasto la forma tradicional de ver a la herencia, para especialización y reutilización con la nueva forma, como un método para clasificar objetos.

· Los nuevos puntos de vista permiten contener variaciones en el comportamiento de los objetos.

· Muestro como la perspectiva conceptual, de especificación y de implementación se relacionan con las clases abstractas y sus clases derivadas.

Quizás esta nueva perspectiva no es del todo original. Creo que esta perspectiva es una que muchos desarrolladores de patrones de diseño mantienen cuando ellos desarrollan lo que podría ser lo que todos conocemos como un patrón. Ciertamente, es una perspectiva que es consistente con los escritos de Christopher Alexander, Jim Coplien, y las Pandilla de los cuatro.

Cuando lo llamo una nueva perspectiva, lo que quiero decir es que probablemente sea una nueva forma para la mayoría de los desarrolladores de ver los objetos. Ciertamente fue una nueva forma para mí cuando estaba aprendiendo patrones de diseño la primera vez.

Objetos: La forma tradicional de verlos y la nueva forma.

La forma tradicional de verlos: datos y métodos

La forma tradicional de ver los objetos es que son datos y métodos. Uno de mis maestros los llamaba “datos inteligentes”. Es solamente un paso adelante de las bases de datos. Esta manera de verlos viene de la forma de ver los objetos en la perspectiva de implementación.

La nueva forma de verlos: cosas con responsabilidades

Mientras que esta definición es acertada, explicada en el capítulo 1, El paradigma orientado a objetos, está basado en la perspectiva de implementación. Una definición más útil es la basada en la perspectiva conceptual, un objetos es una entidad que tiene responsabilidades. Estas responsabilidades dan al objeto su comportamiento. A veces, también pienso que un objeto es una entidad que tiene un comportamiento específico.

Esta es una mejor definición porque ayuda a enfocarse en lo que deben de hacer los objetos, y no simplemente en como implementarlos. Esto me permite construir el software en 2 pasos:

· Hacer un diseño preliminar sin preocuparme de todos los detalles involucrados.

· Implementar el diseño conseguido.

Finalmente, esta perspectiva permite una mejor selección y definición de los objetos (en cierto sentido, el principal punto del diseño). La definición de un objeto es más flexible; enfocándonos en lo que el objeto hace, la herencia nos permite utilizar diferentes, comportamientos específicos cuando sean necesarios. Un enfoque en la implementación puede que alcancemos esto, pero la flexibilidad típicamente viene a un alto precio.

Es más fácil pensar en términos de responsabilidades porque ayuda a definir la interfaz pública del objeto. Si un objeto tiene una responsabilidad, debe de haber alguna manera de preguntarle que haga su responsabilidad. Sin embargo, no implica nada acerca de lo que hay dentro del objeto. La información de la cual el objeto es responsable puede que no este ni siquiera adentro de el mismo.

Por ejemplo, supongamos que tenemos un objeto Shape y sus responsabilidades son:

· Saber donde esta posicionado.

· Capaz de dibujarse así mismo es una pantalla.

· Capaz de removerse así mismo de una pantalla.

Estas responsabilidades implican que un conjunto particular de métodos debe existir:

· getLocation( ... )

· drawShape( ... )

· unDrawShape( ... )

No hay implicación acerca de los que hay dentro de Shape. Solamente me importa que Shape sea responsable de sus propios comportamientos. Puede que tenga atributos dentro de el o puede que tenga métodos que hacen cálculos o inclusive se refieran a otros objetos. Aunque, Shape podría contener atributos de su localización actual o podría referirse a otro objeto de una base de datos para obtener su localización. Esto nos da la flexibilidad que se necesita para alcanzar nuestros objetivos de modelado.

Es interesante, encontrarás que enfocarnos en la motivación en lugar de la implementación es un tema recurrente en el diseño de patrones.

Mira a los objetos de esta manera. Hazlo tu principal punto de vista de los objetos. Si lo haces, tendrás diseños superiores.

Fin de la parte 1, pronto publicaré la parte 2.

Un Saludote !