Jump to content

C# kleines Spiel, bitte um Hilfe

Empfohlene Beiträge

Hallo zusammen,

um meine Note für das 2. Lehrjahr in SAEL noch zu heben sollte ich im Unterricht ein Projekt in Form eines Referats vorstellen. Dazu gehört der Code selbst und ein Klassen-UML.

Datum für den Vortrag: 06.07.2017

Zeit: N/A, Lehrer hat noch keine Zeitangabe gemacht.

Grundidee: Ein textbasiertes Abenteuerspiel. (Form-Anwendung)

Warum? Es war immer schon ein Vorhaben von mir freizeitlich ein Spiel zu programmieren und das wäre die Möglichkeit mich da mal tatsächlich reinzuhängen und eine Grundlage zu schaffen um an diesem Projekt auch nach der Präsentation weiter zu arbeiten. Dadurch das ich mich nicht mit Grafiken rumschlagen muss hoffe ich auch auf einen Lerneffekt was den Code betrifft.

Die Idee steht also, aber mir fehlt es noch an einem guten Grundgerüst und an der Umsetzung einiger Dinge.

Ich wiederhole nochmal das ich kein Anwendungsentwickler bin und meine Programme normalerweise jeden AE dazu bringen die Hände über dem Kopf zusammen zu schlagen. Quasi sämtlichen Code untereinander schreiben, keine extra Klassen, etc. Hinzu kommt das ich eher seltener außerhalb des Unterrichts programmiere. Das möchte ich hiermit wieder ändern. Was ich also sagen möchte: Habt bitte Nachsicht und kommt mir nicht mit tausend neuen Dingen, nur weil sie moderner sind. Außerdem geht es rein um den Code, ich mache mir keine Gedanken über jegliche Texte/Story oder sonst etwas.

Die Idee wie sie in meinem Kopf geistert (absolut nur ein Konzept):

Form: Einen Lebensbalken für den Charakter, eine Level-anzeige, eine Erfahrungs-anzeige, eine Geld/Gold-anzeige, eine Anzeige für die Spiel-Uhrzeit, eine Anzeige für die Spiel-Tage, natürlich ein großes Textfeld in dem die Ausgabe von Text geschieht und zuguterletzt einige Buttons die sich verändern, je nach Situation (ausgrauen, ganz verschwinden, ersetzt werden,...)

Ablauf des Spiels: (für das Verständnis)

- Story-Text-Ausgabe, Namensabfrage

