I got a million of these:
C:\...main.cpp:37: error: invalid use of undefined type `struct Unit'
C:\...main.cpp:12: error: forward declaration of `struct Unit'
For different classes though.
| 1 | #include "color constants.h" |
| 2 | #include <allegro.h> |
| 3 | #include <vector> |
| 4 | |
| 5 | using namespace std; |
| 6 | |
| 7 | class Game; |
| 8 | class Map; |
| 9 | class Cell; |
| 10 | class Player; |
| 11 | class Unit; |
| 12 | class Effect; |
| 13 | class Projectile; |
| 14 | class GUI; |
| 15 | class ChatBox; |
| 16 | |
| 17 | class Game |
| 18 | { |
| 19 | private: |
| 20 | Map *map; |
| 21 | vector<Player*> playerList; |
| 22 | vector<Unit*> unitList; |
| 23 | vector<Effect*> effectList; |
| 24 | vector<Projectile*> projectileList; |
| 25 | GUI *myGUI; |
| 26 | ChatBox *myChatBox; |
| 27 | BITMAP *tileSet[12][5]; // 12 tiles to a set, 5 variations of each tile |
| 28 | long lastClock; |
| 29 | |
| 30 | void step() |
| 31 | { |
| 32 | long dt = clock() - lastClock; |
| 33 | lastClock += dt; |
| 34 | for (int i = 0; i < unitList.size();) |
| 35 | { |
| 36 | if (unitList.at(i)->removeMe) |
| 37 | { |
| 38 | unitList.erase(unitList.begin() + i); |
| 39 | } |
| 40 | else |
| 41 | { |
| 42 | unitList.at(i)->act(dt); |
| 43 | i++; |
| 44 | } |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | void draw() |
| 49 | { |
| 50 | for (int i = 0; i < playerList.size(); i++) |
| 51 | { |
| 52 | map->draw(playerList.at(i)); |
| 53 | for (int j = 0; j < unitList.size(); j++) |
| 54 | { |
| 55 | unitList.at(j)->draw(playerList.at(i)); |
| 56 | } |
| 57 | for (int j = 0; j < effectList.size(); j++) |
| 58 | { |
| 59 | effectList.at(j)->draw(playerList.at(i)); |
| 60 | } |
| 61 | for (int j = 0; j < projectileList.size(); j++) |
| 62 | { |
| 63 | projectileList.at(j)->draw(playerList.at(i)); |
| 64 | } |
| 65 | myGUI->draw(playerList.at(i)); |
| 66 | myChatBox->draw(playerList.at(i)); |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | public: |
| 71 | Game() |
| 72 | { |
| 73 | map = new Map(); |
| 74 | myGUI = new GUI(); |
| 75 | myChatBox = new ChatBox(); |
| 76 | } |
| 77 | }; |
| 78 | |
| 79 | class Map |
| 80 | { |
| 81 | private: |
| 82 | int rows; |
| 83 | int columns; |
| 84 | Cell *cellArray; |
| 85 | |
| 86 | public: |
| 87 | Map() |
| 88 | { |
| 89 | rows = 8; |
| 90 | columns = 16; |
| 91 | cellArray = (Cell*)malloc(rows * sizeof(Cell*)); |
| 92 | for (int i = 0; i < rows; i++) |
| 93 | { |
| 94 | cellArray<i> = (Cell*)malloc(columns * sizeof(Cell*)); |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | void draw(Player *player) |
| 99 | { |
| 100 | for (int i = player->camera->y1() / 32; i <= player->camera->y2() / 32; i++) |
| 101 | { |
| 102 | for (int j = player->camera->x1() / 32; j <= player->camera->x2() / 32; j++) |
| 103 | { |
| 104 | cellArray<i>[j]->draw(player); |
| 105 | } |
| 106 | } |
| 107 | } |
| 108 | }; |
| 109 | |
| 110 | class Cell |
| 111 | { |
| 112 | private: |
| 113 | int x; |
| 114 | int y; |
| 115 | BITMAP *texture; // 32 x 32 |
| 116 | |
| 117 | public: |
| 118 | Cell(BITMAP *tile) |
| 119 | { |
| 120 | texture = tile; |
| 121 | } |
| 122 | |
| 123 | void draw(Player *player) |
| 124 | { |
| 125 | blit(texture, buffer, 0, 0, x - player->camera->x1(), y - player->camera->y1(), texture->w, texture->h); |
| 126 | } |
| 127 | }; |
| 128 | |
| 129 | class Player |
| 130 | { |
| 131 | |
| 132 | }; |
| 133 | |
| 134 | class Unit |
| 135 | { |
| 136 | private: |
| 137 | double x; |
| 138 | double y; |
| 139 | |
| 140 | public: |
| 141 | bool removeMe; |
| 142 | }; |
| 143 | |
| 144 | class Effect |
| 145 | { |
| 146 | |
| 147 | }; |
| 148 | |
| 149 | class Projectile |
| 150 | { |
| 151 | |
| 152 | }; |
| 153 | |
| 154 | class GUI |
| 155 | { |
| 156 | |
| 157 | }; |
| 158 | |
| 159 | class ChatBox |
| 160 | { |
| 161 | |
| 162 | }; |
| 163 | |
| 164 | void init(); |
| 165 | void deinit(); |
| 166 | |
| 167 | int main() |
| 168 | { |
| 169 | init(); |
| 170 | |
| 171 | deinit(); |
| 172 | return 0; |
| 173 | } |
| 174 | END_OF_MAIN() |
| 175 | |
| 176 | void init() |
| 177 | { |
| 178 | int depth, res; |
| 179 | allegro_init(); |
| 180 | depth = desktop_color_depth(); |
| 181 | if (depth == 0) |
| 182 | depth = 32; |
| 183 | set_color_depth(depth); |
| 184 | res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0); |
| 185 | if (res != 0) |
| 186 | { |
| 187 | allegro_message(allegro_error); |
| 188 | exit(-1); |
| 189 | } |
| 190 | install_timer(); |
| 191 | install_keyboard(); |
| 192 | install_mouse(); |
| 193 | buffer = create_bitmap(800, 600); |
| 194 | } |
| 195 | |
| 196 | void deinit() |
| 197 | { |
| 198 | clear_keybuf(); |
| 199 | } |
Also, there's a problem with my dynamic allocation of the Cell pointer array. I've never done that sort of thing before, so I have no idea what I'm doing really.
Thanks.
using namespace std;
This is evil. If you want to save typing std:: for every std::vector, use using std::vector; instead.
The whole concept of namespaces is to separate, which is totally circumvented by using, throwing it all in one pot again.
For your errors:
A forward declaration is no full-type declaration, and you may only perform operations that do not need a full-type (like declaring a pointer or a reference to that type). As soon as you start needing more information (like, dereferencing it, accessing a specific field etc.) about it, the compiler must already know the full type, which means that a forward declaration won't do any more.
Solutions to your problem:
a) Move all method definitions to a .cpp file, and include the full declarations of the types needed (like, if you have class Map; as forward declaration, #include <map.hpp>, assuming class Map is defined in map.hpp.
b) Move all method definitions to a place where the classes are already fully defined.
using namespace std;
This is not evil, it is perfectly valid and recommended, as long as you control the scope of the statement. The basic rule of thumb is that the using namespace foo; DECLARATION IS NOT SOMETHING YOU WANT TO DO IN A HEADER FILE (if you need to do it in a header file, do it on a function by function basis. Never just leave a using namespace statement in the global scope if you can help it.) If you are using a lot of namespaced stuff in a header file, usually you enclose the using directive inside of the function scope to prevent unwanted namespace pollution. This same argument goes for even the using std::vector statement, even though the using std::vector statement is considerably less problematic.
edit: using namespace std; in a cpp file is just fine as long as you don't care that it opens up hundereds of names into your current scope; you just don't want to force the entire std namespace on the user of a header file.
Alternatively, you can use a temporary namespace like this to hide it in a header file:
#include <vector> namespace temporary { using namespace std; class Thing { vector<int> lookImAVector; }; } using temporary::Thing;