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

1

09.06.2015, 10:50

[C++] Architektur um Skripting erweitern

Hi, ich möchte für mein Spiel die KI-Implementierung in Skripte auslagern. Um das ganze (was ich damit bewerkstelligen möchte) mal näher zu zeigen, habe ich mal ein minimales Beispiel gebaut:

game.hpp (in echt natürlich deutlich mehr als eine Header-File^^)

C-/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
#pragma once
#include <string>
#include <vector>

namespace game {

struct Object {
    std::string name, ai_script;
    int pos, velocity;
    
    Object(std::string const & name, int velocity);
};

struct Event {
    enum class Type {
        Move, Stop
    } type;
    
    std::string object_name;
};

// ----------------------------------------------------------------------------

class BaseSystem {
    protected:
        std::vector<Object*> objects;
    public:
        void addObject(Object& object);
};

class EventSystem {
    public:
        virtual void addEvent(Event const & event) = 0;
};

// ----------------------------------------------------------------------------

class PhysicsSystem: public BaseSystem {
    public:
        void update();
        Object const * queryByPos(int pos) const;
};

class GraphicsSystem: public BaseSystem,  {
    private:
        std::vector<Event> events;
    public:
        void render();
        void addEvent(Event const & event);
};

class AiSystem: public BaseSystem {
    private:
        PhysicsSystem const & physics;
    public:
        AiSystem(PhysicsSystem const & physics);
        void update();
};

}


game.cpp (in Echt natürlich deutlich mehr als eine cpp-File^^)

C-/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
#include <iostream>

#include "game.hpp"

namespace game {

Object::Object(std::string const & name, int velocity)
    : name{name}
    , ai_script{""}
    , pos{0}
    , velocity{velocity} {
}

// ----------------------------------------------------------------------------

void BaseSystem::addObject(Object& object) {
    objects.push_back(&object);
}

// ----------------------------------------------------------------------------

void PhysicsSystem::update() {
    for (auto ptr: objects) {
        ptr->pos += ptr->velocity;
    }
}

Object const * PhysicsSystem::queryByPos(int pos) const {
    // implementation is of course a dummy ^^
    for (auto ptr: objects) {
        if (ptr->pos == pos) {
            return ptr;
        }
    }
    return nullptr;
}

void GraphicsSystem::render() {
    for (auto& ev: events) {
        std::cout << "Object '" << ev.object_name << "' is playing '";
        if (ev.type == Event::Type::Move) {
            std::cout << "Move";
        } else {
            std::cout << "Stop";
        }
        std::cout << "' animation" << std::endl;
    }
    events.clear();
    
    for (auto ptr: objects) {
        std::cout << "Object '" << ptr->name << "'\t@ "
            << ptr->pos << std::endl;
    }
}

void GraphicsSystem::addEvent(Event const & event) {
    events.push_back(event);
}

AiSystem::AiSystem(PhysicsSystem const & physics)
    : physics{physics} {
}

void AiSystem::update() {
    for (auto ptr: objects) {
        if (ptr->ai_script.empty()) {
            continue;
        }
        /* trigger script to perform on this object and pass various args like:
            ` loaded_script.main(*ptr, physics, eventsys); `
        */
    }
}

}


main.cpp

C-/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
#include "game.hpp"

int main() {
    game::Object tom{"tom", 1}, carl{"carl", 2}, bob{"bob", 5};
    tom.ai_script = "example_ai.py";
    bob.ai_script = "example_ai.py";
    
    game::PhysicsSystem physics;
    physics.addObject(tom);
    physics.addObject(carl);
    physics.addObject(bob);
    
    game::GraphicsSystem graphics;
    graphics.addObject(tom);
    graphics.addObject(carl);
    graphics.addObject(bob);
    
    game::AiSystem ai{physics};
    ai.addObject(tom);
    ai.addObject(bob);
    
    // terminating loop just for demonstration
    for (auto i = 0; i < 100; ++i) {
        ai.update();
        physics.update();
        graphics.render();
    }
}


example_ai.py (ein KI-Skript)

Quellcode

1
2
3
4
5
6
7
8
9
10
# script needs some parts of the c++ code (classes, enums etc.)
# import game

def main(obj, physics, eventsys):
    """ Stops movement if other object was found - not an AI task but it's just for demonstration what I mean :P """
    target_pos = object.pos + object.velocity
    other = physics.queryByPos(target_pos)
    if other is not None:
        obj.velocity = 0
        eventsys.addEvent(game.Event(gameEvent.Type.Move, obj.name))


Dabei möchte ich jedem GameObject ein KI-Skript zuweisen, welches (wenn die KI mal wieder was machen soll) aufgerufen wird. Dabei benötige ich zum einen eine Schnittstelle in C++ um das Script auszuführen und eine weitere um vom Skript aus auf C++-Konstrukte zuzugreifen (Klassen, enums), z.B. um Events auszulösen auf die der C++-Code wieder reagieren soll.... Vielleicht stelle ich mir das alles auch nur zu einfach vor :D

Was könnt ihr mir empfehlen um das angestrebte realisieren zu können? Die Wahl der Skriptsprache ist dabei nebensächlich; Python ist hier nur ein Beispiel. Prinzipiell könnte ich auch Lua oder JavaScript nehmen. An dieser Stelle wäre ich für konkrete Implementierungen (d.h. wie könnte ich die auskommentierten Script-Calls / Imports im Script) realisieren.

LG Glocke

2

09.06.2015, 12:24

Schau dir mal Lua an, habe selber nie mit gearbeitet aber das was ich drüber gelesen habe könnte es was für dich sein.

Edit: Doofe kleine Handy Displays, Lua hast ja schon selber erwähn. Wie gesagt habe selber noch nie mit gearbeitet, darum kann ich nichts zur konkreten Implementierung sagen.
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

3

09.06.2015, 19:29

Wenn du auch die Anbindung Objektorientiert machen möchtest wäre auch noch angelscript (http://www.angelcode.com/angelscript/) zu nennen, das ist fast wie C++ und ich fand die Anbindung recht gut zu bedienen.

Julién

Alter Hase

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

4

09.06.2015, 20:46

Wenn du konkrete Implementierung suchst, dann suche nach diesen (Google ist dein Freund und Voyeur).
Aus eigener Erfahrung kann ich dir Python empfehlen, speziell mit Boost.Python.
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Werbeanzeige