- Spieler bekommt 4 Buttons angeboten: Warten (1 Spielstunde verstreicht, Spieler bekommt Leben gutgeschrieben); Erkunden (Spieler wird die erste 'Gegend' finden); Gegenden (vorerst ergraut, sollte nach der ersten Erkundung freigeschaltet werden); schlafen (wird erst nach 21 Uhr Spiel-Uhrzeit als einzige Option zur Verfügung gestellt und erhöht den SPiel-Tag um 1)
- Beim wählen von "Gegenden" (nach der Erkundung) werden neue Buttons angezeigt: 'zurück' und "Wald" (sollte die erste gegend sein)
- Beim wählen von "Wald" wird random eines von 5 Ereignissen gewählt: stolpern (minimaler Lebensabzug); keine besonderen Ereignisse; Spieler wird von einem Tier angegriffen; ?; ? (hier überlege ich mir noch irgendwas). Bei jeder Erkundung einer Gegend (Ereignis) verstreicht eine Spielstunden
- Der Kampf gegen das Tier: Die Buttons verändern sich wieder: Angriff; Flucht (führt mit gewisser Wahrscheinlichkeit zurück zu "gegenden". Der Kampf ist rundenbasiert.
Da mag jetzt noch einiges fehlen, gerade die SPiel-Tage haben noch keine Funktion, die würde ich aber gerne auch noch nicht einbeziehen, das wird dann etwas für den weiteren Ausbau des Spiels, je nachdem wie weit ich komme.

Code (soweit ich jetzt schon denken kann)
Klassen (Eigenschaften):

static Spieler (Name, momentanes Leben, maximales Leben, Angriffkraft, Level, momentane Erfahrungspunkt, benötigte Erfahrungspunkte, Gold)

Menüs (ID/Name, benötigte Buttons)

Gegend (id/name, mögliche Ereignisse)

Gegner/Monster (id/name, level, angriffskraft, maximales leben, momentanes leben)

???

 

Wo ich jetzt schon Schwierigkeiten sehe:

- Die Buttons die sich verändern sollen, ich weiß noch nicht genau wie ich das bewerkstelligen werde, ich glaube aber mit etwas experimentieren und google würde ich da was hinzaubern

- Die Logik (Ablauf, kampfsystem, permanente abfragen), ich weiß nicht ob das in die Main soll oder ob ich viel zu wenig Klassen habe und das ausgelagert werden sollte.

 

Ich würde mich über Anregungen, Ideen, VOrschläge oder Verbesserungen freuen, ich werde mich vermutlich direkt schonmal an den Aufbau der Oberfläche machen und hoffe dieses Wochenende schonmal ein Grundgerüst für die Klassen, Eigenschaften und Methoden zu bekommen.

Vielen Dank schonmal

 

Tician

bearbeitet von Tician

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Bevor du dich an ein solches Projekt setzt, solltest du das Konzept der OOP verinnerlicht haben. Alleine schon anhand deiner Fragen kann ich erkennen, dass du ansonsten schnell an deine Grenzen stößt.
 

  • Die Buttons sollten sich nicht verändern, hier bietet sich eine weitere Form mit neuen Knöpfen an.
  • Die Logik sollte nicht in die Main, sondern in den Controller - wenn du dich an das gute, alte MVC-Pattern hältst, welches ich dir empfehle. Hierfür bieten sich dann auch einzelne Klassen an. Dinge, die voneinander unabhängig sind, in deinem Falle "Ablauf" und "Kampsystem" wie du es dir vorgestellt hast, würden einzelne Klassen bilden.
  • Wie kommst du darauf, dass das Spielerobjekt statisch sein soll? Dadurch könntest du es nicht instanziieren, was sich mehr als nur anbietet.
  • Gegner/Monster könntest du über eine abstrakte Klasse abbilden (Monster) und davon dann einige Subklassen bilden, wie Spinne/Wolf o.Ä.

 

Das sind Punkte, die mir gerade ins Auge springen. Unabhängig davon, würde ich dir erstmal empfehlen einfachere Dinge, wie z.B. eine simplere Anwendung im MVC abzubilden. Dafür bietet Microsoft, in diesem Beispiel geht es um eine Filmbibliothek, (da du ja schätzungsweise in .Net [Forms] arbeitest) ein Tutorial an Einführung MVC (ASP.Net Web application)

bearbeitet von Gottlike

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Ich sehe das ähnlich, wie @Gottlike. Dein Kenntnisstand ist noch nicht so weit, um so ein Projekt anzugehen. Ich will nicht zu Nahe treten aber dir ist OOP offenbar immer noch nicht so wirklich klar. Das fängt schon, wie gesagt, mit der statischen Klasse für den Spieler an. Wieso soll sie statisch sein? Das macht überhaupt keinen Sinn. Statische Klassen machen nur in wenigen Situationen wirklich Sinn. In der Praxis werden sie aber oft dann verwendet, wenn der Entwickler gar nicht weiß, was er eigentlich tut. 

Das nächste ist, dass dir gar nicht klar ist, wie man Programmlogik von der Oberfläche trennt. Die Main-Methode einer klassichen WinForms-Anwendung besteht lediglich nur aus drei Zeilen Code:

static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
}

