So I decided to write a game and use classes to better strengthen my class knowledge, and it was going well, however I have one problem I cannot seem to figure out. How do I use variables with other classes when they need to interact? I have a Game Class and a Player class, I need to use some of the player variables in the game class members but I cant seem to figure out how without breaking encapsulation. I have all the code written in main, it works exactly how i want and now im just trying to break it up into smaller chunks.
I was going to have Player class inherit from Game class which is why certain variables are protected, but idk about using inheritance. Not sure if its needed here or not.
I made another class that inherits the other two to act like a bridge between them. This way the two classes can communicate without exposing variables to the outside world. I think the concept may be right but the implementation is wrong, im just inheriting two classes and still using the ClassLink Class. I was thinking of just having it bridge communication between the two but i dont think its doing that. Although this may be a wrong approach altogether. I'm just trying to create a nice clean interface for them all to cooperate through without having to type out a bunch of convoluted kludge duct tape code to do it.
Ok so i decided to just delete that link class and type some pseudocode to get a shell, it doesnt work, and im still unsure how to do that. Is there a way without using inheritance and friend? with friend i have to make every single thing i want to use a friend, that seems counter intuitive. It would be fine if there was only 1 or two but theres pretty much everything in the class. Unless everything in the class can be made friend, but at that point it seems like using inheritance would be a better option.
Player should not implement game rules. Those should go in Game, since the game rules are conceptually part of the definition of the Game.
Friend classes should normally be used sparingly in a codebase, as they tend to significantly increase coupling. A friend declaration is often a sign that your design is inadequate.
The thing you said about a "bridge" class is totally unacceptable. In a code review I'd reject it summarily.
You're way overthinking the problem. Consider this example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
bool Chess::move_piece(Piece &piece, const Point &destination){
if (!this->place_is_free(destination))
returnfalse;
if (!this->move_is_valid(piece.get_type(), piece.get_position(), destination))
returnfalse;
piece.set_position(destination);
returntrue;
}
bool Chess::move_is_valid(PieceType type, const Point &location, const Point &destination){
switch (type){
case PieceType::Pawn:
//...
case PieceType::Bishop:
//...
//And so on.
}
}
ok, but player position is in the player class and the map is in the game class. if im going to set the location of the player in the games map then I have to put it in the brackets of the array, I cant do that now. I'm not really sure what to do or even what to ask.
I'm starting to think you have just too many classes. Player can just go away entirely. It seems like you're trying to create a maze game with only 1 player. All of the data members and methods in player can just be put into Game. Player position can just be represented with std::pair. If this game has more than one player you can keep the Player object and have the Game class keep an array of player objects. Looking at how this works the only thing the player should have are their coordinates. Bound checking or moving up and down, left or right should be in game.
I don't quite agree. While moving the data in Player into Game is not "bad" for this simple game, since the player and the game itself are separate entities, it makes sense to keep both classes.
"What do you mean? "In the brackets of the array"?"
Yes, since the players X and Y coords are part of the player class, it needs to be able to be put in the mapArray brackets so the array knows where the player is and where to place them. I have solved the issue by creating a player object in game class and game object in player class. I was told
"Then, in order to access Game from within Player member functions, perhaps Player could store a pointer to the Game object that owns the Player object. "
Although im not quite sure why this is needed when i can just make a game object in player and that works fine.
You're writing a game. Creating a class named "Game" is redundant at best, because what's a game if not the whole program?
Although I'm not quite sure why this is needed when i can just make a game object in player and that works fine.
Including a Game in the definition of Player directly implies that a player is composed of a Game, which is ridiculous. Including a parent pointer (from Player to Game) is less wrong, but it doesn't avoid the issue with trying to create a class named Game, and is definitely not optimal.
You have a board upon which pieces may appear. Maybe the player's character is a piece?
I was agreeing to helios' comment. Seems these forums are still buggy in terms of updating posts on threads. And as I stated earlier, and may be others could chime in. I think all of the methods besides updating player coordinates should be included in Game.
You're writing a game. Creating a class named "Game" is redundant at best, because what's a game if not the whole program?
In this particular instance it may be redundant (but then again, this particular game is so simple that there may not be any need for OOP in the first place), but it's not redundant in the general case.
Within the same running process there will usually be only one instance of a game running concurrently, but there could be none (e.g. before a game is started or resumed) or many (e.g. if the program is a server hosting games between other players).
"In this particular instance it may be redundant (but then again, this particular game is so simple that there may not be any need for OOP in the first place), but it's not redundant in the general case."
This is just what I have so far. I want to make this a full fledged Console RPG, I just wrote the basics so I could make sure it worked. If I can just figure out how I can use objects in other classes, I can continue unabated.
So, with that said, I decided to just open a new file and write the classes with little in them so I dont lose sight of what im trying to do. So step by step here:
Step one: Create Player Object in Game and Pointer to Game Object:
#include <iostream>
usingnamespace std;
class Player;
class Game
{
public:
Game(Player player);
~Game();
private:
char gme_mapArray[0][0];
};
class Player
{
public:
Player(Game* game);
~Player();
private:
int plr_XPos = 0;
int plr_YPos = 0;
};
int main()
{
cout << "Hello world!" << endl;
return 0;
}
Is this correct so far? I was told since Player is part of a game I can create an object in the Game class, but I cant create an object in the player class because then its saying that game object contains a player object and player object contains a game object, and that goes on for infinity, so thats a problem. HOWEVER, The solution I was given is that I can make a pointer to a game object which contains a player object and that would work.
The question is whether Player needs to know about Game at all. Since Player has no methods, I would default to "no".
Note that your class definitions do not say "Game contains a Player and Player contains a pointer to a Player". What they say is "the constructor for Game takes a Player by value and the constructor for Player takes a Game pointer by value". Neither class is able to store the parameters to their constructors.
Right but I'll need to set the players X and Y value in the map array to set the player on the map though so Game and Player will have to come into contact somehow. Disregard the fact that there isnt a player char yet, this is just an example.
What you'll need to do is place a representation of the player in the map to show the player's location in the world. I.e. you'll need to "draw" the player. Player does not need to know about Game to do this. Game just needs to be able to query Player's position, which can be done using a getter.
1 2 3 4
void Game::draw_player(){
auto pos = this->player.get_position();
this->gme_mapArray[pos.x][pos.y] = PlayerRepresentation;
}
Ok, thats exactly what im looking to do. so the player.get_position() is just a representation or is the actual player character? I assume its part of Game because this-> is pointing to it so it must be a member. then give it a player representation, but how does the code know what the actual player "sprite" is if its just a representation?
'this->player' is a Player, which in the example is a member of Game, 'Player::get_position()' is a member function of Player, and 'this->player.get_position()' calls Player::get_position() passing 'this->player' as it's 'this' parameter.
Player::get_position() returns as a single object both the x and y coordinates of Player. You can use std::pair<int, int> for this, or write a class specifically for this.
Player should also not expose its x and y coordinates individually. The fact that Player stores them separately is an implementation detail which other classes need not know about. Also, this is unrelated, but the way you've written GetPlayerPositionX() and GetPlayerPositionY() makes them setters, not getters. There's no way for the caller to obtain the old values, since just calling the functions overwrites the values.
playerChar does not belong as a member of Player. Player should not be concerned how it's displayed on the screen. Ideally, not even Game should be concerned about the how, just about the where or the whether.