Autor Beitrag
Mike_C
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 207

Win XP
D7 Enterprise
BeitragVerfasst: Sa 03.05.03 20:07 
Hi
ich suche eine Möglichkeit auf einfachem weg eine bewegung zu simulieren.

Dazu folgende situation:

der spieler eines brettspiels (in meinem fall monopoly) hat die möglichkeit zu würfeln. abhängig von der würfelzahl, soll seine figur bewegt werden.

das spielfeld habe ich so auf die form gebracht:

ich habe eine TImagekomponente und habe dann über ein TBitmap eine grafik geladen
ausblenden Quelltext
1:
2:
3:
4:
bmp := TBitmap.Create;
bmp.Loadfromfile(filename);
image1.canvas.draw(0,0,bmp);
bmp.free;


das spart speicher....

zu meinem eigentlichen problem...

ich will die figur auf die gleiche speichersparende art "laden" und auf dem spielfeld plazieren. allerdings soll sie nicht auf die bitmap vom spielfeld gemalt werden (die bekommt man sonst nicht wieder runter), sondern so zu sagen eine ebene darüber.
ich hab keine ahnung, wie ich das machen kann. ich bräuchte eine möglichkeit, das ganze ohne eine zweite TImage-komponente zu lösen...

_________________
Life is, what some people call a mystery. To me life's just a lesson, you're learning when you're through. So why do we try to understand?
maximus
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 896

Win XP, Suse 8.1
Delphi 4/7/8 alles prof
BeitragVerfasst: Mo 05.05.03 10:46 
und was ist wenn dein spielfeld neugezeichnet werden muss...dann ist das bitmap nicht verfügbar, weil du es wieder freigegeben hast. Und fertig ist der salat...oder seh ich das falsch?

_________________
mfg.
mâximôv
Mike_C Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 207

Win XP
D7 Enterprise
BeitragVerfasst: Mo 05.05.03 14:54 
nicht, wenn ich den code in eine procedure Spieler.Draw packe und diese beim neuzeichnen aufrufe

_________________
Life is, what some people call a mystery. To me life's just a lesson, you're learning when you're through. So why do we try to understand?
tommie-lie
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 4373

Ubuntu 7.10 "Gutsy Gibbon"

BeitragVerfasst: Mo 05.05.03 15:15 
Ohne zweite TImage-Komponente wird das nicht gehen, denn ein Image hat nunmal nur ein Bitmap mit einem Canvas. Also könntest du mit manuellem Buffering arbeiten. Also erst alle anderen Sachen (Spielfelder, sondtige grafiken) und das dann in ein TBitmap im Hintergrund. Dann zeichnest du das Bitmap auf dein Image und zeichnest darüber die Spielfiguren. Beim nächsten Frame, also wenn sich die Figur einen Pixel weiterbewegt hat, zeichnest du wiede aus deinem Buffer (dem TBitmap) und darüber wieder deine Spielfigur, diesmal ein wenig woanders und immer so weiter.

Allerdings bringt deine Methode, Speicher zu sparen indem du das Bitmap jedesmal wieder freigibst, nichts, weil du durch das Laden wesentlich mehr Rechenzeit verbrätst, bei großen Bildern und langsamen Festplatten sogar mehr Leistung vebrauchst als die Speicherersparniss es ausgleichen würde. Im schlimmsten Fall (ich weiß nicht, was du vor und nach dem Laden machst) kann es angels gutem Speichermanager der heutigen Compiler (Borland oder MS, beide haben die gleichen Probleme) sogar zu einem erhöhten Speicherverbrauch kommen.
Es wäre also auf jeden Fall schneller, wenn du am Anfang einmal das Bitmap lädtst und dann immer wieder daraus zeichnest und am Ende wieder freigibst.

_________________
Your computer is designed to become slower and more unreliable over time, so you have to upgrade. But if you'd like some false hope, I can tell you how to defragment your disk. - Dilbert
Mike_C Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 207

Win XP
D7 Enterprise
BeitragVerfasst: Mo 05.05.03 15:28 
würde es so funktionieren:

