Autor |
Beitrag |
mvollmer
Beiträge: 42
Erhaltene Danke: 3
Delphi (Seattle), C (MPLAB X)
|
Verfasst: 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.
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
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
Beiträge: 1592
Erhaltene Danke: 79
W8, W7 (Chrome, FF, IE)
Delphi XE2 Pro, Eclipse Juno, VS2012
|
Verfasst: 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
Beiträge: 42
Erhaltene Danke: 3
Delphi (Seattle), C (MPLAB X)
|
Verfasst: Di 12.10.10 14:07
Hab ich auch grade gesehen das die noch drin waren Sind jetzt raus
|
|
Dude566
Beiträge: 1592
Erhaltene Danke: 79
W8, W7 (Chrome, FF, IE)
Delphi XE2 Pro, Eclipse Juno, VS2012
|
Verfasst: Di 12.10.10 14:10
_________________ Es gibt 10 Gruppen von Menschen: diejenigen, die das Binärsystem verstehen, und die anderen.
|
|
mvollmer
Beiträge: 42
Erhaltene Danke: 3
Delphi (Seattle), C (MPLAB X)
|
Verfasst: 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
Beiträge: 211
Erhaltene Danke: 23
|
Verfasst: Di 12.10.10 14:27
Wie machst du es denn für die ersten 2 Fälle?
|
|
mvollmer
Beiträge: 42
Erhaltene Danke: 3
Delphi (Seattle), C (MPLAB X)
|
Verfasst: 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:
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; |
Zuletzt bearbeitet von mvollmer am Di 12.10.10 14:31, insgesamt 1-mal bearbeitet
|
|
Teekeks
Beiträge: 211
Erhaltene Danke: 23
|
Verfasst: Di 12.10.10 14:31
Und wo ist da das Problem momentan?
Das sieht soweit ganz gut aus.
|
|
mvollmer
Beiträge: 42
Erhaltene Danke: 3
Delphi (Seattle), C (MPLAB X)
|
Verfasst: 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
Beiträge: 4106
Erhaltene Danke: 13
Delphi 2010 Pro; Delphi.Prism 2011 pro
|
Verfasst: Di 12.10.10 14:35
_________________ Markus Kinzler.
|
|
Mortal-Shadow
Beiträge: 110
|
Verfasst: 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
Beiträge: 42
Erhaltene Danke: 3
Delphi (Seattle), C (MPLAB X)
|
Verfasst: 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^^
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^^
Einloggen, um Attachments anzusehen!
|
|
mvollmer
Beiträge: 42
Erhaltene Danke: 3
Delphi (Seattle), C (MPLAB X)
|
Verfasst: 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:
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; |
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; |
|
|
|