Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Gegner auf Spielfeld richtig positionieren (https://www.delphipraxis.net/155178-gegner-auf-spielfeld-richtig-positionieren.html)

pustekuchen 12. Okt 2010 09:23

Delphi-Version: 2010

Gegner auf Spielfeld richtig positionieren
 
Liste der Anhänge anzeigen (Anzahl: 3)
Guten Tag,

Ich bräuchte mal eure Hilfe, ich weiß grade nicht wie ich mein Problem genau realisieren soll.

Erstmal zum Programm:

Ich bin dabei eine Tower Defense zu programmieren. Bauen von Türmen, Erstellen von Karten, sowie das "Spawnen" von Gegner und das durchlaufen durch die Karte klappen.
Doch leider sind die Gegner nicht wirklich gut Positioniert, wenn sie über das Spielfeld laufen.

Hier mal ein Screenshot zur Verbildlichung :)

Klick Mich ;)
Und mich

Und hier die Prozedure mit der ich die Gegner zeichne.

Zur Info: Jedes Feld ist 32x32 px groß. Und eine Karte hat 16*16 Felder.

Code:
procedure TEnemyManager.drawEnemys(level: Integer);
var i: integer;
begin
  bmEnemys.Canvas.Brush.Color := clFuchsia;
  bmEnemys.Canvas.Rectangle(-1,-1,513,513);
  bmEnemys.Canvas.Brush.Color := clBlue;
  for i := 0 to High(enemys[level]) do
  begin
    if enemys[level][i].isRunning then
    begin
      bmEnemys.Canvas.Rectangle(
        enemys[level][i].PosX+10,      //ANHANG 1!
        enemys[level][i].PosY+10,      // Hier läufts flüssig, aber 'schief' :/
        enemys[level][i].PosX+15,
        enemys[level][i].PosY+15);
//      bmEnemys.Canvas.Rectangle(         // ANHANG 2!Zeichnet die Gegner
//        enemys[level][i].FeldX*32,      // Oben links in die ecken der Felder
//        enemys[level][i].FeldY*32,      // Kein flüssiger spielverlauf,
//        enemys[level][i].FeldX*32+10,   // da Gegner NUR in die mitte
//        enemys[level][i].FeldY*32+10);  // des Feldes gezeichnet werden
    end;
  end;
  uFormMain.FormMain.pb.Canvas.Draw(0,0,bmEnemys);
end;
Code:

procedure TEnemyManager.moveEnemy(enemy: TEnemy; next: TNextField);
begin
  case next of
    nfDown: enemy.PosY := enemy.PosY+1;
    nfRight: enemy.PosX := enemy.PosX+1;
    nfUp:   enemy.PosY := enemy.PosY-1;
    nfLeft: enemy.PosX := enemy.PosX-1;
  end;
  if next <> nfStay then
    Inc(enemy.movedPixel);

  enemy.FeldX := enemy.PosX div 32;
  enemy.FeldY := enemy.PosY div 32;
end;

Dieser Teil hat sich erledigt:
Zitat:

(Anhang 1)Wie man auf den Screenshots sieht sind die Gegner nicht mittig auf den Feldern.
(Anhang 2)Beim auskommentiertem zeichnen, sind sie zwar mittig auf den Feldern, aber wirklich NUR mittig.
Und ecken überspingen sie.

Nun ist die frage wie ich einen flüssigen Spielablauf hinbekomme und die gegner mittig auf den Feldern laufen.

EDIT: Habe noch ein zweites Problem. Die Gegner "flackern". Das liegt wahrscheinlich an der draw methode. Doch Bitblt kann ich leider nicht benutzten, da diese keine transparenz unterstützt. Gibt es noch etwas anderes?


Habs mitlerweile hinbekommen, das es nach RECHTS und nach UNTEN so klappt wie es soll.

Aber wenns nach LINKS oder nach OBEN gehen soll macht es Probleme...

Ich danke schonmal für jede Antwort ;)

Crosspost im Delphi-Forum

mfg pustekuchen

Alien426 12. Okt 2010 09:48

AW: Gegner auf Spielfeld richtig positionieren
 
Woher kommt denn jeweils PosX/PosY und FeldX/FeldY? Warum addierst du immer fixe Werte zu Pos*?