ich nehme 2 bitmaps: die erste mit dem spielfeld und die zweite mit den anderen grafiken (figuren und so), dann definiere ich eine klasse TSpielfeld mit einer prozedur Draw, in der ich erst das spielfeld und dann die anderen grafiken zeichne und beide auf das canvas vom TImage lege?

an dieser stelle muss ich tommie wiedersprechen:

wenn ich mehrere instanzen von einem objekt erzeuge und mit ihnen arbeite, verbrauche ich auf jeden fall mehr speicher, als wenn ich die instanzen jedes mal wieder frei gebe! Grund: mit jeder operation in einer TBitmap-Instanz steigt der speicherverbrauch!!! wenn ich jedesmal eine grafik drüber male, wird der speicher, den ich vorher belegt habe nicht frei gegeben. was machen da rechner, die nicht so viel speicherkapzität habe? die haben glaub ich ein problem. und dieses problem dürfe größer sein, als die rechengeschwindigkeit, da ich ohne hin nicht vor habe, die figuren pixelweise zu bewegen! das ganze soll eher sprunghaft funktionieren!

_________________
Life is, what some people call a mystery. To me life's just a lesson, you're learning when you're through. So why do we try to understand?
Mike_C Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 207

Win XP
D7 Enterprise
BeitragVerfasst: Mo 05.05.03 15:53 
ich hab's mal so versucht:

die Spielfeldklasse
ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
unit Spielfeld;

interface

uses
  Spieler,
  Windows, Classes, SysUtils, Graphics;

type
  TSpielfeld = class (TObject)
  protected
    Background, foreground: TBitmap;
    FCanvas: TCanvas;

    FActPlayer: TSpieler;
  private

  public
    constructor Create; virtual;
    destructor Destroy; override;

    procedure Initialize;
    procedure SetActualPlayer(Player: TSpieler);
    procedure Draw;
  published
    property Canvas: TCanvas read FCanvas write FCanvas;
  end;


implementation

constructor TSpielfeld.Create;
begin
  inherited;
end;

destructor TSpielfeld.Destroy;
begin
  background.Free;
  foreground.Free;
  inherited;
end;

procedure TSpielfeld.Draw;
begin
  Canvas.Draw(0,0,background);
  foreground.Canvas.draw(factplayer.Position.x,factplayer.position.y, factplayer.Bitmap);
  foreground.Transparent := true;
  foreground.Height := background.Height;
  foreground.Width := background.width;
  canvas.Draw(0,0,foreground);
end;


procedure TSpielfeld.SetActualPlayer(Player: TSpieler);
begin
  FActPlayer := Player;
end;

procedure TSpielfeld.Initialize;
begin
  Background := TBitmap.Create;
  Background.LoadFromFile('..\Graphic\Spielfeld.bmp');

  Foreground := TBitmap.Create;
  FActPlayer := TSpieler.CreateColored('red');
end;

end.


Die Spielerklasse:
ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
unit Spieler;

interface

uses
  Windows, Graphics, Controls, ExtCtrls, Classes;

type
  TSpieler = class (TObject)
  protected
    FBMP: TBitmap;
    fPosition: TPoint;
  public
    constructor Create;virtual;
    constructor CreateColored(color: string);
    destructor Destroy; override;
  published
    property Bitmap: TBitmap read FBMP;
    property Position: TPoint read FPosition;
  end;

implementation

constructor TSpieler.Create;
begin
  fbmp := TBitmap.Create;
  fPosition := Point(0,0);
  inherited;
end;

constructor TSpieler.CreateColored(color: string);
begin
  Create;
  fbmp.LoadFromFile('..\Graphic\man'+color+'.bmp');
  
  fposition.x := 100;
  fposition.Y := 100;
end;

destructor TSpieler.Destroy;
begin
  fbmp.Free;
  inherited;
end;

end.


Das zeichnen:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure TFormGameform.Button1Click(Sender: TObject);
var Spielfeld : TSpielfeld;
begin
  Spielfeld := TSpielfeld.Create;
  Spielfeld.Canvas := Image1.Canvas;
  Spielfeld.Initialize;
  Spielfeld.Draw;
end;


