Colisão com hitTestPoint
01/08/2009 at 00:30 Thiago Araújo Deixe o seu comentário
Antigamento com o AS2, usava uma forma de fazer colisão com os objetos no palco. Ontém transformei o metodo em uma classe pois fica mais genérico essa forma.
Abaixo segue a classe de colisão que foi tirada do código AS2:
import flash.display.DisplayObject;
import flash.geom.Point;
public class ControlColision
{
public function ControlColision()
{
}
public function checkColision(_target:AbstractObject,_checkObject:DisplayObject):void
{
var sizeW:Number = _target.width;
var sizeH:Number = _target.height;
while(_checkObject.hitTestPoint(_target.x, _target.y, true))
{
_target.Yspeed = -Math.abs((_target.Yspeed / Constants.GRAVITY_DIVIDER));
_target.y -= Constants.gravity;
_target.setState(AbstractObject.STATE_STOP);
}
while(_checkObject.hitTestPoint(_target.x + (sizeW / 2), _target.y - (sizeH / 2), true))
{
_target.Xspeed = -Math.abs((_target.Xspeed / Constants.GRAVITY_DIVIDER));
_target.x -= 0.2;
}
while(_checkObject.hitTestPoint(_target.x - (sizeW / 2), _target.y - (sizeH / 2), true))
{
_target.Xspeed = Math.abs((_target.Xspeed / Constants.GRAVITY_DIVIDER));
_target.x += 0.2;
}
while(_checkObject.hitTestPoint(_target.x, _target.y - sizeH, true))
{
_target.Yspeed = Math.abs((_target.Yspeed / Constants.GRAVITY_DIVIDER));
_target.y += Constants.gravity;
}
while(_checkObject.hitTestPoint(_target.x + (sizeW / 4), _target.y - 1, true))
{
_target.Xspeed = -Math.abs((_target.Xspeed / Constants.GRAVITY_DIVIDER));
_target.x -= 0.2;
}
while(_checkObject.hitTestPoint(_target.x - (sizeW / 4), _target.y - 1, true))
{
_target.Xspeed = Math.abs((_target.Xspeed / Constants.GRAVITY_DIVIDER));
_target.x += 0.2;
}
while(_checkObject.hitTestPoint(_target.x + 5, _target.y - (sizeH - 1), true))
{
_target.Xspeed = -Math.abs((_target.Xspeed / Constants.GRAVITY_DIVIDER));
_target.x -= 0.2;
}
while(_checkObject.hitTestPoint(_target.x - 5, _target.y - (sizeH - 1), true))
{
_target.Xspeed = Math.abs((_target.Xspeed / Constants.GRAVITY_DIVIDER));
_target.x += 0.2;
}
}
}
Essa classe faz a verificação do objeto nos seguintes pontos:

