C# Zeichnen von Objekten (das Programm sol zeichnen. Nicht ich)

MasterMito

Cadet 3rd Year
Registriert
Mai 2007
Beiträge
54
Salve,

Programmiere hier gerade an nem kleinen Weltraum Spiel und alles funzt soweit (Steuerung, Schießen). Die meissten Funktionen haben wir aus einer fertigen DLL.
Nun soll das ganze gezeichnet werden. In 2D. Das einzige was ich weiss ist:
-das ich meine Position nicht weiss, folglich wird mein Raumschiff immer in der Mitte sein.
-Die Position von anderen Raumschiffen und Planeten, relativ zu meiner Position und Radius
-Meine Geschwindigkeit und Kurs

Nun soll das ganze etwas Grafisch aufbereitet werden (aber nicht allzu anspruchsvoll, Sprites wären zuviel). Bis jetzt habe ich nur ein riesen Panel an der Stelle wo was sein soll.
Hätte jemand ne Idee wie ich ganz einfach Striche, Kreise und Punkte malen kann?
Auch ne Lösungsidee wäre schon nice da ich dastehe und nich weiss was tun.

XNA oder DirectX stehen nicht zu verfügung- Und wie gesagt, Sprites wären schon zuviel.

Merci schonmal
 
Das Zeichnen ist im Paint Ereignis vom Panel machbar. Das PaintEventArgs (meist ist das die Variable e) hat eine Eigenschaft namens Graphics. Dieses Objekt hat mehrere Methoden: DrawLine() , DrawEllipse() usw... Damit könntest du schon mal was zeichnen. Aber dieses Graphics Objekt kann auch ein Image zeichnen, somit könntest du auch ein Sprit zeichnen, was sicher um einiges leichter sein wird, als mit Linien und Kreisen da was zu machen.

Beim zeichnen im Paint Ereignis ist es jedoch so, das das Paint Ereignis nur dann ausgelöst wird, wenn dein Fenster neu gezeichnet werden muss. Wahrscheinlich musst du dann über einen Timer dieses Ereignis neu auslösen damit du eine Animation hinbekommst.
 
Zuletzt bearbeitet:
aha aha...
ich könnte ja quasi über einen thread, der nur schläft, nach 1 sek. aufwacht aktualisiert und dann wieder schläft regelmäßig das Panel updaten. Der gamestate wird auch nur einmal die Sekunde aktualisiert.

Die ganzen Objeke liegen in einer List<>. Da lässt sich ja ohne Probleme drüber iterieren.
Wenn es nicht klappt melde ich wieder, aber auf jeden Fall mal merci
 
ähm wieso soll es nicht mit XNA sein?

Das Problem mit der Aktuallisierung würde ich nicht so leicht auf die schulter nehmen.

Mach wie bei XNA einen GameTimer. naja ein normaler reicht aus und aktualliesiere dem entsprechend. mit ne liste und itterieren hast du schlechte karten weil da der prozesseor zu schnell sein kann und deine spiele einfach zu schnell ablaufen würden. deswegen sollte man Timer auf jeden fall in betracht ziehen. wenn es 2D ist dann kannst du ja sicher den objekt als datei laden und dann anzeigen lassen. muss ja nicht gezeichnet werden. sparrt man einfach an der performance. und durch die größe des Obejekt kannst du ja auch die kollisionen berechnen.
 
roker002 schrieb:
ähm wieso soll es nicht mit XNA sein?

Weil XNA nicht zur Verfügung steht, bzw. ich es nicht installieren könnte, weil mir auf dem Entwicklungsrechner die Rechte dazu fehlen

@Backslash: Genauso... Wobei ich auch vom Server einen Tick bekomme, was nach langen Überlegen(die ganze Nacht) wohl das bessere ist
Ergänzung ()

Sodele,

das ganze funktioniert ganz nice... ganz nice... Nur noch a weng an den Proportionen rumbasteln, dann siehts auch ordentlich aus.

Nun die nächste Fragen:
-Ist der Punkt den ich angebe beim zeichnen des Objekts der MIttelpunkt(z.B. einer Ellipse) oder ist es der Punkt links oben?
-Ich würde gern in das Objekt den Namen des zu zeichnenden Objektes reinschreiben lassen.
Den Namen bekomme ich als ganz normalen String. NUr finde ich unter e.Graphics nix für Text.

Merci schonmal
 
Die normalen Timer sind sowas von unregelmäßig, das du die komplett vergessen kannst.
Erstelle einen Thread, indem du das ganze in einer Endlosschleife mit Sleep(1000/Framerate) durchlaufen lässt. Das ist VIEL akurater als die Timerkomponenten.
 
Merci, das mit dem Timer läuft mittlerweile ganz gut (es kommt nicht auf die tausendstel an).

Nun habe ich die Funktion DrawString gefunden. Aber er akzeptiert Font noch nicht

Cee Ya
 
Sind nur Unterschiede von locker 10ms, plusminus.
Bei Systemlast steigt das Ganze dann noch sowas von rasant an.
 
-Ist der Punkt den ich angebe beim zeichnen des Objekts der MIttelpunkt(z.B. einer Ellipse) oder ist es der Punkt links oben?
links oben würde ich sagen, weil du ein Rechteck(in diesem Fall ein Quadrat) angibst um eine Ellipse (oder wie du wolltest ein Kreis) zu zeichnen. Im Hintergrund verwendet das .Net Framework GDI+ was seinerseits immer von links oben zeichnet.

-Ich würde gern in das Objekt den Namen des zu zeichnenden Objektes reinschreiben lassen.
Den Namen bekomme ich als ganz normalen String. NUr finde ich unter e.Graphics nix für Text.

Versuchs mal damit:

Code:
e.Graphics.DrawString("Hello World!", this.Font, Brushes.White, 0.0f, 0.0f);

Das ist der Font von deiner Form, alternativ könntest du den Font von deinem Panel nehmen, Brushes.White ist ein sogenannter solider Brush(Zeichenstil) mit der Farbe Weiß, am Ende noch die linke obere Ecke ab dem der Text gezeichnet werden soll.

Im übrigen, das was Cyba Mephisto geschrieben hat, bzgl. der Timer, mag zwar stimmen, ist aber nicht so wild, da du hier scheinbar noch nicht den super duper high tech fancy Ego Shooter von 2010 programmierst. Also den "normalen" Timer kannst du erstmal verwenden. Wenn du später weiter bist, würde ich an deiner Stelle PerformanceCounter einsetzen um das Timing genau abstimmen zu können. Ist zwar etwas komplizierter, aber dafür genauer. Näheres findest du sicher unter: www.gamedev.net Auf dem Weg bist du ja eh schon ;)
 
Zuletzt bearbeitet:
sodele,

weiter gecodet, neue Erkenntnisse.
Mein bisheriger Entwurf ist, naja, für'n Arsch. Er geht, alles fein. Nur öhm, alles sehr umständlich. Habe nun rausgefunden wie man Klickbefehle aus nem Panel bekommt. Und damit arbeite ich, damit es etwas Nutzerfreundlicher wird.
Ausserdem ist das mit dem Timer so. Ich habe ein Radar zum scannen. Muss es aber selber tun und Richtung und Reichweite angeben, dann bekomme ich was in dem Bereich ist. Ich muss es aber nicht. Ich kann quasi auch blind fliegen. Also aktualisiere ich das Bild wann ich möche (mit invalidate).
Mache mich dann mal an das Re-Design.
Das Problem mit dem Mittelpunkt der Ellipse ist gelöst, es ist die Ecke oben rechts (aus Visual C# 2008, Openbook)
Das Problem mit der Schrift ist gelöst wie du es geschrieben hast, merci

Wenn ich weitere Fragen habe, schreibe ich einfach. Auf jeden Fall dickes Merci an alle Mithelfenden
 
sorry das ich da nochmal nachhake, aber laut msdn und hilfe von csharp sind die koordinaten immer oben links beginnend. also entweder das buch hat da einen druckfehler oder wir reden an einander vorbei. sei es wie es sei.
im übrigen würde ich von dem panel die "refresh" methode verwenden, weil dann das ganze sofort neu gezeichnet wird, was auch bei deinem timing etwas hilfreicher sein dürfte als darauf zu warten, wann windows entscheidet, dein panel neu zu zeichnen.
viel erfolg weiterhin...
 
Zuletzt bearbeitet:
@ Rossibaer
leider ist das Buch richtig, ich war falsch. Habe mal wieder meinen Kopf in der IDE.
Es ist oben links. Sorry for confusion

Ich weiss ja nicht was Cyba_Mephisto von sich gibt, aber erstmal tut es ohne timing, bzw. habe eine Möglichkeit gefunden das ganz geschickt zu machen.
Nach jeder Aktion (Bewegen, Schießen, Scannen) werde ich meinen Bildschirm aktualisieren und von Server einen neuen State anfordern. Solange eine Aktion schon geschehen ist, schickt mich der Server bis zum nächsten Tick schlafen. Somit umgehe ich das.
Hoffe das war verständlich, ihr wisst ja wo mein Kopf ist. Das Redesign bis jetzt funzt sehr sehr nice. Übersichtlicherer Code und einfacher zu warten als der alte. Vor allem sicherer(Fehleingaben, etc)

Cee Ya
 
Wie ist das mit den Gegner bzw. bewegenden Objekten, die nicht durch eine Aktion von Dir animiert werden? Ich denke nur daran, das wenn man keine Aktionen auslöst, bleibt dann dein Spiel stehen und wartet auf die nächste Aktion?

@Cyba_Mephisto: Sorry ich habe deinen letzen Satz nicht verstanden...
 
Wenn ich nichts mache, bleibt das Spiel einfach stehen... das ist richtig... das will ich noch umgehen in dem ich den scanner einmal in der Sekunde anwerfe und er dann in der letzten Einstellung anzeigt. Naha Objekte werden mir beim Scannen Automatisch angezeigt,,, auch wenn sie nicht im Scan-Strahl liegen.

Nun habe ich mal wieder ein Problem...
Ich möchte in meinem Panel eine Aktion auslösen wenn das Mausrad losgeht. Dazu habe ich mir einen passenden Eventhandler gebastelt. (aus dem Openbook Visual C# 2008).
Nur leider passiert da garnichts
 
Wollte sagen, dass es mir selbst bei einem 5 Minuten 2D-Spiel stark aufgefallen ist, wie ungenau die Timer-Komponenten waren. Zugegeben, die Bewegungen habe ich nicht nach verstrichener Zeit berechnet, dennoch viel es sehr unangenehm auf.
Die Threadpriorität der Timer-Komponenten ist absichtlich auf sehr niedrig eingestellt worden, damit andere Anwendungen nicht auffallend gestört werden können. Die Komponenten wurden mehr für Dienste oder dienstähnliche Aufgaben erstellt, die eigentlich garnicht exakt zu dem Zeitpunkt dies und das tun müssen, und so den Nutzer bei der Benutzung von anderen Echtzeitvorgängen nicht stören können.
 
Master Mito: denke mal in Ruhe an ein Re-Design deines Spiels nach, weil du aus meiner Sicht in eine falsche Richtung läufst, aus der du so schnell nicht wieder rauskommen wirst.

Also es gibt für die Controls einschl. deine Form eine Methode die heißt WndProc. Du kannst sie locker überschreiben (Stichwort: overrides). Das ist die Methode die immer dann aufgerufen/ausgeführt wird, wenn eine Windows-Message empfangen wurde. Da ständig die unterschiedlichsten Messages an dein Programm gesendet werden, auch im Ruhezustand, kannst du hier deine Zeichenroutine unterbringen. D.h. du müsstest einfach nur rausfinden, wie du auf deinem Panel zeichnen kannst ohne Invalidate/Update und Refresh zu verwenden. Aber Vorsicht ist geboten, da auch die Aufforderungen etwas neu zu zeichnen, ebenfalls mit einer entsprechenden Message vom System angestoßen wird. Diese Nachrichten, das wären diese WM_PAINT Nachrichten kannst du filtern, z.B. dann nicht neu zeichnen. Achte darauf das du in der WndProc stets die Basis-Methode aufrufst, am besten im finally Block. Und noch was, sobald du diese Änderungen machst, musst du wohl oder übel dein Timing an sich überarbeiten. Z.B. PerformanceCounter um nicht ein unspielbares Spiel, will sagen zu schnelles Spiel, zu haben.

Cyba Mephisto: Ich würde mal sagen, das ein Windows Dienst andere Mechanismen verwendet um seine Aktionen zu timen. Da kommt man in den Bereich Scheduling. Ein Timer hat da nichts verloren. Aber es ist wahr, das wo Timer drauf steht nicht immer Timing drin steckt ;)
 
Zurück
Oben