Spiel programmieren anfangen

Leeki

Ensign
Registriert
Nov. 2014
Beiträge
178
Hi ,

ich wollte mich mal mit der Materie Spiele programmieren befassen. Deshalb wollte ich fragen wie ich am besten anfangen sollte ? Programmier Erfahrung habe ich in C# und Java und ich hätte Zugang zu Visual Studio ( kann man mit Visual Studio kleinere Spiele entwickeln wie zB Snake o.Ä. ? ) . Eine konkrete Vorstellung von der Art des Spieles habe ich noch nicht , aber am besten fände ich eine Art Jump'n Run Spiel wie Mario. Eignet sich Unity für solche eine Art Spiel und könnt ihr Unity empfehlen ? Wenn nicht nehme ich auch gerne andere Empfehlungen für Programme entgegen :P

Schon mal vielen Dank für die Antworten :)
 
Also Snake kannst du eigentlich mit allen Sprachen realisieren. Du brauchst halt nur ne IDE und dann gehts schon los. 2D ist da relativ einfach. Wie das ganze dann mit Texturen und "richtiger" Grafik geht weiß ich nicht, weil ich es nie probiert habe.

Oder womit du eventuell auch anfangen könntest ist ein Viereck und das darf sich nur im Spielfeld bwegen und nicht über bestimmte Linien drüber oder so, bis es im Ziel ist.
 
Mit Java lassen sich Jump'n'Runs ziemlich leicht umsetzen. Hier ist eine Video-Reihe, bei der ein simpler Platformer mit Java erstellt wird.
https://www.youtube.com/playlist?list=PL-2t7SM0vDfcIedoMIghzzgQqZq45jYGv

Wenn du dich aber gerne mal tiefgehender mit Spieleprogrammierung auseinandersetzen willst, bereit bist auch hunderte von Stunden zu investieren und dein Englisch gut ist wäre "Handmade Hero" eine Empfehlung. Dort geht es darum, ein Spiel "from Scratch", also von 0 an, zu programmieren. Es werden keine fertigen Bibliotheken benutzt sondern alles per Hand implementiert. Dort ist eindeutig der Weg das Ziel.
https://handmadehero.org/
Da du keine Erfahrung mit C hast wäre aber sinnvoll, die "Intro to C"-Videos vorher anzugucken.
https://hero.handmade.network/episodes
 
Leeki schrieb:
Programmier Erfahrung habe ich in C# und Java und ich hätte Zugang zu Visual Studio ( kann man mit Visual Studio kleinere Spiele entwickeln wie zB Snake o.Ä. ? )

Wenn du mit C# Erfahrung, und Zugang zu Visual Studio hast, wäre das XNA Game Studio wohl die naheliegendste Möglichkeit sich mit der Materie vertraut zu machen. Damit wurden schon einige gute Spiele gemacht. Wenn ich mich recht erinnere müsste z.B. Stardew Valley darauf basieren.

Das Studio ist koslenlos downloadbar und bietet die gewohnt gute MS-Doku auf MSDN-Niveau.
 
Schon mal vielen Dank für die schnellen Antworten :P Ich werde mir mal diese ganzen Empfehlungen genauer anschauen .
 
Hi,

du wirfst einiges durcheinander: "Spiele Programmierung" ist nicht zwingend das gleiche wie "Spiele Entwicklung". Kommt es dir denn auf die Programmierung an? Wenn nicht schau dir die SDKs der gängigen Engines (Unity, Cryengine, Unreal etc) an.

VG,
Mad
 
Tut mir leid wenn ich was durcheinander geworfen habe , mir geht es um die Programmierung.
 
e-Funktion schrieb:
Warum gerade C und nicht CPP?
Die genannte Videoreihe benutzt hauptsächlich C. Casey Muratori (der Macher der Reihe) ist kein Fan von objektiorientierter Programmierung und nutzt deshalb nur wenige Funktionen von C++. Die Anzahl der Programmierer, die Objektorientierung für einen Rückschritt halten, nimmt immer mehr zu. Hier ist ein recht informativer Vortrag (man sollte aber ein bisschen Ahnung vom programmieren haben) zu dem Thema
youtube.com/watch?v=rX0ItVEVjHc
 
Ich habe mir jetzt nicht den kompletten Beitrag angesehen und die Folien nur ein bisschen überflogen. Ich sehe aber grob worauf das abzielt. Ob DOD nun das universelle Mittel ist vermag ich nicht abschließend zu beurteilen und spielt hier wahrscheinlich auch gar keine Rolle, bin auch kein Hauptberuflicher Entwickler.

Aber es ist logisch, dass man mehr Performance Erhält wenn man alles rausschmeißt was die Rechenzeit erhöht. Wenn man eine konsistente Plattform wie die Playstation hat kann man sicherlich auch Teile in Assembler auslagern um es noch weiter zu optimieren. Irgendwann steht der Aufwand immer weniger im Verhältnis zum Nutzen. Pauschal zu Sagen "DOD generell über OOD" halte ich dann doch für etwas übertrieben, wenn auch gleich es in manchen Bereichen sinnvoll sein kann. Ist auch nicht verboten Teile des Projektes in performantere Libraries auszulagern wenn es sich lohnt.

