Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Pacman (https://www.delphipraxis.net/166328-pacman.html)

Blubbel 8. Feb 2012 11:18

Delphi-Version: 5

Pacman
 
Halli Hallo,

Ich will ein PacMan verschnitt programmieren. Ich habe jetzt die Form schon in einzelne Kacheln aufgeteilt. Jetzt möchte ich, dass die "Geister" (bei mir nur kreise") eine bestimmte Anzahl sind und direkt am Anfang mit gezeichnet werden. Irgendwie hab ich da einen Hänger.

ich hab mir gedacht, vielleicht geht es mit einem Array in dem ich sie Speicher und zeichnen lasse aber irgendwie funktioniert das alles nicht.

Habt ihr einen kleinen Denkanstoß für mich oder tipps?

Danke euch schon mal

LG

Coffeecoder 8. Feb 2012 11:30

AW: Pacman
 
Zitat:

Zitat von Blubbel (Beitrag 1149848)

ich hab mir gedacht, vielleicht geht es mit einem Array in dem ich sie Speicher und zeichnen lasse aber irgendwie funktioniert das alles nicht.

Habt ihr einen kleinen Denkanstoß für mich oder tipps?

Danke euch schon mal

LG

Hi Blubbel,
Was funktionniert nicht? Gibt es eine Fehlermeldung?
Du kannst schon mal bisschen Code zeigen.

Blubbel 8. Feb 2012 11:40

AW: Pacman
 
einen Cade gibt es nur "indirekt" habe ein altes projekt ausgekramt und als vorlage benutzt und hat nicht viel geholfen. Bin ein zimlicher neuling. Vor allem sollen sie ja auch zufällig gezeichnet werden.

Also hier ist der Code den ich als vorlage genommen und schon verändert hab.
Delphi-Quellcode:
  for i := 0 to high(Self.FMonsterArray) do
  begin
    if assigned(Self.FMonsterArray[i]) then
    begin

      lRect.TopLeft.X := Self.FMonsterArray[i].Position.X;
      lRect.TopLeft.Y := Self.FMonsterArray[i].Position.Y;

      lRect.BottomRight.X := (lRect.TopLeft.X + 16);
      lRect.BottomRight.Y := (lRect.TopLeft.Y + 16);

      if Self.FCount <= High(Self.FMonsterArray) then
      begin
        Self.FMonsterArray[Self.FCount] := TphMonster.Create;
        Self.FMonsterArray[Self.FCount].Position := Point(random(GetWidth(ACanvas.ClipRect)),   random(GetHeight(ACanvas.ClipRect)));
         Self.FCount := (Self.FCount +1);
      end;
      ACanvas.Ellipse(lRect.TopLeft.X, lRect.TopLeft.Y, lRect.BottomRight.X, lRect.BottomRight.Y);
    end;
  end;

Coffeecoder 8. Feb 2012 12:10

AW: Pacman
 
Ich würde in der Klasse
Delphi-Quellcode:
TphMonster
eine Methode einbringen, die sich um das Zeichnen kümmert:
Delphi-Quellcode:
...
procedure TphMonster.draw(pCanvas : TCanvas);
const
   BREITE = 16;
begin
   pCanvas.brush.color := clWhite; //eventuell Farbe festlegen
   pCanvas.Ellipse(PositionX, PositionY, PositionX + BREITE , PositionY + BREITE);
end;
...
und dann in einer Schleife folgendes tun:
Delphi-Quellcode:
...
    FMonsterArray[i].draw(ACanvas);
...
Wenn du willst kannst du ja mal die Quellen deiner Vorlage geben und deinen gesamten Quellcode anhängen.

Blubbel 8. Feb 2012 13:47

AW: Pacman
 
Das klappt schon mal ganz gut... Mit dem zufälligen zeichnen klappts jedoch noch nicht ganz.

versucht hab ich es so:
Delphi-Quellcode:
  ACanvas.Ellipse(Random(ACanvas.ClipRect.TopLeft.X), random(ACanvas.ClipRect.TopLeft.Y), ACanvas.ClipRect.TopLeft.X + lWidth ,
    ACanvas.ClipRect.TopLeft.Y + lWidth);

Coffeecoder 8. Feb 2012 14:02

AW: Pacman
 
Zitat:

Zitat von Blubbel (Beitrag 1149876)
Das klappt schon mal ganz gut... Mit dem zufälligen zeichnen klappts jedoch noch nicht ganz.

versucht hab ich es so:
Delphi-Quellcode:
  ACanvas.Ellipse(Random(ACanvas.ClipRect.TopLeft.X), random(ACanvas.ClipRect.TopLeft.Y), ACanvas.ClipRect.TopLeft.X + lWidth ,
    ACanvas.ClipRect.TopLeft.Y + lWidth);

Ich würde beim Create die Zufallsposition setzen:
Delphi-Quellcode:
constructor TphMonster.Create();
begin
    self.PositionX := random(); // Angeben der Größe
    self.PositionY := random();
end;

Blubbel 8. Feb 2012 14:32

AW: Pacman
 
hmmm.... Ich glaub ich bin da gerade ein bisschen zu doof für.
Also es sieht jetzt folgender maßen aus:
Delphi-Quellcode:
procedure TphGameField.DrawMonsters(ACanvas: TCanvas);
var
  lRect: TRect;
  i: Integer;
const
  lWidth = 16;
begin      //TODO: zufällig zeichnen lassen (ca. 10)
  for i := 0 to high(Self.FMonsterArray) do
  begin
    Self.FMonsterArray[Self.FCount] := TphMonster.Create;
    FMonsterArray[i].Draw(ACanvas);
  end;
end;

............................................
constructor TphMonster.Create;
begin
//  inherited Create;
  randomize;
  Self.FPosition.X := random(128); // Angeben der Größe
  Self.FPosition.Y := random(128);
end;

destructor TphMonster.Destroy;
begin
  inherited Destroy;
end;

procedure TphMonster.Draw(ACanvas: TCanvas);
var
  x,y: integer;
const
  lWidth = 16;
begin
//  randomize;
//  x := random(ACanvas.ClipRect.TopLeft.X);
//  y := random(ACanvas.ClipRect.TopLeft.Y);

  ACanvas.brush.color := clRed;
//  ACanvas.Ellipse(x, y, (x + lWidth), (y + lWidth));
end;
Der zeichnet zwar die Kreise aber immer nur an einem Fleck statt mehrere Verstreut auf der Form

Hab da was bei zeichnen grad entdeckt aber trotzdem gehts nicht

Coffeecoder 8. Feb 2012 14:44

AW: Pacman
 
Kannst du mal bitte die Klassendefinition der Klasse
Delphi-Quellcode:
TphMonster
mal reinhängen?

Blubbel 8. Feb 2012 14:47

AW: Pacman
 
Delphi-Quellcode:
 //Spieler und Monster
  TphItem = class(TObject)
  private
    FName: String;
    FSize: Integer;
    FPosition: TPoint;
    procedure GetName(const Value: String);
    procedure GetSize(const Value: Integer);
    procedure GetPosition(const Value: TPoint);
  public
    constructor Create();
    destructor Destroy();
    property Name: String read FName write GetName;
    property Size: Integer read FSize write GetSize;
    property Position: TPoint read FPosition write GetPosition;
  end;

  //Spielfigur
  TphPlayer = class(TphItem)
  private
 
  public
    constructor Create();
    destructor Destroy();
  end;

  //Gegner (Monster)
  TphMonster = class(TphItem)
  private

  public
    procedure Draw(ACanvas: TCanvas);
    constructor Create();
    destructor Destroy();
  end;


.........................


TphGameField = class(TObject)
  private
    FArray: Array of Array of Byte;
    FPlayer: TphPlayer;
    FMonsters: TObjectList;
    FViewPort: TphViewPort;
    FSize: Integer;
    FPosition: TPoint;
    FCount: Integer;
    FMonsterArray: Array [0..20] of TphMonster;
    procedure SetPosition(const Value: TPoint);
  protected
    function InitArray(AWidth, AHeight: Integer): Boolean;
  public
    constructor Create(AWidth, AHeight, ASize: Integer);
    destructor Destroy(); override;
    function MovePlayer(ADirection: Byte): TPoint; //????????????????????????
    procedure DrawGameField(ACanvas: TCanvas; AClipRect: TRect);
    procedure DrawPlayer(ACanvas: TCanvas);
    procedure DrawMonsters(ACanvas: TCanvas);
    property Player: TphPlayer read FPlayer {write SetPlayer};
    property ViewPort: TphViewPort read FViewPort {write SetViewPort};
    Property Position: TPoint read FPosition write SetPosition;
  end;

Coffeecoder 8. Feb 2012 15:10

AW: Pacman
 
Zitat:

Zitat von Blubbel (Beitrag 1149888)
Delphi-Quellcode:
 //Spieler und Monster
  TphItem = class(TObject)
  private
    FName: String;
    FSize: Integer;
    FPosition: TPoint;
    procedure GetName(const Value: String);
    procedure GetSize(const Value: Integer);
    procedure GetPosition(const Value: TPoint);
  public
    constructor Create();
    destructor Destroy();
    property Name: String read FName write GetName;
    property Size: Integer read FSize write GetSize;
    property Position: TPoint read FPosition write GetPosition;
  end;

  //Spielfigur
  TphPlayer = class(TphItem)
  private
 
  public
    constructor Create();
    destructor Destroy();
  end;

  //Gegner (Monster)
  TphMonster = class(TphItem)
  private

  public
    procedure Draw(ACanvas: TCanvas);
    constructor Create();
    destructor Destroy();
  end;

Der Konstruktor deiner Oberklasse also TphItem würde ich so anpassen, falls es noch nicht ist:
Delphi-Quellcode:
constructor TphItem.Create(posx, posy) ;
begin
   ... // andere Felder initialisieren, ggf. in der Paramterliste erweitern
   FPosition.Position.X := posx;
   FPosition.Position.Y := posy; // eventuell anpassen wegen TPoint, properties nicht im Kopf ;)
end;
Und dann im Create des Monsters dies machen:

Delphi-Quellcode:
constructor TphMonster.Create;
begin
   randomize; // ---> auslagern , nur einmal nötig
  inherited Create(random(128), random(128));
end;
Zuhause also heute abend kann ich das besser überprüfen ;)

Blup 8. Feb 2012 16:17

AW: Pacman
 
Der komplette Quelltext liegt nicht vor.
Die Änderungsvorschläge basieren also nur auf Vermutungen oder sind allgemeiner Natur:

Den Destructor Detroy immer mit override kennzeichnen, sonst wird dieser durch Free nicht aufgerufen.
Delphi-Quellcode:
  public
    constructor Create();
    destructor Destroy(); override;
Das TphGameField kennt die eigene Position auf dem Canvas und die Position der Elemente und sollte deshalb die Berechnung der absoluten Zeichenposition übernehmen.
Das Erzeugen der TphMonster könnte z.B. im Constructor von TphGameField erfolgen, aber garantiert nicht in eine Zeichenfunktion:
Delphi-Quellcode:
procedure TphGameField.DrawMonsters(ACanvas: TCanvas);
var
  i, x, y: Integer;
begin
  for i := 0 to high(FMonsterArray) do
  begin
    if Assigned(FMonsterArray[i]) then
    begin
      // (Position des Monsters - eigener Scrollposition) * Feldgrösse
      // Feldgrösse nur multiplizieren, wenn die Positionen nur den Feldindex beinhalten
      x := (FMonsterArray[i].Position.x - FPosition.x) * FSize;
      y := (FMonsterArray[i].Position.y - FPosition.y) * FSize;
      FMonsterArray[i].Draw(ACanvas, Rect(x, y, x + FSize, y + FSize));
    end;
  end;
end;
Randomize sollte nur an einer Stelle im Programm genau einmal aufgerufen werden.
Warum ist der Aufruf des geerbten Constructor auskommentiert?
Die Anfangsposition der Monster zu setzen, ist sicher die Aufgabe des TphGameField.
Schließlich kennt nur das Spielfeld seine Größe und die Position anderer Monster, Spieler und Hindernisse.
Am besten gleich nach dem Erzeugen oder wie bereits vorgeschlagen als Parameter.
Delphi-Quellcode:
constructor TphMonster.Create(x, y: Integer);
begin
  inherited Create;
  FPosition.Position.X := x;
  FPosition.Position.Y := y;
end;
Ohne Aufruf einer Zeichenfunktion wird das Monster überhaupt nicht gezeichnet:
Delphi-Quellcode:
procedure TphMonster.Draw(ACanvas: TCanvas; ARect: TRect);
begin
  ACanvas.brush.color := clRed;
  ACanvas.Ellipse(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);
end;

Blubbel 10. Feb 2012 09:32

AW: Pacman
 
Liste der Anhänge anzeigen (Anzahl: 1)
Irgendwie ist hier jetzt was komisch... ich bekomme immer diese meldung
Zitat:

[Pascal Fataler Fehler] phpObjects.pas(6): F2047 Zirkuläre Unit-Referenz auf 'phpObjects'
Wenn ich den Code so änder
Delphi-Quellcode:
    destructor Destroy();
    property Pos: TRect read FPos;
  end;

implementation

uses
  Funktionen;

kommt sowas
Zitat:

[Pascal Fehler] Funktionen.pas(42): E2267 Bei der vorherigen Deklaration von GetNewObjectPosition wurde die Direktive 'overload' nicht angegeben
Das ding ist, die Funktion ist gar kein overload. habe es aus einem anderen Projekt genommen und da war es auch schon keins. Irgendwie hab ich da einen Hänger.

Blubbel 10. Feb 2012 10:50

AW: Pacman
 
Kann mir da keiner nen Tipp geben?

Coffeecoder 10. Feb 2012 12:18

AW: Pacman
 
Zitat:

Zitat von Blubbel (Beitrag 1150272)
Irgendwie ist hier jetzt was komisch... ich bekomme immer diese meldung [Pascal Fataler Fehler] phpObjects.pas(6): F2047 Zirkuläre Unit-Referenz auf 'phpObjects'

Siehe den Beitrag hier: http://www.delphipraxis.net/124762-f...-referenz.html

Blup 14. Feb 2012 09:25

AW: Pacman
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe das Programm ein wenig umgestellt und zumindest lauffähig gemacht.

Blubbel 14. Feb 2012 12:33

AW: Pacman
 
Danke dir ich gucks mir direkt mal an


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:12 Uhr.

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