Hallo Leute,
ich habe kurzer Hand entschlossen das Tutorial von kevin89 ([VB.NET] Multiserver (TCP)) in ein kleines "Onlinespiel" umzubauen.
Vorwarnung: Ein echtes, großes Onlinespiel zu bauen, ist weit mehr Arbeit und gar nicht einfach, dass hier soll nur eine kleine Grundbasis sein.
Zuallererst müssen wir wissen, wie ein Onlinespiel funktioniert, das habe ich einmal in zwei Teile aufgeteilt:
Client + Server
Der Client ist das eigentliche Spiel, in dem das Spiel angezeigt wird und ausgeführt.
Client:
Das schauen wir uns einmal näher an.
Wenn du zum Beispiel die "Vorwärts"-Taste in einem Onlinespiel (kürzen wir es nun mit OP ab), wird nicht nur der Player bewegt, sondern auch eine "Information" an den Server gesendet. So eine Information kann beliebig gross oder klein ausfallen, in unserem Beispiel senden wir aber nur einen String an den Server, der dann von den Clienten "geparst" wird:
NameDesSpieler, X-Position, Y-Position
Das kann dann so aussehen:
Tobi,10,50
Wichtig! Keine Leerzeichen!
Dieser String - wie gesagt - wird an den Server gesendet und bei einer neuen Information von allen Clients heruntergeladen und "geparst". Das "Parsen" (wie ich es gerne nenne), teilt einfach jedes Wort oder jede Zahl nach jedem Komma aus und speichert es in eine Liste, das würde dann so aussehen:
NameDesSpielers
X-Position
Y-Position
Wir speichern da sganze - ich weiss, unschöne Methode, aber so geht es am besten - in ein ListViewControl. Das schöne an einer ListView ist die Sache mit den Spalten, den dort werde unsere aktuellen Daten abgespeichert:
NameDesSpieler X-Position Y-Position
Tobi 10 50
Und nur durch die ListView wird es angezeigt, dass heißt, du könntest auch offline Daten einspeichern und dann werden auch nur die Daten aus der ListView mit GDI gezeichnet, denn es ist immer wichtig, Server und Client zu trennen!
Das heißt, wir haben einen Anzeigebereich und den Serverbereich - in meinem sehr winzigen Beispiel teile ich das ganze nicht in Klassen unter.
Kurz zusammengefasst: Wenn man eine Taste im Spiel drückt, senden wir einen Informationscode an den Server, bei einer neuen Information laden sich alle Clienten die neue Information herunter, heißt: Alles ist synchron (außer wenn ein Spieler vorher schon etwas gemacht hat wird es nicht mehr bei einem neuen Spieler angezeigt). Immer in 2 Teile deinen Clienten aufteilen: Anzeigen & Spiel, Server.
Ich hoffe dass du diese Sache verstanden hast, den nun können wir weiter machen!
Zuerst: Wie ich bereits gesagt habe, machen wir hier nur ein kleines Beispiel, mit dem 127.0.0.1 Server. Heißt: Noch nicht online.
Nun, du bennötigst einen Server. Denn kannst du in VisualBasic entwickeln, kevin89 hat schon ein Beispiel gepostet (siehe: [VB.NET] Multiserver (TCP)). Du kannst den Server schon starten wenn du willst.
Nun, erstelle ein neues VisualBasic-Projekt, mit einer Picturebox (alles Namen nach dem Schema: Control1) und einer Listview.
Für die ListView gilt:
(ich weiss, der Code ist schrecklich, aber es funktioniert ;))
Zuerst: Dieser Code stellt eine Art Schlange dar, und jeder kann online mit anderen seine Schlange zeichnen (oder so...), keine Extras, das könntest du machen:
Unteranderem habe ich nun eine Codezeile rausgeschnitten, damit du kein C&P machst, diese Codezeile gehört ins KeyDown-Event bei "*C" durch "streamw.WriteLine(nick & "," & myx & "," & myy)" ersetzt ;).
Ich werde hier nur die neuen Sachen erklären, den Rest kann man in Vincents (auch bekannt unter kevin89 ;)) Tutorial nachlesen. Ich gehe Zeilenweise den Code durch.
Zuerst gibt's die Variablen
Das sit die aktuelle Position des Spielers (x,y).
Die Funktion AddItem - das wichtigste wohl - habe ich erweitert, hier ist der kleine "Parser" xD:
(es gibt vermutlich bessere Varianten, dass war aber die erste Lösung die mir eingefallen ist)
Erklärung:
Wir splitten ("teilen") den Code in ein Array auf, es wird bei jedem Koma ein Eintrag hinzugefügt.
Wir erstellen einen neuen ListView-Eintrag und fügen gleich das erste "gesplitterte" Wort hinzu, also den Namen.
Hier erstellen wir die Untereinträge ("SubItems") zu unserem Haupteintrag - aus dem Index der neuen Liste - hinzu.
Hier fügen wir diese nun der ListView hinzu.
Wir aktualisieren unsere Picturebox.
Nächstes:
Wir setzten mit den Pfeiltasten unseren aktuellen Spieler.
Wir senden die Informationen an unseren Server nach dem Schema:
Nickname,x,y
selbstverständlich säuberlich mit Kommas getrennt.
Nächstes:
Wir erstellen eine zufällige Position für unsere Spieler, massgeschneidert, so das der Spieler nicht vom Bildschirm verschwindet. (Das Rechteck das wir bald zeichen werden ist 15 px breit und hoch)
Wir setzten unsere generierten Positionen.
Eine Eingabebox fordert - was woll sonst - zur Eingabe auf, hier den gewünschten Spiernamen.
Nachdem man ja auch sein Objekt mit den Maustasten steuern kann und nicht außversehen in der ListView scrollt, setzten wir unsere Form als "Steuerungsmodul" ;).
Nächstes (der folgende Code ist sehr unsauber und gehört in den Paint-Handler der Picturebox, wir zeichnen mit Gdi)
(Schnellzusammenfassung).
Wir haben eine Schleife, die jedes listViewItem - dass wir schon geladen haben (vom Server nämlich) - an die Position des ListveiwItemx und Listviewitemy zeichnet. Ich ersetzte dann auch noch die ListViewItem.ToString, wahrscheinlich gibt es auch 'ne andere Methode.
Tschuldigung für die schlampige Zusammenfassung aber mein Akku geht gleich leer ;).
Dazu noch ein Beispielprojekt im Anhang.
Hoffe es hat euch gefallen ;).
mfg
Epic
ich habe kurzer Hand entschlossen das Tutorial von kevin89 ([VB.NET] Multiserver (TCP)) in ein kleines "Onlinespiel" umzubauen.
Vorwarnung: Ein echtes, großes Onlinespiel zu bauen, ist weit mehr Arbeit und gar nicht einfach, dass hier soll nur eine kleine Grundbasis sein.
Zuallererst müssen wir wissen, wie ein Onlinespiel funktioniert, das habe ich einmal in zwei Teile aufgeteilt:
Client + Server
Der Client ist das eigentliche Spiel, in dem das Spiel angezeigt wird und ausgeführt.
Client:
- Zeigt die Spieloberfläche (Spieler, Objekte, Landschaft) an
- Nimmt die Informationen des Servers auf
- Schickt Informationen an den Server
- Daten aufnimmt & "speichert"
- (Eventuell sendet er auch noch Informationen zurück, zum Beispiel beim Aufheben von Items)
Das schauen wir uns einmal näher an.
Wenn du zum Beispiel die "Vorwärts"-Taste in einem Onlinespiel (kürzen wir es nun mit OP ab), wird nicht nur der Player bewegt, sondern auch eine "Information" an den Server gesendet. So eine Information kann beliebig gross oder klein ausfallen, in unserem Beispiel senden wir aber nur einen String an den Server, der dann von den Clienten "geparst" wird:
NameDesSpieler, X-Position, Y-Position
Das kann dann so aussehen:
Tobi,10,50
Wichtig! Keine Leerzeichen!
Dieser String - wie gesagt - wird an den Server gesendet und bei einer neuen Information von allen Clients heruntergeladen und "geparst". Das "Parsen" (wie ich es gerne nenne), teilt einfach jedes Wort oder jede Zahl nach jedem Komma aus und speichert es in eine Liste, das würde dann so aussehen:
NameDesSpielers
X-Position
Y-Position
Wir speichern da sganze - ich weiss, unschöne Methode, aber so geht es am besten - in ein ListViewControl. Das schöne an einer ListView ist die Sache mit den Spalten, den dort werde unsere aktuellen Daten abgespeichert:
NameDesSpieler X-Position Y-Position
Tobi 10 50
Und nur durch die ListView wird es angezeigt, dass heißt, du könntest auch offline Daten einspeichern und dann werden auch nur die Daten aus der ListView mit GDI gezeichnet, denn es ist immer wichtig, Server und Client zu trennen!
Das heißt, wir haben einen Anzeigebereich und den Serverbereich - in meinem sehr winzigen Beispiel teile ich das ganze nicht in Klassen unter.
Kurz zusammengefasst: Wenn man eine Taste im Spiel drückt, senden wir einen Informationscode an den Server, bei einer neuen Information laden sich alle Clienten die neue Information herunter, heißt: Alles ist synchron (außer wenn ein Spieler vorher schon etwas gemacht hat wird es nicht mehr bei einem neuen Spieler angezeigt). Immer in 2 Teile deinen Clienten aufteilen: Anzeigen & Spiel, Server.
Ich hoffe dass du diese Sache verstanden hast, den nun können wir weiter machen!
Zuerst: Wie ich bereits gesagt habe, machen wir hier nur ein kleines Beispiel, mit dem 127.0.0.1 Server. Heißt: Noch nicht online.
Nun, du bennötigst einen Server. Denn kannst du in VisualBasic entwickeln, kevin89 hat schon ein Beispiel gepostet (siehe: [VB.NET] Multiserver (TCP)). Du kannst den Server schon starten wenn du willst.
Nun, erstelle ein neues VisualBasic-Projekt, mit einer Picturebox (alles Namen nach dem Schema: Control1) und einer Listview.
Für die ListView gilt:
- View: Details
- (optional) Visible: False
- Spalte Name
- Spalte x
- Spalte y
(ich weiss, der Code ist schrecklich, aber es funktioniert ;))
VB.NET-Quellcode
- Imports System.Net.Sockets
- Imports System.IO
- Public Class Form1
- Private stream As NetworkStream
- Private streamw As StreamWriter
- Private streamr As StreamReader
- Private client As New TcpClient
- Private t As New Threading.Thread(AddressOf Listen)
- Private Delegate Sub DAddItem(ByVal s As String)
- Private nick As String = "unknown"
- Dim myx As Integer = -5
- Dim myy As Integer = 10
- Private Sub AddItem(ByVal s As String)
- Dim arr = s.Split(",")
- Dim list = arr.ToList
- Dim i = ListView1.Items.Add(list.Item(0))
- Dim one As String = list.Item(1)
- Dim two As String = list.Item(2)
- i.SubItems.Add(one)
- i.SubItems.Add(two)
- PictureBox1.Refresh()
- End Sub
- Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
- If e.KeyCode = Keys.Right Then
- myx += 5
- End If
- If e.KeyCode = Keys.Left Then
- myx -= 5
- End If
- If e.KeyCode = Keys.Up Then
- myy -= 5
- End If
- If e.KeyCode = Keys.Down Then
- myy += 5
- End If
- *C
- streamw.Flush()
- End Sub
- Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
- Dim posx_rnd As New Random
- Dim posy_rnd As New Random
- Dim posx = posx_rnd.Next(15, Me.Width - 15)
- Dim posy = posy_rnd.Next(15, Me.Height - 15)
- myx = posx
- myy = posy
- nick = InputBox("Gib einen Spielernamen ein!")
- Me.KeyPreview = True
- Try
- client.Connect("127.0.0.1", 8000)
- If client.Connected Then
- stream = client.GetStream
- streamw = New StreamWriter(stream)
- streamr = New StreamReader(stream)
- streamw.WriteLine(nick)
- streamw.Flush()
- t.Start()
- Else
- MessageBox.Show("Verbindung zum Server nicht möglich!")
- Application.Exit()
- End If
- Catch ex As Exception
- MessageBox.Show("Verbindung zum Server nicht möglich!")
- Application.Exit()
- End Try
- End Sub
- Private Sub Listen()
- While client.Connected
- Try
- Me.Invoke(New DAddItem(AddressOf AddItem), streamr.ReadLine)
- Catch
- MessageBox.Show("Verbindung zum Server nicht möglich!")
- Application.Exit()
- End Try
- End While
- End Sub
- Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
- For Each item As ListViewItem In ListView1.Items
- Dim rnd1 As New Random
- Dim rnd2 As New Random
- Dim rnd3 As New Random
- Dim clr1 = rnd1.Next(1, 255)
- Dim clr2 = rnd2.Next(1, 255)
- Dim clr3 = rnd2.Next(1, 255)
- Dim nm_ As String = item.ToString
- nm_ = nm_.Replace("ListViewItem: {", "")
- nm_ = nm_.Replace("}", "")
- Dim nm As String = nm_
- Dim x_ As String = item.SubItems(1).ToString
- x_ = x_.Replace("ListViewSubItem: {", "")
- x_ = x_.Replace("}", "")
- Dim x As Single = x_
- Dim y_ As String = item.SubItems(2).ToString
- y_ = y_.Replace("ListViewSubItem: {", "")
- y_ = y_.Replace("}", "")
- Dim y As Single = y_
- Dim player As New Rectangle(x, y, 15, 15)
- e.Graphics.DrawRectangle(Pens.Transparent, player)
- e.Graphics.FillRectangle(New SolidBrush(Color.FromArgb(clr1, clr2, clr3)), player)
- Next
- End Sub
- End Class
Zuerst: Dieser Code stellt eine Art Schlange dar, und jeder kann online mit anderen seine Schlange zeichnen (oder so...), keine Extras, das könntest du machen:
- Chatbox
- Onlinebox
- Namenanzeigen (einfach)
- Kollissionabfrage
Unteranderem habe ich nun eine Codezeile rausgeschnitten, damit du kein C&P machst, diese Codezeile gehört ins KeyDown-Event bei "*C" durch "streamw.WriteLine(nick & "," & myx & "," & myy)" ersetzt ;).
Ich werde hier nur die neuen Sachen erklären, den Rest kann man in Vincents (auch bekannt unter kevin89 ;)) Tutorial nachlesen. Ich gehe Zeilenweise den Code durch.
Zuerst gibt's die Variablen
Das sit die aktuelle Position des Spielers (x,y).
Die Funktion AddItem - das wichtigste wohl - habe ich erweitert, hier ist der kleine "Parser" xD:
Erklärung:
Wir splitten ("teilen") den Code in ein Array auf, es wird bei jedem Koma ein Eintrag hinzugefügt.
Wir erstellen einen neuen ListView-Eintrag und fügen gleich das erste "gesplitterte" Wort hinzu, also den Namen.
Hier erstellen wir die Untereinträge ("SubItems") zu unserem Haupteintrag - aus dem Index der neuen Liste - hinzu.
Hier fügen wir diese nun der ListView hinzu.
Wir aktualisieren unsere Picturebox.
Nächstes:
VB.NET-Quellcode
- Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
- If e.KeyCode = Keys.Right Then
- myx += 5
- End If
- If e.KeyCode = Keys.Left Then
- myx -= 5
- End If
- If e.KeyCode = Keys.Up Then
- myy -= 5
- End If
- If e.KeyCode = Keys.Down Then
- myy += 5
- End If
- streamw.WriteLine(nick & "," & myx & "," & myy)
- streamw.Flush()
- End Sub
VB.NET-Quellcode
- Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
- If e.KeyCode = Keys.Right Then
- myx += 5
- End If
- If e.KeyCode = Keys.Left Then
- myx -= 5
- End If
- If e.KeyCode = Keys.Up Then
- myy -= 5
- End If
- If e.KeyCode = Keys.Down Then
- myy += 5
- End If
- End Sub
Wir setzten mit den Pfeiltasten unseren aktuellen Spieler.
Wir senden die Informationen an unseren Server nach dem Schema:
Nickname,x,y
selbstverständlich säuberlich mit Kommas getrennt.
Nächstes:
Wir erstellen eine zufällige Position für unsere Spieler, massgeschneidert, so das der Spieler nicht vom Bildschirm verschwindet. (Das Rechteck das wir bald zeichen werden ist 15 px breit und hoch)
Wir setzten unsere generierten Positionen.
Eine Eingabebox fordert - was woll sonst - zur Eingabe auf, hier den gewünschten Spiernamen.
Nachdem man ja auch sein Objekt mit den Maustasten steuern kann und nicht außversehen in der ListView scrollt, setzten wir unsere Form als "Steuerungsmodul" ;).
Nächstes (der folgende Code ist sehr unsauber und gehört in den Paint-Handler der Picturebox, wir zeichnen mit Gdi)
VB.NET-Quellcode
- Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
- For Each item As ListViewItem In ListView1.Items
- Dim rnd1 As New Random
- Dim rnd2 As New Random
- Dim rnd3 As New Random
- Dim clr1 = rnd1.Next(1, 255)
- Dim clr2 = rnd2.Next(1, 255)
- Dim clr3 = rnd2.Next(1, 255)
- Dim nm_ As String = item.ToString
- nm_ = nm_.Replace("ListViewItem: {", "")
- nm_ = nm_.Replace("}", "")
- Dim nm As String = nm_
- Dim x_ As String = item.SubItems(1).ToString
- x_ = x_.Replace("ListViewSubItem: {", "")
- x_ = x_.Replace("}", "")
- Dim x As Single = x_
- Dim y_ As String = item.SubItems(2).ToString
- y_ = y_.Replace("ListViewSubItem: {", "")
- y_ = y_.Replace("}", "")
- Dim y As Single = y_
- Dim player As New Rectangle(x, y, 15, 15)
- e.Graphics.DrawRectangle(Pens.Transparent, player)
- e.Graphics.FillRectangle(New SolidBrush(Color.FromArgb(clr1, clr2, clr3)), player)
- Next
- End Sub
(Schnellzusammenfassung).
Wir haben eine Schleife, die jedes listViewItem - dass wir schon geladen haben (vom Server nämlich) - an die Position des ListveiwItemx und Listviewitemy zeichnet. Ich ersetzte dann auch noch die ListViewItem.ToString, wahrscheinlich gibt es auch 'ne andere Methode.
Tschuldigung für die schlampige Zusammenfassung aber mein Akku geht gleich leer ;).
Dazu noch ein Beispielprojekt im Anhang.
Hoffe es hat euch gefallen ;).
mfg
Epic
Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Epic“ ()