Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filters on SpriteSheets use WAY to much system resources #1056

Open
WindowsTV opened this issue Nov 23, 2020 · 7 comments
Open

Filters on SpriteSheets use WAY to much system resources #1056

WindowsTV opened this issue Nov 23, 2020 · 7 comments
Assignees

Comments

@WindowsTV
Copy link

WindowsTV commented Nov 23, 2020

This is a question and a bug. I have tried Stack Overflow and I was just being ignored so I am here now, hope that's okay. I am working on a game that uses a lot of Sprite Sheets on screen, one of them requires a filter during game play.

I tried:

mySprite.filters = [new createjs.BlurFilter(10,10,1)];
mySprite.cache(0,0,640,480);

mySprite.on("tick", this.updateCostumeColor, this);
function updateCostumeColor (evt) {	         
	evt.currentTarget.updateCache();
};
	

As suggested but all it does is boggle down my game's performance due to the amount of rendering on the screen. I have provided a work around that someone has made, I was able to get it to partially work. I load in my SpriteSheets through Preload.js and can't automate their system to use the details from my spritesheet.json.

I am asking for an internal way to add filters on to the sprite's image set similar to how the workaround acts.

Thank.

Issue Details

@danzen
Copy link
Contributor

danzen commented Nov 23, 2020

Could you create a blurred version of the sprite in an image processing app like photoshop? Then swap out the sprite for the blurred sprite?

@WindowsTV
Copy link
Author

WindowsTV commented Nov 23, 2020

Could you create a blurred version of the sprite in an image processing app like photoshop? Then swap out the sprite for the blurred sprite? I

I would but this particular filter was just for testing and besides all the filters added to the spites need to be dynamic as the player will change the values. The actual filter I’m going to use is a color filter, the player gets a “paint job” and adjusts their color on fly for over a hundred player sprites.

@MannyC
Copy link
Contributor

MannyC commented Nov 23, 2020

I did something with this before. Basically I created filtered versions of the whole spritesheet once and then used the cached version.

I doubt my implementation works anymore, but you may be able to do something with the code: https://github.com/MannyC/FilteredSprite.js

@WindowsTV
Copy link
Author

I did something with this before. Basically I created filtered versions of the whole spritesheet once and then used the cached version.

I doubt my implementation works anymore, but you may be able to do something with the code: https://github.com/MannyC/FilteredSprite.js

Many thanks for this, a few minor adjustments were needed to be made but it works like a charm!

@danzen
Copy link
Contributor

danzen commented Nov 23, 2020

@WindowsTV - glad you worked it out. If you would like, you could let us know the changes and perhaps we can see about getting this implemented. Thanks, too, @lannymcnie ;-)

@WindowsTV
Copy link
Author

Sure can, @danzen! Provided below is the modified code to work with Sprites and SpriteSheets:

/*
 * FilteredSprite
 * Visit https://github.com/MannyC/FilteredSprite.js for documentation, updates and examples.
 *
 * Created by MannyC
 *
 * Modified by WindowsTV
 */
 
