Entwickler-Ecke
Sonstiges (Delphi) - Positionieren von Gegnern auf einem Spielfeld
mvollmer - Di 12.10.10 14:01
Titel: Positionieren von Gegnern auf einem Spielfeld
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.
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, enemys[level][i].PosY+10, enemys[level][i].PosX+15, enemys[level][i].PosY+15); end; end; uFormMain.FormMain.pb.Canvas.Draw(0,0,bmEnemys); end; |
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 [
http://www.delphipraxis.net/155178-gegner-auf-spielfeld-richtig-positionieren.html#post1055202]
Ich danke schonmal für jede Antwort ;)
mfg pustekuchen
mvollmer - Di 12.10.10 14:07
Hab ich auch grade gesehen das die noch drin waren ;) Sind jetzt raus
Dude566 - Di 12.10.10 14:10
mvollmer hat folgendes geschrieben : |
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.
mvollmer - 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 - Di 12.10.10 14:27
Wie machst du es denn für die ersten 2 Fälle?
mvollmer - Di 12.10.10 14:29
Dies ist die Procedure mit der ich die Gegner bewege:
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:
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 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); 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; |
Teekeks - Di 12.10.10 14:31
Und wo ist da das Problem momentan?
Das sieht soweit ganz gut aus.
mvollmer - Di 12.10.10 14:33
Habs oben im Post editiert.
Diese wiederrum, wird alle 10 ms von einem Timer aufgerufen
Mortal-Shadow - 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 - 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^^
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 -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; |
Ok nur noch ein Problem, wenn er von unten nach oben und dann nach rechts muss, biegt er wieder zu früh ab^^
mvollmer - 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:
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:
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; |
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; |
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!