Para usar essa classe e verificar a colisão com vários outros objetos no palco, além de usar os parâmetros
do objeto como “Xspeed” e “Yspeed”, é preciso ter mais três outras classes que auxiliam e completam o sistema de verificação. As classes são: “Constants”, “AbstractObject” e “ColisionList”.
- A Constants tem todos os valores principais que são usados em todas as outras.
- AbstractObject é responsável por armazenar os valores de velocidade vertical e horizontal e servir como uma interface, onde todos os movieclips ou objetos podem herdar suas funções.
- ColisionList é onde serão armazenados todos os objetos que vão colidir entre si.
Abaixo segue os códigos na respectiva ordem:
public class Constants
{
public static const STAGE_WIDTH:uint = 640;
public static const STAGE_HEIGHT:uint = 420;
public static const SPEED_LIMIT:Number = 10;
public static const SPEED_MINIMUM:Number = 0.294;
public static const ACCELERATION_LIMIT:Number = 3;
public static const GRAVITY_DIVIDER:uint = 8;
private static var configSpeed:Number = 0.7;
private static var configGravity:Number = 0.2;
private static var configJump:Number = configGravity * 20;
private static var configBound:Number = 0.98;
private static var configAcceleration:Number = 0.2;
public static function get gravity():Number
{
return configGravity;
}
public static function set gravity(_value:Number):void
{
configGravity = _value;
}
public static function get bound():Number
{
return configBound;
}
public static function set bound(_value:Number):void
{
configBound = _value;
}
public static function get speed():Number
{
return configSpeed;
}
public static function set speed(_value:Number):void
{
configSpeed = _value;
}
public static function get acceleration():Number
{
return configAcceleration;
}
public static function set acceleration(_value:Number):void
{
configAcceleration = _value;
}
public static function get jump():Number
{
return configJump;
}
public static function set jump(_value:Number):void
{
configJump = _value;
}
}
import flash.display.MovieClip;
import flash.events.Event;
public class AbstractObject extends MovieClip
{
public static const STATE_STOP:uint = 1;
public static const STATE_WALK:uint = 2;
public static const STATE_RUN:uint = 3;
public static const STATE_LOWERED:uint = 4;
public static const STATE_ROLL:uint = 5;
public static const STATE_JUMP:uint = 6;
public static const STATE_FLY:uint = 7;
private var velocity:Array;
private var acceleration:Number;
private var accCount:uint;
private var accCountMax:uint;
private var gravity:Number;
private var state:uint;
public function AbstractObject()
{
this.setObjectConfig();
}
private function setObjectConfig():void
{
try
{
this.state = STATE_STOP;
this.acceleration = 0;
this.accCount = 0;
this.accCountMax = Constants.ACCELERATION_LIMIT;
this.addEventListener(Event.ENTER_FRAME, this.refreshAcceleration);
this.setGravity(Constants.gravity);
this.velocity = [0,0];
}
catch(e:Error)
{
trace("(AbstractObject) Erro ao tentar setar configuração: " + e);
}
}
private function refreshAcceleration(evt:Event):void
{
this.accCount++;
if(this.accCount >= Constants.ACCELERATION_LIMIT && this.acceleration > 0)
{
this.acceleration -= Constants.acceleration;
}
}
public function set Xspeed(_value:Number):void
{
this.velocity[0] = _value;
}
public function get Xspeed():Number
{
return this.velocity[0];
}
public function set Yspeed(_value:Number):void
{
this.velocity[1] = _value;
}
public function get Yspeed():Number
{
return this.velocity[1];
}
public function setAcceleration(_value:Number):void
{
this.acceleration = _value;
this.accCount = 0;
}
public function addAcceleration(_value:Number):void
{
this.acceleration += _value;
this.accCount = 0;
if(this.acceleration > Constants.ACCELERATION_LIMIT)
{
this.acceleration = Constants.ACCELERATION_LIMIT;
}
}
public function getAcceleration():Number
{
return this.acceleration;
}
public function setGravity(_value:Number):void
{
this.gravity = _value;
}
public function getGravity():Number
{
return this.gravity;
}
public function setState(_value:uint):void
{
this.state = _value;
}
public function getState():uint
{
return this.state;
}
}
import colision.controller.ControlColision;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;
public class ColisionEngine extends Sprite
{
private var running:Boolean;
private var target:AbstractObject;
private var checkObjectList:Array;
private var control:ControlColision;
public function ColisionEngine()
{
this.running = false;
this.control = new ControlColision();
}
public function initialize(_target:AbstractObject):void
{
if(_target != null)
{
this.target = _target;
this.checkObjectList = new Array();
this.startCheckColision();
}
}
public function startCheckColision():void
{
if(this.target != null && (!this.running))
{
this.running = true;
this.addEventListener(Event.ENTER_FRAME, this.checkColision);
}
}
public function stopCheckColision():void
{
if(this.running)
{
this.running = false;
this.removeEventListener(Event.ENTER_FRAME, this.checkColision);
}
}
private function checkColision(evt:Event):void
{
for(var a:uint = 0; a < this.checkObjectList.length; a++)
{
this.control.checkColision(this.target, this.checkObjectList[a]);
}
}
public function addColisionObject(_obj:DisplayObject):void
{
if(this.checkObject(_obj) <= 1)
{
this.checkObjectList.push(_obj);
}
}
public function checkObject(_obj:DisplayObject):int
{
var result:int = -1;
for(var a:uint = 0; a 0)
{
var tempList:Array = new Array();
for(var a:uint = 0; a < this.checkObjectList.length; a++)
{
if(a != _index)
{
tempList.push(this.checkObjectList[a]);
}
}
this.checkObjectList = tempList;
}
}
}
Existe mais uma classe que criei para testar esses métodos de colisão que coloquei o nome de “Main”.
import colision.ColisionEngine;
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import gravity.GravityEngine;
import moviment.controller.ControlMoviment;
import moviment.elements.AbstractObject;
public class Main extends Sprite
{
public function Main()
{
var ball:MovieClip = new YellowBall();
var retangulo:MovieClip = new BlueSquare();
ball.x = 300;
retangulo.x = 300;
retangulo.y = 300;
this.addChild(DisplayObject(retangulo));
var gravityBall:GravityEngine = new GravityEngine();
var movimentBall:ControlMoviment = new ControlMoviment();
var colisionBall:ColisionEngine = new ColisionEngine();
colisionBall.initialize(AbstractObject(ball));
colisionBall.addColisionObject(retangulo);
movimentBall.initialize(AbstractObject(ball));
stage.addEventListener(KeyboardEvent.KEY_DOWN, movimentBall.keyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, movimentBall.keyUp);
gravityBall.addObject(AbstractObject(ball));
gravityBall.setGravity(1,0.5);
this.addChild(ball);
}
}
Dentro do fla, existe dois movieclips que são a bola e o retângulo assim como está descrito no início do construtor da classe Main.
Exemplo:

Como visto na imagem acima, existem dois objetos criados e em cada um deles a classe básica é AbstractObject, pois todos os objetos entram na lista de colisão e cada um precisa ter os mesmos atributos.
Se você está se perguntando sobre os estados da classe AbstractObject. Eles servem para mostrar algum comportamento em relação ao movimento.
Faça um teste e coloque sete frames dentro do objeto “bola” e em cada frame coloque uma cor diferente. Você vai observar que a cada estado o objeto pode ter comportamentos diferentes e isso pode ser aproveitado para um jogo tipo plataforma![]()
Entry filed under: AS3. Tags: .
Trackback este artigo | Subscribe to the comments via RSS Feed