Collision With A Spritemap


(Zouhair Elamrani Abou Elassad) #1

I’m trying to use collision with Spritemap using a sprite sheet, the Spritemap is about a small object that gets bigger and a player who hits it, but when i calculate the mask of the Spritemap it’s set to the first image of the sprite sheet so my player goes through all the Spritemap, i wounder if there is a way to calculate the mask for every image in the Spritemap so collisions will be launched once the player touches any of image sequence ?


(Martí Angelats i Ribera) #2

If your sprites can be used as pixelmask you can simply do this:

In the constructor:

var spritemap:Spritemap = new Spritemap(IMG, 20, 20);
//the animations
graphic = spritemap;

var maskSource:BitmapData = new BitmapData(20, 20, true, 0); //20, 20 are the sizes of your sprite
var pixelmask:Pixelmask = new Pixelmask(maskSource);
//copy-paste the animation list and change the variable name
mask = pixelmask;

In the render function:

override public function render():void
{
	maskSource.fillRect(maskSource.rect, 0);
	spritemap.render(maskSource, new Point, new Point);
	super.render();
}

This works if, and only if, your sprites can be interpretated as a pixelmask.


(Zouhair Elamrani Abou Elassad) #3

Sorry but i don’t understand where to place my sprite sheet Class, the embedded code for my PNG file ?


(Martí Angelats i Ribera) #4

Sorry, i writed it wrong. Already edited.

The idea is to take the same image and convert it to the mask.

PD: Just to be sure, this goes in the class that extends Entity (usually Player, Enemy, etc.)


(Zouhair Elamrani Abou Elassad) #5

Thank You so much, that worked great, except for one thing, i replaced Bitmap with BitmapData ;), but just one more thing my mask sometimes doesn’t fit exactly the image :

Which launches the collision before even touching the object, is there a way to fix that ?


(Zouhair Elamrani Abou Elassad) #6

… I guess it’s just a problem of the sprite sheet images :D, can you please explain the code, that would be a great


(Martí Angelats i Ribera) #7

Edited (WTF did i do with Bitmap?) >.<

Don’t compress the image becouse the noice created will effect the collision.


(Martí Angelats i Ribera) #8

How does it work?

Ok so at this point i assume you know how OOP, AS3 and FP works (the last one in a more practical way).

So what i do is make the Pixelmask be the BitmapData that i create. Becouse it is not cloned and i save an instance, i can modify the Pixelmask source directly.

How do i modify it? Well i simply fill the source with a non-colliding color (AKA 0) and render the image directly there (does not consume many resources).

So in the end we have a pixelmask wich have the same image than the rendered one.

Code explained line by line

//As you should think we need the Spritemap
var spritemap:Spritemap = new Spritemap(IMG, 20, 20);
//the animations
graphic = spritemap;

var maskSource:BitmapData = new BitmapData(20, 20, true, 0);
//We create the BitmapData that is used to chack the collisions
var pixelmask:Pixelmask = new Pixelmask(maskSource);
//We create the pixelmask wich uses the bitmapData we just created to check collisions
mask = pixelmask;
//we set the mask to be our pixel mask (pretty obvious)
override public function render():void
{
	maskSource.fillRect(maskSource.rect, 0);
	//Errase the bitmapdata by filling with 0 (transparent black)
	spritemap.render(maskSource, new Point, new Point);
	//Renders the spritemap into our bitmapdata in the position 0, 0 (the pixelmask will already be relative to the Entity)
	super.render();
	//render the graphic (in this case the Spritemap)
}

Animated pixelmask has a huge hitbox?
(Lozza JP) #9

Hey guys I have been following along and trying to incorporate this into my code, but it is just making a square hitbox rather than a pixel perfect collision of the object. Have I put some of the code in wrong spots or anything?

package entities {

/**
 * ...
 * 
 */

import net.flashpunk.*;
import net.flashpunk.graphics.Spritemap;
import entities.Player;
import flash.display.*;
import net.flashpunk.masks.*;
import flash.geom.*;

public class Projectile extends Entity
{
	
	private var spriteMP:Spritemap;
	private var initX:Number;
	private var initY:Number;
	private var maxDistance:Number;
	private var faceRight:Boolean;
	
	private var eddy:Player;
	
	private var maskSource:BitmapData;
	
	public function Projectile(x:Number, y:Number, width:int, height:int, maxDistance:Number, assetSprite:*, 
	spriteID:int, collideType:String, faceRight:Boolean) 
	{
		initX = x;
		initY = y;
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
		this.maxDistance = maxDistance;
		this.faceRight = faceRight;
		
		this.spriteMP = new Spritemap(Assets[assetSprite], width, height);
		
		
		
		spriteMP.add("this", [spriteID], 0, false);
		
		type = collideType;
		
		graphic = spriteMP;
		
		
		maskSource = new BitmapData(width, height, true, 0);
		//We create the BitmapData that is used to chack the collisions
		var pixelmask:Pixelmask = new Pixelmask(maskSource);
		//We create the pixelmask wich uses the bitmapData we just created to check collisions
		this.mask = pixelmask;
		//we set the mask to be our pixel mask (pretty obvious)
		
	} // end constructor function
	
	override public function update():void
	{
		this.eddy = eddy || world.getInstance("eddy") as Player;
		
		shoot();
		
		
		if (FP.distance(initX, initY, x, y) > maxDistance) destroyThis();
		
		super.update();
	} // end update function
	
	private function shoot():void
	{
		spriteMP.play("this");
		if (faceRight)
		{
			x ++;
		}
		if (!faceRight)
		{
			x --;
		}
	} // end shoot function
	
	private function destroyThis():void
	{
		FP.world.remove(this);
	} // end destroy this function
	
	override public function render():void
	{
		
		
		maskSource.fillRect(maskSource.rect, 0);
		//Errase the bitmapdata by filling with 0 (transparent black)
		spriteMP.render(maskSource, new Point, new Point);
		//Renders the spritemap into our bitmapdata in the position 0, 0 (the pixelmask will already be relative to the Entity)
		super.render();
		//render the graphic (in this case the Spritemap)
	}
	
} // end class

}


(Martí Angelats i Ribera) #10

I would gess it’s becouse of the tilemap you are using. Try doing cahnging this line:

override public function render():void
	{
		maskSource.fillRect(maskSource.rect, 0xFFFFFF);
		spriteMP.render(maskSource, new Point, new Point);
		super.render();
	}

PD: You don’t need to keep the comments. If you understand what’s going on that’s all you need.


(Lozza JP) #11

I might be thinking this thread is doing something other than what I was trying to get out of it :S

I was thinking this would make a pixel perfect mask, as in a ball would have a circle collision mask rather than a square.

Is that meant to happen? changing to hex white 0xFFFFFF didn’t affect it.


Spritemaps in Masklists
(Martí Angelats i Ribera) #12

This thread is another thing. You are looking for a class called Pixelmask. You create the mask and simply do:

[Embed]
public static const MASK:Class;

public function MyEntity()
{
mask = new Pixelmask(MASK);
}

For more information have a look at the documentation.


(Zouhair Elamrani Abou Elassad) #13

Thank You So Much, i’ve been thinking about how to implement the mask with Spritemaps :smile:


(Martí Angelats i Ribera) #14

The mask is 100% independent to the graphic. This thread is only referyng a dynamic Pixelmask that have the same collision than a Spritemap wich sizes modifies. You can simply use the regular mask types as you do with a Stamp or a Image.


(Zouhair Elamrani Abou Elassad) #15

Yep, Got it :wink: , once more Thanks ^^