Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Nochmal Andorra: Problem bei Änderung einer Spriteanimation (https://www.delphipraxis.net/138028-nochmal-andorra-problem-bei-aenderung-einer-spriteanimation.html)

MechMac666 2. Aug 2009 15:46


Nochmal Andorra: Problem bei Änderung einer Spriteanimation
 
Hallo,

hab schon wieder ein Problem.
Ich habe mir mal das tutorial "Spriteengine angeschaut. Das Resultat sind ja einige Männekikken die über den Screen laufen.

Ich habe nun versucht nur ein Männchen zu erzeugen und dieses dann mittels den Cursortasten zu steuern.
Das Funktioniert eigentlich perfekt.

Nun wollte ich aber auch das die Animation entsprechend geändert wird.
in der Textur-Datei sind ja die Bewegungen als Einzelframes hintereinander abgelegt.
16 Einzelframes. Je 8 für links bzw. rechts.
Ich rede gerade von der Datei "boy.png".

In dem Quelltext wird das ja mit AnimStart und AnimStop angegeben.

Jetzt habe ich einfach folgendes gemacht:

Delphi-Quellcode:
procedure TFigur.SetLine;
begin
  if x_left then
  begin
   AnimStart := 8;
   AnimStop := 15;
  end;
  if x_right then
  begin
   AnimStart := 0;
   AnimStop := 7;
  end;
end;

x_left und x_right werden über OnKeyDown und OnKeyUp gesetzt bzw. zurückgesetzt.

Das Problem besteht darin das der Wechsel von rechts nach links etwas dauert. Anders herum komischer Weise nicht.
Das Männchen bewegt sich also ein Stück nach links aber erst einige 100stel Sekunden Später wechselt die Animation, was natürlich schäbbig aussieht.

hier der gesamte Quelltext:
Delphi-Quellcode:
unit Main;

interface

uses
  Windows, Dialogs, SysUtils, Graphics, Classes, Forms, AdDraws, AdClasses,
  Controls, ExtCtrls, AdSprites, AdSetupDlg, AdPNG, AdPerformanceCounter;

type
  TFigur = class(TImageSprite)
    private
    protected
      procedure DoMove(TimeGap:double);override;
    public
      XSpeed:integer;
      constructor Create(AParent:TSprite);override;
      procedure SetLine;
  end;

  TForm1 = class(TForm)
    procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    AdDraw:TAdDraw;
    AdPerCounter:TAdPerformanceCounter;
    AdImageList1:TAdImageList;
    AdSpriteEngine:TSpriteEngine;
    procedure Idle(Sender:TObject;var Done:boolean);
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  x_right:boolean=false;
  x_left:boolean=false;
  x_up:boolean=false;
  x_down:boolean=false;

const
  path = './resources/';

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  i:integer;
  AdSetupDlg:TAdSetup;
begin
  AdPerCounter := TAdPerformanceCounter.Create;

  AdDraw := TAdDraw.Create(self);

  AdSetupDlg := TAdSetup.Create(AdDraw);
  AdSetupDlg.Image := path+'logo1.png';

  if AdSetupDlg.Execute then
  begin
    if AdDraw.Initialize then
    begin
      Application.OnIdle := Idle;

      AdImageList1 := TAdImageList.Create(AdDraw);
      with AdImageList1.Add('figur') do
      begin
        Texture.LoadGraphicFromFile(path+'boy.png', true, clFuchsia);
        PatternWidth := 96;
        PatternHeight := 96;
      end;
      AdImageList1.Restore;

      AdSpriteEngine := TSpriteEngine.Create(nil);
      AdSpriteEngine.Surface := AdDraw;

      Randomize;


        with TFigur.Create(AdSpriteEngine) do
        begin
          Image := AdImageList1.Find('figur');
          AnimActive := true;
          AnimLoop := true;
          XSpeed := -100;
          AnimSpeed := Abs(XSpeed / 7.5);
          SetLine;
        end;
    end
    else
    begin
      ShowMessage(AdDraw.GetLastError);
      halt;
    end;
  end
  else
  begin
    halt;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  AdSpriteEngine.Free;
  AdImageList1.Free;
  AdPerCounter.Free;
  AdDraw.Free;
end;



procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
if key=VK_RIGHT then
x_right:=true;
if key=VK_LEFT then
x_left:=true;
if key=VK_UP then
x_up:=true;
if key=VK_DOWN then
x_down:=true;
end;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if key=VK_RIGHT then
x_right:=false;
if key=VK_left then
x_left:=false;
if key=VK_UP then
x_up:=false;
if key=VK_DOWN then
x_down:=false;
end;

procedure TForm1.Idle(Sender: TObject; var Done: boolean);
begin
  if AdDraw.CanDraw then
  begin
    AdPerCounter.Calculate;
    Caption := 'FPS:'+inttostr(AdPerCounter.FPS);

    AdDraw.ClearSurface(clBlack);
    AdDraw.BeginScene;

    AdSpriteEngine.Move(AdPerCounter.TimeGap / 1000);
    AdSpriteEngine.Draw;
    AdSpriteEngine.Dead;

    AdDraw.EndScene;
    AdDraw.Flip;

    Done := false;
  end;
end;

{ TFigur }

constructor TFigur.Create(AParent: TSprite);
begin
  inherited;
  X := 0;
  Y := 0;
  XSpeed := -150;
end;




procedure TFigur.DoMove(TimeGap: double);
begin
  inherited;

  SetLine;
  if (x_right and not (x_up or x_down)) then
  begin
  x:=x+0.2;
  end;

  if (x_left and not (x_up or x_down)) then
  begin
  x:=x-0.2;
  end;

  if (x_up and not (x_right or x_left)) then
  begin
  y:=y-0.2;
  end;

  if (x_down and not (x_right or x_left)) then
  begin
  y:=y+0.2;
  end;
end;



procedure TFigur.SetLine;
begin
  if x_left then
  begin
   AnimStart := 8;
   AnimStop := 15;
  end;
  if x_right then
  begin
   AnimStart := 0;
   AnimStop := 7;
  end;
end;


end.


Wer kann mir sagen warum der Schwenk von rechts nach links so lange dauert?
Mfg

MechMac666 2. Aug 2009 16:01

Re: Nochmal Andorra: Problem bei Änderung einer Spriteanimat
 
Interessant:

ich habe mal folgendes gemacht:

Delphi-Quellcode:
procedure TFigur.SetLine;
begin
  if x_left then
  begin
   form1.Caption:='left';
   AnimStart := 8;
   AnimStop := 15;
  end;
  if x_right then
  begin
   form1.Caption:='right';
   AnimStart := 0;
   AnimStop := 7;
  end;
end;
Die Caption ändert sich blitzschnell. Bei dem Bild dauert es bis es die neue Animation anzeigt.

Gehe ich das möglicherweise generell falsch an?

MechMac666 2. Aug 2009 19:10

Re: Nochmal Andorra: Problem bei Änderung einer Spriteanimat
 
Okay, ich habe auch das hinbekommen.

Möglicherweise handelt es sich um einen Bug, denn in dem Tutorial-Code ist das auch so. Ändert mal den Bereich wo die
Männchen laufen dürfen so ab, das sie auf der sichtbaren Fläche "umkehren". Dann kommt der gleiche Effekt zum tragen.

Fazit: Man darf die Animation nicht direkt ändern, sondern muss vorher mit AnimPos:=X eine Frame-Position festlegen. Erst dann
darf man über
AnimStart := X;
und
AnimStop := X;

den neuen Bereich festlegen. K.a. warum.

Ach ja, bei meinem Code muss man bei OnKeyDown noch eine invertierte Selbsthaltung einbauen, so das der die Boolschen Variablen nicht dauernd auf "True" setzt.

Weiterhin darf SetLine NUR beim tatsächlichen wechsel der Richtung bzw beim loslassen einer Taste aktiviert werden.

Wenn jemant interesse an dem geänderten Quelltext hat, kann ich den bei Bedarf posten.


Mfg


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:31 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz