Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Tician

Frischling

  • »Tician« ist der Autor dieses Themas

Beiträge: 32

Wohnort: Bad Friedrichshall

Beruf: FISI

  • Private Nachricht senden

1

22.06.2016, 17:22

Das erste Spiel fertig - und Fragen dazu

Hallöööchen mit 3 öchen,

ich bin im 1. Lehrjahr zur FISI und wir sollten ein kleines Programm in C# schreiben und vorstellen. Ich und meine Klassenkameradin sind beide Zocker weswegen wir auch ein Spiel geschrieben haben. Es ist zwar fertig (absolut simpel und ohne irgendwelche Features) und wir haben es geschrieben ohne uns andere Snake-Spiele anzuschauen (Wobei ich es nichtmal Snake nennen würde, es ist ein Punkt der etwas einsammeln muss und dann schneller wird). Mit dem Wissen was wir hatten und ein paar neuen Klassen und Methoden.
Ich wollte es hier mal zeigen und Fragen zu Problemen loswerden auf die wir gestoßen sind - und die wir Laienhaft umgangen/ignoriert haben :D

Die Form-Anwendung ist ein ganz normales Fenster ohne Buttons/Tools mit der Größe 378*400
Das Programm wurde in VS geschrieben und wir haben auch nur das benutzt was VS hergibt ohne externe Dateien zu verwenden.

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Snake_no2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Timer timer = new Timer();
        Random random1 = new Random();
        Random random2 = new Random();

        short headX = 170;
        short headY = 170;
        byte circleW = 10;
        byte circleH = 10;
        int score = 0;
        int rndFutterX;
        int rndFutterY;

        byte richtung = 0;

        private void Form1_Load(object sender, EventArgs e)
        {
            this.Paint += Form1_Paint; //wird benötigt um Kreis bei Programm-Ausführung zu zeichnen
            timer.Interval = 1000;
            timer.Tick += new EventHandler(Update);
            timer.Start();

            rndFutterX = 10 * random1.Next(0, 35);
            rndFutterY = 10 * random2.Next(0, 35);
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            SolidBrush playerBrush = new SolidBrush(Color.Red);
            Graphics grafik = this.CreateGraphics();
            Rectangle circle = new Rectangle(headX, headY, circleH, circleW);
            //grafik.DrawEllipse(Pens.Red, circle);
            grafik.FillEllipse(playerBrush, circle);

            SolidBrush foodBrush = new SolidBrush(Color.Blue);
            Graphics futter = this.CreateGraphics();
            Rectangle rekt = new Rectangle(rndFutterX, rndFutterY, 10, 10);
            futter.FillRectangle(foodBrush, rekt);
        }

        private void Update(object sender, EventArgs e)
        {
            if (richtung == 1)
            {
                headY += 10;
                this.Refresh();
            }
            if (richtung == 2)
            {
                headY -= 10;
                this.Refresh();
            }
            if (richtung == 3)
            {
                headX -= 10;
                this.Refresh();
            }
            if (richtung == 4)
            {
                headX += 10;
                this.Refresh();
            }
            //Schlange an Rand
            if (headY == 360 || headY == -10 || headX == 360 || headX == -10)
            {
                timer.Stop();
                MessageBox.Show("Game Over. Your Score: " + score);
            }
            //Schlange auf Futter
            if (headY == rndFutterY && headX == rndFutterX)
            {
                rndFutterX = 10 * random1.Next(0, 35);
                rndFutterY = 10 * random2.Next(0, 35);
                score += 1;
                if (timer.Interval > 250)
                {
                    timer.Interval = timer.Interval - 250;
                }
                if (timer.Interval > 100 && timer.Interval <= 250)
                {
                    timer.Interval = timer.Interval - 50;
                }
                if (timer.Interval > 20 && timer.Interval <= 100)
                {
                    timer.Interval = timer.Interval - 20;
                }
                if (timer.Interval > 2 && timer.Interval <= 20)
                {
                    timer.Interval = timer.Interval - 2;
                }
            }
        }


        public void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Down)
            {
                richtung = 1;
            }
            if (e.KeyCode == Keys.Up)
            {
                richtung = 2;
            }
            if (e.KeyCode == Keys.Left)
            {
                richtung = 3;
            }
            if (e.KeyCode == Keys.Right)
            {
                richtung = 4;
            }
        }
    }
}


Wie gesagt erschlagt mich nicht, ich kann mir gut vorstellen das es um Welten besser und sauberer geht.

Frage 1: Die KeyCodes für die Richtung der Schlange wollte ich irgendwie mit den Richtungen im Update-Event verbinden (einbinden) anstatt es separat zu haben, allerdings habe ich null Ahnung von den Events und das eine Unterstützt das andere nicht. Die Laien-Lösung war also eine neue Variable zu benutzen die beide kennen.

Frage 2: Ursprünglich wollten wir eine PictureBox benutzen um Score und Start-Button in das Fenster zu integrieren aber wir haben gefühlt alles versucht, entweder wird der Punkt für die Schlange gar nicht erstellt, erstellt sich hinter der PictureBox oder auf der PictureBox wo er sich dann aber nicht mehr bewegen lässt. Nach 5 Stunden rumprobieren haben wir die pictureBox aufgegeben und es direkt auf dem Fenster gemacht.

