There's something about platformers which makes me think they're given a bit of a bad rap thanks to the plethora of ez-mode tools that have templates for such a thing.
If you're making a platformer from the ground up, with no libraries for things like collision detection, it actually seems like a pretty good way to learn a lot of the voodoo techniques that most gamedevs have to have in their back pocket to get around common issues.
You don't get as much of this with things like GMS or Unity, but you'll get other problems related to how their built in implementations for things to solve their problems don't entirely "solve" them.
Seriously though, the nuts and bolts of a platformer can be pretty weird and hacky to get it to feel "just right":
* jump response. Do you use a single impulse or temporary disable gravity and give a series of impulses while the button is held down?
* jumping slack / edge detection slack (n-frames to accept input to do the thing the player intended despite the world conditions not allowing it, such as jumping off the edge of a ledge or fitting between 2 tight blocks)
* push-out code for a-postieri collision detection so players and enemy AI doesn't get stuck
* raycasting and scanning for a-priori collision detection (sometimes you have to mix and match different approaches to avoid getting stuck, or going straight through things depending on how fast an object's moving)
* a camera that won't make the player sick
This is all the most basic stuff that agd's often take for granted, before even having to worry about things like character or level development. But those (particularly level development) are just as important for making a game fun as well as competently coded.
I found this guide pretty helpful for understanding how a game like Sonic did things like the loops and angled surfaces, since that is practically the gold standard of platform engines (well, at least what sonic 2/3 did with it): http://info.sonicretro.org/Sonic_Physics_Guide
For the more basic/critical nuts and bolts of platform engines, I'd recommend looking into how SMB1 handled collision detection. Its "push-out" code can be exploited somewhat but everyone can become familiar with it quite quickly and serves as a good base to move towards more complicated techniques for handling slopes and context-switching circumstances (grappling hook, "loop-de-loops", etc).