Una vez mas recurro a los expertos en Action Script para que me puedan echar una manito.
Estoy haciendo una Animación Educativa, similar a un rompecabezas (hmm, esto mismo escribí en un post anterior) con un conjunto de piezas y diferentes opciones sobre cada pieza. Es decir, tengo un conjunto de Piezas que podrán ser movidas por el usuario, con la posibilidad de ser borradas de la animación, escaladas, rotadas o pintadas, si así se desea. Sin mencionar la opción de 'Deshacer'. Todo esto solo con ActionScript.
Bueno, para pude definir una clase que extiende de MovieClip, con los métodos de eventos sobrecargados y métodos para las diferentes acciones que se puede llevar a cabo sobre una pieza. Todo esto lo pude hacer gracias a este portal, recogiendo trozos de códigos ejemplo y preguntas que fueron respondidas por verdaderos expertos de esta comunidad. Les paso la clase que definí:
import flash.geom.ColorTransform
class Pieza extends MovieClip{
static var symbolName:String = "__Packages.Pieza";
static var symbolOwner:Function = Pieza;
static var symbolLinked = Object.registerClass(symbolName, symbolOwner);
var miColor:ColorTransform;
var img:MovieClip;
var tinta:MovieClip;
var rajaduraClip:MovieClip;
var seleccionado:Boolean;
var mancha:Boolean;
var presionado:Boolean;
var rajaduras:Array;
var pilaManchas:Array;
var indexRajadura:Number;
var indexManchas:Number;
var px:Number;
var py:Number;
var posIniX:Number;
var posIniY:Number;
var numeroPieza:Number;
var posActualX:Number;
var posActualY:Number;
static function __resolve(name){
return Pieza[name];
}
public function drawShape( imagen:String, contenedor:String, xx:Number, yy:Number, nroPieza:Number){
/** Cargar la imagen en el punto (0,0) del movie clip principal */
img = createEmptyMovieClip (contenedor, this.getNextHighestDepth () );
img._x = 0;
img._y = 0;
var loader:MovieClipLoader = new MovieClipLoader();
loader.loadClip(imagen, img);
/** Definir la posición de la pieza de acuerdo a las acciones pasadas */
img._x = xx;
img._y = yy;
posIniX = xx;
posIniY = yy;
rajaduras = new Array();
indexRajadura = 0;
/** Sobrecarga de los eventos para esta pieza */
onPress = doOnPress;
onRelease = doOnRelease;
onRollOver = doOnRollOver;
onRollOut = doOnRollOut;
onMouseMove = doOnMouseMove;
/** Banderas auxiliares */
seleccionado = false;
presionado = false;
mancha = false;
pilaManchas = new Array();
indexManchas = 0;
miColor = new ColorTransform();
numeroPieza = nroPieza;
trace("Dimensiones Iniciales" + getDimensiones() );
}
public function getCoords(){
return [img._x, img._y]
}
public function getDimensiones(){
return [img._height, img._width]
}
/** Sobrecarga del método 'onPress' del MovieClip */
private function doOnPress():Void{
if( seleccionado ){
miColor.alphaMultiplier = 1;
seleccionado = false;
}else{
if( _root.manchas.selectedIndex<=0 ){
miColor.alphaMultiplier = .5;
seleccionado = true;
}
}
tinta.clear();
/** Realizar una accion en base a la accion del usuario */
switch(_root.accion){
case "rajadura":{
rajaduraClip = img.createEmptyMovieClip(img._name, img.getNextHighestDepth() );
rajaduraClip.moveTo(rajaduraClip._xmouse, rajaduraClip._ymouse);
rajaduras[indexRajadura] = [rajaduraClip._xmouse, rajaduraClip._ymouse];
indexRajadura ++;
presionado = true;
}break;
case "reestablecer":{
reestablecer();
_root.caries.selectedIndex = 0;
}break;
case "mover":{
img.startDrag();
}break;
case "tintas":{
if( _root.caries.selectedIndex > 0 ){
tinta.clear();
agregarMancha(this._name);
}
}break;
case "rehubicar":{
devolverPosicion();
}break;
case "rotar":{
posActualX = img._x;
posActualX = img._y;
rotarPieza();
}break;
default:{
img.transform.colorTransform = miColor;
}
}
}
private function doOnRelease():Void{
img.stopDrag();
tinta.clear();
presionado = false;
if( mancha ){
drawAllManchas();
}
}
private function doOnMouseMove():Void{
if( presionado && _root.accion=="rajadura" ){
dibujarRajadura(img._xmouse, img._ymouse, rajaduraClip);
rajaduras[indexRajadura] = [img._xmouse, img._ymouse];
indexRajadura ++;
}
}
private function doOnRollOver():Void {
// definir acciones
}
private function doOnRollOut():Void {
// definir acciones
}
private function doOnMouseDown():Void {
this.miColor.alphaMultiplier = .5;
img.transform.colorTransform = miColor;
}
public function agregarMancha(contenedor:String):Void{
px = _xmouse-img._x;
py = _ymouse-img._y;
if(_root.caries.selectedIndex==1 ){
pilaManchas[indexManchas] = ["I",px,py];
indexManchas ++;
}
if(_root.caries.selectedIndex==2){
pilaManchas[indexManchas] = ["II",px,py];
indexManchas ++;
}
if(_root.caries.selectedIndex==3){
pilaManchas[indexManchas] = ["III",px,py];
indexManchas ++;
}
if(_root.caries.selectedIndex==4){
pilaManchas[indexManchas] = ["IV",px,py];
indexManchas ++;
}
drawAllManchas(contenedor);
mancha = true;
}
/**
* Dibuja una mancha sobre una máscara, dependiendo del tipo Mancha
* seleccionada por el usuario y el tipo de pieza
*/
public function drawAllManchas(contenedor:String ):Void{
tinta = createEmptyMovieClip (contenedor, getNextHighestDepth() );
tinta._x = img._x;
tinta._y = img._y;
var Mx = new flash.geom.Matrix();
var lados:Object = {x1:0, y1:0, x2:0, y2:0,
x3:0, y3:0, x4:0, y4:0 };
var colores;
var alphas;
var ratios;
var a;
var b;
var foco;
var difx;
var dify;
if( isPiezaSuperior() ){
lados.x1 = this._x+(img._width/5); lados.y1 = this._y+img._height-(2*img._height/3);
lados.x2 = this._x+img._width-(img._width/5); lados.y2 = this._y+img._height-(2*img._height/3);
lados.x3 = this._x+img._width; lados.y3 = this._y+img._height;
lados.x4 = this._x; lados.y4 = this._y+img._height;
}else{
lados.x1 = this._x; lados.y1 = this._y;
lados.x2 = this._x+img._width; lados.y2 = this._y;
lados.x3 = this._x+img._width-(img._width/5); lados.y3 = this._y+img._height-(img._height/3);
lados.x4 = this._x+(img._width/5); lados.y4 = this._y+img._height-(img._height/3);
}
for(var i=0; i<this.pilaManchas.length; i++) {
switch (pilaManchas[i][0]){
case "I":{
/** Combinacion de valores para Mancha GRADO 1 */
colores = [0x000000,0x3F1C0515,0x94604000,0xffffcc];
alphas = [80,90,85,0];
ratios = [0,10,25,250];
a = 20; b = 20; foco = 0;
difx = 8; dify = 8;
}break;
case "II":{
/** Combinacion de valores para Mancha GRADO 2 */
colores = [0x000000,0x3F1C0515,0x94604000,0xffffcc];
alphas = [80,90,85,0];
ratios = [0,30,55,150];
a = 35; b = 35; foco = 0;
difx = 17; dify = 17;
}break;
}
px = pilaManchas[i][1] -difx;
py = pilaManchas[i][2] -dify;
Mx.createGradientBox(a,b,Math.PI/2,px, py);
//tinta.lineStyle(1, 0x000000, 100);
tinta.beginGradientFill("radial",colores,alphas,ratios,Mx,"pad","RGB",foco);
tinta.moveTo(lados.x1, lados.y1);
tinta.lineTo(lados.x2, lados.y2);
tinta.lineTo(lados.x3, lados.y3);
tinta.lineTo(lados.x4, lados.y4);
tinta.lineTo(lados.x1, lados.y1);
tinta.endFill();
}
}
function dibujarRajadura(xx:Number, yy:Number, lienzo:MovieClip):Void {
lienzo.lineStyle(1, 0x3F1C05, 100);
lienzo.lineTo(xx, yy);
lienzo.lineStyle(10, 0xFCF7E2, 15);
lienzo.lineTo(xx+1, yy+1);
}
private function isPiezaSuperior():Boolean{
if( this._name.charAt(1)=="1" || this._name.charAt(1)=="2" ){
return true;
}else{
return false;
}
}
private function devolverPosicion():Void{
img._x = posIniX;
img._y = posIniY;
}
private function reestablecer():Void{
tinta.clear();
rajaduraClip.clear();
pilaManchas = new Array();
rajaduras = new Array();
indexRajadura = 0;
indexManchas = 0;
devolverPosicion();
}
private function rotarPieza():Void{
img._x += img._width/2;
img._y += img._height/2;
img._rotation += 5;
img._x += posActualX;
img._y += posActualY;
}
}
Y mi FLA, tiene una barra de herramientas para llevar a cabo las acciones necesarias, uso varios Clips de Película a manera de botones. Les paso el codigo de una opción de mi barra:
Código :
onClipEvent(mouseDown){
if (this.hitTest(_root._xmouse,_root._ymouse)){
if( _root.accion=="mover" ) _root.accion = "";
else [b]_root.accion = "mover";[/b]
_root.accionLabel.htmlText = "Acción: <b>"+_root.accion.toUpperCase()+"</b>";
this._height = 22;
this._width = 22;
}
}
onClipEvent(mouseUp){
if (this.hitTest(_root._xmouse,_root._ymouse)){
this._height=20;
this._width=20;
}
}
Y la forma de instaciar una pieza, es como sigue (dentro del mismo FLA):
Código :
import Pieza;
/* Variables Globales */
var accion = "";
/**
* Cargar Piezas Cuadrante 1
*/
attachMovie(Pieza.symbolName,"p16",getNextHighestDepth());
p16.drawShape("piezas/f_16_m.png","p16",179.3,108.5, 16);
attachMovie(Pieza.symbolName,"p15",getNextHighestDepth());
p15.drawShape("piezas/f_15_m.png","p15",187.8,112, 15);
attachMovie(Pieza.symbolName,"p14",getNextHighestDepth());
p14.drawShape("piezas/f_14_m.png","p14",203,118, 14);
attachMovie(Pieza.symbolName,"p13",getNextHighestDepth());
p13.drawShape("piezas/f_13_v.png","p13",215.8,123, 13);
attachMovie(Pieza.symbolName,"p12",getNextHighestDepth());
p12.drawShape("piezas/f_12_v.png","p12",234.3,128, 12);
attachMovie(Pieza.symbolName,"p11",getNextHighestDepth());
p11.drawShape("piezas/f_11_v.png","p11",262.0,131, 11);
Todo esto debo hacerlo solo en ActionScript, ya que para mas adelante los nombres de las imágenes me las pasaran como parámetros leidos de una BD, por medio de AMFPHP. Las imágenes se muestran bien y puedo moverlas sin problema, tambien pintarlas o reestablecerlas.
Mi problema, es que para la accion de 'Rotar' (en el método 'rotarPieza') necesito conocer, desde que se instancia un objeto, las dimensiones del MC que se crea, de manera que pueda calcular el centro y se muestre adecuadamente la rotacion, pero al instanciar el objeto obtengo los valores de (0,0) de las dimensiones (hago un trace en el método 'drawShape').
Intenté cargar la imagen de varias maneras, para así obtener las dimensiones iniciales de la imagen pero no conseguí mucho
No entiendo qué estoy haciendo mal, agradezco mucho de antemano el que hayan leido, por lo menos, este post y más aun si me sugieren algo.
Saludos
PD: Hmmm, mi codigo sale con con salto de linea doble