Was du noch in die Main()-Methode reinkloppen willst, erschließt sich mir erst mal nicht. Ein erfahrener Entwickler wird mit Sicherheit diese Methode noch erweitern, z.B. mit der Initialisierung eines IoC-Containers oder sonstigen Frameworks aber das sind Techniken, mit denen du mit deinem Wissensstand noch nichts anfangen kannst. Ich vermute auch mal, dass dir die ganzen Designpatterns nichts sagen.

Wenn man dein Beitrag auch durchliest, machst du dir viel mehr Gedanken, um die Oberfläche, anstatt um die Architektur der Software, daher ist das Ziel noch viel zu hochgesteckt. Fange mit Konsolenanwendungen an, um überhaupt OOP zu verstehen und um ein Gefühl dafür zu bekommen. Eine Oberfläche ist eigentlich nur ein schmuckes Beiwerk für eine Software. 

Ich persönlich würde vielleicht vorschlagen, eine API für Schach zu entwerfen. Ohne Oberfläche. Also überlegen, welche Datenstruktur ein Schachbrett und die Figuren haben könnten und dann noch Logiken, die ermitteln, welche Figur welchen Zug machen kann. Testen kann man das Ganze ja auch mit Unittests. Eine grafische Oberfläche muss ja nicht immer eine gute Note bedeuten aber keine Ahnung, ob das nicht schon zu schwer ist. Eine einfachere Form wäre Dame oder noch einfacher: Tic-Tac-Toe.

 

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Vielen Dank für eure Ideen und eure Meinungen. Ich bin vermutlich etwas starrköpfig, das war natürlich nicht das was ich hören wollte und vielleicht kommt noch der Punkt an dem ich vollkommen verloren bin, aber bis es soweit ist würde ich das gerne durchziehen. Dementsprechend habe ich das Wochenende über auch schon etwas Code produziert, würde mich aber freuen wenn ihr mir jetzt trotz allem bei einem Problem auf die Sprünge helfen könntet. Mein Projekt besteht aus zahlreichen Klassen, deren Eigenschaften und diese Eigenschaften im Konstruktor vereinigt.

Dann gibt es da noch meine World-Klasse, diese ist statisch und in der werden sämtliche Objekte angelegt. Die World ist noch weit davon entfernt fertig zu sein, aber hier renne ich noch gegen ein Problem.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BasicTextgame
{
    public static class World
    {
        //Lists
        public static readonly List<Monster> monsters = new List<Monster>();
        public static readonly List<Location> locations = new List<Location>();
        public static readonly List<Controls> controls = new List<Controls>();

        static int time = 7;
        static int day = 1;

        //Monster
        public const int monster_id_wolf = 1;
        public const int monster_id_bee = 2;

        //Locations
        public const int location_id_home = 1;
        public const int location_id_forest = 2;

        static World()
        {
            PopulateMonsters();
            CreateControls();
            PopulateLocations();
            
        }

        public static int GetNextTime()
        {
            time += 1;
            return time;
        }

        public static int GetNextDay()
        {
            day += 1;
            return day;
        }

        private static void PopulateMonsters()
        {
            Monster wolf = new Monster(monster_id_wolf, "Wolf", 10, 10, 1, 10, 2, 1);
            Monster bee = new Monster(monster_id_bee, "Bee", 1, 1, 1, 1, 1, 1);

            monsters.Add(wolf);
            monsters.Add(bee);
        }

        private static void PopulateLocations()
        {
            //Location forest = new Location(location_id_forest, "Forest", "A normal forest", );
            //Location home = new Location(location_id_home, "Home", "This is your home", );

            //locations.Add(home);
            //locations.Add(forest);
        }

        private static void CreateControls()
        {
            //????
        }
    }
}

Bisher haben alle meine Klassen einzelne Eigenschaften die auch nur ein mal vorkommen, bisher kein Problem. "Controls" sollte ein Panel (erbt von Panel) mit Buttons sein das an die Location gebunden ist (deswegen fehlt bei den Locations noch der letzte Wert in der Klammer).

