PDA

View Full Version : How to kill last image of animation...



Wizard
27-08-2007, 08:20 AM
Hi everyone. My game is a SpaceFighter programmed with DelphiX. I followed Mr Farmer's advice and created a seperate class for the explosion, i.e.when my bullet hits my enemy the enemy image is replaced by an animated explosion:


//The explosion class
TExplode = class(TImageSprite)
public
constructor Create(AParent: TSprite); override;
end;


Constructor TExplode.Create(AParent: TSprite);
begin
inherited Create(AParent);
self.Image := Form1.DXImageList1.Items[form1.ExplodeImageIndex];
self.X := Enemy.X;
self.Y := Enemy.Y;
self.Width := Enemy.Image.Width;
self.Height := Enemy.Image.Height;
self.PixelCheck := False;
self.AnimCount := Image.PatternCount;
//self.AnimLooped:= True;
self.AnimSpeed:= (60/1000) * UpdateSpeed;
end;

procedure TForm1.BulletCollision(Sender:TObject;var done:Boolean);
begin
if (sender is TEnemy) then
begin
Enemy := TEnemy(sender);
if (not Enemy.Hit) then
begin
Explode := TExplode.Create(dxSpriteEngine1.Engine);
Enemy.hit := true;
Enemy.Dead;
Bullet.Dead;
Points := Points + 1000;
EnemyCount := EnemyCount + 1;
Enemy := TEnemy.create(dxspriteEngine1.Engine,dximageList1, EnemyLeftImageIndex);
end;
end
else ...

Problem is that once the bullet hits the enemy the explosion animation runs perfectly but stops at the last image of the animation. This "last" image of the animation then stays on ths screen. How do I kill it? Explode.Dead kills it but then the animation does not run :-(

DraculaLin
27-08-2007, 11:23 AM
See this Sprite Engine shooter demo.It use Asphyre but Sprite Engine is the same as DelphiX.
http://www.afterwarp.net/forum/thread220.html

Wizard
27-08-2007, 12:04 PM
Thanks, I'll have a look :-)

I tried the following:

procedure TExplode.DoMove(MoveCount : integer);
begin
lifecount := lifecount +1;
if lifecount > 5 then
self.Dead;
end;

It works but the animation is too fast, no matter how slow I set the animspeed * updatespeed :(

Another solution is that I add a black (trransparent) image at the end of the animation...it works but I don't know if it will cause problems because the image is simply transparent and not realy dead. I tried it for long periods and there doesn't seem to be any negative effects. Maybe someone can comment on the last solution?

Thanks!

Legolas
27-08-2007, 12:13 PM
Try this:


procedure TExplode.DoMove(MoveCount : integer);
begin
inherited doMove(MoveCount);
lifecount := lifecount +1;
if lifecount > 5 then
Dead;
end;

Wizard
27-08-2007, 12:24 PM
Legolas, it works but as I said before the animation is just too fast, you only see a little bit more than a flicker :(

What about if I just set the last image in the animation to be transparent without the doMove and simply calling the explode in the collision procedure?

FNX
27-08-2007, 01:07 PM
Try to slow down your Animspeed, then check AnimPos vs Animcount
and you're done :)

something like this


if (AnimPos > ((AnimCount-1)-AnimSpeed)) then Dead

should work.

Anyway make large use of screen debugs (TextOut) so that you may
understand how the sprite behave

Wizard
27-08-2007, 04:02 PM
Tanks guys. FNX can you explain what you mean with large TextOuts? Do you mean that large TextOuts will slow down the game so that sprites move slower?

Maybe my over all speed is too fast because I tried your suggestions and I get the same effects...FPS is 1000 div 200 and the OneMSec is 100/1000 and UpdateSpeed := (NewTime - OldTime) * OneMSec; Maybe DelphiX is not good enough...

I tried getting Animspeed down and even with a Null value I get the same effects.

FNX
27-08-2007, 04:40 PM
Hi Wizard,
no i mean "large use" of Textout, as a debug so that you can see how
anim is going, for example print on screen the AnimPos value
and see if it goes from 0 to AnimCount-1 correctly or not :D Sorry for my
bad english ;)

About speed, this was discussed a lot in the past, I try to remember
everything in hope to help you :) (corrections are welcome of course!)

-Put a TimeBeginPeriod(1) inside you FormCreate event
-Set the Timer Interval at 1000/60 (that is 16 or somethin')
-Inside the Timer loop set Engine.DoMove(LagCount)
-Inside your sprites classes use, for ex: X = X + Speed*MoveCount

if you're using UnDelphiX to achive more speed be sure your main form
is declared as TDXForm and the DXDraw Options has do3D true.
WaitVBlank is up to you, i always turn it on even if it slow things down.

Last but not least, you don't need to code a custom constructor for your
class but inherit from TImageSprite that is more than enough. I try
to write something but don't take it as gold ;)


type
TMyExplosionSprite = class(TImageSprite)
private
//... whatever you need
public
procedure DoMove(MoveCount: Integer); override;
end;

// when you need to create a new explosion, i think in some DoCollision event of any other sprite do

with TExplosionSprite.Create(Form.DXSpriteEngine.Engine ) do
begin
Image := Form.DXImageList.Items.Find('explosion');
Width := Image.PatternWidth;
Height := Image.PatterHeight;

X := XPos; //whatever...
Y := YPos; //whatever...
Z := ZPos; //whatever but above the other sprites

AnimCount := Image.PatternCount;
AnimSpeed := 0.06; //whatever...
AnimLooped:= True;

Visible := True;
end;

procedure TExplosionSprite.DoMove(MoveCount : Integer);
begin
inherited DoMove(MoveCount);

AnimLooped := True;
AnimSpeed := 0.06*MoveCount; //whatever...

// if AnimPos has reached the last frame
if (AnimPos >= ((AnimCount-1)-AnimSpeed*MoveCount) then Dead;
end;



That, with the obvious needed corrections (i don't have delphi here so i wrote it by memory :oops: ) should work, at least is similar to what i use
for games myself :)

Wizard
27-08-2007, 05:24 PM
Hi FNX, thanks for your comments/help. I have found that setting the timer to a slow rate might cause jerky movement, therefore I've got it a lot faster and I use updatespeed to get time based movement in stead of frame based movement. Also, my dxDraw resolution is 1024/768 16 bit.

I don't have do3d but I'll do some tests, WaitVblank slows things down too much. I downloaded your game about the Japanese robots and I liked your explosions a lot 8) One thing I did notice is that your sprites move a lot slower than mine.

There's a lot of talk that DelphiX is outdated but I think it still has a lot of power :o Tip,I see you're using Find for the image change, an Index is a lot faster :-)

My game is working very well and it runs at the same speed on slow and fast machines...I'll get the animation right, I just need to do a few more tests :-) One thing I did realize is that there's a lot of different ways to do things when programming :-)

Happy coding :-)

Wizard
28-08-2007, 05:22 AM
Ok guys, it's working :-)

Thanks to FNX for this:

self.AnimSpeed := 0.06;
if (AnimPos >= ((AnimCount-1)-AnimSpeed)) then
self.Dead;

My AnimSpeed was too high, 0.06 works perfectly!

FNX
28-08-2007, 10:27 AM
Good job!

anyway, you don't need to call self. inside own method :)

Wizard
28-08-2007, 10:46 AM
8) 8) 8)