|
-
Blood Splatters: Best Practices?
I'm making a zombie game and when a zombie get's shot, a movieclip of blood splattering appears on the wall behind it and stays there.
Problem is, the death of each zombie produces 100 of these splatters (which is intentional) which eventually causes the gamer to lag.
I've optimized the image down to like 10% it's original value (now 44 shapes), but it still causes it to lag.
I heard about drawing them within a bitmap, or tracing the pixels to a bitmap, but have no idea how to do that. Is there anyone who knows the best way to do permanent blood splatters?
Thanks
PS: I'm using AS3
-
Senior Member
http://blog.bluemagica.com/?p=22
If you have multiple images you can try blitting too. google on as3 blitting for loads of examples.
If you like me, add me to your friends list  .
PS: looking for spriters and graphics artists for a RPG and an Arcade fighting project. If you can help out, please pm me!
My Arcade My Blog
Add me on twitter: 
-
Hi,
I tried downloading the .RAR file, but access is denied
-
Senior Member
It should be working now!
If you like me, add me to your friends list  .
PS: looking for spriters and graphics artists for a RPG and an Arcade fighting project. If you can help out, please pm me!
My Arcade My Blog
Add me on twitter: 
-
I'm not sure how all of the code works, especially with Blood being a Class. It looks great, but I can't get it implemented in my game. I keep getting error
TypeError: Error #1007: Instantiation attempted on a non-constructor.
at Scripts::Zombie/drawBloodSplatter()
at Scripts::Zombie/checking()
Here's my current code (my final attempt at implementation left me just copying and pasting your code into my game).
Actionscript Code:
package Scripts{ import flash.display.*; import flash.events.*; import flash.utils.Timer; import flash.display.Bitmap; import flash.display.BitmapData; import flash.geom.ColorTransform; import flash.geom.Matrix; import flash.geom.Point; import flash.geom.Rectangle;
public class Zombie extends MovieClip {
var thisZombie:MovieClip; var ground:MovieClip; var thisParent:*; var spawnPosition:uint=Math.random()*2; var distance:Number; var isTouchingGround:Boolean; var zombieRight:Boolean; var zombieWalking:Boolean=false; var attacking:Boolean=false; var attackTimer:Timer=new Timer(1000); var zombieHealth:int; var bullet:MovieClip; private var blood:Class; protected var canvas:Bitmap;
public function Zombie() { if (spawnPosition==0) { this.x=490; } else { this.x=0; } zombieHealth=100; trace("FUN"); this.scaleX=0.6; this.scaleY=0.6; this.addEventListener(Event.ADDED,initialize); } function initialize(event:Event):void { thisParent=event.currentTarget.parent; ground=thisParent.ground; thisZombie=MovieClip(this.parent.getChildByName(this.name)); attackTimer.start(); canvas = new Bitmap(); var bmd:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight); bmd.floodFill(0, 0, 0x444444); canvas.bitmapData = bmd; stage.addChild(canvas);
attackTimer.addEventListener(TimerEvent.TIMER, attackable); this.addEventListener(Event.ENTER_FRAME,moveZombie); this.addEventListener(Event.ENTER_FRAME,checking); } function moveZombie(evt:Event) { distance=this.x-thisParent.player.x; if (isTouchingGround==true) { if (distance>-70&&distance<70) { if (attacking==false) { thisZombie.gotoAndStop(1); } zombieWalking=false; } else { if (distance>0) { if (zombieRight==false) { thisZombie.scaleX*=-1; zombieRight=true; } if (zombieWalking==false) { thisZombie.gotoAndPlay("Walk"); zombieWalking=true; } thisZombie.x-=5; } else { if (zombieRight==true) { thisZombie.scaleX*=-1; zombieRight=false; } if (zombieWalking==false) { thisZombie.gotoAndPlay("Walk"); zombieWalking=true; } thisZombie.x+=5; } } } if (! this.hitTestObject(ground)) { isTouchingGround=false; thisZombie.y+=9.8; } else { isTouchingGround=true; } } function checking(evt:Event) { //ZOMBIE ATTACK CHECK if (distance>-70&&distance<70) { if (attacking==false) { thisZombie.gotoAndPlay("Attack"); trace("ATTACK"); thisParent.decreasePlayerHealth(); attacking=true; } } //BULLET HIT TEST for (var i=0; i<thisParent.bulletArray.length; i++) { if (this.hitTestObject(thisParent.bulletArray[i]) && thisParent.bulletArray[i] != null) { zombieHealth--; drawBloodSplatter(canvas, thisParent.bulletArray[i].x, thisParent.bulletArray[i].y, 12, 0, 75, 160);
thisParent.bulletArray[i].removeEventListener(Event.ENTER_FRAME, thisParent.bulletArray[i].moveBullet); thisParent.removeChild(thisParent.bulletArray[i]); thisParent.bulletArray.splice(i,1); } } if(zombieHealth<=0) { attackTimer.removeEventListener(TimerEvent.TIMER, attackable); attackTimer.stop(); this.removeEventListener(Event.ENTER_FRAME, moveZombie); this.removeEventListener(Event.ENTER_FRAME, checking); this.removeEventListener(Event.ADDED,initialize); thisParent.removeChild(thisZombie); } } function attackable(evt:TimerEvent) { attacking=false; } private function drawBloodSplatter(container:Bitmap,destX:Number,destY:Number,particleCount:uint,distance:uint,intensity:uint,size:uint):void { /** * drawBloodSplatter * @param container: Bitmap where the blood will be drawn * destX: X coordinate of where the splatter should be drawn at * destY: Y coordinate of where the splatter should be drawn at * particleCount: Number of particles in the splatter. (1-100) * distance: spread distance of the splatter. * intensity: transperancy of the splatter. (1-100) * size: approx size of each particle. */ for (var b:uint = 0; b < particleCount; b++ ) { var temp:Bitmap = new blood(); var transMat:Matrix = new Matrix(); transMat.rotate(Math.random() * 359); transMat.scale((Math.random() * size + size/4)/100, (Math.random() * size + size/4)/100); transMat.translate(destX + Math.random() * distance - (distance / 2), destY + Math.random() * distance - (distance / 2)); container.bitmapData.draw(temp.bitmapData, transMat, new ColorTransform(1,1,1,(Math.random()*intensity+(intensity/4))/100), null, null, true); } } } }
I've added the blood Splatter image you provided into the library and exported it to Actionscript as blood. What is the blood:Class representing?
-
Senior Member
err actually, just remove this line:
private var blood:Class;
I needed to use this cause I used flexSDK to compile my file, and there the only way to quickly add an instance, let it be graphics, sound, another swf or whatever, is to use the Embed tag(you can see that in my file just above that line). Since the resource can be of any type, we need to define a class to handle it(which we can cast to a specific type when using it) . But in flash you are using the built-in exporter, so you don't need that declaration.
Another thing, isn't this class you are implementing this is inside the zombie class? are you thinking of creating a separate canvas and blood splatter layer for every zombie instance? cause it really doesn't make any sense. You have to create the canvas only once on the stage before any zombie, bullet, player or other objects are created, otherwise a blood splatter might get created "over" the zombies.
Last edited by bluemagica; 06-07-2010 at 10:44 PM.
If you like me, add me to your friends list  .
PS: looking for spriters and graphics artists for a RPG and an Arcade fighting project. If you can help out, please pm me!
My Arcade My Blog
Add me on twitter: 
-
It's still not working 
Do you have Flash? Would it be better if I sent you the .fla and .as files?
My current code:
Actionscript Code:
package Scripts{ import flash.display.*; import flash.events.*; import flash.utils.Timer; import flash.display.Bitmap; import flash.display.BitmapData; import flash.geom.ColorTransform; import flash.geom.Matrix; import flash.geom.Point; import flash.geom.Rectangle;
public class Zombie extends MovieClip {
var thisZombie:MovieClip; var ground:MovieClip; var thisParent:*; var spawnPosition:uint=Math.random()*2; var distance:Number; var isTouchingGround:Boolean; var zombieRight:Boolean; var zombieWalking:Boolean=false; var attacking:Boolean=false; var attackTimer:Timer=new Timer(1000); var zombieHealth:int; var bullet:MovieClip; protected var canvas:Bitmap; var blood:Bitmap = new blood(thisParent.back);
public function Zombie() { if (spawnPosition==0) { this.x=490; } else { this.x=0; } zombieHealth=100; trace("FUN"); this.scaleX=0.6; this.scaleY=0.6; this.addEventListener(Event.ADDED,initialize); } function initialize(event:Event):void { thisParent=event.currentTarget.parent; ground=thisParent.ground; thisZombie=MovieClip(this.parent.getChildByName(this.name)); attackTimer.start(); canvas = new Bitmap(); var bmd:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight); bmd.floodFill(0, 0, 0x444444); canvas.bitmapData = bmd; stage.addChild(canvas);
attackTimer.addEventListener(TimerEvent.TIMER, attackable); this.addEventListener(Event.ENTER_FRAME,moveZombie); this.addEventListener(Event.ENTER_FRAME,checking); } function moveZombie(evt:Event) { distance=this.x-thisParent.player.x; if (isTouchingGround==true) { if (distance>-70&&distance<70) { if (attacking==false) { thisZombie.gotoAndStop(1); } zombieWalking=false; } else { if (distance>0) { if (zombieRight==false) { thisZombie.scaleX*=-1; zombieRight=true; } if (zombieWalking==false) { thisZombie.gotoAndPlay("Walk"); zombieWalking=true; } thisZombie.x-=5; } else { if (zombieRight==true) { thisZombie.scaleX*=-1; zombieRight=false; } if (zombieWalking==false) { thisZombie.gotoAndPlay("Walk"); zombieWalking=true; } thisZombie.x+=5; } } } if (! this.hitTestObject(ground)) { isTouchingGround=false; thisZombie.y+=9.8; } else { isTouchingGround=true; } } function checking(evt:Event) { //ZOMBIE ATTACK CHECK if (distance>-70&&distance<70) { if (attacking==false) { thisZombie.gotoAndPlay("Attack"); trace("ATTACK"); thisParent.decreasePlayerHealth(); attacking=true; } } //BULLET HIT TEST for (var i=0; i<thisParent.bulletArray.length; i++) { if (this.hitTestObject(thisParent.bulletArray[i]) && thisParent.bulletArray[i] != null) { zombieHealth--; drawBloodSplatter(canvas, thisParent.bulletArray[i].x, thisParent.bulletArray[i].y, 12, 0, 75, 160);
thisParent.bulletArray[i].removeEventListener(Event.ENTER_FRAME, thisParent.bulletArray[i].moveBullet); thisParent.removeChild(thisParent.bulletArray[i]); thisParent.bulletArray.splice(i,1); } } if(zombieHealth<=0) { attackTimer.removeEventListener(TimerEvent.TIMER, attackable); attackTimer.stop(); this.removeEventListener(Event.ENTER_FRAME, moveZombie); this.removeEventListener(Event.ENTER_FRAME, checking); this.removeEventListener(Event.ADDED,initialize); thisParent.removeChild(thisZombie); } } function attackable(evt:TimerEvent) { attacking=false; } private function drawBloodSplatter(container:Bitmap,destX:Number,destY:Number,particleCount:uint,distance:uint,intensity:uint,size:uint):void { /** * drawBloodSplatter * @param container: Bitmap where the blood will be drawn * destX: X coordinate of where the splatter should be drawn at * destY: Y coordinate of where the splatter should be drawn at * particleCount: Number of particles in the splatter. (1-100) * distance: spread distance of the splatter. * intensity: transperancy of the splatter. (1-100) * size: approx size of each particle. */ for (var b:uint = 0; b < particleCount; b++ ) { var temp:Bitmap = new blood(); var transMat:Matrix = new Matrix(); transMat.rotate(Math.random() * 359); transMat.scale((Math.random() * size + size/4)/100, (Math.random() * size + size/4)/100); transMat.translate(destX + Math.random() * distance - (distance / 2), destY + Math.random() * distance - (distance / 2)); container.bitmapData.draw(temp.bitmapData, transMat, new ColorTransform(1,1,1,(Math.random()*intensity+(intensity/4))/100), null, null, true); } } } }
and current Compiler Errors:
1180: Call to a possibly undefined method blood. var temp:Bitmap = new blood();
1180: Call to a possibly undefined method blood. var blood:Bitmap = new blood(thisParent.back);
-
I also thought about the bitmap with each Zombie thing, I first wanted to get this working before I moved that stuff. I'm becoming obsessed with fixing this, but cannot for the life of me figure it out. The best I've done is made a bitmap that filled the screen, but the blood always created itself in the top left corner, for some reason my position data (blood.y then mybitmapdata.draw(blood) wasn't applying itself to the draw. I searched the internet for information on how to apply positional data to a draw function, and couldn't find anything.
Thanks for all the time your putting into this.
-
Senior Member
yeh, you can pm me the fla, I have cs4.
from there it seems, blood is not defined, or flash can't find it. There can be quite a few reasons for this, but it would be better if I see the thing upfront, rather than guessing possible solutions.
Oh, and if this doesn't have a fixed deadline, I would advice you to think and restructure your game properly; a mish-mash of as2/as3 isn't very flexible and will only cause problems for you.
as for the draw, you user the translate function of the matrix that is being passed in the draw method.
If you like me, add me to your friends list  .
PS: looking for spriters and graphics artists for a RPG and an Arcade fighting project. If you can help out, please pm me!
My Arcade My Blog
Add me on twitter: 
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|