Ein Panel sieht zum Beispiel so aus:

		public Panel main		

		Button explore = new Button();
            explore.Location = new Point(3, 3);
            explore.Size = new Size(75, 23);
            explore.Text = "Explore";
            explore.UseVisualStyleBackColor = true;

            Button wait = new Button();
            wait.Location = new System.Drawing.Point(84, 3);
            wait.Size = new System.Drawing.Size(75, 23);
            wait.Text = "Wait";
            wait.UseVisualStyleBackColor = true;

            Button locations = new Button();
            locations.Location = new System.Drawing.Point(165, 3);
            locations.Size = new System.Drawing.Size(75, 23);
            locations.Text = "Locations";
            locations.UseVisualStyleBackColor = true;
            locations.Enabled = false;

            Button sleep = new Button();
            sleep.Location = new System.Drawing.Point(246, 3);
            sleep.Name = "button4";
            sleep.Size = new System.Drawing.Size(75, 23);
            sleep.TabIndex = 3;
            sleep.Text = "button4";
            sleep.UseVisualStyleBackColor = true;
            sleep.Enabled = false;

            main = new Panel();
            main.Location = new Point(185, 279);
            main.Name = "panel1";
            main.Size = new Size(377, 75);
            main.TabIndex = 22;
            main.Controls.Add(explore);
            main.Controls.Add(wait);
            main.Controls.Add(locations);
            main.Controls.Add(sleep);

Jetzt weiß ich keinen eleganten Weg um ein Panel zu bilden weil ein Panel unterschiedlich viele buttons hat. Mein Weg wäre eine Klasse zu machen die von 'Button' erbt und dann wieder in der World (?) Buttons zu erstellen und die dann dem Panel zuweisen. Geht es auch einfacher als eine rießen Ansammlung von Buttons zu haben und sie dann erst zu gruppieren?

 

PS: Player ist nicht statisch^^ Ich dachte an die Erklärung unseres Lehrers der gemeint hat das man bei einem "Objekt" das es nur ein mal gibt eine statische Klasse nehmen könnte.

bearbeitet von Tician

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Mal das, was mir so auffällt:

  • Es gibt kaum Gründe, eine Klasse statisch zu machen (es gibt welche, die sind für dich im Augenblick aber noch irrelevant). Daher solltest du standardmäßig mit normalen Klassen arbeiten.
  • Es ist in .NET verpönt, public Felder zu nutzen. Stattdessen werden Properties genutzt; das sieht dann in deinem Fall bspw. so aus:
    private List<Monster> monsters = new List<Monster>();
    public List<Monster> Monsters { get { return monsters; } private set { monsters = value; } }

    Hier sind damit gleich mehrere Sachen erreicht: Zum einen kapselst du deine interne Datenstruktur innerhalb deines Objekts (da kann man später noch weiter gehen, indem die Property bspw. keine List<Monster> ist, sondern vllt. ein IEnumerable<Monster> - je nachdem, was du damit vorhast). Zum anderen erlaubst du das Setzen der Liste nur noch aus dem Objekt heraus, nicht mehr von außen. (Die Liste ist allerdings noch komplett änderbar. Das kannst du dir später mal überlegen, ob du das wirklich willst).

  • Dieses hier

    //Monster
    public const int monster_id_wolf = 1;
    public const int monster_id_bee = 2;

    hat einerseits wieder das, was ich oben schrieb in Bezug auf öffentliche Felder. Zum anderen stellt sich mir hier die Frage, wieso die überhaupt public sind? Auch das const ist fragwürdig. Das wird in deinem jetzigen Projekt höchstwahrscheinlich keine Probleme machen, aber da solltest du dich nochmal schlau machen, was das wirklich bedeutet und was die Auswirkungen sind. Ich frage mich, wozu du diese IDs überhaupt brauchst? Wäre es nicht vielleicht sinnvoll, Wolf und Bee als eigene Klassen, die von Monster erben, zu implementieren? Dann könntest du auch solche Sachen machen wie 

    Monster b = new Bee(...);
    b.Attacks(player);  // Ausgabe so etwas wie "Biene sticht Spieler";
    
    Monster w = new Wolf(...);
    w.Attacks(player); // Ausgabe hier dann "Wolf beißt Spieler";

    Du könntest also deinen Monstern unterschiedliche Verhalten spendieren.
    Wenn du so weit nicht gehen möchtest, würde ich dir dennoch empfehlen, die IDs nicht als int zu halten, sondern enums daraus zu machen (auch, wenn das für den vorliegenden Fall nicht wirklich die perfekte Lösung ist):

    public enum MonsterType
    {
    	Unknown,
    	Bee,
    	Wolf
    }

    Damit hast du Typensicherheit und mischst keine Werte (mglw. aus Versehen).

  • Zu deinen GetXXX-Methoden:

    public static int GetNextTime()
    {
        time += 1;
        return time;
    }

    Gemeinhin wird von einer Get-Methode erwartet, dass sie keine Werte ändert. Ich würde hier also einen passenderen Namen verwenden, wie bspw. Wait(). Gleiches gilt für GetNextDay().

  • Zu der Problematik Button<->Location: WinForms ist in der Hinsicht einfach ein wenig unhandlich, wenn man die Oberfläche dynamisch umgestalten möchte. Es geht, ist aber (meiner Erfahrung nach) immer mit viel Schreibarbeit verbunden. Spontan würde ich das ähnlich angehen wie die Monster: Mach aus deinen Locations Unterklassen (z.B. Wald), die eine Methode 

    public Control MakeLocationControl();

    haben. Diese kannst du dann von deiner World-Klasse her aufrufen, wenn die Location sich wechselt und das erzeugte Control in das Panel schmeißen. Das kannst du auch als UserControl machen, dann musst du den Code zumindest dafür nicht selber schreiben, sondern kannst den Designer nutzen.

