Autor Beitrag
mvollmer
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 42
Erhaltene Danke: 3


Delphi (Seattle), C (MPLAB X)
BeitragVerfasst: Di 12.10.10 14:01 
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.

Im Anhang zwei Screenshot zur Verbildlichung :) + Compilierte exe


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.

ausblenden Delphi-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:
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;


ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
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;



(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...

CROSSPOST auf DelphiPraxis

Ich danke schonmal für jede Antwort ;)

mfg pustekuchen
Einloggen, um Attachments anzusehen!


Zuletzt bearbeitet von mvollmer am Di 12.10.10 14:27, insgesamt 2-mal bearbeitet
Dude566
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1592
Erhaltene Danke: 79

W8, W7 (Chrome, FF, IE)
Delphi XE2 Pro, Eclipse Juno, VS2012
BeitragVerfasst: Di 12.10.10 14:03 
Wenn du schon Bilder aus einem anderen Delphi Forum postest, kannst du auch gleich den Crosspost angeben: www.delphipraxis.net...ren.html#post1055202 ;)

_________________
Es gibt 10 Gruppen von Menschen: diejenigen, die das Binärsystem verstehen, und die anderen.
mvollmer Threadstarter
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 42
Erhaltene Danke: 3


Delphi (Seattle), C (MPLAB X)
BeitragVerfasst: Di 12.10.10 14:07 
Hab ich auch grade gesehen das die noch drin waren ;) Sind jetzt raus
Dude566
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1592
Erhaltene Danke: 79

W8, W7 (Chrome, FF, IE)
Delphi XE2 Pro, Eclipse Juno, VS2012
BeitragVerfasst: Di 12.10.10 14:10 
user profile iconmvollmer hat folgendes geschrieben Zum zitierten Posting springen:
Hab ich auch grade gesehen das die noch drin waren ;) Sind jetzt raus


Das ist ja nicht schlimm, nur man sollte angeben wenn man die selbe Frage noch in einem anderen Forum gestellt hat, deshalb die Angabe des Crossposts von mir.

_________________
Es gibt 10 Gruppen von Menschen: diejenigen, die das Binärsystem verstehen, und die anderen.
mvollmer Threadstarter
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 42
Erhaltene Danke: 3


Delphi (Seattle), C (MPLAB X)
BeitragVerfasst: Di 12.10.10 14:23 
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...
Teekeks
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 211
Erhaltene Danke: 23



BeitragVerfasst: Di 12.10.10 14:27 
Wie machst du es denn für die ersten 2 Fälle?
mvollmer Threadstarter
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 42
Erhaltene Danke: 3


Delphi (Seattle), C (MPLAB X)
BeitragVerfasst: Di 12.10.10 14:29 
Dies ist die Procedure mit der ich die Gegner bewege:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
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;


Und hier wird sie aufgerufen:

ausblenden volle Höhe Delphi-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:
procedure TFormMain.moveEnemys(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
//      PosX := EnemyManager.enemys[FPlayerLevel][k].PosX div 32;   // 7
//      PosY := EnemyManager.enemys[FPlayerLevel][k].PosY div 32;   // 71
//      if (map.Playground[PosX][PosY].nextField = nfLeft)then
//      begin
//        fieldX := ((EnemyManager.enemys[FPlayerLevel][k].PosX+7) div 32 );
//        fieldY := ((EnemyManager.enemys[FPlayerLevel][k].PosY+7) div 32);
//      end
//      else
//      begin
        fieldX := (EnemyManager.enemys[FPlayerLevel][k].PosX -7div 32;
        fieldY := (EnemyManager.enemys[FPlayerLevel][k].PosY -7div 32;
//      end;
      case map.Playground[fieldX][fieldY].nextField of
        nfDown:  EnemyManager.moveEnemy(EnemyManager.enemys[FPlayerLevel][k],nfDown);
        nfRight: EnemyManager.moveEnemy(EnemyManager.enemys[FPlayerLevel][k],nfRight);
        nfLeft:  EnemyManager.moveEnemy(EnemyManager.enemys[FPlayerLevel][k],nfLeft);
        nfUp:    EnemyManager.moveEnemy(EnemyManager.enemys[FPlayerLevel][k],nfUp);
        nfStay:
        begin
          EnemyManager.enemys[FPlayerLevel][k].isRunning := false;
          Dec(FPlayerLives);
          initLabels;
          if FPlayerLives = 0 then
          begin
            SetGameStatus(gsGAMEOVER);
            exit;
          end;
        end;
      end;
    end;
  end;


Zuletzt bearbeitet von mvollmer am Di 12.10.10 14:31, insgesamt 1-mal bearbeitet
Teekeks
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 211
Erhaltene Danke: 23



BeitragVerfasst: Di 12.10.10 14:31 
Und wo ist da das Problem momentan?
Das sieht soweit ganz gut aus.
mvollmer Threadstarter
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 42
Erhaltene Danke: 3


Delphi (Seattle), C (MPLAB X)
BeitragVerfasst: Di 12.10.10 14:33 
Habs oben im Post editiert.

Diese wiederrum, wird alle 10 ms von einem Timer aufgerufen


Zuletzt bearbeitet von mvollmer am Di 12.10.10 14:35, insgesamt 1-mal bearbeitet
mkinzler
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 4106
Erhaltene Danke: 13


Delphi 2010 Pro; Delphi.Prism 2011 pro
BeitragVerfasst: Di 12.10.10 14:35 

_________________
Markus Kinzler.
Mortal-Shadow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 110



BeitragVerfasst: Di 12.10.10 14:56 
Ich habs mir angeschaut.
Du scheinst den Eckfeldern falsche Werte zugeordnet haben.
Wenn sie nach links laufen und danach nach oben, hast du ja ein Eckfeld.
Das muss noch nfLeft zugeordnet bekommen, da sie ja immer von Field.next abfragen, welche richtung sie gehen müssen.
Wenn nun das Eckfeld schon nach oben zeigt, gehen sie folglich eins vor ihm schon nach oben.
Mfg.
mvollmer Threadstarter
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 42
Erhaltene Danke: 3


Delphi (Seattle), C (MPLAB X)
BeitragVerfasst: Di 12.10.10 15:09 
Zitat:
Wenn sie nach links laufen und danach nach oben, hast du ja ein Eckfeld.
Das muss noch nfLeft zugeordnet bekommen, da sie ja immer von Field.next abfragen, welche richtung sie gehen müssen.


Danke erstmal ;)

Es ist so, das das Aktuelle Feld abgefragt wird auf welches er als nächstes gehen soll. D.h Wenn er aktuell auf dem Eckfeld ist muss .nextField = nfUp sein

Siehe Anhang, dort ist der Weg angezeigt ;)


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^^

ausblenden volle Höhe Delphi-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:
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 -7div 32;
        fieldY := (EnemyManager.enemys[FPlayerLevel][k].PosY -7div 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 +23div 32;
          fieldY := (EnemyManager.enemys[FPlayerLevel][k].PosY +23div 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;


Ok nur noch ein Problem, wenn er von unten nach oben und dann nach rechts muss, biegt er wieder zu früh ab^^
Einloggen, um Attachments anzusehen!
mvollmer Threadstarter
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 42
Erhaltene Danke: 3


Delphi (Seattle), C (MPLAB X)
BeitragVerfasst: Mi 13.10.10 09:39 
Hab jetzt entgültig den Fehler gefunden, wodran es liegt das sie halt manchmal früher abbiegen.

Ich habe die Gegner immer nur einen pixel verschoben. Sobald also der Feldrand erreicht wurde zählte schon das nextField vom neuem Feld, obwohl er noch nicht richtig drauf ist und somit sind sie dann zu früh abgebogen.

Jetzt hab ich aber ein Problem.
Wenn ich die Zeichenprozedur ausführe sobald i-ein gegner bewegt wird, dann läufts so ab:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
Gegner 1 bewegt sich 1 Feld nach vorne...
[ZEICHNEN]
Gegner 1 bewegt sich 1 Feld nach vorne...
[ZEICHNEN]
[..bis 32..]

Gegner 2 bewegt sich 1 Feld nach vorne...
[ZEICHNEN]
Gegner 2 bewegt sich 1 Feld nach vorne...
[ZEICHNEN]
[..bis 32..]

usw..


Also wird jeder gegner nacheinander bewegt. Aber es soll ja so sein als würden, sich alle "gleichzeitig" bewegen.

Hier jetzt nochmal die aktuellen Prozeduren:


ausblenden volle Höhe Delphi-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:
procedure TFormMain.moveEnemies(value: TGameStatus);
var
  fieldX, fieldY: Integer;
  i,k,j: Integer;
  tmpField :array of TNextField;
begin
  SetLength(tmpField,High(EnemyManager.enemys[FPlayerLevel])-1);
  for k := 0 to High(EnemyManager.enemys[FPlayerLevel]) do
  begin
    fieldX := (EnemyManager.enemys[FPlayerLevel][k].Pixels.X ) div 32;
    fieldY := (EnemyManager.enemys[FPlayerLevel][k].Pixels.Y ) div 32;
    tmpField[k] := map.Playground[fieldX][fieldY].nextField;
  end;

  for j := 0 to 31 do
  begin
    for i := 0 to High(EnemyManager.enemys[FPlayerLevel]) do
    begin
      if EnemyManager.enemys[FPlayerLevel][i].isRunning then
      begin
        case tmpField[i] of
          nfDown:  EnemyManager.moveEnemy(EnemyManager.enemys[FPlayerLevel][i],nfDown);
          nfRight: EnemyManager.moveEnemy(EnemyManager.enemys[FPlayerLevel][i],nfRight);
          nfLeft:  EnemyManager.moveEnemy(EnemyManager.enemys[FPlayerLevel][i],nfLeft);
          nfUp:    EnemyManager.moveEnemy(EnemyManager.enemys[FPlayerLevel][i],nfUp);
          nfStay:
          begin
            EnemyManager.enemys[FPlayerLevel][i].isRunning := false;
            Dec(FPlayerLives);
            initLabels;
            if FPlayerLives = 0 then
            begin
              SetGameStatus(gsGAMEOVER);
              exit;
            end;
          end;
        end;
      end;
    end;
    Draw;
  end;
end;


ausblenden volle Höhe Delphi-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:
procedure TEnemyManager.moveEnemy(enemy: TEnemy; next: TNextField);
var Pos: TPoint;
begin
  case next of
    nfDown:
    begin
      Pos.Y := enemy.Pixels.Y+1;
      Pos.X := enemy.Pixels.X;
    end;
    nfRight:
    begin
      Pos.X := enemy.Pixels.X+1;
      Pos.Y := enemy.Pixels.Y;
    end;
    nfUp:
    begin
      Pos.Y := enemy.Pixels.Y-1;
      Pos.X := enemy.Pixels.X;
    end;
    nfLeft:
    begin
      Pos.X := enemy.Pixels.X-1;
      Pos.Y := enemy.Pixels.Y;
    end;
  end;
  if next <> nfStay then
  begin
    enemy.Pixels := Pos;
    Inc(enemy.movedPixel);
  end;
end;