ngoaho91 is basically hinting in the right direction but is not spelling it out explicitly, so I will try to make it more explicit.
So you took the framework and started implementing the logic within the separate framework classes. The problem why you can't simply test the game logic in isolation, is because it is not isolated.
You write that you
Projectile is a
Sprite, but that is simply not true. You use a sprite to visualize your projectile. The first thing is you need to separate your logic from your presentation, so like ngoaho91 said, without any presentation logic. You get bonus points if you wrap the logic into a separate library without any links to the presentation framework.
Then you build your presentation either by writing an observer called
ProjectileView for each projectile or an observer that contains an array of Sprite objects, one for each projectile. For input you would write one object, say called PlayerController. This would then translate the raw inputs into calls on the game logic.
Now with this setup, you can take the game logic and put it through any amount of unit tests.
You may have noticed, I just decried MVC (model-view-controller). There is a valid reason why this pattern has persisted for such a long time, it separates the concerns in the system.
Before I finish, I want to give some real world advice. In general and especially the larger the code base becomes, it makes sense to factor your code into well defined chunks of responsibility. But with smaller project this just does not make that much sense, you can overdo it and thus the extra effort is not worth the cost. For example one common pattern is to clump the input handling into the Screen class instead of factoring it out into a separate object. My basic rule of thumb is, refactor when it starts hurting.