I was developing a simple Board Game and I used a class that determined where each piece could move to on the board depending on the position of the rest of the pieces. I already have all of the game logic ready to go but I want to know what would be the simplest way of including this code in UE4? I was thinking of using the Add Code functionality, but on which class should I base it on?
For reference, here’s the basic flow of the game
1.- Player clicks on a game piece (using blueprints for this) and gets the “PieceID”
2.- The ID is passed to my Game Logic class and a series of “Valid Moves” is generated
3.- These valid moves are highlighted for the Player
4.- The player picks new location of the game piece.
For the game logic, there are multiple different approaches. Some people implement it on their player controller actor. Some people add this logic to custom game state.
I’d say that the important logic which manages multiple game pieces and interaction between them, belongs to Game Instance, Game Mode and Game State. GameMode resets each match/level change, which might be what you want in case of playing multiple levels and rounds. GameState is synced across all players, in case you want a multiplayer game in the future, and in case of multiplayer game GameMode exists only on the server. So, if you manage to do it right from the beginning, you might be able to turn your game into multiplayer without too much effort
If I have correct understanding (I’m just a beginner who’s been reading UE4 docs and tutorials lately) Game Mode and Game State manages overall “bigger picture” of the game and orchestrates the rules of the game. Also, when you read UE4 docs here: https://docs.unrealengine.com/latest/INT/Gameplay/Framework/GameState/index.html
you’ll find it saying:
GameState […] can keep track of properties like score, list of connected players, number of caps in a CTF game, where the pieces are in a chess game …
Seems to be exactly what you need. This seems to support my point that you should tie your main logic into classes of game mode and/or game state. Of course, you can leave your existing code in a separate code class as it is now, but you’ll have to attach some calls into it from Game Mode and/or Game State.
Basically, you start with a “Top Down” UE4 project in C++, implement custom Game Instance, Game mode and Game State. Then you define your actors - you’ll need at least Board and GamePiece with PieceID property. GamePieces might be of UE4 Pawn class because you will need to “posess” and “unposess” them (using UE4 terminology).
For the Board actor you’ll have to figure out how to display valid moves on it - there might be different solutions for it, such as changing render state of the actor to trigger rendering lines of valid moves or to make valid moves to be Actors themselves and show/hide them based on game state rules.
I guess, the first tasks would be to start coding the game and see what can be accessed from Game Mode and Game State. Most probably, you might want to spawn your Game Pieces in your GameMode and assign PieceIDs to them and also keep them in a local 2D array (dictionary with PieceID seems a good solution), so your current game logic class can process them as some abstract entities on some abstract board, unrelated to rendering or UE4 specifics.
One thing that I’m not sure though - how would your Board actor access your game logic class on the game piece click event to calculate valid moves and to display them. A quick search for possible solutions returned the following piece of code:
GetWorld()->GetAuthGameMode()
You could call this from your Board Actor or Game Piece actor and then you just call the function of your game class passing currently clicked PieceId and return valid moves array and update your rendering state.
Also, PieceId might be unnecessary at all - you need piece’s position on your board and PieceId doesn’t give you any useful information about it. You just need a reference or pointer to the GamePiece actor and its custom BoardPosition property. But really it all depends on your game logic organization - whether you store BoardPosition on the GamePiece actor or store it in some objects inside your game logic class thus mirroring your GamePiece actors and linking them through PieceId.
When player clicks on the GamePiece actor, you might want to store the reference of the actor somewhere, e.g. in the PlayerController as current game piece. It might turn out, that this could be achieved through UE4’s “possessing a pawn” logic, although I’m not sure if this won’t be an overkill because UE4’s possessing a pawn logic might be meant for more complex control (movements in space, camera controls etc.) but not for simple logical indication of the fact that the user wants to control an Actor. Also, when possessing a pawn, you might need to store current player camera fer and restore it after possessing to avoid camera view jumping to the “possessed” game piece. See this therad for the issue and solution:
But I might be wrong here, I hope others will correct me.
Later when player clicks on the board, you receive event on your Board actor and once again call your game mode to see if the current piece can really moved to the position. If it can, you return true and update both current GamePiece and Board rendering state, so the GamePiece is redrawn at a new piece and old valid move paths get deleted from the Board.
A tip for receiving click events on your game piece actors:
I asume you you have a Board like Chess (Grid) but even if not its roughly same with a Node path. I base my Example on Chess.
You need a Grid/Graph (your Chessboard) this can be a Abstract representation we use this to determine which Coordinate is occupied by a Pawn. This is also a good place to add additional information like this Tile is a Forest +25% defense for the Pawn standing on it (in case you do something tactical) the Board piece itself if you need a refference back to manipulate its Material for example.
Now who knows best where it can move to? Well its the Pawn itself. So make a BasePawn or Interface (thats up to you) that has a Function lets Call it GetPossibleMoveLocations() that will return you a array of Board Locations. You can add extra info if you let it return a Array of MyStructs. The Struct holds the Locations + additional info that you Calculate or simple Flags like EnemyAtLoc = True/false so you can highlight your tile in Red that means its a Attack Move.
So every Type of Pawn in Chess has a fixed Moveset. Like the Knight can Move 2 up + 1 left, 2 up + 1 right, 2right + 1 up, etc etc. you get what I mean. So in the GetPossibleMoveLocations function that everyone implements individually you simply get your Grid/Graph and make one move after another from your Position + Your Movement Set and look at what there is at the Grid Position. Is there a Pawn? If False than add this Location to the Array you want to return. If true check is it a Enemy? If False dont add this Location to your Array its a impossible move. If True its a Possible Move add it to the Array and if you use a struct like I mentioned earlier also set the IsEnemy Flag to true. I Stop here but be aware that you can do a lot more here like if you have a Bowman that cant Attack Units with Shields you can exclude it as possible move, Precalculate Terrain Boni etc.
Now you get a Array back with all the Info you need to Highlight and get other crazy stuff you can use as visual Aid. Where and how you process this information is not that important it can be in the GameMode, GameInstance or a Actor for all I care even the Level BP (not recommanded though xD)
I did not cover Graphs here there are a bit more Complicated because they don have a “direction” like a grid (up,left,down,right) instead the have “neighbour Nodes” that can be in all sorts of directions. I leave you a link here if you want to know more about Graphs and Pathfinding (the stuff above is sort of pathfinding) in case you need a more advanced thing. Its Theory so you have to implement it yourself. ( http://www.redblobgames.com/ )