It's often better to prefer composition to inheritance.
In this specific case, I would strongly advise against using inheritance to arrive at a solution. What you are trying to do is take a sprite, which is naturally a rendering entity, and inject into it some methods and data for handling responsibilities outside its domain -- namely what sounds like AI and pathfinding. This is violating the single responsibility principle.
A far superior solution would be to have some kind of object (for things dealing with AI and scheduling, such objects are often called "actors") that contains a pointer or reference to a sprite and manipulates that sprite as-needed based on its own logic. This sounds more similar to your second, "controller" type approach.
However I would also advise, along the same lines, against creating a subclass of this controller type for each classification of actor (player, enemy, bullet). The behavior of those different types of controllers tend to differ in data, not in code, so there's little reason to create a complex inheritance hierarchy where no hierarchy is required at all. The differences between a player and a bullet are probably all things that can be altered by altering properties of the controller or sprite -- the image used, its bounded, and perhaps the name of the script that controls motion behavior.