Making a Web Based VR game (Part 1)
This weekend I decided I wanted to try making a web based VR game. I wanted to test the viability of the web as a VR platform and also hone my coding skills a little bit since I’ve been mostly involved with management in the past year. The web offers the advantage of accessibility, but it cannot match native performance. I wanted to see if it will be enough to implement a visually appealing game that could run on the Oculus Quest 2. The chosen game concept is something I had in mind for several years. It involves placing players in control of a battleship turret, navigating through a cosmic battlefield filled with enemies. To mitigate motion sickness, the battleship moved linearly, eliminating the need for complex maneuvers that can cause discomfort.
The technology that makes this possible is WebXR. WebXR, or Web Extended Reality, is an API that enables the creation of immersive experiences directly within web browsers. Leveraging WebXR allows users to access VR and AR content directly from the browser, without the need for additional installations or plugins. Instead of using WebXR directly, I opted for A-Frame, a web framework for building virtual reality experiences. Its simplicity and declarative nature made it an attractive choice for quickly crafting immersive scenes and interactions. The Entity Component System (ECS) architecture within A-Frame allowed for modular and reusable components, streamlining the development process. I also decided to enlist the assistance of Github Copilot to verify how useful it is in such a scenario or will it be just a distraction.
Creating a basic scene in A-Frame is straightforward: just place a a-scene element in your html page. The next thing I needed was a skybox. For the background, I turned to Skybox 360-image generator, a powerful tool that enabled the creation of a stunning nebula as the game’s environment. It is a pity that blockade labs cannot generate stereoscopic images, but the ease of use makes up for it.
With the foundation set, the next phase of development involved introducing some 3D assets. Using Blender, I crafted a very primitive battleship to serve as the user’s vessel, seamlessly integrating it into the A-Frame scene. The export process from Blender to A-Frame was straightforward.
Afterwards I added an asteroid field. For the asteroid field I needed to create an asteroid component that moves an entity along the Z axis and another component that would spawn entities within a bounding box that have an asteroid component.
Then I added a turret with cannons that would point to wherever I pointed. This was a bit tricky since just copying the rotation would not be enough. I needed to take distance into account. Github Copilot helped to a degree but needed to be corrected several times. On the other side, the shooter component was trivial: First I renamed the asteroid component to ‘projectile’ and parameterized the direction, so I could shoot wherever the turret is pointing. It turns out that the Entity Component System has already started paying off its dividends. Then I just needed to spawn projectiles on a time interval.
A-Frame has a built-in editor that proved instrumental in arranging the components of the turret. For the time being I completely skipped using Blender and assembled the turret using only A-Frame primitives.
After admiring my creation for an instant I realized that all my attempts were futile and I decided to replace some of my hideous 3D assets with some open source ones. OpenGameArt proved to be a reliable source of assets not requiring subscription and not trying to sell you paid assets.
I replaced the ship and the turret. I also needed to decompose the turret into 3 parts to have proper rotation. The mid part would just mimic the rotation of the top part but only along the Y axis. For this I made a component to mimic rotation of a target along the specified axes. Creating this component took just a couple of minutes.
My initial time estimates for feature implementation were consistently being surpassed. Copilot’s assistance in navigating unfamiliar APIs and tackling trigonometry intricacies contributed significantly to the accelerated pace. The inherent modularity of A-Frame’s ECS model facilitated faster coding, emphasizing clear separation of concerns and ease of integration.
The development pace continued as I introduced enemy ships. I crafted a ‘fly-along-curve‘ component, utilizing a Catmull-Rom curve for smooth entity movement and rotation. This approach allowed precise definition of points, enabling seamless interpolation between them.
Then I added an enemy spawner that would create ships according to a schedule. The schedule is essentially an array of enemy waves. Each wave in the array specifies key parameters, such as start time, ship quantity and type, spawning interval, and specific data for a the chosen enemy type such as the curve points for ship movement. The enemy spawner also sets the stage for future enhancements. While the current waves are static, plans are in place to introduce a function for generating waves in a pseudorandom manner to boost level design productivity.
The asteroid field underwent a transformation, evolving into a debris field to address aesthetic concerns and optimize the model’s triangle count. In parallel, an auditory dimension was introduced with the incorporation of a laser sound, generated by using the 8-bit synthesizer from https://sfxr.me/.
The cumulative effort so far took less than a dozen hours. There are still a number of features I want to implement in order to call this a proper game:
- Enemy Interaction: The ability to destroy enemy ships is still missing. Implementing visually satisfying explosions while maintaining good performance on the Oculus Quest 2 will be a challenging task.
- Audiovisual Polish: The game could benefit from a number of small enhancements such as better projectile sprites, turret tracking sound as well as controlled tracking speed.
- Diverse Enemies: Expanding the array of enemy types will add variety and complexity to gameplay.
- Survivability Mechanics: The introduction of shield and dying mechanics brings a layer of strategy and risk, enhancing the overall depth of the gaming experience.
- Power-Up System: Power-ups inject dynamic elements into gameplay, providing players with a progression system.
- Weapon Variety: Different weapon types, such as lasers and missiles, will offer players a range of tactical choices, allowing for personalized combat strategies.
- Secondary Weapons Arsenal: Adding secondary weapons like missile barrages and bombs will further deepen the strategic dimension to battles.
- User Interface and Interaction: A main menu, coupled with a point system and high scores, enhances the overall user experience, providing a structured and rewarding gaming environment.
- Immersive Elements: The incorporation of a player cockpit brings a sense of realism, immersing players further into the virtual battlescape.
- Battleship Customization: Allowing the addition of more turrets to the battleship empowers players to tailor their gameplay style, creating a personalized and formidable war machine.
- Multiplayer Possibilities: The ambitious goal of potentially implementing multiplayer functionality opens doors to collaborative or competitive experiences, expanding the game’s reach and engagement.
Stay tuned for Part 2 of this series…