Grundsätzlich ist es nicht trivial, ein Spiel zu gestalten, weil man sich ganz schnell in Sackgassen manövrieren kann, wenn man das ganze nicht sauber entwirft. Allein zu dem Problem, wie man Angriffe geschickt modelliert gibt's Dutzende Artikel.

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

@arlegermi Danke für deine vielen Verbesserungsvorschläge! Ich würde das Programm aber gerne erstmal zum laufen bringen und die Verbesserungen hinterher umsetzen. Ich wollte keine Unterrichts-fremden Dinge einsetzen (IEnumerate) weil ich sie nicht erklären kann. Was ich jetzt alles gemacht habe verstehe ich noch und kann es auch nachvollziehen.

Mein Problem mit dem Control hast du leider nicht verstanden. Ich habe kein Problem ein Control (Panel) an eine Location zu binden, es geht eher um die reine Erstellung des Panels da es mehrere Buttons hat, aber wie du sagtest wird es wohl einfach mehr Schreibarbeit. Ich werde es mal so anfangen wie gehabt das ich einfach eine Klasse nur für Buttons mache, hinterher kann man ja immer noch ändern.

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen
vor 1 Stunde schrieb Tician:

Jetzt weiß ich keinen eleganten Weg um ein Panel zu bilden weil ein Panel unterschiedlich viele buttons hat. Mein Weg wäre eine Klasse zu machen die von 'Button' erbt und dann wieder in der World (?) Buttons zu erstellen und die dann dem Panel zuweisen. Geht es auch einfacher als eine rießen Ansammlung von Buttons zu haben und sie dann erst zu gruppieren?

Ich verstehe dein Problem nicht ganz und warum du jeweils noch von bereits vorhandenen Klassen neue erstellen möchtest, die von diesen erben. Was soll diese denn von der ursprünglichen Klasse unterscheiden? Für unterschiedliche Eigenschaftswerten kannst du ja einfach entsprechend Konstruktoren bauen.