Frage 3: Wir haben hauptsächlich "int" für unsere Zahlen genommen obwohl wir so große Zahlen gar nicht brauchen aber irgendwie lässt sich nicht mit anderen Datentypen rechnen (short) kann das sein? Wir bekamen bei Berechnungen immer die Meldung "Datentyp short kann nicht in int konvertiert werden" oder sowas in der Art.

Ist der Code verständlich oder bedarf es Erklärungen?

Tician

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

22.06.2016, 17:31

Frage 1: Die Lösung klingt erstmal OK. Andere Alternative wäre gewesen aktiv nachzufragen, ob Tasten gedrückt sind. Wäre aber aufwendiger gewesen.
Frage 2: PictureBox hat diverse Probleme mit Events, denn sie ist nicht fokussierbar und kann daher keine Key-Events empfangen. Sie wegzulassen ist doch durchaus in Ordnung.
Frage 3: Bleib bei int. Den Bereich unnötig einzuschränken hat keinerlei Vorteile. Eventuell sogar Nachteile.

Die 4 IFs für die Richtungen hätte man in ein Switch packen können. Das this.Refresh() hätte man rausziehen können, es wird ja eh bei mindestens einem der Fälle aufgerufen.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Tician

Frischling

  • »Tician« ist der Autor dieses Themas

Beiträge: 32

Wohnort: Bad Friedrichshall

Beruf: FISI

  • Private Nachricht senden

3

22.06.2016, 18:10

Supi, danke für das Feedback und die Erklärung zur pictureBox!
Switch hatten wir noch nicht, habe ich aber schon gesehen, ich werde es beim nächsten Programm bedenken. Für unser Refarat behalte ich es erstmal so.
Und ja das mit den this.Refresh() kann ich auch nachvollziehen und wird noch gefixt!

Vielen vielen Dank dir :)

4

22.06.2016, 20:13

Habs gerade gespielt und finde es cool, passt alles gut zusammen. Sowohl vom Spielprinzip als auch von der Umsetzung.

Bei den Tasten beißen sich jetzt die Konzepte, WinForms ist ereignisgesteuert, euer Spiel eigentlich eine klassische Spieleschleife. Deshalb wohl der auch der Wunsch die Tasten innerhalb der Spieleschleife abzufragen und nicht erst den Umweg über die Ereignisse zu gehen und dort zwischenzuspeichern, nur um sie dann doch letztendlich innerhalb der Schleife wieder abzufragen. Eine Möglichkeit wäre Get(Async)KeyState aus der User32.dll.

Sobald ein Steuerelement den Focus besitzt werden auf der Form die Tastenereignisse nicht mehr ausgelöst. Abhilfe schafft die Eigenschaft KeyPreview der Form. Es funktioniert aber trotzdem nicht weil die Cursortasten von der Windows-Tastensteuerung reserviert sind. Würdet ihr zb. WASD nehmen könntet ihr auch Steuerelemente verwenden.

Ihr könnt den Text auch direkt auf die Form zeichnen mit DrawString oder wars DrawText?.

Ich finde es wirklich erstaunlich welche Techniken ihr schon sauber verwendet und dabei noch nicht mal alle Mehrfachauswahlen behandelt habt. Der einzige Verbesserungsvorschlag wäre deshalb nur alle Ereignisse in der Form zu abonnieren. Dann könnte man einfach ein neues Projekt erstellen und euren Code kopieren und es würde laufen.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

5

22.06.2016, 20:14

Der einzige Verbesserungsvorschlag wäre deshalb nur alle Ereignisse in der Form zu abonnieren. Dann könnte man einfach ein neues Projekt erstellen und euren Code kopieren und es würde laufen.
Das ist kein sehr guter Vorschlag. Baue niemals Dinge, von denen Du nicht weißt, ob Du sie jemals brauchst. Baue Dinge dann, wenn Du sie brauchst.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Tician

Frischling

  • »Tician« ist der Autor dieses Themas

Beiträge: 32

Wohnort: Bad Friedrichshall

Beruf: FISI

  • Private Nachricht senden

6

22.06.2016, 20:53

Ich frage jetzt mal blöd: Was heißt denn der Audruck "ein Ereignis in der Form abonnieren"? Das habe ich noch nie gehört :hmm:

Was wäre denn eine Idee für ein nächstes Spiel - nichts großartiges, einfach zum üben und um neues kennen zu lernen mit dem Wissen was ich habe? Ich dachte an eine Art Labirinth wie man es vom Papier her kennt in 2D, mit dem Unterschied das man nicht das ganze Labirinth sieht sondern nur einen kleinen Teil (quasi "gezoomt" wenn man so will auf die Position in der man sich befindet), ich denke auch ich würde das hinbekommen, nur das Labirinth selbst mit den Tausenden von Linien zu machen stelle ich mir ziemlich zeitaufwendig vor - und diese dann auch als "nicht übertretbar" zu setzen.
Vielleicht eine Art Space Invader/Touhou, bei dem ich denke das es etwas mehr Mathe bedarf je nach gewünschter Komplexität. Sollte ich auch mal Töne mit rein bringen? (Ich meine die System-Sounds, einfach nur ein "beep" wenn etwas bestimmtes passiert)

