I just launched Blobby Tennis on Steam and the Oculus Store as a very small, but free VR experience. Turns out that getting anything VR released on those two platform is currently very easy, as all it took was submitting it to the Oculus Store using their developer dashboard, while I had to send an email to some Valve address and got a developer invitation in return.
While this was and still is very exciting, it is too early to draw any conclusions or anything, but I might write some more about it in the future.
But Blobby Tennis was really just a short stop on a longer plan of me making VR games. What I have now is a somewhat well working game engine with a DirectX 12 renderer and VR support, but a still limited feature set (no animations, no particles, only very hacky post processing and probably a lot more...).
My next and much more ambitious project is a VR multiplayer sword fighting game. I don't expect to be able to turn this into a realistic sword fighting simulator, but I want to make the most out of what's possible without hard haptic feedback.
The amazing working title is "Swords"!!1111
The great thing about this is that I can easily get a first prototype working with only few assets and keep iterating and expanding it for as long as I want to hopefully turn it into an enjoyable game.
And while doing all this I'll try to write a new devlog every now and then about my progress and problems I encountered along the way.
And then the game is released, highly successful, I can start working on something new and pay other people to keep this game going and that is pretty much the plan :D
Oh and also I'd like make the game accessible to others while still in development and at some point begin charging a small amount of money for it, when it gets closer to completion.
I am not at a point where I got something to release, but I hope I will be by maybe the end of july.
For a first public build of the game I want to have some kind of moving around together in multiplayer with basic ingame voice chat.
I am using bullet physics for the physics simulation, mainly because I have been using it in many projects before and while having lots of issues it always kinda worked in the end.
One big problem I already had to solve for Blobby Tennis was attaching the racket to a hand. It turned out that using a constraint was somewhat unstable and especially caused some way too random behaviour when hitting the ball. Sometimes the ball was accellerated far too little and sometimes it just flow out of the map.
For some reason the solution was to directly set the acceleration of the racket to stay at the hand position.
Which in my code looks like this:
RN::Vector3 speed = GetWorldPosition() - _racketBody->GetWorldPosition(); speed /= delta; RN::Quaternion rotationSpeed = GetWorldRotation()*_racketBody->GetWorldRotation().GetConjugated(); RN::Vector4 axisAngleSpeed = rotationSpeed.GetAxisAngle(); if(axisAngleSpeed.w > 180.0f) axisAngleSpeed.w -= 360.0f; RN::Vector3 angularVelocity(axisAngleSpeed.x, axisAngleSpeed.y, axisAngleSpeed.z); angularVelocity *= axisAngleSpeed.w*M_PI; angularVelocity /= 180.0f; angularVelocity /= delta; _racketBody->SetLinearVelocity(speed); _racketBody->SetAngularVelocity(angularVelocity);
While I represented the racket collider as a compound of just two cylinders to approximate the rackets head, I want objects such as swords and shields to have an accurate physics representation. Bullet offers basicly two solution for this:
- btGImpactMeshShape - Can handle concave and even changing meshes, but it is supposed to be slow and somewhat unstable.
- Convex decomposition and then using either btConvexHullShape or btConvexTriangleMeshShape - A compound of butConvexHullShape objects seems to be the recommended way to do it.
I tried all of them and the btGImpactMeshShape didn't want to collide with my ground plane for some reason, so I didn't really bother with it any further.
There is some utility code in bullet to do a convex decomposition of arbitrary meshes, but doing this at runtime every time is very slow and also the algorithm used is somewhat outdated. Fortunately there is V-HACD V2.0 including a well working blender plugin!
The plugin is even nice enough to create a unique material per generated mesh, which allowed me to just merge and export them as a single model into my custom format and can now just load it and generate a shape for each of the meshes.
While all this worked great from the start, it turned out that the resulting collision shape was WAY too big.
It took me a day to find out that bullet applies additional margins to all it's shapes. It is possible to turn them off, but not recommended, instead the mehes used for the collision shapes are supposed to be scaled smaller in a special way that correctly takes the generation of the margings into account. I didn't manage to figure this out in blender, but bullet provides a utility function to do so in its btConvexHullComputer class:
btConvexHullComputer *convexHullComputer = new btConvexHullComputer(); btScalar actualMargin = convexHullComputer->compute(vertices, stride, margin, 0.001f);
Here 'margin' is the preferred margin, '0.001' makes sure that the hull doesn't get too small and 'actualMargin' is the actual margin value used to shrink the mesh. I am then creating the btConvexHullShape using the vertices in 'convexHullComputer->vertices' and setting the shapes margin to 'actualMargin'.
While not 100% accurate, the resulting collision meshes are working good enough for my current needs. There are still issues where two objects (sword and shield) can pass through each other, especially at the cracks between two convex hull shapes, if only enough force is applied. With both my objects following a hand, this is still way too easy to accomplish. I hope that adjusting the forces is going to be good enough in the future, but it may not be...
While not finished with physics any time soon, I want to get networking in soon, but am somehow most excited to start out with the voice chat. For this I first need audio playback. I used OpenAL soft before, but it's a bit limited in terms of correct audio physics. So I just started implementing a somewhat custom audio solution utilizing Steam Audio and libsoundio.
I am probably going to use the Opus Audio Codec reference implementation for the voice chat codec and enet for networking.
I'll probably write more about all that in future devlogs :).