Aber du kannst die Buttons ja auch, wie @arlegermi es schon für die Monster vorgeschlagen hat, als Liste anlegen und ihnen erst einmal dann allgemeingültige Werte zuweisen und danach eben noch jedem einzelnen die speziellen Properties. Da wirst du wohl so oder so nicht drum herum kommen.

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen
vor 1 Minute schrieb Tician:

Was ich jetzt alles gemacht habe verstehe ich noch und kann es auch nachvollziehen.

Das ist das wichtigste :) Sorry, falls ich zuviel anderen Kram geschrieben habe.

Nochmal zu dem Problem mit den Buttons: Da kann man natürlich ein wenig Schreibarbeit sparen. Wenn du deine Buttons regelmäßig anordnest (bspw. in einer Gitter-Struktur), dann lässt sich das durch Schleifen wunderbar kürzen:

// nur so weggeschrieben, Details fehlen
string[] buttonTexte;
Action[] buttonActions;
for(int i = 0; i < buttons.Length; i++)
{
 	var button = new Button();
  	button.Text = buttonTexte[i];
  	button.Clicked += buttonActions[i];
  	button.Location = new Location(GetX(i), GetY(i));
  	panel.Children.Add(button);
}

Dann musst du das Styling und die Positionierung nur 1x schreiben und dich nicht für jeden Button wiederholen.

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

@arlegermiDas ist perfekt! Ich muss das gerade in meinem Kopf nur zusammen bauen (und es sieht gerade so aus als wäre es für mich dann etwas anders als du es vor hattest, aber ich muss mal schauen ob das was ich da fabriziere später noch passt und Sinn macht). Aber der Gedankenstoß ist gut!

Ich habe keine Button-Klasse gemacht, das wäre tatsächlich Schwachsinn, die Unterscheiden sich nicht von normalen Buttons.

Aber: Da von den Controls (Panel) ein paar der EIgenschaften immer gleich sind habe ich sie gleich in der Controls-Klasse festgelegt.

Wieviel Sinn macht das hier? (in meinem Kopf viel :P)  :

public class Controls : Panel
    {  
        public int id { get; set; }
        
        public Controls(int id, string name)
        {
            this.id = id;
            this.Name = name;

            Location = new Point(185, 279);
            Size = new Size(377, 75);
        }
        
        public void AddButton(Button button, string text, bool enabled)
        {
            button.Size = new Size(75, 23);
            button.Text = text;
            button.UseVisualStyleBackColor = true;
            button.Enabled = enabled;

            int ccount = Controls.Count; //numer of buttons
            int x = ccount * 81 + 3;
            button.Location = new Point(x, 3);

            Controls.Add(button);
        }                 
    }

Ich weiß die Buttons machen noch nichts, aber dazu werde ich später bei der Logik bzw dem Programmablauf noch kommen, vermutlich muss ich dann nochmal einiges ändern.

bearbeitet von Tician

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

So, das ist der momentane Code: https://pastebin.com/3krETNbs

Das Player-Objekt ist noch ein Problem weil es ja viele der Elemente auf der Form braucht. Ich brauche jetzt noch die Logik/den Ablauf, aber dazu brauche ich ebenfalls die Form um meine Panels darauf zu aktivieren und zu deaktivieren, deswegen bin ich mir unsicher wo ich sie hinschreibe, ich möchte ungern alles in die Form1-Klasse rein klopfen.

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen
vor 16 Minuten schrieb Tician:

Das Player-Objekt ist noch ein Problem weil es ja viele der Elemente auf der Form braucht

Wieso braucht das Player-Objekt Elemente des Formulars? Das Player-Objekt sollte von den Buttons überhaupt nichts wissen. Das sollte so laufen, dass der ("echte") Spieler einen Button auf dem Formular anklickt und das Programm dann dem Spieler-Objekt sagt, was es tun soll. Wenn du bspw. einen Button "Wolf angreifen" hast, dann muss die Player-Instanz davon nichts wissen. Eine Möglichkeit wäre es, einfach eine Methode in Player aufzurufen à la

public void Attack(Monster m)
{
	m.curHp -= this.attack;
	if(m.curHp <= 0)
	{
		m.Die();              
	}
}

