I have added the CollisionSystem code to Lyridia and things are looking mostly ok. I can create a BoxGeometry, translate it, rotate it, and add it to the collisionTargets array and the collision detection system works great. There’s still no gravity and the collision sphere is too big, but it works. I’m a little disappointed because I tried switching out the BoxGeometry with a SphereGeometry and the results were a little mixed. The system seemed to mostly work but I was able to walk into the sphere in one place at least one time, and another time it actually crashed the browser. So there is still some work to do on the collision system, but overall I’m still very pleased with it. The next step is to add an invisible collision mesh to another object in the world, like the fence or the Penrith farmhouse, and make sure I can use the system there.
Author: Bvckshot
Collision system refactoring
Planning and DevelopmentI have rearranged the code from Fauerby’s paper into a single Javascript function (class) in a separate file. I called it CollisionSystem and a single instance of that function keeps up with everything related to collisions. Fauerby used a “CollisionPackage” (or “CollisionPacket”, depending on where you look in the code) to pass variables to the collision functions. I moved that into a single class with the appropriate members and methods. So now my code looks like this:
var _cs = new CollisionSystem();
_cs.collisionTargets.push(collidableObject);
var newPosition = _cs.run(position, velocity);
position = newPosition;
Once the CollisionSystem
is created and at least one collisionTarget
is added to it, I just call run
with the collider’s current position and velocity. run
returns the new position and I can then update the scene with that position. Easy peasy chicken squeezy.
A current limitation of the system is that I’m not implementing gravity right now. That will need to be done eventually, but I thought I could add that later after the core system is running. I’m also not taking a collidableObject
‘s rotation into account at the moment. This will obviously need to be implemented but it shouldn’t be difficult at all. I’ll need to look through the code to confirm this but I believe that the collider has a hard-coded radius of 1. Since the base unit in Lyridia is 1 meter, a collider sphere with a diameter of 2 meters is really just too big for a humanoid player character, so that will need to be adjusted.
My next step is to take my CollisionSystem class and bring it into the rest of Lyridia’s code base. The only real challenge with that is that the player doesn’t move based on velocity directly right now, but that should be easy to change.
Collide and Slide!
Planning and DevelopmentI haven’t done a ton of testing with it yet but it looks like I have successfully implemented collision response a la Fauerby’s paper. I’ve only tried against a simple box but it is absolutely beautiful to watch a sphere collide with the box near the edge and just slide over until it’s past the edge then continue on its merry way. The code listings from the paper are, in my opinion, an absolute mess. I just don’t like code that follows this structure:
var object;
function doSomething(object) {
object.prop = “value”;
object.otherProp = “otherValue”;
}
doSomething(object);
if (object.prop == “value”) {
// whatever
}
I don’t like it when a function changes the properties of an object passed into it as a parameter, and Fauerby’s code does a bunch of that. Maybe that’s a very common practice for some programmers but it drives me crazy because it becomes very difficult to follow the values of an object’s properties. So I’ll be rewriting all that code but regardless of all that it seems to be working! So exciting. Once I’ve refactored this code I’ll integrate it into the rest of Lyridia’s code, then test some in the world and as long as everything looks good I’ll definitely release a new version at that point. So stay tuned.
Collisions update, again
Planning and DevelopmentThe collision detection system is still moving along. I can now test a sphere against an arbitrary triangle and if there is a collision the sphere simply stops. This works whether the sphere hits the face, vertices, or edges of the triangle. I also made a simple test case with the sphere moving against a SphereGeometry mesh in THREE.js. This just basically involved looping through all of the faces of the sphere to test for collisions. That simple test seems to be working but I’m reserving judgment until I have done much more testing. Specifically it would be really nice if I could load an object modeled in Blender with a custom, hidden collision cage and see if that works. That’s the ultimate goal since I don’t want the collision system to test against the relatively complicated geometry of the objects visible in the world, but rather against a set of hidden, simpler geometries custom made for each object. I think this should be fairly straightforward to pull off.
The next step, after I’ve tested with some other objects, is to implement collision response. Right now if the sphere hits an object it just stops. For a game, when the sphere hits an object it needs to slide along the surface of that object. The paper I’m following includes a collision response code listing, so hopefully converting it over to Javascript will be pretty easy as well.
Collisions update
Planning and DevelopmentI’ve been working on collision detection and I think my previous optimism from having worked on this stuff a pretty good bit before was well founded. So far I have implemented the simplest case of collision detection from this paper. So with a single triangle and a sphere moving around in space the sphere stops at the surface of the triangle no matter how it is oriented. The sphere doesn’t react to the collision, it just stops. It also doesn’t work if the sphere hits an edge or vertex of the triangle. I just haven’t implemented that part yet. Still, it’s exciting to have this much done. The paper describes using ellipsoid space so that a single ellipsoid can represent a humanoid character. This is fine but I think I would rather use two equally sized spheres, one at the top of the capsule representing the player, and one at the bottom. This may require twice the checks, but I also don’t have to worry about world space versus ellipsoid space. In any case, I’m going to get sphere-mesh collisions working correctly, then I’ll decide whether to use ellipsoids or two spheres. I’ll have a demo of basic collision detection up soon.
Collision detection
Planning and DevelopmentYep, the next step is definitely collision detection. I’ve tried this before so I have some context to start from so hopefully I can get something in place pretty soon. I was thinking about collision detection on a long drive yesterday and I think I’ll need to split collision detection into at least three different types. First, normal collisions between the player and the environment. This will be the most complicated type of system because I need to detect and respond to collisions between a capsule representing the player and arbitrary meshes in the world. Second, collisions between enemies and the world. I think I can simplify this to sphere-sphere collision detection by simply defining the collision zones of all objects as oversized spheres. Some things don’t lend themselves well to being defined by spheres, for instance a fence. But it doesn’t matter if an enemy will never walk right up next to any particular object in the world. It won’t look weird if a boar is never standing right next to a fence object, just as long as no boar ever walks through the fence. I think the sphere-sphere collision system will be needed because these collisions will have to be handled by the server, and there are potentially a lot of those to calculate multiple times a second. Third, I’ll need to be able to calculate collisions between players and enemies for battle. If you swing your sword I need to know if you are close enough to an enemy to hit it. I think I can use the raycasting capabilities built into THREE.js to do this.
I’ll start with the hardest general case, then maybe the others will be pretty straightforward. This will take me a while and I may not post many updates while I’m working on it, so stay tuned.
Screenshot
Planning and DevelopmentShader testing
Planning and DevelopmentI’ve been digging around in THREE.js and one of the bits that’s always confused me is shaders. I’ve been writing software for some time but every time I look at shader code I just get completely confused. I found a little “shaders for beginners” page today and it’s helped fill in some of the gaps. The primary reason it’s so confusing (at least when using THREE.js) is that THREE.js does a lot of the grunt work for you and that hidden grunt work makes examples incomprehensible if you don’t know what THREE.js is doing in the background. Since I understand that a bit better now it affects some design choices going forward. For instance, I am now convinced that implementing splat maps for the terrains in Lyridia is completely doable. It will require some custom tools to do it well but I see no reason I can’t use an essentially arbitrary number of textures for each terrain chunk and mix them together with a shader.
This is a really big deal because using textures for the terrain means I’ll need to use textures on every other asset as well. I’m not 100% ready to pull the trigger on this yet but I definitely want the game to have as wide an appeal as possible and a world with textured assets will be more familiar to more players so the decision might be made for me already. We’ll see.
Design choices
Planning and DevelopmentLyridia is getting to the point that it would be helpful to start making some concrete design choices. For instance, what’s the overall look that I want for the game? Am I sticking with the super-low-poly thing or a more traditional style with textures? It would also be helpful if I knew how some of the game mechanics were going to work, like NPC interactions, fighting mobs, etc. Unfortunately, I don’t know any of those things. And I guess that’s really the primary advantage of developing the game iteratively. I can add assets to the world now and then just update them later if they no longer fit the style of the game. Ultimately it creates more work but I really don’t have the resources to plan out the entire world before implementing it. Again, I realize this isn’t the “correct” way to do things, but it’s the only way I see making any progress. So for now, and for the foreseeable future, ugly, simple, awful art assets will be used in the game. The main thing is to just keep moving forward no matter what. At some point I will either hire some help or ask for help from the (currently non-existent) community of players to create better quality art assets for the game.
Penrith Forest 2018.05.31
Planning and DevelopmentAs the last day of May comes to a close I thought I’d post the state of Penrith Forest right now:
It’s a little hard to tell from the screenshot but the character is standing on a hill, not just floating ominously. Anyway, you can see here that I’ve been taking advantage of the new terrain editing tools. I made a ring of mountains all the way around Penrith Forest. Right now you can just walk up and over them, but eventually they will be a barrier to players going where they aren’t allowed. I also added some more trees, although many more are needed. I’m a little torn because the trees in a little game you may or may not be familiar with are HUGE!
The trees in Penrith Forest are big, but not that big. The great thing about huge trees is that they take up so much screen space and very easily keep the world from feeling empty. This is a technique I may have to use because in the screenshot above I increased the fog distance by about 200 meters so you can see pretty much everything at once but eventually I’d like to keep that distance fairly low and have assets load dynamically for efficiency’s sake. But if the world feels empty because you can only see things less than 100 meters away that’s not going to work. Maybe huge trees (and huge buildings, for that matter) will help take up a lot of screen space so that it feels like you are “somewhere” all the time. We’ll see.