Ich denke es wird darauf hinaus laufen, die Berechnung(?) von Pos* zu richten oder bei der Feld*-Variante Zwischenschritte (z.B. über einen Zähler, der je nach Richtung zu X oder Y addiert/subtrahiert wird und alle 3 Schritte zurück gesetzt wird) einzubauen.

pustekuchen 12. Okt 2010 09:54

AW: Gegner auf Spielfeld richtig positionieren
 
Zitat:

Woher kommt denn jeweils PosX/PosY und FeldX/FeldY?
Code:
enemys: array of array of TEnemy;
Und PosX/PosY/FeldX/FeldY sind Eigenschaften von TEnemy.
Diese werden beim erstellen auf die Position des Einganges(Grüne Tür) gesetzt.
Code:
FeldX := PosX div 32;
Zitat:

Warum addierst du immer fixe Werte zu Pos*?
Die sind eigentlich überflüssig ;) War nur ein Test.

EDIT: Habe mein Konzept jetzt einmal überdacht.

Ich mache es jetzt so das die Obere - Linke Ecke des Gegners(Also PosX/Y) = FeldX/Y * 32 +7 ist.

Somit kann ich dann dort ein 16x16 Bild(atm noch ein Recangle) einfügen und es ist genau in der Mitte.

pustekuchen 12. Okt 2010 11:49

AW: Gegner auf Spielfeld richtig positionieren
 
Sry 4 Doppelpost ;)

Habe noch ein zweites Problem. Die Gegner "flackern". Das liegt wahrscheinlich an der draw methode. Doch Bitblt kann ich leider nicht benutzten, da diese keine transparenz unterstützt. Gibt es noch etwas anderes?

EDIT: Habe im Erste Post noch die Methode wie ich die Enemys bewege angehangen und das Compilierte Projekt, damit man sich das mal etwas genauer anschauen kann ;)

Habs mitlerweile hinbekommen, das es nach RECHTS und nach UNTEN so klappt wie es soll.

Aber wenns nach LINKS oder nach OBEN gehen soll macht es Probleme...

mkinzler 12. Okt 2010 13:31

AW: Gegner auf Spielfeld richtig positionieren
 
CrossPost DF

pustekuchen 12. Okt 2010 13:33

AW: Gegner auf Spielfeld richtig positionieren
 
stehst doch schon bereits oben mit drin ;)

Aphton 12. Okt 2010 13:34

AW: Gegner auf Spielfeld richtig positionieren
 
Zeichne alles auf ein Offscreenbitmap (dh. einfach bmp Instanz erstellen und auf dessen Canvas zeichnen) und letzendlich diese dann auf die Paintbox/Canvas klatschen.
ODER noch angenehmer - du verwendest diese zuvor schon genannte und von haus aus implementierte Methode per "DoubleBuffered := True;"

Edit:
Noch etwas zum Code:
1. setz in Delphi Tags und nicht Code Tags [ DELPHI ]
2. der letzte Befehl in drawEnemIEs() gefällt mir nicht:
Delphi-Quellcode:
procedure TEnemyManager.drawEnemys(level: Integer);
var i: integer;
begin
  bmEnemys.Canvas.Brush.Color := clFuchsia;
  bmEnemys.Canvas.Rectangle(-1,-1,513,513);
  bmEnemys.Canvas.Brush.Color := clBlue;
  for i := 0 to High(enemys[level]) do
  begin
    if enemys[level][i].isRunning then
    begin
      bmEnemys.Canvas.Rectangle(
        enemys[level][i].PosX+10,      //ANHANG 1!
        enemys[level][i].PosY+10,      // Hier läufts flüssig, aber 'schief' :/
        enemys[level][i].PosX+15,
        enemys[level][i].PosY+15);
//      bmEnemys.Canvas.Rectangle(         // ANHANG 2!Zeichnet die Gegner
//        enemys[level][i].FeldX*32,      // Oben links in die ecken der Felder
//        enemys[level][i].FeldY*32,      // Kein flüssiger spielverlauf,
//        enemys[level][i].FeldX*32+10,   // da Gegner NUR in die mitte
//        enemys[level][i].FeldY*32+10);  // des Feldes gezeichnet werden
    end;
  end;
  uFormMain.FormMain.pb.Canvas.Draw(0,0,bmEnemys);