Allein der Umstieg vom .net-Framework (C#) zu C(pp) bringt einen enormen Performance-Gewinn ;D
 
Raybeez schrieb:
Die Anzahl der Programmierer, die Objektorientierung für einen Rückschritt halten, nimmt immer mehr zu.

Ähhh ... watt?? :freak: Dass OOP exzessiv gehyped wurde und von vielen unberechtigt als Allheilmittel angepriesen wurde, lass ich ja nur durchgehen, aber Objektorientierung als Rückschritt (gegenüber was?) zu bezeichnen, wird mir dann doch ein bißchen zu wild.

OOP ist nicht für jedes Problem das passende Mittel, aber in vielen Fällen ist es definitiv ein guter Weg.
 
@ Raybeez
Er verwendet doch im Prinzip auch Objektorientierung bei seinem DoD ansatz. Ob man seine Objekte jetzt als Array of Structures im Speicher liegen hat oder sie zu einem einzigen größeren Objekt zusammenfasst, was dann die einstigen kleineren Objekte zerstückelt als Structure of Arrays beinhaltet, ist für die Objektorentierung zweitrangig. Solche Überlegungen lohnen sich aber in der Regel nur bei performancekritischen Anwendungen und dort auch nur bei den 10 \% des Codes die 90 \% der Laufzeit ausmachen und 90 \% des Speichers belegen. Den Rest kann man dann dort auch meist elegant durch Objektorientierung programmieren, ohne sich auch nur irgendwelche Gedanken über die Performance machen zu müssen.
 
Zuletzt bearbeitet:
Ich habe vor einem halben Jahr ne größere Videoserie gemacht wo ich Schritt für Schritt erkläre wie man einen 2D Platformer inkl. Physik-Engine in Java programmiert.
Da wird alles notwendige behandelt: Grafikdarstellung, Mathematik, Physik, Eingabe, etc.

Hier im Forum gibt es einen Thread dazu, finde den aber grad nicht, aber hier ist der direkt Link zum ersten Video:
https://www.youtube.com/watch?v=0FUuXQW9jq8

Nai schrieb:
@ Raybeez
Er verwendet doch im Prinzip auch Objektorientierung bei seinem DoD ansatz. Ob man seine Objekte jetzt als Array of Structures im Speicher liegen hat oder sie zu einem einzigen größeren Objekt zusammenfasst, was dann die einstigen kleineren Objekte zerstückelt als Structure of Arrays beinhaltet, ist für die Objektorentierung zweitrangig. Solche Überlegungen lohnen sich aber in der Regel nur bei performancekritischen Anwendungen und dort auch nur bei den 10 \% des Codes die 90 \% der Laufzeit ausmachen und 90 \% des Speichers belegen. Den Rest kann man dann dort auch meist elegant durch Objektorientierung programmieren, ohne sich auch nur irgendwelche Gedanken über die Performance machen zu müssen.

Ah Moment mal: 1000 Klassen mit Sprungtabellen, Virtuellen-Methoden, Vererbungsinformationen sind deutlich langsamer als reine 1000 Structs! Das mag mittlerweile nicht mehr so arg ins Gewicht fallen, da die stetig schneller werden aber der Overhead bleibt. Darum geht's Casey ja auch - er will keinen unnötigen Balast haben, weder unnötige Cycles noch mehr Speicher verbrauchen. Ebenfalls werden Instanzen einer Klasse immer im Heap abgelegt - auch wenn diese nur grad im Lokalen Scope benötigt werden!

Klar komplexe Vererbungssysteme zu programmieren ohne Klassen ist nicht ganz einfach aber mit "union" geht das auch mit structs ;-)
 
Finalspace schrieb:
Ah Moment mal: 1000 Klassen mit Sprungtabellen, Virtuellen-Methoden, Vererbungsinformationen sind deutlich langsamer als reine 1000 Structs!

Das ist eine vollkommen bedeutungslose Aussage, denn die 1000 Structs ohne Sprungtabellen, Virtuellen-Methoden, Vererbungsinformationen existieren ja nicht in einem Vakuum sondern zusammen mit dem Code, der Dinge mit diesen Structs tut. Du hast lediglich die Sprungtabellen, Virtuellen-Methoden, Vererbungsinformationen von den Structs selbst in den umgebenenden Code verlagert und in eine andere Form umgestaltet, sei es als if-else-Kaskade oder switch-case-Kaskade oder über anderweitig selbst gebaute Polymorphie-Mechanismen, und in den meisten Fällen dürfte der Compiler deine eigene Implementierung um Längen schlagen.
 
