I am attempting to plan a text-adventure RPG, and have tried a couple of times to jump right into the coding and kind of get lost on what to do next, so I need to plan it all out on paper first. This is honestly just an exercise for me to further my skills in programming. I need some advice.
What are some things to consider when "Planning" a game?
Once I have a general idea of what it is I want the game to, what do I do?
Do I need to have every gritty detail planned before coding?
And a somewhat related question. I am at a loss of how to create a map.
I have attempted a two-dimensional array as a map, kind of like a coordinate plane, but I feel that it's limiting...
I feel like I could potentially create a two-dimensional array of room objects but I am unsure of how to do it. I would need them to point to another room using pointers, and once the move has occurred, display a little descriptions of the area.
ANY help, advice, critics are entirely welcome, THANK YOU FOR YOUR TIME !!!
I've heard the phrase: "I'm almost done, I just have to code it now".
The look of your design will really depend on how complicated your program will be and which programming paradigms you'll use. UML is a fairly established method of creating designs. If you don't want to use UML/OOP, then start from the very high level concepts and move towards the specific.
It's easy to think that you want your character to have 100 HP, then for attacks to average 2 points per hit, etc. But those are implementation details. Leave that to the end.
Start by thinking about which sections you'll need for your game... You might want: A) A city to move around, B) A map to move between cities, C) a battle system, D) a character tracking system.
Then go one section deeper:
You may want your character tracking to include experience, health, skills, inventory
Then you might want to define a skill progress system.
As you work your way down, you'll start to understand what data is needed to perform specific actions. Once you've defined all of the concepts, then you're ready to implement. Start from the high-level and also define the data structures you'll need. Eventually get to the point where you are defining the individual if/else statements and you're done!
Edit: Budget about 1/3rd of your time for design/implementation and 2/3rds for debugging. Debugging. You're not quite done until everything works.
I got to be the mentor for an undergrad during his graduation project. He came in as an aerospace engineer and left as an adept programmer. The first thing I told him was that programming is just a tool we use to get our ideas implemented. The second thing I told him was to start from the most generic concepts, and then slowly move to the specific.
I haven't had to mentor too much past those lessons. He just graduated last week (8 months later) and has embraced OOP naturally based on that second item. I was actually amazed at how he turned those lessons into something completely tangible and useful. He definatley had an aptitude for this, despite never having seen a line of code beforehand.
When I was in college our professor told us to take the end result and think of everything you needed to make that end result. Basically what STEWBOUND said.
You then take the sub ideas, a city to move around, a battle system, character tracking, etc. With the sub ideas you will know where to start because all of them will require the same thing. In this case, I would think you need a character to be in the city, to fight in the battle, to walk the maps.
Now you implement character with those things in mind...
I'm in the middle of writing my own RPG game myself. So far I have over 10,000 lines of code and countless number of classes (and always try to remove all repetitions using helper functions and macros). Here are the following notes I've jotted for myself while programming, just to give you a sense of how much you may need to learn to program an RPG game. I have to give credit to JLBorges for suggesting some of these tools and design pattern ideas to me.
- variadic templates: struct DamageAttacks, struct BoolValues, struct basic_vstream (svout), predicate_and_actions,
- recursive call over template int because loop iteration not allowed (iterating down): createStandardWeapons(), checkDragonTypeDecorateUnderSpell, checkDragonTypeSpellWearsOffOneSpell, checkDragonTypeSpellWearsOffMultipleSpells, checkDragonTypeUnderHasteSpell, checkDragonTypeUnderGirdleOfGiantStrengthSpell
(iterating up): checkPlayerTypeAction, checkPlayerTypeSpellWearsOffOneSpell, checkPlayerTypeSpellWearsOffMultipleSpells, checkPlayerTypeDecorateUnderSpell
- emulation of template function partial specialization through use of partially specialized template classes and wrapper functions: createDoubleParameterWeapons()
- Virtual inheritance with multiple base classes: The concrete Monster subtypes have their constructors bypass the MonsterImplement constructor and use the Monster constructor directly because MonsterImplement is a virtual derived class of Monster, PlayerDecorator (and its derived classes), MonsterDecorator (and its derived classes)
- Visitor Pattern: LivingBeing is a visitor class with visit function LivingBeing::takesItem acting on all MagicalItem subtypes with accept functions, a secondary accept function is Ring::acceptBeingWorn
- CRTP: template <class MONSTER> class MonsterImplement, template <class DERIVED_DRAGON> class Dragon, template <class DERIVED> struct InventoryItemCRTP
- Decorator Pattern Method: PlayerDecorator and MonsterDecorator (for specializing action() when under a spell)
- Template Pattern Method: Player::rollToHit (with two hook methods rollNeededBeforeAdjustments and damageWithoutAdjustments), LivingBeing::makesSavingThrow (with hook method wisdomSavingThrowAdjustment() used in 3 places), Save<MONSTER, CLASS_SAVE_AS, LEVEL>::rollsSavingThrow (with hook method applySpecialSavingThrowAdjustment overridden by Medusa), actionUnderInvisibilitySpell (with hook method buildActionUnderInvisibilitySpellMenu), Player::rollsSavingThrow (with hook method SavingThrowClass)
- Builder Pattern Method: MonsterTreasureChestBuilder: public TreasureChestBuilder, TreasureChestMenuBuilder: public MenuBuilder, DeadBodiesItemsMenuBuilder: public MenuBuilder
- Observer Pattern Method: RegenerationClass: public ObserverPatternClass, RingOfRegeneration: public ObserverPatternClass, HitPointsLossPerRoundClass: public ObserverPatternClass, {LivingBeing::wasAttackedNotifyCharmers, LivingBeing::registerCharmedObserver, LivingBeing::removeCharmedObserver}
- Mediatator Pattern Method: Usage of ItemsExchangeMediator in battleAftermath()
- Singleton Pattern: SurpriseClass::Instance(), CharmedBehaviourA::Instance(), CharmedBehaviourB::Instance(), etc...
- Strategy Pattern: class CharmedBehaviourInterface used by class CharmClass
- Function pointer to member function: 'static const std::map<Spell, ResultOfAction (Player::*)(SpellCastingChange)> actionUnderSpellMap' in Player::actionUnderSpell, actionUnderHasteSpellHelper (int numAttacks, ResultOfAction (LivingBeing::*func)(SpellCastingChange s)),
'static const std::map<Spell, bool (MonsterImplement<MONSTER>::*)(LivingBeing*, int, const Weapon*, const MissileType*, int, int) const> rollToHitMap' in MonsterImplement<MONSTER>::rollToHit, static const std::map<Potion*, void (LivingBeing::*)()> potionMap in Player::choosePotion(),
- Using macros for large repeated blocks of code that cannot be abbreviated with a helper function: #define ALL_REMAINING_PLAYER_DECORATOR_OVERRIDES(playerType)
- std::iterator_traits<InputIterator>::value_type: used in quantityMap, sentenceNamesListWithQuantities
- Lambda function with default parameter: auto normalAction = [this, &result](LivingBeing::SpellCastingChange s = LivingBeing::NoChange)->LivingBeing::ResultOfAction in PlayerUnderSpells<PLAYER_TYPE>::action()
- rValue as parameter without an accompanying overload with the lvalue parameter: Player::toHitChart (const std::array<int, NUM_ATTACK_LEVELS>&& level, ...), Monster constructors (..., const BoolStats<NumMonsterBoolValues>&& b = BoolStats<NumMonsterBoolValues>())