end;
Besser und wiederverwertbarer wäre es, wenn du der Methode den Parameter Canvas gleich mitgibst ala:

Delphi-Quellcode:
procedure TEnemyManager.drawEnemies(Canvas: TCanvas; level: Integer);
{...}
begin
{...}
  Canvas.Draw( 0, 0, bmEnemies );
end;
Die Begründung wäre eben - deine Klasse TEnemyManager wäre somit nicht abhängig von "uFormMain.FormMain.pb.Canvas" dh du könntest diesen Manager dann später auch einmal bei anderen Canväsen :roll: einsetzen

MfG

pustekuchen 12. Okt 2010 13:55

AW: Gegner auf Spielfeld richtig positionieren
 
Gut habs geändert. Flackert nicht mehr ;)
Doch leider bleibt das Bild stehen wenn ich mit der Maus über die Paintbox gehe. Wodran könnte das liegen?

BTMT

HAB DIE LÖSUNG! ;)
Ok nur noch ein Problem, wenn er von unten nach oben und dann nach rechts muss, biegt er wieder zu früh ab^^

Delphi-Quellcode:

procedure TFormMain.moveEnemies(value: TGameStatus);
var k: integer;
  fieldX, fieldY,PosX, PosY: Integer;
begin
  for k := 0 to High(EnemyManager.enemys[FPlayerLevel]) do
  begin
    if EnemyManager.enemys[FPlayerLevel][k].isRunning then
    begin
        fieldX := (EnemyManager.enemys[FPlayerLevel][k].PosX -7) div 32;
        fieldY := (EnemyManager.enemys[FPlayerLevel][k].PosY -7) div 32;
      case map.Playground[fieldX][fieldY].nextField of
        nfDown: EnemyManager.moveEnemy(EnemyManager.enemys[FPlayerLevel][k],nfDown);
        nfRight: EnemyManager.moveEnemy(EnemyManager.enemys[FPlayerLevel][k],nfRight);
        nfStay:
        begin
          EnemyManager.enemys[FPlayerLevel][k].isRunning := false;
          Dec(FPlayerLives);
          initLabels;
          if FPlayerLives = 0 then
          begin
            SetGameStatus(gsGAMEOVER);
            exit;
          end;
        end;
        else
        begin
          fieldX := (EnemyManager.enemys[FPlayerLevel][k].PosX +23) div 32;
          fieldY := (EnemyManager.enemys[FPlayerLevel][k].PosY +23) div 32;
          case map.Playground[fieldX][fieldY].nextField of
            nfLeft: EnemyManager.moveEnemy(EnemyManager.enemys[FPlayerLevel][k],nfLeft);
            nfUp:   EnemyManager.moveEnemy(EnemyManager.enemys[FPlayerLevel][k],nfUp);
          end;
        end;

      end;
    end;
  end;
end;

pustekuchen 12. Okt 2010 15:41

AW: Gegner auf Spielfeld richtig positionieren
 
Zitat:

Doch leider bleibt das Bild stehen wenn ich mit der Maus über die Paintbox gehe. Wodran könnte das liegen?
Lag an
Delphi-Quellcode:
lblPoints.Caption := IntToStr(MPosX) + ' ' + IntToStr(MPosY);
im onMouseMove Event
-.-

xZise 12. Okt 2010 19:50

AW: Gegner auf Spielfeld richtig positionieren
 
Kann es sein, dass FeldX/Y immer PosX/Y div 32 ist?
Dann würde ich eines entweder raus schmeißen oder das zu einer RO-Property zu machen. Also zum Beispiel:
Delphi-Quellcode:
type
  TEnemy = class(TObject)
  private
    FPos : TPoint; // Gibt die Position in Feldern an

    function GetPixels : TPoint;
  public
    property Field : TPoint read FPos write FPos;
    property Pixels : TPoint read GetPixels;
  end;

function TEnemy.GetPixels : TPoint;
begin
  Result.X := FPos.X * 32;
  Result.Y := FPos.Y * 32;
end;
Besser wäre natürlich, die 32 irgendwo als Konstante zu definieren.

MfG
Fabian


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:59 Uhr.
Seite 1 von 2  1 2      

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