(das ist jetzt extrem verkürzt, aber das Prinzip sollte klar sein)

Dein Spiel ist doch quasi rundenbasiert. Zu Beginn jeder Runde entscheidet das Programm, welche Aktionen dem Spieler gerade erlaubt sind und zeigt diese an / aktiviert sie. Zusätzlich zeigst du noch die aktuellen Lebens- / Erfahrungspunkte, Gold, usw. an. Für all das muss das Player-Objekt nichts vom einem Formular oder einem Panel wissen (genaugenommen solltest du in der Player-Klasse keinen Verweis auf System.Windows.Forms haben, aber das kann man später mal angehen).

bearbeitet von arlegermi

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen
vor einer Stunde schrieb arlegermi:

Wieso braucht das Player-Objekt Elemente des Formulars?

Ich hatte mich falsch ausgedrückt. Eigentlich ist es andersrum

1. Die Elemente auf der Form brauchen Zugriff auf den Player, weil die Label und Leisten die HP, Exp,... des Spielers repräsentieren.

2. Die "Controls" braucht Zugriff auf die Form da die Panels schließlich auf der Form angezeigt werden sollen. Die Controls sind wiederum Bestandteil der Locations.

Und das ganze jetzt noch mit der Logik unter einen Hut zu bringen fällt mir schwer, weil mir die Idee fehlt.

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Jetzt habe ich doch wieder 2 Dinge.

Es geht um folgende Abschnitte:

	public partial class Form1 : Form
    {
        private void InitializeButtons()
        {
            World.LocationById(location_id_home).control.Controls[0].Click += homeExplore;
        }

        private void homeExplore(object sender, EventArgs e)
        {
            if (_player.discoveredForest == false)
            {
                _player.discoveredForest = true;
                richTextBox1.Text = "You walk around and found a forest!";
                World.LocationById(location_id_home).control.Controls[2].Enabled = true;
            }
            else
            {
                richTextBox1.Text = "There is nothing more to find here...";
            }
        }
	}


    public static class World
    {
        public static readonly List<Location> locationsList = new List<Location>();
        public const int location_id_home = 1;


        private static void PopulateLocations()
        {
            Location home = new Location(location_id_home, "Home", "This is your home", ControlById(control_id_home));
            locationsList.Add(home);
        }

        public static Location LocationById(int id)
        {
            foreach(Location location in locationsList)
            {
                if(location.id == id)
                {
                    return location;
                }
            }
            return null;
        }
    }

1. Problem ist, dass mir irgendwas fehlt wenn ich rein schriftlich ein click-event für meinen Button schreiben möchte, ich muss immer die Tab-Taste drücken, das Event umbenennen und dann schreit mein Visual Studio nach einem Fehler und ich es benennt mein Event um. Das ist aber das kleinere Problem.

2. In meiner Form1 schreit es das es den Namen "location_id_home" nicht kennt, dabei ist das doch eine public variable oder habe ich das jetzt missverstanden? Die Funktion "LocationByID" kann ich ja auch aufrufen.

Hat sich erledigt, ich sollte auch ein "World." davior schreiben^^

 

Wäre toll wenn mir jemand helfen könnte ohne mein Programm komplett auseinander zu nehmen, das dürft ihr noch früh genug^^

bearbeitet von Tician

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Wenn du sowas schreibst:

theButton.Clicked +=

dann sollte Visual Studio dir per Tabulator den Rest ergänzen:

theButton.Clicked += theButton_Clicked;

// weiter unten (so ähnlich):

private void theButton_Clicked(object sender, EventArgs e)
{
  
}

Wenn du jetzt den Namen hinter ".Clicked +=" änderst, dann musst du auch den Namen der Methode ändern, die erzeugt wurde.

Alternativ kannst du das auch über den Designer machen, wie @KeeperOfCoffee das geschrieben hat.

bearbeitet von arlegermi

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

