Thanks for the feedback!
I showed this game to some of my friends, and they noticed many of the same issues. This is the most glitchy game I have made so far. Since the timers still run even while the rest of the game is frozen, you can go through a wall by hugging up against one and then dragging the window. Since the movement is frame-independent, the player will tunnel through the walls with a large enough time step.
The super fast enemy definitely needs to be nerfed! Its collision box is actually smaller than the distance at which the player holds the gun away from his body, so you cannot hit if it is too close. A bit of a problem.
Oh, and the pixelation shader was my attempt to hide my horrible art
.
The lighting was done with OpenGL directly, but not with any built in lighting or lighting used for 3D. It is the same system I use in Gore Factor. The lighting system actually comprises about 90% of the effort put in the game :wink:. Here is an explanation of how it works:
There are lights, emissive lights, and convex hulls. The lights come in 2 variations: purely dynamic and semi-static. The former means that the shadow geometry is regenerated every frame, and the later only updates when a hull it affects moves. Otherwise, it re-uses the previous geometry that is stored on a render texture.
Lights, emissive lights, and convex hulls are all stored in their own quad trees. With this, I can query which lights are visible on-screen and then rapidly query which hulls each of the lights affects. I then use an intermediate render texture to render a light with all of its shadow geometry.
The shadow geometry is generated in 2 steps: First the umbra portion, and then the penumbra. The umbra is generated by cycling through all the points in a convex hull and taking the dot product with the normals of all the sides and a vector to the midpoint of a side. This is then used to determine which sides are back-facing. After that, the shadow boundaries can be determined. The shadow geometry isn't rendered by color, but rather replaces the stencil test by using the depth buffer to create regions where the light won't draw. After that, the light is drawn.
After the light is drawn, the soft regions are computed by offsetting the original light-to-hull vertex vector origins by the radius of the light source. 2 vectors are calculated, which can then be used to render the soft shadows texture, which is just a gradient. This is applied to the light edges with multiplicative alpha blending, causing it to fade into darkness.
When the light is finally composed, it is rendered to the lighting render texture. This lighting render texture is rendered to the scene after all lights have been rendered using multiplicative blending.
All the maths are based off of what is presented in this article:
http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/dynamic-2d-soft-shadows-r2032