How do I represent a world and dynamic objects in a C++ console game? [closed]

StackOverflow https://stackoverflow.com/questions/23652136

  •  22-07-2023
  •  | 
  •  

Frage

I'd appreciate some help with a small project of mine. It's supposed to be a console game, using elements from roguelikes, RPGs, sandboxes and survival games.

I have attempted about three times so far to get a working architecture. Each time, I hit problems I couldn't solve without hacking my way around it...

I already looked at numerous blogs and tutorials for this, but none of them fit my purpose exactly.

1) http://trystans.blogspot.co.at/2011/08/roguelike-tutorial-01-java-eclipse.html
2) http://www.kathekonta.com/rlguide/index.html

I have already followed Trystan's blog - who uses Java - and recreated his design in Java and AS3.
However, I wasn't quite content with the way he linked the classes together. Commands like World.dig() - To me, it makes more sense to call Player.dig() - or the map representation as a 3d(!) array made me believe that there must be a better way to do this.

The second link I posted is coded in C++, however, there is only one central map. My goal is to be able to have multiple maps, which I can enter with characters, etc.

I will post the code of my newest attempt below. It doesn't feature any movement or interaction at all, since I want to get the design right from the beginning, not failing after hours spent into the project (which I already encountered way too often).

main.cpp:

# include <iostream>

# include "World.h"
# include "Entity.h"

using namespace std;

int main(){

    int testFloor[] = {
        0, 0, 0, 0, 0, 
        0, 1, 1, 1, 0, 
        0, 1, 0, 0, 0, 
        0, 1, 1, 1, 0,
        0, 0, 0, 0, 0
    };

    World world(testFloor, 5, 5);

    //Creating an entity at the top left corner 
    Entity nine(9, 0);
    world.addEntity(nine);

    //Draw the entire world
    world.draw(0,0,5,5); 

    system("PAUSE");
    return 0;
}

World.h:

# ifndef WORLD_H
# define WORLD_H

# include <vector>

# include "Entity.h"

using namespace std;

class World {
private:
    int* _floor;
    int _width;
    int _height;

    vector<Entity> _entities;

public:
    World(int* floor, int width, int height) :
        _floor(floor), _width(width), _height(height){}

    /*Pushes an Entity to the _entities-vector*/
    void addEntity(Entity e){
        _entities.push_back(e);
    }

    /*Displays the floor at a position, or the glyph of an entity, if applicable*/
    //This "glyph" is just a number here, similar to the contents of the _floor array
    int glyph(int ID){
        int out = _floor[ID];
        for(Entity e : _entities){
            if(e.pos() == ID){
                out = e.glyph();
                break;
            }
        }
        return out;
    }

    //Prints the World as seen from "above" - entities will cover the floor
    void draw(int left, int top, int width, int height){
        system("cls");

        int ID;

        for(int y = 0; y < height; y++){
            for(int x = 0; x < width; x++){
                ID = (x+left)+(y+top)*width;
                cout << glyph(ID);
            }
            cout << endl;
        }
    }
};

# endif

Entity.h:

# ifndef ENTITY_H
# define ENTITY_H

class Entity{
private:
    int _glyph; //Will be a char later, integer for now, since the glyph function returns
                //an int for simplicity
    int _pos;

public:
    Entity(int glyph, int pos) : _glyph(glyph), _pos(pos) {}

    int glyph(){return _glyph;}
    int pos(){return _pos;}
};

# endif

The code compiles and works. A new Entity is spawned at the top left, represented by a "9", the map is drawn as expected and all... but I'm seeing problems even right now.

1) As I create a new Entity, I need to give it the ID (Worldposition) to spawn at - however it has no clue about its actual position in the world.

2) Whenever the Entity would move, it would need a reference to the map it is on, in order to know, where it's going.

To solve these problems, it would probably be beneficial to store a reference to the world inside the Entity. However, I want to be able to perform a command like World.update(), which automatically updates all the Entities, giving them the opportunity to move, attack, open doors, build barricades, ... The world would then iterate through all the entities, calling their respective update functions.

I found out from a previous attempt, that it causes problems to store a reference to a world in the entity class, and storing an array/vector of entities inside the world class.

So here are my actual questions:

- How can I design my classes in order to have a meaningful relationship between Entities and the World(s)?
- Where do I put my references - directly into function calls, maybe (that's going to cost performance, I guess)?

Edit: Please note, that I'm not expecting code samples, I rather want to write the code myself. What would help me most would be hints such as which class should hold which variables.

Thank you all for your time!

War es hilfreich?

Lösung

1) If I understand your question right, in order to find your 2d position on the map from your 1d coordinate, you can use something like the following:

Point Entity::pos2D(World& world) const {
    int y = _pos / world.width();
    int x = _pos % world.width();
    return Point(x, y);
}

Assuming you have a Point class to aggregate x and y. Also adding width() and height() accessor functions to the World object here.

You may fnd, however that it is better to store a 2d position in the first place - calculating the 1d position from it would involve a multiply instead of a divide.

2) You could pass in a reference to the world in the various entity manipulation member functions. e.g.

Entity::update(World& world) {
   // do some stuff
}
Entity::move(World& world) {
   // do some stuff
}

This will save storing a pointer to the world in every entity. This will reduce memory usage and also give better locality of reference. i.e. if you have many entities then it will probably improve performance by having more complete entities in the processor cache, depending upon how they are stored. I would not be worrying about performance at this stage too much though.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top