A Flash Developer Resource Site

Results 1 to 17 of 17

Thread: [F8] [Disc] 2D Effects Rendering

  1. #1
    Qwaizang:syntax_entity_ Q__Hybrid's Avatar
    Join Date
    Aug 2005
    Posts
    270

    [F8] [Disc] 2D Effects Rendering

    In the process of figuring out my game engine, I've decided to create an open discussion about the methods I've found to achieve certain visual effects so that others can learn from my experiments and I can learn from others' responses.

    Before I get into anything, I want to point out that my engine utilizes a document stack of container movieclips. By that I mean I have a seperate container for all interactive objects, a seperate container for players, a seperate container for background graphics, a seperate container for buildings, etc. Each container serves as a layer that is composited into the final frame at render time. With that in mind, let's continue.

    1. Residual Frames

    A specific goal I had from the beginning was the ability to render residual frames. This is an effect that is typically used in fighting or action games during special moves or power ups. Although a bit of work can make this staple of eye candy look original, it generally tends to look like this:




    My first approach to this effect was the assumption that I could simply use a seperate BitmapData surface to copy the position of affected objects and composite that surface into each rendered frame like everything else, however, this would not address two particular issues. First, it would retain all frames rendered until the effect was turned off, rather than only retaining a specified number of frames. Second, in a multiplayer situation, the residual frames would render relative to the visible region of the screen, not world coordinates of the game level itself, so not every one would see the same thing at render time. I devised the following method to address these issues, which holds up well at 60 fps on my mashed up machine:

    Code:
    // New Document: frame 1, main timeline
    import flash.display.BitmapData
    import flash.geom.ColorTransform
    import flash.geom.Point
    import flash.geom.Rectangle
    
    var myRoot:MovieClip = this;
    var playerMC:MovieClip = myRoot.createEmptyMovieClip("playerMC", myRoot.getNextHighestDepth());
    var renderMC:MovieClip = myRoot.createEmptyMovieClip("renderMC", myRoot.getNextHighestDepth());
    var renderPoint:Point = new Point(0, 0);
    var startP:Point = new Point(-1, -1);
    var endP:Point;
    var renderW:Number = Stage.width;
    var renderH:Number = Stage.height;
    var residualBuffer:Number = 8; // legal values are 1 thru 255
    var residualFade:ColorTransform = new ColorTransform(1, 1, 1, 1, 0, 0, 0, -Math.round(256 / (residualBuffer + 1)));
    var residualSurface:BitmapData = new BitmapData(renderW, renderH, true, 0x00000000);
    var renderSize:Rectangle = new Rectangle(0, 0, renderW, renderH);
    
    function testResidual() {
    	// reduce render quality to improve framerate
    	if(myRoot._quality != "LOW") myRoot._quality = "LOW";
    	// remove our player from video memory
    	if(playerMC._visible) playerMC._visible = false;
    	// erase previous line
    	playerMC.clear();
    
    	// start drawing new line
    		playerMC.lineStyle(10, 0xffffff, 100);
    		if((startP.x < 0) && (startP.y < 0)) {
    			startP.x = Math.round(Math.random() * renderW);
    			startP.y = Math.round(Math.random() * renderH);
    		} else {
    			startP.x = endP.x;
    			startP.y = endP.y;
    		}
    		endP = new Point(Math.round(Math.random() * renderW), Math.round(Math.random() * renderH));
    		playerMC.moveTo(startP.x, startP.y);
    		playerMC.lineTo(endP.x, endP.y);
    	// finished drawing new line
    	
    	// fade residual frames
    	residualSurface.colorTransform(renderSize, residualFade);
    	// append a current frame
    	residualSurface.draw(playerMC);
    	
    	// clean up before rendering
    	renderMC.clear();
    	// start rendering current frame
    		renderMC.lineStyle(0, 0x000000, 0);
    		renderMC.moveTo(0, 0);
    		renderMC.beginBitmapFill(residualSurface);
    			renderMC.lineTo(renderW, 0);
    			renderMC.lineTo(renderW, renderH);
    			renderMC.lineTo(0, renderH);
    			renderMC.lineTo(0, 0);
    		renderMC.endFill();
    	// finished rendering current frame
    }
    
    // render once per frame
    myRoot.onEnterFrame = testResidual;
    The way this works is pretty straight forward. Each frame of animation is drawn to residualSurface, then the entire contents of the BitmapData are manipulated using a ColorTransform so that their alpha channel is reduced. Older frames appear more transparent and eventually disappear because the effect is cumulative. By controlling the rate of dissipation, the number of visible residual frames can be accurately constrained.

    This demo is a basic primer on the technique, but it doesn't give any real indication of its limitations or practical use. A bit of rewriting and additional logic is required to properly test this effect. Below is a beefed up version, complete with full commentation:

    Code:
    // New Document: frame 1, main timeline
    
    // import the classes we need
    import flash.display.BitmapData
    import flash.geom.ColorTransform
    import flash.geom.Matrix
    import flash.geom.Point
    import flash.geom.Rectangle
    
    // allow or disallow residual frame rendering
    var ALLOW_RESIDUAL:Boolean = true;
    // numerics
    var worldW:Number = Stage.width;
    var worldH:Number = Stage.height;
    var charW:Number = 64;
    var charH:Number = 96;
    var residualBuffer:Number = 8;
    
    // the behavior of our character
    var behavior:Object = {maxSpeed : 10, moveX : 0, moveY : 0};
    
    // clean reference to _root
    		var myRoot:MovieClip = this;
    // a container for all elements of our world
    		var world_mc:MovieClip = myRoot.createEmptyMovieClip("world_mc", myRoot.getNextHighestDepth());
    // a surface to render our frames on
    		var render_mc:MovieClip = myRoot.createEmptyMovieClip("render_mc", myRoot.getNextHighestDepth());
    // a container for all elements of our character
    		var char_mc:MovieClip = world_mc.createEmptyMovieClip("char_mc", world_mc.getNextHighestDepth());
    // a surface to render our character's residual frames on
    		var residual_mc:MovieClip = char_mc.createEmptyMovieClip("residual_mc", char_mc.getNextHighestDepth());
    // a surface to render our character's current frame on
    		var graphics_mc:MovieClip = char_mc.createEmptyMovieClip("frame_mc", char_mc.getNextHighestDepth());
    
    // objects used in rendering residual frames
    var residualFader:ColorTransform = new ColorTransform(1, 1, 1, 1, 0, 0, 0, -Math.round(256 / (residualBuffer + 1)));
    var residualMatrix:Matrix;			// to be initialized later
    var residualRegion:Rectangle;		// ...
    var residualSurface:BitmapData;	// ...
    var renderSurface:BitmapData = new BitmapData(worldW, worldH, false, 0xff000000);
    
    // the events of our demo
    myRoot.onLoad = init;
    myRoot.onEnterFrame = drawFrame;
    
    // initilization code
    function init() {
    	initRender();
    	initRegion();
    	initSurface();
    	initChar();
    };
    // optimize rendering
    function initRender() {
    	// reduce render quality to improve framerate
    	myRoot._quality = "LOW";
    	// free up video memory by hiding the contents of our world
    	world_mc._visible = false;
    };
    // calculate surface area needed for residual frames
    function initRegion() {
    	residualRegion = new Rectangle(0,
    																 0,
    																 charW + (2 * (residualBuffer * behavior.maxSpeed)),
    																 charH + (2 * (residualBuffer * behavior.maxSpeed)));
    };
    // allocate memory for surface area of residualRegion
    function initSurface() {
    	residualSurface = new BitmapData(residualRegion.width, residualRegion.height, true, 0x00000000);
    };
    // draw the content of our character
    function initChar() {
    	graphics_mc.clear();
    	graphics_mc.lineStyle(0, 0xc0c0c0, 100);
    	graphics_mc.moveTo(0, 0);
    	graphics_mc.beginFill(0xc0c0c0, 100);
    		graphics_mc.lineTo(charW, 0);
    		graphics_mc.lineTo(charW, charH);
    		graphics_mc.lineTo(0, charH);
    		graphics_mc.lineTo(0, 0);
    	graphics_mc.endFill();
    	residual_mc._x = -(residualBuffer * behavior.maxSpeed);
    	residual_mc._y = -(residualBuffer * behavior.maxSpeed);
    };
    // process keypresses independent of Key.addListener() event handlers
    function getInput() {
    	// assume no key is pressed
    	behavior.moveX = 0;
    	behavior.moveY = 0;
    	if(Key.isDown(Key.LEFT)) {
    		if(char_mc._x - behavior.maxSpeed >= 0) {
    			// enable left movement
    			behavior.moveX = -1;
    		}
    	}
    	if(Key.isDown(Key.RIGHT)) {
    		if(worldW - (char_mc._x + charW + behavior.maxSpeed) >= 0) {
    			// enable up movement
    			behavior.moveX = 1;
    		}
    	}
    	if(Key.isDown(Key.UP)) {
    		if(char_mc._y - behavior.maxSpeed >= 0) {
    			// enable right movement
    			behavior.moveY = -1;
    		}
    	}
    	if(Key.isDown(Key.DOWN)) {
    		if(worldH - (char_mc._y + charH + behavior.maxSpeed) >= 0) {
    			// enable down movement
    			behavior.moveY = 1;
    		}
    	}
    	// toggle rendering of residual frames
    	ALLOW_RESIDUAL = !Key.isToggled(Key.CAPSLOCK);
    };
    // process the movement flags and update character position on screen
    function moveChar() {
    	char_mc._x += behavior.moveX * behavior.maxSpeed;
    	char_mc._y += behavior.moveY * behavior.maxSpeed;
    };
    function drawFrame() {
    	// build translation matrix
    	residualMatrix = new Matrix(1, 0, 0, 1, residualBuffer * behavior.maxSpeed, residualBuffer * behavior.maxSpeed);
    	// once-per-frame code
    		getInput();
    		moveChar();
    		// translate the residual frames rendered up until this point
    		residualSurface.scroll(-behavior.moveX * behavior.maxSpeed, -behavior.moveY * behavior.maxSpeed);
    		// apply fade to residual frames rendered up until this point
    		residualSurface.colorTransform(residualRegion, residualFader);
    		// conditionally allow current frame to be added to residual frames
    		(ALLOW_RESIDUAL) ? residualSurface.draw(graphics_mc, residualMatrix) : null;
    
    		// clean up before compositing
    		residual_mc.clear();
    		// composite the residual frames into the final frame
    		residual_mc.lineStyle(0, 0x000000, 0);
    		residual_mc.moveTo(0, 0);
    		residual_mc.beginBitmapFill(residualSurface);
    			residual_mc.lineTo(residualRegion.width, 0);
    			residual_mc.lineTo(residualRegion.width, residualRegion.height);
    			residual_mc.lineTo(0, residualRegion.height);
    			residual_mc.lineTo(0, 0);
    		residual_mc.endFill();
    	
    		// clean up before capturing
    		renderSurface.fillRect(new Rectangle(0, 0, worldW, worldH), 0xff000000);
    		// capture the current composite
    		renderSurface.draw(world_mc);
    	
    		// clean up before rendering
    		render_mc.clear();
    		// render the current final frame
    		render_mc.lineStyle(0, 0x000000, 0);
    		render_mc.moveTo(0, 0);
    		render_mc.beginBitmapFill(renderSurface);
    			render_mc.lineTo(worldW, 0);
    			render_mc.lineTo(worldW, worldH);
    			render_mc.lineTo(0, worldH);
    			render_mc.lineTo(0, 0);
    		render_mc.endFill();
    	// end of once-per-frame code
    };
    It is important to note that while the first demonstration can be run using 255 residual frames with no perceptible bogging, this second demonstration begins to bog very noticably with a residual frame count of only 32 (on my junky machine, at least). While a strict rectangle is far from being anything remotely like a fully animated character, you get the idea.

    The first demo can be used to generate fog-like effects by setting the alpha value of playerMC.lineStyle() to 1 and changing the alpha channel transformation in residualFade to return a positive value instead of a negative one. Unfortunately, this takes time to generate anything very interesting, but perhaps using a for() loop might be handy in churning out a randomized haze layer in no time.

    More soon.
    Qwai•zang \kwî-'zan\ n [origin unknown] 1 : abstract designer, esp. of complex real-time experiments, c. 21st century

  2. #2
    Please, Call Me Bob trogdor458's Avatar
    Join Date
    Aug 2006
    Location
    Pensacola, FL
    Posts
    915
    hows this for a residual effect?
    http://trogdorffe.tripod.com/junk.htm
    note, it actualy looks kindof cooler on low quality (which makes it somewhat pixelated)

    EDIT: advertisements appear to have some effect on the thing...

  3. #3
    Please, Call Me Bob trogdor458's Avatar
    Join Date
    Aug 2006
    Location
    Pensacola, FL
    Posts
    915
    ...and if you combine that with a ColorMatrixFilter, you can make a lava-lampish effect.
    http://trogdorffe.tripod.com/junk2.htm
    note that the ColorMatrix filter stays, allowing the whiteness to "overtake" the darkness, unlike in the other version

    so i made it draw the opposite color of getPixel(1,1) instead of just white

  4. #4
    Qwaizang:syntax_entity_ Q__Hybrid's Avatar
    Join Date
    Aug 2005
    Posts
    270
    Sorry Trog, either the file's been removed or Player 9 won't run it. Nonetheless, I want to begin working with ColorMatrixFilter to see what it can do. It sounds powerful.

    For the time being, I'm a bit stumped as to why my second demo is bogging when my first one isn't. I think it's related to the dimensions of the BitmapData, but even when I reduce maxSpeed to 1 it runs at about half the expected framerate. Not that I would ever need more than 8 residual frames, I just don't understand where the bottleneck is. Ah well, if it isn't a problem, I guess I won't dwell on it.
    Qwai•zang \kwî-'zan\ n [origin unknown] 1 : abstract designer, esp. of complex real-time experiments, c. 21st century

  5. #5
    M.D. mr_malee's Avatar
    Join Date
    Dec 2002
    Location
    Shelter
    Posts
    4,139
    why are you using beginBitmapFill when you're not actually repeating anything, it looks like an unnecessary step. Just attach residual Surface to render_mc

    render_mc.attachBitmap(residualSurface, 0) //do once
    lather yourself up with soap - soap arcade

  6. #6
    Senior Member webgeek's Avatar
    Join Date
    Sep 2000
    Posts
    1,352
    heh, I like the second one, thats a fun effect.

  7. #7
    Qwaizang:syntax_entity_ Q__Hybrid's Avatar
    Join Date
    Aug 2005
    Posts
    270

    Dynamic Lo-fi Lighting

    One thing I wanted to incorporate into my engine was simulated light sources. I managed to come up with a fairly versatile solution that can achieve some fairly decent results even though it's considerably lo-fi. A rudimentary example follows. As usual, "copy, paste, run"; replace "YOUR_URL_HERE" in the script with an url to a source image, use keys 1 thru 6 to enable different blend modes, and use the mouse to translate the position of your source image:

    Code:
    // new document: frame 1, main timeline
    // set document dimensions to: 640 x 480
    // set document framerate to: 30 or 60
    
    // import the classes we need
    import flash.display.BitmapData
    import flash.geom.ColorTransform
    import flash.geom.Matrix
    import flash.geom.Rectangle
    
    // clean reference to root
    var myRoot:MovieClip							= this;
    // the container of our world
    var world:MovieClip								= myRoot.createEmptyMovieClip("world", myRoot.getNextHighestDepth());
    // the surface where our frames are rendered
    var render:MovieClip							= myRoot.createEmptyMovieClip("render", myRoot.getNextHighestDepth());
    // the surface that contains the terrain
    var terrain:MovieClip							= world.createEmptyMovieClip("terrain", world.getNextHighestDepth());
    // the surface where lights are drawn
    var lighting:MovieClip 						= world.createEmptyMovieClip("lighting", world.getNextHighestDepth());
    // the discreet layers of the lighting data
    var lightSurface_0:MovieClip 			= lighting.createEmptyMovieClip("lightSurface_0", lighting.getNextHighestDepth());
    var lightSurface_1:MovieClip 			= lighting.createEmptyMovieClip("lightSurface_1", lighting.getNextHighestDepth());
    var lightSurface_2:MovieClip 			= lighting.createEmptyMovieClip("lightSurface_2", lighting.getNextHighestDepth());
    var lightSurface_3:MovieClip 			= lighting.createEmptyMovieClip("lightSurface_3", lighting.getNextHighestDepth());
    var lightSurface_4:MovieClip 			= lighting.createEmptyMovieClip("lightSurface_4", lighting.getNextHighestDepth());
    var lightSurface_5:MovieClip 			= lighting.createEmptyMovieClip("lightSurface_5", lighting.getNextHighestDepth());
    var lightSurface_6:MovieClip 			= lighting.createEmptyMovieClip("lightSurface_6", lighting.getNextHighestDepth());
    var lightSurface_7:MovieClip 			= lighting.createEmptyMovieClip("lightSurface_7", lighting.getNextHighestDepth());
    var lightSurface_8:MovieClip 			= lighting.createEmptyMovieClip("lightSurface_8", lighting.getNextHighestDepth());
    // the object responsible for downloading our terrain
    var terrainLoader:MovieClipLoader	= new MovieClipLoader();
    // the url of our terrain
    var terrainSource:String = "YOUR_URL_HERE";
    // the surface where our frames are compositted
    var frontBufferData:BitmapData		= new BitmapData(Stage.width, Stage.height, false, 0xff000000);
    // the array of light source objects
    var lightSources:Array = new Array();
    // this enables different blend modes
    var renderFlag:Number = 0;
    
    // establish our events
    myRoot.onLoad = init;
    myRoot.onEnterFrame = renderScene;
    
    // initialixation code
    function init() {
    	// reduce quality to improve framerate
    	myRoot._quality = "LOW";
    	// free up video memory by hiding our world
    	world._visible = false;
    	// prevent our lighting from obscuring our terrain
    	lighting._visible = false;
    	// create our light source objects
    	lightSources.push({x : 300, y : 230, r : 200});
    	lightSources.push({x : 420, y : 250, r : 80});
    	lightSources.push({x : 550, y : 190, r : 40});
    	lightSources.push({x : 40, y : 300, r : 300});
    	// establish rendering surface
    	render.attachBitmap(frontBufferData, 0);
    	// establish event handling
    	Key.addListener(myRoot);
    	terrainLoader.addListener(myRoot);
    	// begin transfer of terrain
    	terrainLoader.loadClip(terrainSource, terrain);
    };
    
    // event handlers
    function onKeyDown() {
    	// enable different blendmodes
    	if(Key.isDown(49)) {
    		renderFlag = 0;
    		return;
    	} else if(Key.isDown(50)) {
    		renderFlag = 1;
    		return;
    	} else if(Key.isDown(51)) {
    		renderFlag = 2;
    		return;
    	} else if(Key.isDown(52)) {
    		renderFlag = 3;
    		return;
    	} else if(Key.isDown(53)) {
    		renderFlag = 4;
    		return;
    	} else if(Key.isDown(54)) {
    		renderFlag = 5;
    	}
    };
    // more event handlers
    function onLoadInit() {
    	// go through all of the discreet layers of the lighting data
    	for(var lCount:Number = 0; lCount < 9; lCount++) {
    		// dynamically get the scope of the current discreet layer
    		with(lighting["lightSurface_" + lCount]) {
    			if(lCount < 1) {
    				// if this is the backdrop layer...
    				// apply a fill whose value is the darkest value in the lighting data
    				lineStyle(0, 0x000000, 100);
    				beginFill(0x000000, 100);
    					moveTo(0, 0);
    					lineTo(Stage.width, 0);
    					lineTo(Stage.width, Stage.height);
    					lineTo(0, Stage.height);
    					lineTo(0, 0);
    				endFill();
    			} else {
    				// otherwise...
    				// create a placeholder for our lighting value
    				var fillColor:Number;
    				// calculate the percentage of the radius for any given light source object
    				var m:Number = 1 - ((lCount - 1) / 8);
    				// the first layer is darkest, the last layer is lightest, so...
    				// assign the proper lighting values to our placeholder
    				if(lCount == 1) {
    					fillColor = 0x1f1f1f;
    				} else if(lCount == 2) {
    					fillColor = 0x3f3f3f;
    				} else if(lCount == 3) {
    					fillColor = 0x5f5f5f;
    				} else if(lCount == 4) {
    					fillColor = 0x7f7f7f;
    				} else if(lCount == 5) {
    					fillColor = 0x9f9f9f;
    				} else if(lCount == 6) {
    					fillColor = 0xbfbfbf;
    				} else if(lCount == 7) {
    					fillColor = 0xdfdfdf;
    				} else if(lCount == 8) {
    					fillColor = 0xffffff;
    				}
    				// establish lineStyle for this discreet layer
    				lineStyle(1, fillColor, 100);
    				// go through every light source object
    				for(sCount:Number = 0; sCount < lightSources.length; sCount++) {
    					// begin rendering the fill of this value for this light source object
    					beginFill(fillColor, 100);
    					// start drawing a lo-fi, 8-point circle
    					moveTo(lightSources[sCount].x + m * lightSources[sCount].r, lightSources[sCount].y);
    					// draw the remaining points
    					for(var t:Number = 0; t < Math.PI * (8 / 4); t += Math.PI * (1 / 4)) {
    						lineTo(	lightSources[sCount].x + Math.cos(t) * m * lightSources[sCount].r,
    										lightSources[sCount].y - Math.sin(t) * m * lightSources[sCount].r);
    					}
    					// draw the final point
    					lineTo(lightSources[sCount].x + m * lightSources[sCount].r, lightSources[sCount].y);
    					// complete rendering the fill of this value for this light source object
    					endFill();
    				}
    			}
    		}
    	}
    };
    
    function renderScene() {
    	// update position of terrain
    	terrain._x = (myRoot._xmouse) - (terrain._width / 2);
    	terrain._y = (myRoot._ymouse) - (terrain._height / 2);
    	// clean up the front buffer before capturing
    	// < comment out the clean up for some interesting residual imaging effects >
    	frontBufferData.fillRect(new Rectangle(0, 0, Stage.width, Stage.height), 0xff000000);
    	// apply blend modes...
    	switch(renderFlag) {
    		case 0:
    			// multiply, single pass lighting
    			frontBufferData.draw(world);
    			frontBufferData.draw(lighting, new Matrix(), new ColorTransform(), "multiply");
    			break;
    		case 1:
    			// render only the lighting data
    			frontBufferData.draw(lighting);
    			break;
    		case 2:
    			// render only the world
    			frontBufferData.draw(world);
    			break;
    		case 3:
    			// multiply, overlay, dual pass lighting
    			frontBufferData.draw(world);
    			frontBufferData.draw(lighting, new Matrix(), new ColorTransform(), "multiply");
    			frontBufferData.draw(lighting, new Matrix(), new ColorTransform(), "overlay");
    			break;
    		case 4:
    			// overlay, single pass lighting
    			frontBufferData.draw(world);
    			frontBufferData.draw(lighting, new Matrix(), new ColorTransform(), "overlay");
    			break;
    		case 5:
    			// hardlight, single pass lighting
    			frontBufferData.draw(world);
    			frontBufferData.draw(lighting, new Matrix(), new ColorTransform(), "hardlight");
    			break;
    	}
    };
    The foremost thing to notice in this demo is that the lightsources simulate blending when their gradient fills overlap. That is to say, values that are alike in adjacent gradients merge so that no gradient fills are superimposed on top of other gradient fills (darkest values in one covering up lightest values in another, etc.)

    The principles of this demo are in the process of being converted over to a self-contained class and will not be so chunky in its final form.

    The strange thing about this approach is that when Flash Player is rendering using high quality, artifacts start showing up in the final frame. I won't be using high quality, so this isn't an issue for me. All the same, does anybody know why those artifacts are happening?
    Last edited by Q__Hybrid; 04-24-2007 at 02:45 AM.
    Qwai•zang \kwî-'zan\ n [origin unknown] 1 : abstract designer, esp. of complex real-time experiments, c. 21st century

  8. #8
    Pumpkin Carving 2008 ImprisonedPride's Avatar
    Join Date
    Apr 2006
    Location
    Grand Rapids MI
    Posts
    2,377
    Is there no way to gradiently blend each ring from the lightest value in the first ring, to the lightests color in the second? The concept is really cool, but the rings look slightly foolish. As I said, if you were able to blend each ring into the one larger than it, it would be really something...
    The 'Boose':
    ASUS Sabertooth P67 TUF
    Intel Core i7-2600K Quad-Core Sandy Bridge 3.4GHz Overclocked to 4.2GHz
    8GB G.Skill Ripjaws 1600 DDR3
    ASUS ENGTX550 TI DC/DI/1GD5 GeForce GTX 550 Ti (Fermi) 1GB 1GDDR5 (Overclocked to 1.1GHz)
    New addition: OCZ Vertex 240GB SATA III SSD
    WEI Score: 7.6

  9. #9
    M.D. mr_malee's Avatar
    Join Date
    Dec 2002
    Location
    Shelter
    Posts
    4,139
    it nice, but very ugly looking, hows the performance with a higher poly count?
    lather yourself up with soap - soap arcade

  10. #10
    Please, Call Me Bob trogdor458's Avatar
    Join Date
    Aug 2006
    Location
    Pensacola, FL
    Posts
    915
    oh thats right, i replaced my lava lamp with this bizarre thing:
    http://trogdorffe.tripod.com/junk3.htm

  11. #11
    Pumpkin Carving 2008 ImprisonedPride's Avatar
    Join Date
    Apr 2006
    Location
    Grand Rapids MI
    Posts
    2,377
    You're movie doesn't load, trog. And yes, I do have flash player 9.
    The 'Boose':
    ASUS Sabertooth P67 TUF
    Intel Core i7-2600K Quad-Core Sandy Bridge 3.4GHz Overclocked to 4.2GHz
    8GB G.Skill Ripjaws 1600 DDR3
    ASUS ENGTX550 TI DC/DI/1GD5 GeForce GTX 550 Ti (Fermi) 1GB 1GDDR5 (Overclocked to 1.1GHz)
    New addition: OCZ Vertex 240GB SATA III SSD
    WEI Score: 7.6

  12. #12
    Qwaizang:syntax_entity_ Q__Hybrid's Avatar
    Join Date
    Aug 2005
    Posts
    270
    IP: I'm a little bit confused as to exactly what you're asking. Do you mean a blending of contour to create more of a "blob" pattern, or do you mean some sort of blending of colors that is different than the one I'm using?

    This would require a bit more math and would slow down the framerate somewhat. However, I've already figured out most of the logic behind it in my head and I should really figure out just how much slower it actually runs, right?

    Malee: You're right that it does look choppy, but when it's blended into the final frame I really don't notice it that much. Using a series of curveTo() calls would help reduce the chunky look of it. When I get the "blob" version written the poly count will be 32 points per circle, not 8.
    Qwai•zang \kwî-'zan\ n [origin unknown] 1 : abstract designer, esp. of complex real-time experiments, c. 21st century

  13. #13
    Pumpkin Carving 2008 ImprisonedPride's Avatar
    Join Date
    Apr 2006
    Location
    Grand Rapids MI
    Posts
    2,377
    Use a gradient on the mask of the inner circle to meet the color of the next circle so that you have one continuous gradient instead of rings.
    The 'Boose':
    ASUS Sabertooth P67 TUF
    Intel Core i7-2600K Quad-Core Sandy Bridge 3.4GHz Overclocked to 4.2GHz
    8GB G.Skill Ripjaws 1600 DDR3
    ASUS ENGTX550 TI DC/DI/1GD5 GeForce GTX 550 Ti (Fermi) 1GB 1GDDR5 (Overclocked to 1.1GHz)
    New addition: OCZ Vertex 240GB SATA III SSD
    WEI Score: 7.6

  14. #14
    Qwaizang:syntax_entity_ Q__Hybrid's Avatar
    Join Date
    Aug 2005
    Posts
    270
    IP: again you've lost me. Maybe a picture would help explain?

    Back to code...
    Qwai•zang \kwî-'zan\ n [origin unknown] 1 : abstract designer, esp. of complex real-time experiments, c. 21st century

  15. #15
    Senior Member
    Join Date
    Feb 2005
    Posts
    1,836
    Can't load the movie here either. If I load it in Safari it says that the swf is not found.
    .

  16. #16
    Zombie Coder EvilKris's Avatar
    Join Date
    Jun 2006
    Location
    Fukuoka, Japan.
    Posts
    796
    This is a good thread. Anybody else have some unusual techniques to get cool special effects on their movieclips?

  17. #17
    Please, Call Me Bob trogdor458's Avatar
    Join Date
    Aug 2006
    Location
    Pensacola, FL
    Posts
    915
    wont load? does this include the blob effect? ill just post the code then:
    import flash.display.BitmapData;
    import flash.filters.ColorMatrixFilter;
    import flash.filters.BlurFilter;
    import flash.geom.Point;
    removeMovieClip(drawer);
    if(bitmap==undefined){
    var bitmap:BitmapData=new BitmapData(200,200,true,0xFF000000);
    this.createEmptyMovieClip("bitmappy",this.getNextH ighestDepth());
    bitmappy.attachBitmap(bitmap,this.getNextHighestDe pth(),"auto",true);
    }
    this.createEmptyMovieClip("drawer",-500);
    drawer.lineStyle(19.5,0xFFFFFF-bitmap.getPixel(1,1));
    drawer.beginFill(0,0);
    drawer.moveTo(oldx,oldy);
    drawer.lineTo(_root._xmouse,_root._ymouse);
    drawer.endFill();
    bitmap.draw(drawer);
    var matrix:Array = new Array(2,0,0,0,-128,0,2,0,0,-128,0,0,2,0,-128,0,0,0,1.1,0);
    var filter:BlurFilter= new BlurFilter(6,6,3);
    var filter2:ColorMatrixFilter= new ColorMatrixFilter(matrix);
    bitmap.applyFilter(bitmap,bitmap.rectangle,new Point(0,0),filter);
    bitmap.applyFilter(bitmap,bitmap.rectangle,new Point(0,0),filter2);
    var oldx:Number=_root._xmouse;
    var oldy:Number=_root._ymouse;
    its a two framer

    EDIT: something wrong with this forum adds an extra space here and there, delete the one in getNextHighestDepth
    Last edited by trogdor458; 04-26-2007 at 05:12 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center