ich sehe aber nur die grafik vom spielfeld, nicht aber eine rote Figur. Kann mir jemand sagen, warum nicht?

_________________
Life is, what some people call a mystery. To me life's just a lesson, you're learning when you're through. So why do we try to understand?
maximus
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 896

Win XP, Suse 8.1
Delphi 4/7/8 alles prof
BeitragVerfasst: Mo 05.05.03 16:30 
Bei spielen hat man immer resourcen probleme...aber bei jedem frame alles neu zu laden ist gelinde gesagt grausam, derbst uneffizient und unprofessionell! -> bitte nicht persönlich nehmen, ich versuch dich nur davon abzuhalten einen fiesen architektonischen fehler zu machen :wink:

_________________
mfg.
mâximôv
mimi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3458

Ubuntu, Win XP
Lazarus
BeitragVerfasst: Mo 05.05.03 17:21 
verwende DelphiX(DirecX) oder GLXTreen(OpenGl) damit ist das einfacher als mit Canvers:)

_________________
MFG
Michael Springwald, "kann kein englisch...."
tommie-lie
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 4373

Ubuntu 7.10 "Gutsy Gibbon"

BeitragVerfasst: Mo 05.05.03 17:51 
Mike_C hat folgendes geschrieben:
an dieser stelle muss ich tommie wiedersprechen:

wenn ich mehrere instanzen von einem objekt erzeuge und mit ihnen arbeite, verbrauche ich auf jeden fall mehr speicher, als wenn ich die instanzen jedes mal wieder frei gebe! Grund: mit jeder operation in einer TBitmap-Instanz steigt der speicherverbrauch!!! wenn ich jedesmal eine grafik drüber male, wird der speicher, den ich vorher belegt habe nicht frei gegeben. was machen da rechner, die nicht so viel speicherkapzität habe? die haben glaub ich ein problem. und dieses problem dürfe größer sein, als die rechengeschwindigkeit, da ich ohne hin nicht vor habe, die figuren pixelweise zu bewegen! das ganze soll eher sprunghaft funktionieren!

Mit Free wird aber nicht wirklich Speicher frei gegeben. Zumindest nicht für Windows. Der Speichermanager von Delphi holt den Speicher, und schaufelt da seine Daten aus der Klasse (TBitmap) rein. Beim .Free wird dann zwar der Speicher für andere Variablen des gleichen Prozesses frei gegeben, andere Programme können aber immer noch nicht auf den Speicher zugreifen. Das ist das gleiche Problem, das auftritt, wenn man Strings oder dynamische Arrays mehrmals in der Größe verändert (oder immer ein Zeichen dranhängt, das hatten wir hier irgendwann mal).
Außerdem sind die Pixel in einem Bitmap immer als Array gespeichert, dessen Dimensionen der Höhe und Breite entsprechen. Zeichnest du rein, werden die Werte im Array geändert, aber nicht die Größe des Arrays (das geschieht nur bei Größenänderungen). Ein weißes Bitmap braucht genausoviel Speicher, wie ein schwarzen oder ein rot-blau kariertes. Wenn du reinzeichnest, änderst du lediglich den Wert der im Array enthaltenen Integer-Werte.
Wenn du sie jedesmal freest und wieder createst, ist es Zufall, ob das alte "Speicherloch" noch frei ist. Wenn nicht, brauchst du mehr Speicher als wenn du das Bild im Speicher gelassen hättest.

_________________
Your computer is designed to become slower and more unreliable over time, so you have to upgrade. But if you'd like some false hope, I can tell you how to defragment your disk. - Dilbert
Mike_C Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 207

Win XP
D7 Enterprise
BeitragVerfasst: Mo 05.05.03 17:51 
problem: ich kann weder DelphiX noch OpenGL. Wie soll das also gehen?

_________________
Life is, what some people call a mystery. To me life's just a lesson, you're learning when you're through. So why do we try to understand?
mimi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3458

Ubuntu, Win XP
Lazarus
BeitragVerfasst: Mo 05.05.03 18:12 
lehren es, für DelphiX gibt es genügen tutors.....
(u.a eins von mir, hier im forum)

_________________
MFG
Michael Springwald, "kann kein englisch...."