READY, AIM, FIRE
Space Shooter is a 3D networked multiplayer game where players battle in spaceships to score points.



void AuthoritativeServer::Receive( Message const& msg, IPv4Address const& address ) { if( msg.header.isReliable ) { PacketWriter writer; ReliableAckMsg ack = ReliableAckMsg::Default(); ack.SetSequence(msg.GetSequence()); writer.AddMessage(ack); Packet ackPacket = writer.EmitMessage(); int ackPacketSize = ackPacket.header.size; m_endpoint->SendMessage( m_netSys->GenerateNewMessage( m_bindAddress, address, reinterpret_cast<char*>(&ackPacket), ackPacketSize ) ); } Message const* msgPtr = &msg; switch( msg.header.id ) { case MessageId::RELIABLE_ACK: { HandleMessage( reinterpret_cast<ReliableAckMsg const*>(msgPtr), address ); break; } case MessageId::CLIENT_JOIN_REQUEST: { HandleMessage( reinterpret_cast<ClientJoinRequestMsg const*>(msgPtr), address ); break; } case MessageId::CLIENT_PLAYER_CREATED: { HandleMessage( reinterpret_cast<PlayerCreatedMsg const*>(msgPtr), address ); break; } case MessageId::CLIENT_DISCONNECT: { HandleMessage( reinterpret_cast<ClientDisconnectMsg const*>(msgPtr), address ); break; } case MessageId::UPDATE_PLAYER: { HandleMessage( reinterpret_cast<PlayerUpdateMsg const*>(msgPtr), address ); break; } case MessageId::ENTITY_REQUEST: { HandleMessage( reinterpret_cast<EntityRequestMsg const*>(msgPtr), address ); break; } default: break; } }
// Pixel stage for lighting models float4 PixelMain(v2p_t input) : SV_Target0 { float3 light = float3(0.577, 0.577, 0.577); // construction of TBN matrix float3 n = input.normal; float3 b = input.binormal; float3 t = input.tangent; t = normalize(t); b = normalize(b - t * dot(t, b) / dot(t, t)); n = normalize(n - t * dot(t, n) / dot(t, t) - b * dot(b, n) / dot(b, b)); float3x3 tangentMat = float3x3(t, b, n); float2 texCoord = input.uv; float4 normalVal = NormalMap.Sample(SurfaceSampler, texCoord); float3 normalValToFloat = 2 * normalVal.xyz - 1; float3 normalValInWorld = normalize(mul(normalValToFloat, tangentMat)); // lighting calc with transformed normal map normal float3 reflection = reflect(-normalize(light), normalValInWorld); float3 toEye = (CameraPosition - input.worldPosition).xyz; float3 diffuseIntensity = max(dot(normalValInWorld, normalize(light)), 0); float3 specularIntensity = pow(max(dot(normalize(reflection), normalize(toEye)), 0), SpecularExp); float3 ambientIntensity = max(dot(normalValInWorld, -normalize(light)), 0); // Taper off diffuse and specular if( dot( n, light ) <= 0 ) { float t = (dot(n, light) + 0.3) / (0.3); t = clamp(t, 0, 1); diffuseIntensity = diffuseIntensity * t; specularIntensity = specularIntensity * t; } float4 textureColor = SurfaceTexture.Sample(SurfaceSampler, texCoord); float4 lightColor = DiffuseColor * float4(diffuseIntensity, 1) + SpecularColor * float4(specularIntensity, 1) + AmbientColor * float4(ambientIntensity, 1) + float4(0.05, 0.05, 0.05, 1); return float4( input.color * textureColor * lightColor ); }
// Geometry stage for particle system [maxvertexcount(6)] void GeometryMain(point v2g_t input[1], inout TriangleStream<g2p_t> stream) { g2p_t output[4]; float4 vertex; for(int idx = 0; idx < 4; ++idx) { vertex = input[0].position + offset[idx] * float4(0.0, input[0].uv, 0.0); output[idx].position = mul(ProjectionMatrix, vertex); output[idx].color = input[0].color; output[idx].uv = uvCorner[idx]; } stream.Append(output[0]); stream.Append(output[1]); stream.Append(output[3]); stream.RestartStrip(); stream.Append(output[0]); stream.Append(output[3]); stream.Append(output[2]); stream.RestartStrip(); }
Post-Mortem
In Space Shooter, my greatest challenge was learning new technology - mainly networking and lighting. The greatest hurdle in creating a networking framework was understanding how to integrate the server-client architecture into my standard project. There ended up being a lot of information traveling up and down from the server/client sockets to the game entities. Debugging issues with the netcode was also a rough task - however, that helped me learn how to thoroughly check every step of the pipeline.