Ich denke mal, dass der Code dadurch deutlich hässlicher wird, ist auch nicht zu vernachlässigen. Und je hässlicher der Code, umso langsamer programmiert man im Endeffekt und umso weniger Zeit kann man dann am Schluss letztendlich für die optimierung aufwenden. Gutes Beispiel ist das Codebeispiel am Ende des Videos (https://youtu.be/rX0ItVEVjHc?t=1h8m9s ): Leicht verständlicher Code sieht anders aus . . . .
 
antred schrieb:
Das ist eine vollkommen bedeutungslose Aussage, denn die 1000 Structs ohne Sprungtabellen, Virtuellen-Methoden, Vererbungsinformationen existieren ja nicht in einem Vakuum sondern zusammen mit dem Code, der Dinge mit diesen Structs tut. Du hast lediglich die Sprungtabellen, Virtuellen-Methoden, Vererbungsinformationen von den Structs selbst in den umgebenenden Code verlagert und in eine andere Form umgestaltet, sei es als if-else-Kaskade oder switch-case-Kaskade oder über anderweitig selbst gebaute Polymorphie-Mechanismen, und in den meisten Fällen dürfte der Compiler deine eigene Implementierung um Längen schlagen.

Ja da muss ich tatsächlich zurückrudern nachdem ich nochmal drüber nachgedacht habe.
Structs sind identisch zu Klassen, aber mit dem Unterschied das alle Felder und Methoden public und bei Klassen private sind.
Performancetechnisch sind beide Identisch - auch unterstützen beide Virtuelle Funktionen, wo dann auch wieder die Sprungtabellen ins Spiel kommen und dann die Performance senken können. My bad: Hätte es besser wissen müssen...
 
Zuletzt bearbeitet:
Finalspace schrieb:
Structs sind identisch zu Klassen, aber mit dem Unterschied das alle Felder und Methoden public und bei Klassen private sind.
Ich werfe hier noch ein, dass Klassen in C++ nur keine simple Syntax haben, um private-Felder zu modifizieren. Wenn man es wirklich will, hält einen nichts auf, es trotzdem zu tun.
Und weiterhin, dass man das mit Strukturen in Form einer Forward-Declaration auch haben kann, wenn man gern möchte.

€: Habe dazu mal vor Ewigkeiten ein Beispielprogramm gebastelt, falls es jemanden interessiert. Programmiere normalerweise kein C++, deshalb seid nicht zu hart zu mir.
Code:
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <iostream>

#define RET_ERR     0
#define RET_OK      1

#define MAX_TRIES   10
#define CHANCE_DUPE 80

class sample {
    public:

    void change_peter(void) {
        peter = rand();

        if((peter % 100) < CHANCE_DUPE)
            hansi = peter;
    }

    int get_peter(void) {
        return peter;
    }

    private:
        int horst;
        int peter;
        int hansi;
};

char *findmember(sample *obj) {
    char *ptr = (char*)obj;
    char *candidate, *out;
    size_t n_candidates, offset;
    size_t tries = 0;
    int currval;

    std::cout << " Suche nach \"private\"-member..." << std::endl;
    do {
        std::cout << " Versuch " << tries + 1 << "/" << MAX_TRIES << std::endl;

        currval = obj->get_peter();
        std::cout << "  Wert: '" << currval << "'. Suche..." << std::endl;
        n_candidates = 0;

        for(offset = 0; offset < sizeof(*obj) - sizeof(int) + 1; offset++) {
            candidate = ptr + offset;
            if(!memcmp(candidate, &currval, sizeof(currval))) {
                out = candidate;
                n_candidates++;
                std::cout << "   Offsetkandidat: " << offset << std::endl;
            }
        }
        std::cout << "  Anzahl Kandidaten: " << n_candidates;

        tries++;
        if(n_candidates != 1) {
            std::cout << " :( " << std::endl;
            std::cout << "  Schreibberechtigte Methode aufrufen...";
            obj->change_peter();
        } else {
            std::cout << " :D";
        }
        std::cout << std::endl;
    } while((n_candidates != 1) && (tries < MAX_TRIES));

    if(n_candidates != 1)
        return NULL;

    return out;
}

int setprivate(sample *obj, int val) {
    char *ptr;

    if((ptr = findmember(obj)) == NULL)
        return RET_ERR;

    memcpy(ptr, &val, sizeof(val));
    return RET_OK;
}

int main(int argc, char **argv) {
    sample sample_obj;
    int newval;

    if(argc == 1)
        newval = 1234;
    else
        newval = atoi(argv[1]);

    srand(time(NULL));
    sample_obj.change_peter();

    std::cout << "Gewuenschter Wert: " << newval << std::endl;
    if(setprivate(&sample_obj, newval) == RET_OK)
        std::cout << " ERFOLG! Variable geaendert." << std::endl;
    else
        std::cout << " Aufgegeben. :(" << std::endl;

    std::cout << "Aktueller Wert: " << sample_obj.get_peter() << std::endl;

    return sample_obj.get_peter() == newval ? EXIT_SUCCESS : EXIT_FAILURE;
}
 
Zuletzt bearbeitet:
Zurück
Oben