- Published on
Devlog #5 - Zones, Movement, & Data Design
NOTICE: We just blew past 40 Gamer tier patrons! Welcome to all you Gamer's out there and if you haven't become a patron yet, what are you waiting for? Join the Gamer tier today and log in to https://fantasyonline2.com/ to view your rewards!
And hello to another devlog. The year is 2023 and it's still winter. That's all I know.
I started off by translating mouse clicks from screen space to 3D world space and then hit testing them against the tile map plane. This hit detection will allow us to move the camera around when the player moves. Right now it's jumpy but I'll smooth it out later. Now I'll send the player's position from the server to the client and position the camera based on that. Then we'll move on to send movement commands to the server.
I moved the main camera to the noob island new player spawn location and realized the camera was zoomed too far out, so let's adjust it to look like FO.
There we go, zoomed it in and it nearly matches tile size of FO. Everything's just much larger on a larger screen! Let's see how it would look on a smart phone.
Map looks great! UI will definitely need some scaling work but it looks generally awesome. Once I get a bit more done I'll test it on a mobile browser and it should just work!
Now before I spawn the player I need to setup some containers on the server side. We at least need zones and we need something to hold the zones, let's call them worlds. So we have Server->World->Zone. That way servers can potentially have more than one "world" and worlds can possibly make more than one instance of a zone. Zones will be rectangles positioned by the bottom left corner. So we need id, width, height, position, name, map file, and more later. So let's create a new MySQL table to model this. Ok, all done, and it's called ZoneDefinition. Now I need to make a ZoneDefinitionTranslations table for the names... and done.
I'm taking a detour to setup the player names table in MySQL as I'm filling out the basic player info on the server. This includes id, name, position, direction, zone id, health, etc. Player names are unique and I've decided to make them 2 to 16 characters. And there we go Gamer was created at 2023-03-05 15:41:18 UTC. Now I'll load the name on the server and get back to designing more of the player data.
So on the server side the player currently has inventory data which is your bags, equipment, bank, anything to do with items. Then we need our location data which is the position, direction, zone id, etc. And of course we need display data which is our body, face, hair, etc. And lastly, for now, we need our player identity which is the player's id, name, and I guess that's it for now. Later we'll come back around to add skills, quests, guilds, etc.
Ok, that's all setup in the database and on the server side, now we can send the initial player spawn message to the client. That is once we have zones modeled on the server. Ok, got a simple model going that I will update as I add more functionality. Now I can send the zone spawn message to the client and I'll have to start setting up how players and enemies are represented on the client.
Before doing that I'm going to look at FO and AO codebases to see how I dealt with this in both. I'll wittle down what I don't like or don't need and use both to come up with a new solution. This part of how I handle players and enemies is very different between FO and AO. In FO they were completly separate things and in AO they were all "Actors" that shared a lot of code for fighting and movement. I never really liked either approach totally so I'll study this code and decide on how to model it for the third time.
AO has so much code for dealing with 3D models and animations. It's so complex and I can just throw that out for now, ha. FO's animations are extremely simple, so I'll setup a class to hold the player's sprite and animate it soon, but for now I'm just going to use a basic body sprite.
In FO we have an "Entity" class which is the base class for both "Player" and "Mob" classes. It contains id, name, and x/y position. The class that extends "Entity" is "MovingEntity" and this handled all movement. The class that extends "MovingEntity" is "AnimatedEntity" and contains all the sprite information. The class that extends "AnimatedEntity" is "FightingEntity" which of course handles all combat. Then there is the "Mob" and "Player" class which extend "FightingEntity" and those are the top classes. This approach was very messy and not well thought out but hey it worked.
In AO we have an "Actor" id which is just a number. Taking inspiration from the design of Unity, AO's system was component based. Instead of a bunch of classes extending each other, each "Actor" id had several component classes associated with it. This approach is much more versatile and leads to much easier to maintain code. So "Actor" ids could have "Mover", "Fighter", and "Appearance" components that could be attached. We'll go with something like this for FO2.
I'm going to stop and setup source control now. I should have done this at the beginning but I'm dumb sometimes. I'm going to use https://bitbucket.org/ as they allow for free private repositories. Ok, got a repo setup for the client and the server. Now we're official.
And now I've setup the start of actors on the client and I'm sending the spawn message from the server and boom we've got a little dude.
Now let's make him move around. I'm taking the mouse click position, converting it to world coordinates, then sending it to the server as a move message. We'll send the position the client thinks the player is at and the destination. Ok, got that running, but now we need a Java math library. Java has no built in Vector3, Matrix3, etc so I'll be pulling from libGDX https://github.com/libgdx/libgdx/tree/master/gdx/src/com/badlogic/gdx/math. Math code is very easy to get wrong so it's important to pull from a very widely used, old, and well tested library. I could literally spend the rest of the year writing my own math code and not finish it and have it be filled with bugs and performance issues.
And now the server has an update tick thread which runs every 100 milliseconds and this will update the interpolation of the player position. And that's done and tested and working. Now we send a message back to everyone near this player to tell them they are moving. And now on the client we need to parse that message and set our little pixel human in motion.
I then setup movement code on the client which required setting up a main update loop which then interpolates the player's position over time. The loop seems to run at 125 fps on my computer. Now I have to attach the main camera to the main player so it follows the pixel dude around and voila we've got movement around the map. No collision detection yet, but we're moving. I'll need to alter the camera interpolation so it's smoother but that can be done later. Now I can add npcs and shops in order to buy items and fill up my inventory in order to test edge cases.
And that wraps up this devlog. It's been a very productive week as we went from only inventory and displaying Noob Island to spawning players and moving them on the server and client. In the upcoming week I will be working on npcs, shops, little bits and pieces of players, and possibly even the start of skills.
See you in a week or less!
Have Fun & Keep Gaming!