@KeeperOfCoffee Es gibt kein Eigenschaftsfenster, diese Buttons werden alle rein über Code erzeugt, nix mit klicken^^

@arlegermi Das wusste ich, aber sobald ich diese Namen änder erscheint oben rechts ein Fenster in dem Visual Studio mir sagt "Form1_Click umbenennen. 2 Referenzen in 1 Datei gefunden." Alles was ich machen kann ist auf "Übernehmen" zu klicken und damit hat es sich. Trotzdem wunder ich mich natürlich warum das überhaupt kommt und ob es eine Eigenschaft von Button gibt die ich vielleicht umbenennen muss.

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Nächstes Problem, ihr seid super hilfreich!

Folgende Zeilen:

    public static class World
        private static void CreateControls()
        {
            Controls overview = new Controls(control_id_overview, "overview");
            Button back = new Button();
            overview.AddButton(back, "Back", true, true);
            foreach(Places place in placesList)
            {
                string name = place.name;
                Button button = new Button();
                overview.AddButton(button, name, true, false);
            }
            controlsList.Add(overview);
        }


    public class Controls : Panel
        public int id { get; set; }
        
        public Controls(int id, string name)
        {
            this.id = id;
            this.Name = name;

            Location = new Point(185, 279);
            Size = new Size(377, 75);
        }
        
        public void AddButton(Button button, string text, bool enabled, bool visible)
        {
            button.Size = new Size(75, 23);
            button.Text = text;
            button.UseVisualStyleBackColor = true;
            button.Enabled = enabled;
            button.Visible = visible;

            int ccount = Controls.Count; //numer of buttons
            int x = ccount * 81 + 3;
            button.Location = new Point(x, 3);

            Controls.Add(button);

 

Die Buttons die "direkt" als Controls zum Panel dazu geaddet werden funktionieren einwandfrei.

Die Buttons die durch die foreach-schleife auftauchen sollten tun es nicht (ja, auch wenn ich sie sichtbar mache). Ich weiß nicht wie ich herausfinden kann was fehlt oder warum die nicht angelegt werden weil ich keinen Punkt im Programm habe an dem ich pausieren und den Code verfolgen kann. Ich kann nur allgemein pausieren und sehen das mein overview-Panel statt 2 Controls (back-button + ein place) nur den back-Button hat, also nur 1 Control. Seht ihr einen Fehler?

bearbeitet von Tician

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Ja, aus der Liste habe ich ausgelesen das mein Panel nur 1 Control hat^^

Durch den Aufruf meiner Methode "CreateControls" sollte ja auch die foreach schleife ausgeführt werden oder nicht?

Ich habe die World-Klasse mal angehängt.

World.cs

bearbeitet von Tician

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Auweia.

Da ist so ziemlich alles falsch, was man nur falschmachen kann. Ich komme erst am Wochenende dazu, etwas längeres zu schreiben aber man sieht schon deutlich, dass dies für dich einige Nummern zu groß ist. Sorry, aber fange mit was kleinerem an. Ehrlich, du machst dir keine Freude damit.

bearbeitet von Whiz-zarD

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Tician ist doch FISI. Dachte sie programmiert nur in der Schule mit C#. Darum verstehe ich auch nicht, warum sie sich mit einem kleinen Schulprojekt so viel aufhalst.

Aber was mir auffällt, ohne Ahnung von den Windows Form Kram zu haben: Müsstest du nicht noch wesentlich mehr Eigenschaften der Buttons festlegen, bevor du sie auf ein Panel packst? Sie haben z.B. alle keinen eindeutigen Namen.

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.


Fachinformatiker.de, 2019 SE Internet Services

fidelogo_small.png

if_icon-6-mail-envelope-closed_314900.pnSchicken Sie uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App


Get it on Google Play

Kontakt

Hier werben?
Oder senden Sie eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...

Wichtige Information

Fachinformatiker.de verwendet Cookies. Mehr dazu in unserer Datenschutzerklärung