3
\$\begingroup\$

for a personal project i started making a 2d game engine in C++ that uses sfml. The idea is having base "game object" classes from which a game will inherit.

Right now i have:

Game_engine class which has a run method that takes care of the game loop (fixed timestep loop). The loop consists in:

  • dequeuing SFML window events
  • step
    • dequeue networking events
    • call step function for each Object instance
  • draw
    • call draw update function for each Object instance
    • call draw function for each Object instance

Resource_manager class which takes care about loading and holding resources and holding animations.

Animation and Animated_sprite, where animation exists only once per animation, has a pointer to the texture and a list of the frames, while animated sprite is a child of sf::Sprite and there's one instance per each instance of a game object. Animated sprite points to its animation and frames are updated when Object's draw_update is called.

Logger class, which queues up strings from the engine thread and uses a second thread to write the strings to file without the main thread suffering from write-to-disk delay

Networking_client class, which queues up networking packets in a secondary thread, and returns the queue to the Game_engine when it requires it for the networking part of the step.

Object class which is the basis on which an actual game's objects will be built. It has by default vertical and horizontal speed variables, and function to set them both as vertical and horizontal components or as speed and direction. It has both a sprite with its coordinates and its own coordinates. Sprite's coordinates are used by sfml to draw and will be updated with interpolation when draw_update is called. The own coordinates are updated when the step function is called, which in an actual game will take care of checking collisions and stuff like that.

Up until that point i really did everything kinda by instinct, but now i don't know how to design networking managed objects. Ideally i would have a server which runs the game without the drawing part, only the fixed steps, and holds information about all connected clients. My issues are not about lag compensation right now, but about how to deal with these classes.

When i shoot on my client, i would tell the server i shot, the server creates a projectile and its creation is sent to all clients together with an id that identifies the networking object for future updates (changes in direction, destruction). However this adds a delay in the client when it's shooting its own projectile. If i create the projectile in the client first and tell the server about its creation, the client can cheat about its coordinates. If i create the projectile individually in both, once the client receives the information "create projectile" from the server it can't tell it's its own already existing projectile and not someones else's. Same issue when a client is changing it's controlled object's direction...

Can i get help designing that? I did something like that in javascript (without lag compensation it was a teleporting fest) but idk i'm finding it harder to design now, because i'm making it more generic, while my javascript project was directly with the actual game objects.


Before anyone tells something like "use an existing engine", part of my interest is actual making my own, after all it's an hobby and i'll likely never publish any game with that, i just enjoy writing such things and overcomplicating my life in a way that ends in never having any concrete result whatsoever.

\$\endgroup\$
  • 1
    \$\begingroup\$ When you said you started making your own game engine, do you mean you only have designs right now? Unfortunately this is not a site to hire people. Is there something specific you are stuck on? \$\endgroup\$ – TomTsagk Aug 8 at 12:54
  • 2
    \$\begingroup\$ I don't think an inheritance hierarchy is the right place for this. Not every object in your game needs network replication of its position/velocity (some are static, some need network replication of different properties). So you might instead want to introduce a notion of a NetworkTransform or NetworkBody component that an object can have rather than something it is. This is the principle of composition over inheritance. With that in mind, could we phrase your question to be about the replication issue, not your object class? \$\endgroup\$ – DMGregory Aug 8 at 13:00
  • \$\begingroup\$ @TomTsagk i wrote the actual code for all i mentioned, but my imagination is stuck when it comes to objects that must be synchronized over the network. I can't code that without a concept idea. \$\endgroup\$ – Barnack Aug 8 at 13:35
  • 1
    \$\begingroup\$ @DMGregory that's why i have an Object class for all ingame objects, and will have a Synchronized_object class which inherits from Object and takes care of sycnrhonizing movement and creation. Anything in a game that needs to be synchronized will be a child of Synchrnoized_object and won't have to do anything explicitely about networking, the base class will take care of that. Anything that is only local doesn't need to inherit from Synchronized_object, just from Object. Considered i want a "game object" to be transparently using the engine features, i think inheritance is better here. \$\endgroup\$ – Barnack Aug 8 at 13:38
  • \$\begingroup\$ @DMGregory a character that moves or a projectile that is being shot IS an object handled by the engine, doesn't HAVE an object handled by the engine. \$\endgroup\$ – Barnack Aug 8 at 13:38
1
\$\begingroup\$

AFAIK, many commercial MMORPGs use a kind of lock-step execution, with a modification of being able to "undo" changes. Each client executes its part of game's code, predicting NPCs, PCs and projectile movement, then consults server to see if the prediction of game state is correct and corresponds with actual movement. So on a laggy low bandwidth connection it is possible to see characters jerking back and forth, and hits not landing in time. True lock-step would be impossible when player count gets really high.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.