To understand this, you need to understand the basic architecture of any computer program. Typically you want split your application into tiers. One of the tiers should be the presentation tier and then you can have one or more tiers that take care of the rest, again usualy a logic tier and a data tier.
Now everything that happens in the game is happening in the logic tier. Your logic takes a marine and calls
marine.shoot(zergling) that can look like this:
if target.hit() then
Methods like showGunEffect(), showDamage() and showMiss() are calls to the presentation tier to actually show the graphics.
Now let's make the program more complex:
bullet = shootInDirection(target)
if (event == hit)
else if (event == miss)
Now for the first program you simply need to show the gun effects, hits and misses. For the second one you actually need some kind of collision engine that will take care of the event like
bullet colliding with
target. The first one is of course very simple and as you said - the entities are so small, that it doesn't make sense to actually show bullets for each shot, not even talking about calculating the trajectories, hits etc.
But for both programs, everything that happens is just a calculation. And only the calls to presentation layer will make something visible. In the first case, the bullets probably fly instantly. So you don't have to show anything, or you can simply draw a line from marine to zergling to show the bullet trajectory.
In the second case, some game loop will be updating the bullets position and calling the rendering to show the bullet.