El lunes próximo (26 Noviembre), comienza nuevamente el curso Flash Expert en el instituto Training Division (www.trainingdivision.com.ar).
Quedan dos vacantes, a quienes estén interesados, pueden contactarse mediante la página web.
Siendo el instructor, me pone verdaderamente contento la continuidad del curso, habla a claras de lo útil de los contenidos.
En este ejemplo, la idea es generar el escenario y la colisión de una bola contra un terreno. Utilizando conocimientos muy básicos de física y BASTANTE de los ejemplos anteriores, cree este PROTOTIPO muy chico que se acerca bastante a la idea. Pueden probarlo, utilicen las teclas IZQ y DER (Flechas) del teclado para mover esa bola azul.
El código es basicamente un rejunte de cosas ya armadas, o para este site o para proyectos propios. Está todo contenido dentro de una movie general, y comentado en cada linea.
Al ser un prototipo muy simple de editar, contiene errores y algunas lineas que no son lo eficiente que deberían ser, por ejemplo la generación de puntos. Siendo dínamico, podríamos generar al vuelo, las que se necesiten y liberar memoria.
Cualquier consulta o aporte, dejar el comentario.
Codigo Fuente en CS3
Ejemplo
En este ejemplo la idea es generar un algoritmo que represente el conjunto de Mandelbrot. La representación gráfica de ésto, es ni más ni menos que uno de los gráficos fractales mas conocidos y utilizados. Alterando los coeficientes de la fórmula, es bastante sencillo ver en detalle el gráfico, digamos, hacia el infinito.
La interpolación de color es bastante sencilla. Les dejo el ejemplo, y quiero destacar que el algoritmo tiene una gran cantidad de transcripciones a otros lenguajes; este en particular es una adaptación de uno que vi en C++.
Source CODE: fract.zip
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | import flash.display.BitmapData; var myBitmapData:BitmapData = new BitmapData(Stage.width, Stage.height, false, 0x0ffffff); var mc:MovieClip = this.createEmptyMovieClip("mc", this.getNextHighestDepth()); mc._alpha=0 mc.attachBitmap(myBitmapData,this.getNextHighestDepth()); ///Limites horizontales y verticales Maxx = 1; Minx = -2 Maxy = 1.5; Miny = -1.5; initer = 100;//Numero de iteraciones, a mayor valor, mas detalle i = 0;//Var para el loop j = 0;//Idem scrsizex = Stage.width;//Tamaño de pantalla scrsizey = Stage.height;//IDEM pixcorx = (Maxx-Minx)/scrsizex;//ESCALA pixcory = (Maxy-Miny)/scrsizey;//IDEM function mandel(xpt, ypt) { x = 0; y = 0; xnew = 0; ynew = 0; for (k=0; k<=initer; k++) { xnew = x*x-y*y+xpt*pixcorx+Minx ynew = (2*x*y+Maxy-ypt*pixcory); x = xnew; y = ynew; if ((x*x+y*y)>4) { break; } } color = k; if (k>=initer) { myBitmapData.setPixel(xpt,ypt,parseInt("0xFFFFFF")); } else { miColor = Number(255-(Math.abs(Math.cos((color*color)/180*Math.PI)*Math.sin((color*color)/180*Math.PI)*255))).toString(16); if (String(miColor).length<2) { miColor = "0"+miColor; } miRgb = "0xff"+miColor+miColor myBitmapData.setPixel(xpt,ypt,parseInt(miRgb)); } } function imprime() { for (r=0; r<=50; r++) { if (i<Stage.width) { if (j<Stage.height) { mandel(i,j); j += 1; } else { j = 0; i += 1; } } else { clearInterval(idInt); } } } stop(); |
En este ejemplo vamos a tratar de ampliar el primer ejemplo, para lograr una interacción mas compleja. La idea es que las “bolas” no se superpongan unas con otras, ya que ahora hay mas de dos bolas, necesitamos chequear una por una contra la otra. Es un procedimiento bastante demandante de CPU, pero se logran buenos resultados rapidamente.
Como es una continuación del primer ejemplo, recomiendo observar primero el mismo Ejemplo Anterior.
Por otro lado, estamos usando una clase que contiene algunas funciones númericas necesarias que se crearon en otro ejemplo: Clase útil para funciones númericas
Espero les sea útil.
Source CODE: ejemplobolas.zip
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | import Math2; factorReductor = 4;///Factor que determina la fuerza con la cual se acerca un objeto al otro this.onEnterFrame = function() { mc1._x = _root._xmouse;///Una de las bolas sigue al mouse, en este caso en el eje X mc1._y = _root._ymouse;///Una de las bolas sigue al mouse, en este caso en el eje Y for (i=1; i<=7; i++) { a = i+1; seguir(_root["mc"+a],_root["mc1"],(_root["mc1"]._width/2)+(_root["mc"+a]._width/2)+2);///Llamo a la función que acerca una Movie a la otra, primer parametro: Mc a mover, segundo: Mc de destino, tercero: distancia minima permitida entre los objetos for (j=1; j<=7; j++) { mantenerDistancia(_root["mc"+i],_root["mc"+j],(_root["mc"+i]._width/2)+(_root["mc"+j]._width/2)+1);///chequeo entre todas las bolas que no se estén superponiendo unas con otras. } } }; ///Funcion que realiza el acercamiento de una MC hacia otra function seguir(mc, destino, distanciaMinima) { orig = {x:mc._x, y:mc._y};////Determino el punto determinado por la MC a mover dest = {x:destino._x, y:destino._y};////Determino el punto que representa la MC de de destino miAngulo = Math.atan2((orig.y-dest.y), (orig.x-dest.x));///Calculo el angulo entre dichos dos puntos miDistancia = Math2.distanceBetween(orig.x, orig.y, dest.x, dest.y)-distanciaMinima;////Calculo la distancia entre los dos puntos y le resto la distancia minima del tercer parametro ///Aca se controla si la MC a mover se acercò demasiado a destino, de no ser asi, la acerco utilizando trigonometria (coseno sobre X y seno sobre Y) if (miDistancia+distanciaMinima>distanciaMinima) { mc._x -= Math2.cos(miAngulo)*(miDistancia/factorReductor); mc._y -= Math2.sin(miAngulo)*(miDistancia/factorReductor); } } function mantenerDistancia(obj1, obj2, dist) { orig = {x:obj1._x, y:obj1._y};////Determino el punto determinado por la MC a mover dest = {x:obj2._x, y:obj2._y};////Determino el punto que representa la MC de de destino miAngulo = Math.atan2((orig.y-dest.y), (orig.x-dest.x));///Calculo el angulo entre dichos dos puntos miDistancia = Math2.distanceBetween(orig.x, orig.y, dest.x, dest.y)-dist;////Calculo la distancia entre los dos puntos y le resto la distancia minima del tercer parametro if (miDistancia+dist<dist) {/////Si estan superpuestas las movies, las alejo en forma pareja a ambas en el sentido contrario. obj1._x -= Math2.cos(miAngulo)*(miDistancia/2); obj1._y -= Math2.sin(miAngulo)*(miDistancia/2); obj2._x += Math2.cos(miAngulo)*(miDistancia/2); obj2._y += Math2.sin(miAngulo)*(miDistancia/2); } } |
Muchas veces, a lo largo de algunos desarrollos, nos es necesario crear funciones para manejo de números. Una muy particular es la conversión de radianes a grados, o viceversa. O tener que especificar grados en las funciones trigonómetricas, o calcular el ángulo entre puntos..etc.
Una buena solución, es crear una clase que extienda la clase Math..en mi caso utilizo una llamada Math2, a la cual le incorporo todos los métodos que se, usaré con frecuencia. Incluso de esta forma es posible utilizar todos los métodos de Math, aun en Math2, debido a la herencia.
Solo es necesario tener la clase Math2.as, dentro de la carpeta del proyecto, e importarla cuando es necesario.
El código de Math2.as es:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | class Math2 extends Math { static function rndBetween(n1:Number, n2:Number) { return n1+random(n2-n1+1); } static function radToDeg(n:Number) { return n*180/Math.PI; } static function degToRad(n:Number) { return n/180*Math.PI; } static function degSin(n:Number) { return Math.sin(n/180*Math.PI); } static function degCos(n:Number) { return Math.cos(n/180*Math.PI); } static function degTan(n:Number) { return Math.tan(n/180*Math.PI); } static function angleBetweenRad(x1:Number, y1:Number, x2:Number, y2:Number) { return Math.atan2((y1-y2), (x1-x2)); } static function angleBetweenDeg(x1:Number, y1:Number, x2:Number, y2:Number) { return Math.atan2((y1-y2), (x1-x2))*180/Math.PI; } static function distanceBetween(x1:Number, y1:Number, x2:Number, y2:Number) { return Math.sqrt(Math.pow((y1-y2),2)+ Math.pow((x1-x2),2)); } } |
Cada función es bastante descriptiva en su nombre, random entre dos numeros, conversion de grados a radianes y viceversa, angulo entre dos puntos, distancia entre dos puntos, seno, coseno y tangente con grados decimales como parámetros, etc.
Una manera sencilla de comprobar la utilidad en el .FLA seria con el siguiente código:
1 2 3 4 5 6 7 8 9 10 | import Math2; trace(Math2.rndBetween(2, 15)); trace(Math2.radToDeg(1.2)); trace(Math2.degToRad(360)); trace(Math2.degCos(90)); trace(Math2.degSin(90)); trace(Math2.angleBetweenRad(0, 0, 1, 1)); trace(Math2.angleBetweenDeg(0, 0, 1, 1)); trace(Math2.sin(90/180*Math2.PI)); trace(Math2.distanceBetween(0,0,1,1)); |
Lo mas importante es importar la clase (primera linea), luego pueden usar esta clase, como si fuera Math, pero con sus agregados.
Existe otra forma, mas formal, de realizar lo anterior, modificando el paquete util.Math.* , que pronto lo explicaré.
