Rotate The Entity's Mask To Match Its Angle


(Zouhair Elamrani Abou Elassad) #1

Hi,

I’m rotating my entity’s spritemap and i would like to rotate the mask as well, i’ve checked the solution that was published before but i can’t get it to work, this is my class :

 override public function added():void 
	{
		super.added();
		
		_maskSource = new BitmapData(SPRITE_WIDTH, SPRITE_HEIGHT, true, 0);
		
		_missileIdleSprite.play(PLAY_MISSILE_IDLE);
		_missileExplosionSprite.alpha = 0;

		
		graphic = new Graphiclist(_missileIdleSprite, _missileExplosionSprite);
		
		mask = new Pixelmask(_maskSource, -SPRITE_WIDTH / 2, -SPRITE_HEIGHT / 2);
		
		setRotation(120);

	}

 private function setRotation(angle:Number):void 
	{
		matrix = new Matrix();

		matrix.rotate(angle);
		rotatedMask = new BitmapData(SPRITE_WIDTH, SPRITE_HEIGHT, true, 0xFFFFFFFF);
		rotatedMask.draw(_maskSource, matrix);
		(mask as Pixelmask).data = rotatedMask;
	}

override public function render():void 
	{
		super.render();
		
		_maskSource.fillRect(_maskSource.rect, 0);
		_missileIdleSprite.render(_maskSource, new Point(SPRITE_WIDTH/2, SPRITE_HEIGHT/2), new Point);
	}

It’s like the matrix rotation not working :p.


(Mike Evmm) #2

If you run the debugger and rotate the entity (and the mask), does the bounding box (red box) change side or stay the same? Could you give a screenshot? (I’m thinking that maybe because of the rotation, a bitmapdata of size SPRITE_WIDTH*SPRITE_HEIGHT might not be large enough.


(Martí Angelats i Ribera) #3

If it’s not big enough, you’ll have to increase the size and offset the mask.


(Zouhair Elamrani Abou Elassad) #4

Yes i’ve checked, the box won’t change angle, as for the size, i gave the exact sprite size, this is what i get :


(Martí Angelats i Ribera) #5

I think everything is wrong. You are not the first to have this problem so i made this class. I don’t have a project to test this with but the idea it’s out there:

package net.flashpunk.masks 
{
	import flash.display.BitmapData;
	import flash.geom.Matrix;
	import net.flashpunk.FP;
	
	/**
	 * ...
	 * @author Copying
	 */
	public class RotateblePixelmask extends Pixelmask
	{
		
		public function RotateblePixelmask(source:*, x:int = 0, y:int = 0, angle:Number = 0) 
		{
			if (source is Class) source = FP.getBitmap(source);
			if (!(source is BitmapData)) source = null;
			
			//save some values of the source
			_source = source;
			if (source)
			{
				_width = source.width;
				_height = source.height;
			}
			
			_offsetMatrix.tx = x;
			_offsetMatrix.ty = y;
			
			//calculate the internal bitmap size
			_size = Math.ceil(Math.sqrt(_width * _width + _height * _height));
			_rotated = new BitmapData(_size, _size); //new white square
			
			//make the initial rotation
			setRotation(angle);
			
			//make the pixelmask itself
			super(_rotated, ((_size - _width) >>> 1), ((_size - _height) >>> 1));
		}
		
		public function setRotation(angle:Number):void
		{
			if (!_source) return;
			
			//angles are a modular scale
			angle %= 360;
			
			//avoid to rotate an already rotated mask
			if (_angle == angle) return;
			_angle = angle;
			
			//set the angle in radians
			angle = FP.RAD * angle;
			
			//make the rotation matrix
			_rotationMatrix = _offsetMatrix.clone();
			_rotationMatrix.rotate(angle);
			
			//aply the changles
			_rotated.fillRect(_rotated.rect, 0xFFFFFF); //clean the old one
			_rotated.draw(_source, _rotationMatrix);
		}
		
		private var _width:uint = 0;
		private var _height:uint = 0;
		private var _size:uint = 0;
		
		private var _offsetMatrix:Matrix = new Matrix;
		
		private var _source:BitmapData;
		private var _rotated:BitmapData;
		
		private var _angle:Number = 361; //forces the first rotation to be done.
		private var _rotationMatrix:Matrix = new Matrix;
	}

}

notice that the package is net.flashpunk.masks so be sure to have it there.

PS: x and y are the offset when the angle is 0 degrees. It calculates it when you rotate the pixelmask automatically.

PPS: I haven’t got the time to test the code.


(Zouhair Elamrani Abou Elassad) #6

Thanks for the feedback, i used the class, but now i can’t even see the red square in the console mode, this is what i have :


(Martí Angelats i Ribera) #7

That’s becouse it don’t sets the width and height from the hitbox… try using the code:

//in the world update function
trace(missile.collidePoint(mouseX, mouseY));

then move slowly the mouse and see if it collides or not depending of the mouse poisition.


(Zouhair Elamrani Abou Elassad) #8

I tried but always the same result, the collidePoint returns false, it’s like there is no Mask.


(Martí Angelats i Ribera) #9

Could you send me your project so i can have a testing enviroment?


(Zouhair Elamrani Abou Elassad) #10

Ok, i’m gonna prepare a link and send it to you :).


(Zouhair Elamrani Abou Elassad) #11

I sent you a private message, hopefully there will be a way to achieve this