Orion, how you doin?
I joke you not when I tell you that checking your repo last commit its one of my first things in the morning, great work and very fun to follow.
And I just created this account to ask you this:
Have you thought about implementing a tiled-based movement?
Id love to see your approach to that!
I think any combat system (pvp/pve) would be positively affected by it. In my personal opinion, is overall funnier when you are not just a free hitbox spinning and colliding around.
If not, any insight in how can I achieve something like that myself? I could make a fork.
Thank you!
edit: im also thinking about Minecraft and how chunks are loaded/managed. Even when entities have free-movement everything is inside a grid (with lot of benefits).
@ozmuye thanks for the kind words, and welcome to this awesome forum. I’m glad people are enjoying watching my progress
To be honest, I’ve never considered tile based movement, but I would say it should end being easier to implement in multiplayer than a “free hitbox running around” as you say : no need for a navmesh, less affected by lag, and more I’m sure.
I’ve never done this, but here’s how I would go about it to get the basic tile base movement done:
on the server, make a virtual grid that represent your world and the positions where entities are allowed to be (sounds simple, but start simple like a cube of 10x10)
on the client, send to the server every arrow key press event
on the server, use that key press event to determine the next tile position,
on the client, lerp from current tile position to updated tile position
in the end, it’s not that different from I’m doing anyway.
About the loading/unloading of entities in a range around the players or in a grid, I know I’m going to have to dive into that one day, but I’m not sure I’m good enough to tackle this one yet. I would not even know where to start.
About the loading/unloading of entities in a range around the players or in a grid, I know I’m going to have to dive into that one day, but I’m not sure I’m good enough to tackle this one yet. I would not even know where to start.
On that, I would do something not too crazy.
(hidden cause I wouldn’t dare to off-topic this master-piece of thread)
Summary
Define a square chunk size (preferable a little bigger than player’s desired viewport + some margins). If you are at a border, load neighbors too. To a maximum of 4 loaded chunks in a corner scenario.
What do you get? A GRID! haha
You load all the entities in those chunks. Every time you modify an entity you can easily calculate if this entity is “touching” any border and broadcast the new state to all three neighbors chunks (and itself).
This way you can jump borders back and forth without problem and you also give other players some time to load your awesome skin.
Then, when you are too far away from a chunk, forget about it and everything it has. Kill them. Make space from whats next. You can add some quadrant magic to it if you like maths. I do not.
did a massive refactoring ( merged entity and player classes and states on both the server and the client and extended player class from the base entity class, it was something that needed to be done for a long time )
added the concept of race with attributes (in my example: Bear, Unicorn, Hobbit Player)
added an animationSpeed to each “race” to achieve better looking animation
I like your solution thanks, and I will work on something similar to that in the future.
Until then, I found a “very basic” solution to only load entities in a range around a player, which works pretty well, and I can now have many more entities loaded than before.
// only enable entities in a range around the player
for (let sessionId in this.entities) {
const entity = this.entities[sessionId];
// set entity to disable by default
entity.mesh.setEnabled(false);
// only check type "entity"
if(entity.type === 'entity'){
// find distance to player
let entityPos = entity.position();
let playerPos = this._currentPlayer.position();
let distanceFromPlayer = Vector3.Distance(playerPos, entityPos);
// if in allowed range, set as enabled
if(distanceFromPlayer < 15){
entity.mesh.setEnabled(true);
}
}
}
I spent a while trying to integrate YUKA to use for the enemy AI with no success as it all become so cimplicated, so I started to work on adding my own enemy AI and after a day work, I’m very happy with the result:
default is all enemies wanders around
at all times, I have a function that determines the closest player for each entity
if a player get’s in a certain range, it starts chasing that player until either
– it gets in range, an then starts attacking player or
– player manage to get away and the enemy returns to wandering
It was the first time doing “AI”, and I enjoyed it very much, and it’s great to see enemies coming alive
After a few fights with ES6 tree shaking and webpack, I managed to bring my bundle.js from 16mo to 550kb gzipped. Demo should be a little quicker to load now
Nothing is easy, but I’m currently quite happy with the ai behaviour, and have started working on next feature, the abity to select & attack units with a fireball ( very simple in single player games but in an networked environment, it’s so hard to get right ).
Currently, you can press digit1 on keyboard and then click on any unit and a firebal will spawn every second until unit is dead, but I’m not very happy with it as it doesnt feel very user friendly. So I’m gonna go with a more standard approach,
Here are my thoughts on how to approach it:
ability select unit with left mouse button
– add a local only highlight to the selected unit
– make sure server knows which unit is selected ?? (not sure about this one, to be tested)
ability to use the keyboard or click on ui to start an attack on selected unit
– send server click/keyboard events
process attack on server only
– rotate player in direction of target ?? (not sure about this one, to be tested)
– check on server if current selected unit is in range & player is not in cooldown
– if already attacking, cancel current setInterval
– start a setInterval each 1s until unit is dead
— select unit loses health
— send player attack confirmation with latest attacker position and selected unit position
Process attack on client
– client can spawn a fireball and move it from startPos to endPos (we have to use server positions because on the client, everyone is “in the future” and positions would be different)
I’m sure I’m forgetting lots of steps but as you can see even for something that seems very simple it can get very quickly quite complicated
I’m looking forward to get started on easier things if there are such a thing
In the meantime, to relax, I started working on the ability bar and I’m not far off, I just need to find a way for each button height to be proportionned to the width else icons looks stretched
@oriongu, I love reading your progress on this thread since the beginning. It is fascinating to see the game is taking life !!! Please, keep sharing !!!
Ok, so I’m getting to point where I’m going to have to decide where am I going with this project before I go any deeper, indedd I need decide whether it is:
an open source project to help & give everyone some sort of good base to start with
a personal coding challenge and see how far I can go & learn in the process
a potential game I’d like to release / commercialise
all three at the same time?
So let’s do a quick retrospective:
In august 2022, I decided to put in a bit of time every day into making a game with these goals in mind:
– could hold 20-25 people playing simultaneously
– top down rpg similar to t4c (the 4th coming)
I started in oct 2022 just playing around with babylon.js and colyseus
I posted my first post on november 2022 so I could share my progress
366 commits later and 3 months later, I’m starting to have a solid little prototype working:
— fully authorative movement with client side prediction and server reconciliation
— server & client controlled collisions (client reconciles from server)
— simple scene management & switching
— networked animated characters
— networked NPC entities with basic AI
— health and mana stats
— 2 working abilities (Fireball + Health)
— zoning system (ability to teleport to different location)
— login / character selection/creation scene
— database persistence
— global chat
Addionnally, as you all would know, there are alot of things that you cannot really show but are also important:
how to format & bundle correctly with webpack and import dependencies to minimize bundle size
how to setup a workflow for the level design between blender, unity and babylon
how to prepare and export a navmesh
how to setup a working demo (that is easily updatable from every github commit)
how to organize & structure your code to keep it as dynamic as possible (probably where I spent the most of my time: refactoring loops)
How to code in a networked way and make sure client never decides of anything and if he does, reconcile it from the server. Fake it on the client basically
So in regards to my initial roadmap, I’ve exceeded it and more. The result is that I’m feeling much more confident in my abilities that when I started so I want to be a little smarter into where I put my time and make a plan/roadmap/goal for the future.
I’d love to hear your toughts on this matter? Maybe some of you have been in the same situation? In all cases, I’m going to be thinking about this over the next few week and will get back with a plan/roadmap.
Last but not the least, a big thanks to the whole Babylon.js community for the continuous support & encourgement! You’re the best!
I enjoy seeing the updates on your project in my github feed, I typically jump to your games website to see the progress towards the end of the night. It’s inspirational.
Having it opensource this entire time I believe helps with maintaining an audience. Perhaps, some community members might jump in to help out in the near future (you never know). It could possibly be a community project if that happens (that would be pretty cool).
But hey I get it; you dump a lot of time into developing and refactoring the code to get it just right. However, there’s still a ton of things you have yet to do and this opensource project could be your guineapig, or better yet your first draft. You can get it to a state where you are somewhat satisfied and then fork into a private repo.
www.draxus.io was my first go at babylonjs, I guess you can consider it my first draft. I did not opensource it since I was learning JavaScript at the same time and the code was a whole lot of spaghetti, super slopy. had multiple attempts to refactor it, and didn’t think it was worthy enough for others to study. It became such a huge monolith that I decided to desert it. I definitely learned a lot though from that project, maybe I’ll come back to in the future. Since then I’ve pursued a new project (which I am still working on in my spare time) and the code is starting to scale just right (meaning no refactoring is really needed).
I say keep it opensource to grow an audience (you’re going to need players when you release it, why not have a couple from babylonjs community)
Let me add @Deltakosh for his open source wisdom and @PirateJC about the turn it could take.
From my point of view, what you achieved is already amazing and you can now only pile more greatness on top of it. I love open source as it is a huge motor for me in both awesomeness (they ll cheer you when things are great) and as a mediocrity shield (they ll help catching early issues so they do not creep too long)