(function () {
	//"use strict";

	var p = createjs.SpriteSheet.prototype;

	/**
	 * Object mapping filterName->Array of filtered images
	 * @property _filteredImages
	 * @type Object
	 * @protected
	 */
	//p._filteredImages = {};


	/**
	 * Object mapping filterName->Array of filtered frames
	 * @property _filteredFrames
	 * @type Object
	 * @protected
	 */
	//p._filteredFrames = {};

	/**
	 * Creates a filter with the given name.  This method creates a set of filtered frames
	 * that can later be retrieved with the {getFilteredFrame} method by specifying the passed name
	 * Make sure the spritesheet and images are fully loaded before calling this method, and don't change
	 * the frame data afterwards.
	 * @param {String} name The name to use for the new filter
	 * @param {Array} filters The array of filters to apply
	 * @return {Boolean} True if successful, otherwise false
	 * @method createFilter
	 */
	p.createFilter = function(name, filters) {

		this._filteredImages = this._filteredImages || {};
		this._filteredFrames = this._filteredFrames || {};

		if( this._filteredImages[name] || !this.complete) return false;
		
		this._filteredImages[name] = [];
		var images = this._images;
		
		// Create the set of filtered images
		for(var x = 0; x<images.length; x++){
			var img = images[x];
			var fi = new createjs.Bitmap(img);
			fi.filters = filters;
			fi.cache(0, 0, img.width, img.height);
			this._filteredImages[name][x] = fi.cacheCanvas;
		}
		
		// Create a filtered frame for all of the frames
		this._filteredFrames[name] = {};
		for(var x = 0; x<this._frames.length; x++){
			var frame = this._frames[x];

			if(!frame._imageIndex){
				// first time filtering this frame so search for image index
				for(var y = 0; y<images.length; y++){					
					if(frame.image === images[y]){
						frame._imageIndex = y; // store the index of the image for subsequent use
					}						
				}
			}

			// Create the new frame with the filtered image
			this._filteredFrames[name][x] = {
				_imageIndex: frame._imageIndex,
				image: this._filteredImages[name][frame._imageIndex],
				rect: frame.rect,
				regX: frame.regX,
				regY: frame.regY
			}
		}		
		return true;
	};

	/**
	 * Deletes a filter with the given name.  Note that this method doesn't check to see if there
	 * are still BitmapAnimations that refer to this filter.
	 * @param {String} name The name of the filter to delete
	 * @return {Boolean} True if successful, otherwise false
	 * @method deleteFilter
	 */
	p.deleteFilter = function(name){
		if(!this._filteredImages || !this._filteredImages[name]) return false;

		delete this._filteredImages[name];
		delete this._filteredFrames[name];

		return true;
	};
	/**
	 * Retrieves a filtered frame.  See getFrame.	 
	 * @param filterName the name of the filter to get the frame of
	 * @method getFilteredFrame
	 */
	p.getFilterFrame = function(frameIndex, filterName) {
		var frame;
		if (this.complete && this._filteredFrames && this._frames && (frame=this._filteredFrames[filterName][frameIndex])) { return frame; }
		else if ( this.getFrame ) return this.getFrame(frameIndex); 
		return null;
	};

	/**
	 * Sprite Overrides
	 */
	var q = createjs.Sprite.prototype;


	/**
	 * The name of the currently applied filter
	 * @property _appliedFilter
	 * @type String
	 * @protected
	 */
	//p._appliedFilter = null;


	/**
	 * Applies the named filter to this BitmapAnimation.  The filter must exist in the 
	 * associated SpriteSheet or the method will fail.
	 * @param {String} name The name of the filter to apply
	 * @return {Boolean} True if successful, otherwise false
	 * @method applyFilter
	 */
	q.applyFilter = function(name){
		if(!this.spriteSheet._filteredImages || !this.spriteSheet._filteredImages[name]) return false;
		this._appliedFilter = name;

		return true;
	};

	/**
	 * Removes the currently applied filter.  	 
	 * @return {Boolean} True if successful, otherwise false
	 * @method removeFilter
	 */
	q.removeFilter = function(){
		if (!this._appliedFilter) return false;		

		this._appliedFilter = null;

		return true;
	};

	/**
	 * Overrides the original draw method in order to call getFilteredFrame where applicable.  See documention 
	 * for original method.  
	 */

	q.draw = function(ctx, ignoreCache) {
		if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; }
		this._normalizeFrame();
		
		var o;
		if (this._appliedFilter) o = this.spriteSheet.getFilterFrame(this._currentFrame|0, this._appliedFilter);
		else o = this.spriteSheet.getFrame(this._currentFrame|0);
		
		if (!o) { return false; }
		var rect = o.rect;
		if (rect.width && rect.height) { ctx.drawImage(o.image, rect.x, rect.y, rect.width, rect.height, -o.regX, -o.regY, rect.width, rect.height); }
		return true;
	};	

}());

The way to activate the filters is the same in MannyC's version. I have to say props to them for making a great system because it was easily upgradable to the current Sprite API!

@danzen
Copy link
Contributor

danzen commented Nov 24, 2020

Thanks! @WindowsTV - looking forward to going through it. Will let you know what happens! Cheers.

@danzen danzen self-assigned this Mar 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants