Delphi Hilfe

12/01/2013 20:30 Ky0n'#1
Hallo,
ich mache es kurz:
Zurzeit programmaiere ich mit einem Freund an einen kleinerem 2D-Spiel, um vor allem die Grundlagen des Programmierens zu erlernen. Jetzt haben wir den Wunsch, praktische eine "Karte" von, sagen wir mal 3000x3000 pixel zu machen ( hypothetischer Wert). Jetzt wollen wir aber, das immer wenn sich unser Spieler Bewegt, sich die Kamera anpasst, und so der Spieler immer in der Mitte ist. Ich blicke da nicht durch, Normalerweiße sollte doch sowas irgendwie mit ClipRect oder sowas gehen??

-> Ja delphi ist kacke, hat aber was mit der Schule zu tun. Bin über jede, vor allem schnelle Hilfe, sehr dankbar ;)
12/01/2013 20:45 Saedelaere*#2
Quote:
Originally Posted by Drag0n' View Post
Ja delphi ist kacke, hat aber was mit der Schule zu tun. Bin über jede, vor allem schnelle Hilfe, sehr dankbar ;)
Den Satz will ich mal überlesen haben :bandit: :D

Ist die karte statisch in einem Bitmap gespeichert? Ich würde so verfahren, dass ich pro "Frame" / OnPaint Ereignis erstmal den Hintergrund komplett schwarz fülle und dann je nach Position des Spieler mit Canvas.Draw() die Karte auf an die entsprechenden Koordinaten zeichnen lasse.
12/01/2013 20:50 Ky0n'#3
Ich will jetzt nicht, naja faul klingen, aber kannst du mir das bitte als Code schreiben? Ich habs schon so lange versucht... Zudem wäre es besser wann man,naja das Form verschiebt, da auch noch Objekte mit eigenen Koordinaten existieren.

Hintergrundbild ist TImage
12/01/2013 21:03 Brendan Jordan#4
Kenne mich mit Delphi nicht aus aber in der Theorie würde ich einfach beim "bewegen des Charakters" einfach die Karte verschieben
12/01/2013 21:07 Ky0n'#5
... und wie geht das???
-.-
12/01/2013 21:20 Saedelaere*#6
Quote:
Originally Posted by Drag0n' View Post
... und wie geht das???
Man verändert einfach entsprechend die X und Y Koordinaten der Karte beim Zeichnen. Die Mathematik dahinter ist recht trivial.

Code:
function TForm3.GetTransformedPosition: TPoint;
var
  SX, SY: Extended;
begin
  SX := FMap.Width / FMapPos.X;
  SY := FMap.Width / FMapPos.Y;
  Result.X := Round(Width / 2 - FMap.Width / SX);
  Result.Y := Round(Height / 2 - FMap.Height / SY);
end;
FMap ist ein Bitmap, welches die Karte enthält und FMapPos ist ein TPoint mit der Position des Spielers relativ zur Karte.
12/01/2013 22:19 Ky0n'#7
Und was ist mit den ganzen Objekten auf der Karte?
12/01/2013 23:16 マルコ#8
Du speicherst deine Objekte sicherlich in nem Array? dann prüf doch einfach dein Array gegen das aktuell sichtbare Feld.

Code:
type
  TVector2D = record
  begin
    x,y
    : Integer;
  end;

  TGameObject = record
  begin
    // some stuff
    position
    : TVector2D;
  end;

// some methods n shit

var
  // lots of things here
  myObjects
  : array of TGameObject;

  i, // Counter
  displayWidth, // width of visible area
  displayHeight // height of visible area
  : integer;

  upperLeftField // contains coords of  upper left corner field of visible area
  : TVector2D;
begin
  // do whatever
  for i := low(myObjects) to high(myObjects) do
  begin
    if ((myObjects[i].position.x > upperLeftField.x) and
       (myObjects[i].position.x <= upperLeftField.x + displayWidth) and
       (myObjects[i].position.y > upperLeftField.y) and
       (myObjects[i].position.y <= upperLeftField.y + displayWidth)) then
    begin

      // Arguments 2 and 3 do not need to be given,
      // since this can be calculated inside the method
      // but I wrote them down for clarification
      drawObject(myObjects[i], // Object to draw
                      myObjects[i].position.x - upperLeftField.x, // X coord on display rect
                      myObjects[i].position.y - upperLeftField.y); // Y coord on display rect

    end;
  end;
  // do something exciting here
end.
*Das sollte alles natürlich in deine Klasse gekapselt sein, und nicht wie bei mir einfach so dastehen...

**Ungetestet ;P

***Dieser Ansatz ist anfängerfreundlich und LANGSAM. Falls du mal weiter bist empfielt sich hier, einen binary tree o.ä. zu benutzen.
12/01/2013 23:24 MrDami123#9
Wie M3BF05B bereits geschrieben hat, reicht es die Karte zu verschieben und den Charakter in der Mitte zu lassen.
Die Frage ist, ob du deine ganze Karte angezeigt hast oder nicht.

Sonst programmierst du einfach, dass wenn du die z.B. Pfeiltasten drückst sich die Karte um z.B. 10px in die jeweilige Richtung verschiebt.
12/02/2013 00:17 Saedelaere*#10
Quote:
Originally Posted by MrDami123 View Post
Wie M3BF05B bereits geschrieben hat, reicht es die Karte zu verschieben und den Charakter in der Mitte zu lassen.
Die Frage ist, ob du deine ganze Karte angezeigt hast oder nicht.

Sonst programmierst du einfach, dass wenn du die z.B. Pfeiltasten drückst sich die Karte um z.B. 10px in die jeweilige Richtung verschiebt.
Ist exakt die Funktionalität, die ich in meinem Beispielsource implementiert habe.

@Threadersteller:
Zeig mal ein bisschen mehr Eigeninitiative :P Die Berechnung von mir, kannst du mit einer simplen Addition ohne weiteres auch auf Objekte der Karte übertragen.

Code:
P := GetTransformedPosition;
  { ... }
  for I := Low(FMapObjects) to High(FMapObjects) do
  begin
    Canvas.Draw(P.X + FMapObjects[I].Pos.X, P.Y + FMapObjects[I].Pos.Y, FMapObjects[I].Image);
  end;
12/02/2013 01:45 マルコ#11
Quote:
Originally Posted by Saedelaere* View Post
Code:
P := GetTransformedPosition;
  { ... }
  for I := Low(FMapObjects) to High(FMapObjects) do
  begin
    Canvas.Draw(P.X + FMapObjects[I].Pos.X, P.Y + FMapObjects[I].Pos.Y, FMapObjects[I].Image);
  end;
Du musst an dieser Stelle aufpassen. Du zeichnest hier nämlich alle Objekte, was wesentlich langsamer ist, als zu filter (siehe meinen Code), welche Objekte überhaupt sichtbar sind.
Theoretisch müsste man bei der Karte das selbe tun.
Ich würde dort 2 Bitmaps nehmen, das eine enthält die Karte, das andere ist das sichtbare Objekt auf der Form. Und dann immer nur den sichtbaren Bereich vom Kartenbitmap auf das Formbitmap kopieren. Deine Berechnung muss dabei selbstverständlich voraus gehen, um den sichtbaren Bereich zu ermitteln.
12/02/2013 01:53 Saedelaere*#12
Quote:
Originally Posted by マルコ View Post
Du musst an dieser Stelle aufpassen. Du zeichnest hier nämlich alle Objekte, was wesentlich langsamer ist, als zu filter (siehe meinen Code), welche Objekte überhaupt sichtbar sind.
Das stimmt. In meinem Code sind weder Visible- noch Range Checks implementiert. Hier wollte ich nur demonstrieren, wie der TE die Map Koordinaten der Objekte in die Relative Position im Fenster umrechnen kann.

Je nach Position der Map kann es auch noch zu Divisionen durch 0 kommen, was man vorher noch abfangen sollte.
12/02/2013 16:19 Ky0n'#13
Quote:
Originally Posted by Saedelaere* View Post
Das stimmt. In meinem Code sind weder Visible- noch Range Checks implementiert. Hier wollte ich nur demonstrieren, wie der TE die Map Koordinaten der Objekte in die Relative Position im Fenster umrechnen kann.

Je nach Position der Map kann es auch noch zu Divisionen durch 0 kommen, was man vorher noch abfangen sollte.
Kann ich dich auf skype adden?
Wenn ja schick mir bitte ne pn :)
12/02/2013 23:36 Saedelaere*#14
Sorry, habe nicht allzu viel Zeit für persönliche Hilfestellungen. Wenn du noch Fragen hast, kannst du dich aber gerne hier oder per PM melden.
12/03/2013 06:41 Ky0n'#15
ok ;)
Also ich kapiere das nicht ganz, und die Projekte die du geschickt hast gehen auch nicht richtig, weil da immer irgendwelche Fehler sind.