Sonst Vorschläge?

7

23.06.2016, 08:50

Der Link sollte weiterhelfen: http://www.lmdfdg.com/?q=Ereignis+abonnieren+c%23

Wenn man deinen Quellcode in ein neues Projekt kopiert läuft er erst einmal nicht. Die Ereignishandler sind zwar da werden aber nicht ausgelöst. Normalerweise geht man als Anfänger über den Designer der dir die Ereignisse abonniert und die Behandlungsroutine generiert. Bei dir ist das Paint-Ereignis in deinem Quellcode implementiert (this.Paint += Form1_Paint), andere Ereignisse wie KeyDown fehlen (weil sie wahrscheinlich über den Designer integriert wurden und sich in der Datei "Form1.Designer.cs" befinden. Mein Vorschlag wäre jetzt, wie beim Paint-Ereignis, die noch in deinen Quellcode aufzunehmen. Wenn du normalerweise die Projektmappe weitergibts ist es egal.

Ich hab sehr wenig Erfahrung mit Spieleprogrammierung, besonders mit C# scheinen die Möglichkeiten eher begrenzt. Die meisten verwenden hier wohl C++? Andererseits reichen die Möglichkeiten in C# und GDI durchaus aus um z.B. SpaceInvaders zu programmieren. Trotzdem ist GDI nicht für Spiele gedacht und man stößt an die Grenzen. Andererseits wirst du schneller Erfolge haben mit C# und GDI als mit C++ und DirectX. Ehrlich gesagt halte ich C++ und DirectX für einen Anfänger der beide Bereiche nicht kennt äußerst schwierig. Von daher würde ich aus meiner begrenzten Perspektive zu SpaceInvaders mit C# und GDI raten.

Wirago

Alter Hase

Beiträge: 1 193

Wohnort: Stockerau

Beruf: CRM Application Manager

  • Private Nachricht senden

8

23.06.2016, 09:26

C# ist bestimmt nicht "begrenzt". Besonders durch die weite Verbreitung von Unity.
Es ist zwar nicht zu bestreiten, dass C++ häufiger verwendet wird, aber du kommt mit C# schon sehr weit. Solltest du mal soweit kommen, dass dir C# nicht mehr reicht, kann man ja umsatteln.

http://www.monogame.net bietet eine solides Framework dafür.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

9

23.06.2016, 12:25

Was wäre denn eine Idee für ein nächstes Spiel - nichts großartiges, einfach zum üben und um neues kennen zu lernen mit dem Wissen was ich habe?

Versuch dich doch mal an Sokoban. Da kannst du die Bewegung wieder Kachel für Kachel geschehen lassen, dafür ist das Spiel aber an einigen anderen Stellen etwas komplexer. Gucks dir vielleicht einfach mal an. Ansonsten gibt es noch das 15-Puzzle welches auch recht einfach ist. Das schöne ist hier, statt Zahlen kannst du auch mit verschiedenen Bildern arbeiten. Das Spiel ist dir sicherlich bekannt. Das ist noch etwas einfacher. Was auch schön zum üben ist ist Minesweeper. Das kannst du theoretisch sogar einfach mit den Form-Buttons umsetzen. Minesweeper ist an sich ein sehr einfach zu implementierendes Spiel, die Schwierigkeit liegt hier eher im Aufdecken größerer Flächen, wenn du auf ein Feld ohne Nummer klickst wird soll ja der gesamte Bereich drum herum aufgedeckt werden. Das ist aber auch nicht besonders schwer zu lösen. Der Algorithmus der hier sinnvoll ist nennt sich Floodfill. Ist vielleicht mal ein interessantes Projekt bei dem du lernst einen Algorithmus nachzuschlagen und selbst zu implementieren. Wobei das auch erst mal schwerer klingt als es eigentlich ist.
Ansonsten gäbe es noch viele viele weitere Spiele die für den Anfang gut zum reinkommen sind. Aber irgendwo muss man ja anfangen. Alternativ kannst du dein Spiel ja auch erst mal nehmen und ein normales Snake daraus machen.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Tician

Frischling

  • »Tician« ist der Autor dieses Themas

Beiträge: 32

Wohnort: Bad Friedrichshall

Beruf: FISI

  • Private Nachricht senden

10

23.06.2016, 13:27

Ich fasse also mal zusammen das ihr alle der Meinung seid das ich nicht nur mit Forms weiter machen soll, sondern das ich mir ein Programm runter lade und benutze um wahrscheinlich mehr ins Grafische gehen zu können. Ich habe mal versucht mir etwas zu installieren, was war es denn... achja XNA, weil ich das kostenlos über die Schule von Microsoft bekommen würde, aber keine Anleitung der Welt konnte das zum Laufen bringen.
Ich werde also mal in Monogame rein schnuppern.

Ist dann das neue Programm eine eigene Entwicklungsumgebung oder wird es implementiert oder wie sieht das dann aus?

Werbeanzeige