In the arcades, games were difficult on purpose to make the player put more coins in, in the first consoles, games had artificial difficulty to make up for the lack of content that the games had.
Right now games tend to have a decent difficulty, in some cases too forgiving. Here are some notes (which are by no means strict rules) on how you could make a decent difficulty system:
You might wanna give your player options
A really easy mode can expand your game to new public, maybe people who just recently got interested in games, a hardcore mode can be of interest to those who love to spend the time mastering your game, or unlocking new exclusive content. An easy mode can be great for those who are just interested in the narrative side of your games. A normal mode will be most likely the mode that most people will choose and consider the ‘vanilla‘ or ‘default‘ experience.
You don’t have to give your player options, depends on what you think is appropriate for your game, Sekiro is an example of a game that doesn’t need to allow multiple difficulty settings, the game is about overcoming a defined challenge, but the wider the range of your difficulty is, the more people you can appeal to.
Don’t make the player repeat unnecessary stuff
A lot of games, especially old games, sent you back to the first level, previous level, or to a previous point in time. If you’re 10 hours in-game, and if you lose your last life and the game returns you to the first level, then that game is not difficult, it’s unfair.
Apart from that, if you’re in a difficult section and you insert a checkpoint for when the player fails, make sure to insert the checkpoint after a cinematic if any. Or at least make the cinematic skippable (being always or after the player has already watched it.)
Put the player back into action
A continuation of the checkpoint rule. Make it easy for the player to iterate through that part in which they failed. A great example of this is Super Meat Boy or Metal Slug, where if you die, with the press of a button or automatically, you’re back at the point where you failed.
Super Meat Boy levels are also easy to iterate through because of their size and the efficiency of Meat Boy’s movement.
Avoid relying on randomness
If the roll of a dice decides if the player dies or lives, it’s not difficult, it’s just chance. Which will most likely translate to unfairness.
Also, try not to make the player rely on memorization or input choreography unless that’s related to your gameplay somehow.
Be careful when modifying the rules
Related to dynamic difficulty, if the player is easily beating the enemies or if the player level has augmented, don’t artificially ‘enhance‘ the enemies, don’t convert them in bullet sponges or soldiers who’ve consumed performance-enhancing drugs. Insert a new type of enemy instead, or try to hide the fact that those enemies are now somehow stronger (giving them a visible armor, for example), make the rules of your world consistent.
Give the player ways to approach a problem
You can give the player different ways to approach the same subject, some easier, some difficult, some obvious, some obscure. The easy one can be the obscure one, or the difficult one can be the obscure one. Different ways to approach something will most likely enhance the experience of the player as well.
Avoid horrendous controls
If you need to use ‘g‘ to move forward, ‘F12‘ to move backwards, ‘middle click‘ to move to the right and ‘a‘ to the left. Then that game is not difficult, it’s senseless.
Using the excuse of difficulty to justify the lack of a decent control scheme or system will doubtfully make your players happy. There are some games where this might not be that problematic, like QWOP.
Make it interesting
Better to vary the behavior and actions of the enemy’s AI than to simply increase their health or damage. Just beware of not making it obvious.
Avoid indecent level design
Inserting pixel perfect jumps doesn’t make a game more difficult, makes it silly. Avoid placing stuff in nonsensical spots or making the player make leaps of faith in your platformer, unless that’s what your game is about (I Wanna be the Guy, etc…)
Avoid out-of-no-where difficulty spike
If you were to have a difficulty spike: first make sure that the rules of your world or lore is one that the player enjoys, second, you better make sure to justify that spike with your own rules.
Forcing the player to spend hours of grinding just to have a reasonable chance of beating that spike is not a great way to make your game more difficult, just a cheap way to make your player spend more time doing repetitive tasks (being the case that they decide to keep playing.)
Keep the difficulty invisible
After all it comes all down to being consistent with your world, this doesn’t mean that you can’t modify the difficulty of your game in-real time depending on how the player is performing (that’s a nice idea), but if you’re going to do that, make sure that the player doesn’t realize, make sure the player doesn’t feel cheated because you’ve increased the difficulty, or patronized because you’ve decreased it.