How to write more flexible game code

Поділитися
Вставка
  • Опубліковано 2 лис 2024

КОМЕНТАРІ • 57

  • @diegonorambuena4194
    @diegonorambuena4194 Рік тому +8

    My man, the last tip part hit me hard I have spent a lot of time trying to solve the perfect solution, but whenever I start coding, I freeze after a couple of lines and go back to the drawing board. It's endless rn. Thanks for your words :D

  • @krysidian
    @krysidian 2 роки тому +16

    You don't know how glad I am that I found your channels. It's a godsend of useful and concise information and I really hope more people will find it.

  • @learningforever957
    @learningforever957 2 роки тому +10

    This video is a gem, is CRUCIALfor anyone who is working on any relatively "big" game. For me is the point where I struggle the most, to keep things organized in a way that Im able to look at past code and know exactly where I have to look if I want to check something.
    I enjoy your content a lot! Keep it up!

  • @pythonxz
    @pythonxz Рік тому +1

    I love that you go over "Tell, Don't Ask.". Everyone should read The Pragmatic Programmer.

    • @TheShaggyDev
      @TheShaggyDev  Рік тому +1

      They really should! I also kind of mixed it with Martin Fowler's take on the topic for this video since he brings up some points, like co-locating data is good, but attempting to remove every getter function in your codebase is probably overkill

  • @NicholasGrigoriev
    @NicholasGrigoriev Рік тому +2

    I don't know why, but it's your code example for Dependency Injection, that finally made a click in my head, and I finally understood it. (or at least I hope so). Thank you Sir!

    • @TheShaggyDev
      @TheShaggyDev  Рік тому +2

      Glad it finally made sense! I always liked the saying that dependency injection is "a 25-dollar term for a 5-cent concept". Not too bad once you know it, but the name for it can make it sound like it's something more complex than it really is.

  • @kemeros3562
    @kemeros3562 2 роки тому +3

    Incredibly well made, useful and concise video that hit close to home. The final tip? Oh man, I hear you and i will need to play it in repeat in my head again and again because... i've been learning theory for a year and haven't done anything useful and mostly forget everything i learn because i don't actually use it.

  • @bugimplementer
    @bugimplementer Рік тому +1

    The final tip is so true!! Thanks for the reminder. Great video.

  • @queenofsquiggles
    @queenofsquiggles 2 роки тому +9

    I absolutely love this! The details and the way you explained it was incredibly useful! I'm really interested in good design practices, and this will definitely be a video I reference!

  • @learningforever957
    @learningforever957 2 роки тому +10

    3:45 you nailed it! Is what happens to me EVERYTIME; I know I have to keep things separated, but when I have to add a single thing is like "huh, but creating just a class/script for this.... I can handle this here". And thats how problems start D:

    • @TheShaggyDev
      @TheShaggyDev  2 роки тому +2

      For sure! I've finally gotten myself in the habit of mostly just doing it right the first time and haven't regretted it.

  • @pedroehler
    @pedroehler Рік тому

    The most important thing "it takes time"!

  • @pabletoday9782
    @pabletoday9782 10 місяців тому

    These videos of yours are masterpieces

  • @juanloutech2864
    @juanloutech2864 Рік тому +1

    Very well explained basics of programming (not just game programming)

  • @panampace
    @panampace Рік тому

    I put off making a state machine for my character controller for such a long time because I thought it was more complicated than it was worth - BOY was I wrong. Setting up a state machine ought to come first in a character controller - makes it SO much easier to add functionality without screwing up another part.

  • @spudrat
    @spudrat Рік тому

    wowwww this channel is so underrated, just found you, really sick!

  • @mbg4681
    @mbg4681 Рік тому

    Well said, all of it but especially that final tip. Reasonable, approachable, fun, candid, considerate advice! You sound way too young and spry to be this wise already.

  • @realMenta
    @realMenta 2 роки тому +1

    Thank you, really nice tips and easy to understand.

  • @circusmonkey28
    @circusmonkey28 9 місяців тому

    The Final Tip is the only tip that made sense to me which means it is too early for me to watch this video xD

  • @ozanmrcan
    @ozanmrcan 4 місяці тому

    i will watch all your videos

  • @Rin-qj7zt
    @Rin-qj7zt Рік тому

    you should mention that assumption of structure is actually fine in cases where the architecture is specifically designed for that to be the case. for example, every major location could be a sibling of the same parent node by designe, so they can be switched in and out of memory like legos. assuming that the parent has the same resources it always does is fine, because we never intend on putting a major location anywhere else in the tree.
    it's okay for some structure to be designed not to change, and this grants some level of flexibility when coding because it allows an assumption to be made. it depends on what advantages you gain compared to the advantages of staying dynamic.

  • @psyboyo
    @psyboyo 2 роки тому

    Super useful video!

  • @ThunderThoster
    @ThunderThoster 2 роки тому

    Love it! Many thanks for your enlightenment _/\_

  • @RobertoMaurizzi
    @RobertoMaurizzi Рік тому +1

    Very good video (but yeah, I found your channel yesterday and all your videos are REALLY good :D).
    How would you manage things like driving a camera for a (sub)viewport?
    Situation: I'm scoping the effort required to make an old skool dungeon crawler game for a friend whose programmer ran away. I have a UI composed of different panels (main 3D window, health, inventory, character status and equipment, mini map, commands, direction, text area because the game has a visual novel component, time of the day, ...). The game will probably have multiple levels and I can't decide if I should put all the levels and the player under the viewport, or try to drive a remote camera from the player using a RemoteTransform3D or some bit of code that fetches the remote camera and drives it...
    Also: where to put the levels? 😵‍💫

    • @TheShaggyDev
      @TheShaggyDev  Рік тому +2

      Glad you're liking the content!!
      Hmm, that's a tricky one. For something like a dungeon crawler (which I'm also assuming will be entirely / largely UI driven and the camera is really just a lens into the level's content), I would probably have level contents within that viewport and pass camera and other commands to it from the UI. That would also let you swap levels on the fly while still keeping the main UI on screen if that's something you want to do.
      But it's really probably something to just try out and see what happens. Pick whichever one feels "most" right to you and try to minimally implement it and see how good / bad of an idea it was after all! That's what I always do when I can't decide.

    • @RobertoMaurizzi
      @RobertoMaurizzi Рік тому +1

      @@TheShaggyDev Thanks! I'll try to experiment a bit 😄

  • @badunius_code
    @badunius_code Рік тому

    5:40 that's where I'd argue in favor of using signals.
    Because what is presented relies on having a very specific owner.
    Signals otoh allows owner to listen to the ones that are relevant and interpret them in its own way

    • @TheShaggyDev
      @TheShaggyDev  Рік тому

      The tricky thing is that signals are for fire-and-forget purposes where you don't care if anyone is listening, but for something like a state machine you probably do want some amount of ownership over the object as you may need to call specific functions on it or receive values from it in order to operate properly.

    • @badunius_code
      @badunius_code Рік тому

      @@TheShaggyDev true, but imagine the object under control is currently unable to move, say, left. Or the object is under "disorientation" effect or "paralysis". Either controller should be aware of all of this possible condition, or it might make the object behave against the rules and expectations.

    • @TheShaggyDev
      @TheShaggyDev  Рік тому

      @@badunius_code In those examples, I would let the states know about such conditions. May be a matter of taste, but I want my states to be the authority on things in their domain.

    • @badunius_code
      @badunius_code Рік тому

      @@TheShaggyDev true, but here's another one: you can easily switch from a FSM controller to a Player Input controller without duplicating controller's owner related code as long as they implement the same interface

    • @TheShaggyDev
      @TheShaggyDev  Рік тому

      ​@@badunius_code These are all fair points but that's honestly just not something I would worry about. I think you run the risk of making more work for yourself by crippling the state machine and adding more layers of abstraction for something that probably won't be required most of the time.

  • @UhGoomba
    @UhGoomba 10 місяців тому

    How do you use components in practice? If I need to hit a character (from a bullet, for example), how should I get the character's health component? Do I check if the character has a health component child, wouldn't that violate the first principle? Or should I make an additional take damage function in the character that sends it to the health component? That seems over complicated. I would love to see how you have done this

    • @TheShaggyDev
      @TheShaggyDev  10 місяців тому

      There's a little bit of a variance to how I tend to use components, depending on if the component is for "internal" use or not. For an internal component, like an AI controller that shouldn't be accessed outside of the character, just exporting a node of the correct type can suffice to let me modify behavior as needed and keep code more compartmentalized.
      For something external, like with your example of a bullet hitting a character to deduct health, you could flip the approach and have a component in the character that can react to bullets rather than having the bullet check the character for specific functionality. Oftentimes, this may be what you want anyways as you may have instances where you need to modify whether or not damage is taken or how much is taken based on other properties of the character (defensive powerups, i-frames, etc). Of course, you now have to figure out how to let the bullet know it has hit something but it's probably simpler in its structure than a character and, depending on the game, even just a simple type check may be enough to know what you're working with.
      If you do find yourself needing to check for the presence of a component on another object, you may want to expose a pass-through function on the top-level node and check for that, since checking for component names or something like that could be finicky. Not my first choice of approach, but sometimes it can make sense.

  • @JacobKinsley
    @JacobKinsley Рік тому

    Does stuff like "@export var entity: Rigidbody" count as dependency injection?

    • @TheShaggyDev
      @TheShaggyDev  Рік тому

      I would say it does, as it lets you decouple your code from a specific instance of your dependency.

    • @JacobKinsley
      @JacobKinsley Рік тому

      @@TheShaggyDev 2 days later and I forgot what dependency injection means, but I have used @export var in a practice game I made

  • @SLSat
    @SLSat Рік тому

    Loved the video, one question though
    0:42 when you say "player code access" do you mean the player's children can have access to the parent's code, or the other way around (the player being able to access its children code?)

    • @TheShaggyDev
      @TheShaggyDev  Рік тому

      It's from the perspective of the Player object. So the Player code should generally only access the Sprite out of the items on that list, but not the Level or Bitmap Importer.

  • @snowman7514
    @snowman7514 Рік тому

    in godot you can use export player:NodePath or in gd4 @ export player:KinematicBody2D, idk if this is the dependency injection you are talking about

    • @TheShaggyDev
      @TheShaggyDev  Рік тому

      Yep, that's definitely a form of dependency injection! In addition to exports, FuncRefs (or Callables in Godot 4) are another Godot-specific tool for dependency injection, though oftentimes just passing some data from the parent to the child can also serve this goal

  • @McHumaty
    @McHumaty Рік тому

    Let's suppose I have a skill tree and they are released as the player progresses and chooses the path they want to follow when creating their character (build). Can each of these skills be a component? Can I put them in a database and add them to the player? I say this because there may be enemies in the game that have common skills that the player can choose.

    • @TheShaggyDev
      @TheShaggyDev  Рік тому

      Hmm, in cases like this the concept of separating data from presentation comes to mind, so my immediate thought is to store as much data about the actions externally to any one character as possible, since it needs to be shared, and then think of a way to let the player and enemies select and activate their actions. Could be a component that makes an action available, could be just a data structure that pulls in the data for their available actions to activate it, etc. Would need to think on it.

    • @McHumaty
      @McHumaty Рік тому

      @@TheShaggyDev ...it gives me a good headache, but I'm still lost on the solution. rs

  • @Portponky
    @Portponky 2 роки тому +1

    What games are at 0:22 and 1:47? Also, really good video!

    • @TheShaggyDev
      @TheShaggyDev  2 роки тому +1

      Thank you! First game is Tile Cities and the second is Mini Motorways - both are fun, puzzlely experiences

  • @krzyszt0fus
    @krzyszt0fus 2 роки тому

    Cool

  • @Niohimself
    @Niohimself Рік тому

    If two objects in a hierarchy can depend on their parent, but not on each other or their children - does that mean we are not allowed to take things that depend on each other, and make them into objects? I prefer to have lots of small, manageable objects rather than one big god object that knows about everything, but two cooperating parts of the same whole necessarily know about each other, which breaks encapsulation.

    • @TheShaggyDev
      @TheShaggyDev  Рік тому

      An object can depend on its direct children, you just don't want to dig multiple levels down. And you can absolutely have two cooperating objects in one larger object, and certainly don't need a god object for everything, as that's also not great design imo. What you're describing is essentially what I'm talking about with making small, resusable components.
      The question to ask with that is how will the two side-by-side objects know about each other? A hardcoded path to the other isn't ideal, but the parent object that owns both of them CAN know they exist and can coordinate the appropriate dependency injection.
      Of course, no one's going to strike you down for telling the two siblings about each other directly, you'll just make it harder on yourself if you need to later break them up or reorganize things.

  • @trainzmarcel2074
    @trainzmarcel2074 Рік тому +1

    all my homies hate object oriented programming