Hola, siento el retraso
Veamos, las funciones utilizadas son estas.
Para el escenario:
Código ActionScript :
package clases{
import flash.display.MovieClip;
import flash.display.Stage;
public class General extends MovieClip {
public function General() {
var escenario:FFondo = new FFondo(stage);
var prota:Personaje = new Personaje(stage, escenario);
stage.addChildAt(escenario,0);
stage.addChild(prota);
}
}
}
No hay mayor complicación. Se importa lo necesario, se crean dos variables para poner el fondo y el personaje, y se añaden el movie clip del personaje y del fondo al Stage.
Ahora, el fondo. Pongo anotaciones:
Código ActionScript :
package clases{
import flash.events.*;
import flash.display.MovieClip;
import flash.display.Stage;
import flash.utils.Timer;
import flash.events.*;
public class FFondo extends MovieClip {
private var vhorizonte:Number=0.9; //Velocidad horizontal de la capa mas lejana del fondo
private var vdelantera:int=6; //Velocidad horizontal de la capa mas lejana del fondo (la que interesa)
private var vnubes:Array=new Array(0.1,0.3,0.2); //Velocidad de las tres nubes
private var pantalla:Stage; //El escenario
private var desplazarse:Timer=new Timer(10,0);
private var nubemov:Timer=new Timer(150,0);
public function FFondo(pantalla:Stage) {
this.pantalla=pantalla; //Ahora pantalla es una referencia al escenario
desplazarse.addEventListener(TimerEvent.TIMER,FMover);
nubemov.addEventListener(TimerEvent.TIMER,MovNube);
desplazarse.start();
nubemov.start();
}
private function FMover(e:TimerEvent):void {
//Esta función mueve las dos capas del fondo según marquemos arriba.
//Si la mas cercana llega a su límite derecho, vuelve a 0, creando un scroll interminable.
if (horizonte.x>(-(horizonte.width)+pantalla.stageWidth)) {
horizonte.x-=vhorizonte;
}
if (delantera.x>(-(delantera.width)+pantalla.stageWidth)) {
delantera.x-=vdelantera;
} else {
delantera.x=0;
}
}
private function MovNube(e:TimerEvent):void {
//Esta función mueve las nubes del fondo a poca velocidad.
//Cuando alcanzan el límite derecho, reaparecen a la izquierda.
for (var i:uint = 0; i <= nubes.numChildren-1; i++) {
nubes.getChildAt(i).x+=vnubes[i];
if (nubes.getChildAt(i).x>=pantalla.stageWidth+nubes.getChildAt(i).width) {
nubes.getChildAt(i).x=-(nubes.getChildAt(i).width);
}
}
}
}
}
Ahora el personaje
Código ActionScript :
package clases{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.*;
import clases.HitTest;
public class Personaje extends MovieClip {
//referencia al stage y fondo
private var pantalla:Stage;
private var escenario:FFondo;
public function Personaje(pantalla:Stage,escenario:FFondo) {
this.pantalla=pantalla;
this.escenario=escenario;
//Recoloca el personaje para que impacte con el fondo
this.y=430;
this.x=200;
addEventListener(Event.ENTER_FRAME,contacto,false,0,true);
}
private function contacto(e:Event):void {
//Hace un impacto complejo. Si se están dando, devuelve true
//si no se dan, devuelve false. Siempre devuelve false, ese es
//mi problema.
//No funciona ni de la forma general (comparando el personaje
//con el fondo, como en este caso) ni específica (comparando
//un movie clip de un personaje con un movie clip del escenario).
trace(HitTest.complexHitTestObject(this,escenario))
}
}
}
Y por último, la función de impacto complejo, sacada del link que mencioné en el anterior mensaje. Voy a intentar explicarlo lo mejor que pueda.
Código ActionScript :
package clases
{
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
public class HitTest
{
public static function complexHitTestObject( target1:DisplayObject, target2:DisplayObject, accurracy:Number = 1 ):Boolean
{
//Función dentro de la función estática
return complexIntersectionRectangle( target1, target2, accurracy ).width != 0;
}
public static function intersectionRectangle( target1:DisplayObject, target2:DisplayObject ):Rectangle
{
//No pueden colisionar si no están en el escenario y si una colision común o funciona.
if( !target1.root || !target2.root || !target1.hitTestObject( target2 ) ) return new Rectangle();
// Obtiene la bandas de cada objeto, con las coordenadas de la root como punto de referencia
var bounds1:Rectangle = target1.getBounds( target1.root );
var bounds2:Rectangle = target2.getBounds( target2.root );
// Determina los limites del area de impacto. Devuelve x430 y200, las coordenadas que puse en Personaje, ademas de 80x80, las dimensiones del personaje. En principio esta bien.
var intersection:Rectangle = new Rectangle();
intersection.x = Math.max( bounds1.x, bounds2.x );
intersection.y = Math.max( bounds1.y, bounds2.y );
intersection.width = Math.min( ( bounds1.x + bounds1.width ) - intersection.x, ( bounds2.x + bounds2.width ) - intersection.x );
intersection.height = Math.min( ( bounds1.y + bounds1.height ) - intersection.y, ( bounds2.y + bounds2.height ) - intersection.y );
return intersection;
}
public static function complexIntersectionRectangle( target1:DisplayObject, target2:DisplayObject, accurracy:Number = 1 ):Rectangle
{
//En caso de que la precisión sea mas pequeña o igual a 0 sale un error. No ocurre.
if( accurracy <= 0 ) throw new Error( "ArgumentError: Error #5001: Invalid value for accurracy", 5001 );
// Esto hace una colisión normal. Si no hay colisión normal, naturalmente no hay colision compleja.
// Comprobé con un trace si la salida estaba aquí, y no lo estaba. Así que el programa llega hasta aquí bien.
if( !target1.hitTestObject( target2 ) ) return new Rectangle();
var hitRectangle:Rectangle = intersectionRectangle( target1, target2 );
// Si sus límites no impactan, no puede haber colision. También puse un trace y no hubo error.
if( hitRectangle.width * accurracy <1 || hitRectangle.height * accurracy <1 ) return new Rectangle();
//Crea un nuevo mapa de bits, con las dimensiones de la caja de impactos.
var bitmapData:BitmapData = new BitmapData( hitRectangle.width * accurracy, hitRectangle.height * accurracy, false, 0x000000 );
// Dibuja el primer objeto de impacto. Le pone un color determinado para comprobarlo luego.
bitmapData.draw( target1, HitTest.getDrawMatrix( target1, hitRectangle, accurracy ), new ColorTransform( 1, 1, 1, 1, 255, -255, -255, 255 ) );
// Crea un segundo objeto de impacto y lo entremezcla con el anterior, cambiando el color en las zonas de impacto.
bitmapData.draw( target2, HitTest.getDrawMatrix( target2, hitRectangle, accurracy ), new ColorTransform( 1, 1, 1, 1, 255, 255, 255, 255 ), BlendMode.DIFFERENCE );
// Busca la interseccion
var intersection:Rectangle = bitmapData.getColorBoundsRect( 0xFFFFFFFF,0xFF00FFFF );
bitmapData.dispose();
// Esto es en caso de que la precisión sea diferente. No se cumple
if( accurracy != 1 )
{
intersection.x /= accurracy;
intersection.y /= accurracy;
intersection.width /= accurracy;
intersection.height /= accurracy;
}
//Y ahora la intersección toma las dimensiones del hitRectangle
intersection.x += hitRectangle.x;
intersection.y += hitRectangle.y;
//Y a estas alturas la dimension ya es 0, y ya no detecta la colisión
return intersection;
}
protected static function getDrawMatrix( target:DisplayObject, hitRectangle:Rectangle, accurracy:Number ):Matrix
{
var localToGlobal:Point;;
var matrix:Matrix;
//Crea una matriz
var rootConcatenatedMatrix:Matrix = target.root.transform.concatenatedMatrix;
//Especifica las coordenadas en global, ajusta su posicion y dimensión
localToGlobal = target.localToGlobal( new Point( ) );
matrix = target.transform.concatenatedMatrix;
matrix.tx = localToGlobal.x - hitRectangle.x;
matrix.ty = localToGlobal.y - hitRectangle.y;
matrix.a = matrix.a / rootConcatenatedMatrix.a;
matrix.d = matrix.d / rootConcatenatedMatrix.d;
//Si la precisión es diferente a 1, escalarla de acuerdo a ella. No se cumple para mi caso.
if( accurracy != 1 ) matrix.scale( accurracy, accurracy );
return matrix;
}
}
}
Y eso es. Logré discernir dos puntos donde parece ir bien y un punto en el que ya no funciona, pero no logro saber que es lo que falla entre ellos dos.
Espero que así sea mas cómodo.
Gracias!