Autor Beitrag
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 03.09.14 15:14 
Zitat:
es gibt 2 anfänge und 1 ende (man kann sich das feld wie ein gedrehtes "T" vorstellen

ich möchte gerne die anfänge und das ende makieren.


Aber nicht miteinander verbinden? Woraus folgt ein Panel braucht kein Wissen über seine Nachbar-Panel. Richtig?
Das ist eigentlich der zentrale Punkt um zu entscheiden wie man das am besten strukturiert.
Braucht man Wissen der Gesamtmatrix oder reicht das die einzelnen Panels sich selber kennen?
C#
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 561
Erhaltene Danke: 65

Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
BeitragVerfasst: Mi 03.09.14 15:45 
Also so wie ich das sehe hat das Panel nur Augen für sich selbst (ist halt ein egoistisches Panel :mrgreen:). Er braucht die Infos über die umliegenden Panels meiner Ansicht nach nicht - wozu auch? Wenn das jetzt das Spiel wäre, dann ja. Aber das was er vor hat ist ja nur eine Art Gedächtnisstütze, dass er sich die Felder mit den Towers markieren kann.

@DonKannallie
Wenn dir was an meinem Code unklar ist, dann frag konkret was.
Ach und google mal Multidimensionale Arrays (z.B. int[,])

_________________
Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
DonKannallie Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 16



BeitragVerfasst: Mi 03.09.14 17:18 
Rein theoretisch bräuchten die Panels schon information über die anderen Panels , da ich ganz gerne noch eine funktion einbauen würde dass wenn ich auf ein Panel klicke soll das darunten liegende , rechtslegende und unten rechts liegende panel sich dem entsprechent färben soll (welche taste man drückt)


@ C#

wenn du mir erklähren könntest wie du das Speichern und laden gemacht hast wäre ich dir sehr dank bar
genau gesagt von Zeile 36 bis 97 bei der ersten Version (ich glaub zwischen den Versionen hast du nichts geändert)
falls du irgentwo eine art "Tutorial" hättest oder irgntwas wo ich sowas nachlesen könnte wäre das auch schön


Ich habe für Mehrdimensionale Array schon gegooglt bzw. auf Galileo Computing geschaut wusste jedoch nicht wie ich dass in mein Prog. einbiden konnte wobei mir Herr Jansen geholfen hat und ich seine Version bevorzuge
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 03.09.14 17:46 
user profile iconDonKannallie hat folgendes geschrieben Zum zitierten Posting springen:
wobei mir Herr Jansen geholfen hat und ich seine Version bevorzuge


Aua. Ich sag trotzdem du.

Zitat:
Rein theoretisch bräuchten die Panels schon information über die anderen Panels , da ich ganz gerne noch eine funktion einbauen würde dass wenn ich auf ein Panel klicke soll das darunten liegende , rechtslegende und unten rechts liegende panel sich dem entsprechent färben soll (welche taste man drückt)


Ist das ~Spielfeld~ immer rechteckig? Dein Testprojekt deutet etwas anderes an.


PS: bei "rechtslegende" muß ich irgendwie an den Mann mit dem 2-Fingerbart denken. Das war wohl nicht so gemeint ;)
C#
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 561
Erhaltene Danke: 65

Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
BeitragVerfasst: Mi 03.09.14 18:10 
Also das Speichern der Daten ist eigentlich recht einfach. Der BinaryWriter speichert die Rohdatensätze von bestimmten Typen (int, string, char, bool, ...).
Meine Klasse Map besteht aus int und string Variablen. Ich gehe die einzelnen Variablen durch und übergebe deren aktuellen Wert einfach dem BinaryWriter, der diesen Wert in der angegebenen Datei ablegt. Jeder weitere Wert wird einfach hinten an die Datei dran gehängt.

Im Prinzip würde die Datei so aussehen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
map.Name = "Test";
map.Width = 10;
map.Height = 10;
// map.MapData ist dann 10x10 groß

// Die Datei würde im Prinzip so aussehen:
Test\0000000000000000000000... // bis 10x10 Nullen drin stehen.


In Wahrheit sieht die Datei etwas anders aus, weil sie alles Binär speichert. Aber zum Vorstellen ist das hier besser.

Beim auslesen funktioniert das ganze genau anders rum. Der BinaryReader öffnet die Datei und ließt den string zuerst aus (der hört bei dem Zeichen "\0" auf; das ist das String-Abschlusszeichen). Da ein int 4 Byte speichergröße hat, ließt der Reader bei reader.ReadInt(); die nächsten 4 Bytes aus der Datei und wandelt diese in einen Integer um (also int). Diese Werte weiße ich dann wieder der Map-Klasse zu.

Deshalb ist es von Vorteil, wenn du Logik und UI voneinander trennst.

Logik:

Was dein Problem mit den MultiArrays angeht, überleg mal:
Deine Karte im TD ist Zweidimensional, also hast du eine X- und eine Y-Achse. Wenn du also Logik von UI trennst, musst du zuerst mal dieses Feld im Speicher anlegen.
Sagen wir dein Feld ist 20x20 groß, dann erzeugst du ein Array in dieser größe mit einem passenden Typ. Da dir ja nur die Farben der Felder wichtig sind, bietet sich als Typ int oder Color an. Letzteres verursacht bei manchen Speichermethoden problemen, deshalb habe ich int genommen. Wenn du noch mehr Informationen über die Karte wissen solltest (z.B. Name), erstelle dir eine Klasse, die die ganzen Infos bereithält. Bei mir ist das die Klasse Map. Hier wird die Feldgröße, der Name und das eigentliche Spielfeld angelegt.
Das eigentliche Spielfeld ist bei mir map.MapData. Dieses Array wird in den Maßen [Breite, Höhe] angelegt, sodass es den X- und Y-Achsen entspricht.
Der Vorteil darin liegt nun dass du ganz einfach dein Spielfeld ändern kannst.
Wenn du z.B. das rechte, untere und diagonale Feld einer bestimmten Stelle markieren willst, kannst du einfach so vorgehen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
Map map = new Map("Karte schlagmichtot"2020);
int x = 8, y = 10;
map.MapData[x, y] = Color.Red.ToArgb();   // Hier wird jetzt dein "geklicktes" Feld markiert
map.MapData[x + 1, y] = Color.Red.ToArgb();   // und hier das Feld rechts daneben,
map.MapData[x, y + 1] = Color.Red.ToArgb();   // und hier das Feld darunter,
map.MapData[x + 1, y + 1] = Color.Red.ToArgb();   // und hier das Feld diagonal darunter,

Du siehst also, die einzelnen Felder müssen nichts voneinander wissen um sie zu ermitteln oder zu manipulieren.

So das wäre der Logikteil.



Kommen wir zur UI:
Jetzt hast du ja alle Daten schon im Speicher liegen wie du sie brauchst. Nun musst du sie nur noch auf den Bildschirm bringen. In Version 2 von meinem Projekt steht drin wie es richtig geht.
Also zuerst einmal bracuhen wir die Größe der Zeichenfläche. Ich habe bei mir eine Klasse geschrieben die von Control abgeleitet ist. Somit kann man sie einfach im Designer auf die Form ziehen und die Spielfeldgröße selbst bestimmen.
ausblenden C#-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:
class DrawingSurface : Control
{
    Map map;          // dieser Variable wird dann die oben erstelle Map zugewiesen
    SizeF tileSize;   // das ist die Größe eines einzelnen Felds

    public DrawingSurface()
    {
         // Die größe eines Feldes in Pixel wird so berechnet: Die Breite der Zeichenfläche (Width) / die Anzahl der Felder in X-Richtung (map.Width)
         tileSize = new SizeF(Width / map.Width, Height / map.Height);
    }

    protected override void OnPaint(PaintEventArgs e)  // Paint-Methode überschreiben, damit wir das Feld zeichnen können
    {
      base.OnPaint(e);

      Graphics g = e.Graphics;  // Graphics object nehmen

      for (int x = 0; x < Map.Width; x++)  // Das Feld im Speicher in X-Richtung abtasten
      {
        for (int y = 0; y < Map.Height; y++)  // Das Feld im Speicher in Y-Richtung abtasten
        {
          // Das momentane Feld zeichnen
          g.FillRectangle(new SolidBrush(Color.FromArgb(Map.MapData[x, y])), tileSize.Width * x, tileSize.Height * y, tileSize.Width, tileSize.Height);
          g.DrawRectangle(new Pen(Color.Black, 2), tileSize.Width * x, tileSize.Height * y, tileSize.Width, tileSize.Height);
        }
      }
    }


Hoffe ich konnte es klarer machen.

P.S.: Hier sind alle per Du ;)

Nachtrag
Ich habe dir im Anhang noch zwei Bilder. Das eine zeigt dir, wie das Array prinzipiell im Speicher aussieht und das Andere stellt das Spielfeld dar. Du siehst, sie sind beide fast identisch. Sie haben nur eine andere Skalierung. Und genau diese Skalierung wird bei der Paint-Methode umgerechnet (bei g.FillRectangle(...
Einloggen, um Attachments anzusehen!
_________________
Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler

Für diesen Beitrag haben gedankt: DonKannallie
DonKannallie Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 16



BeitragVerfasst: Mi 03.09.14 19:24 
gut danke , ich werde mich morgen noch mal ran setzten und versuchen das ganze mit einem Array zu machen da es offenbar für meine zwecke einfacher ist xD

genau so hatte ich mir den speicher vorgang auch gedacht jedoch wusste ich nicht dass es diesen befehl gibt :D


ich wollte jetzt auch nicht respektlos sein daher spreche ich eher personen mit nachnamen an ;)