How to write more flexible game code

  Рет қаралды 20,696

The Shaggy Dev

The Shaggy Dev

Күн бұрын

Пікірлер: 57
@diegonorambuena4194
@diegonorambuena4194 Жыл бұрын
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 Жыл бұрын
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.
@TheShaggyDev
@TheShaggyDev Жыл бұрын
Thank you! Glad you find it useful!
@Microphunktv-jb3kj
@Microphunktv-jb3kj 5 ай бұрын
4:32 - or use ECS ;D
@learningforever957
@learningforever957 Жыл бұрын
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!
@learningforever957
@learningforever957 Жыл бұрын
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 Жыл бұрын
For sure! I've finally gotten myself in the habit of mostly just doing it right the first time and haven't regretted it.
@pythonxz
@pythonxz Жыл бұрын
I love that you go over "Tell, Don't Ask.". Everyone should read The Pragmatic Programmer.
@TheShaggyDev
@TheShaggyDev Жыл бұрын
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 Жыл бұрын
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 Жыл бұрын
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 Жыл бұрын
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.
@queenofsquiggles
@queenofsquiggles Жыл бұрын
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!
@TheShaggyDev
@TheShaggyDev Жыл бұрын
Thank you! Glad you enjoyed it!
@circusmonkey28
@circusmonkey28 6 ай бұрын
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
@bugimplementer
@bugimplementer Жыл бұрын
The final tip is so true!! Thanks for the reminder. Great video.
@pabletoday9782
@pabletoday9782 8 ай бұрын
These videos of yours are masterpieces
@juanloutech2864
@juanloutech2864 Жыл бұрын
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!
@TheShaggyDev
@TheShaggyDev Жыл бұрын
Thank you!
@realMenta
@realMenta Жыл бұрын
Thank you, really nice tips and easy to understand.
@pedroehler
@pedroehler Жыл бұрын
The most important thing "it takes time"!
@ozanmrcan
@ozanmrcan 2 ай бұрын
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.
@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.
@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.
@psyboyo
@psyboyo Жыл бұрын
Super useful video!
@ThunderThoster
@ThunderThoster Жыл бұрын
Love it! Many thanks for your enlightenment _/\_
@TheShaggyDev
@TheShaggyDev Жыл бұрын
Thanks! Glad you liked it!
@RobertoMaurizzi
@RobertoMaurizzi Жыл бұрын
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 Жыл бұрын
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 Жыл бұрын
@@TheShaggyDev Thanks! I'll try to experiment a bit 😄
@UhGoomba
@UhGoomba 8 ай бұрын
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 8 ай бұрын
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.
@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.
@Portponky
@Portponky Жыл бұрын
What games are at 0:22 and 1:47? Also, really good video!
@TheShaggyDev
@TheShaggyDev Жыл бұрын
Thank you! First game is Tile Cities and the second is Mini Motorways - both are fun, puzzlely experiences
@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
@McHumaty
@McHumaty 10 ай бұрын
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 10 ай бұрын
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 10 ай бұрын
@@TheShaggyDev ...it gives me a good headache, but I'm still lost on the solution. rs
@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
@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.
@krzyszt0fus
@krzyszt0fus Жыл бұрын
Cool
@trainzmarcel2074
@trainzmarcel2074 Жыл бұрын
all my homies hate object oriented programming
Communicating between game objects with the observer pattern
6:53
The Shaggy Dev
Рет қаралды 7 М.
لااا! هذه البرتقالة مزعجة جدًا #قصير
00:15
One More Arabic
Рет қаралды 52 МЛН
11 tips for writing cleaner code
7:19
The Shaggy Dev
Рет қаралды 10 М.
How to make a tactics game in only two weeks
19:00
The Shaggy Dev
Рет қаралды 74 М.
An introduction to Utility AI
8:57
The Shaggy Dev
Рет қаралды 9 М.
Stop Fighting! Systems for Non-Combat AI
28:32
GDC
Рет қаралды 26 М.
A new way to generate worlds (stitched WFC)
10:51
Watt Designs
Рет қаралды 525 М.
Dear Game Developers, Stop Messing This Up!
22:19
Jonas Tyroller
Рет қаралды 706 М.
Advanced state machine techniques in Godot 4
13:02
The Shaggy Dev
Рет қаралды 29 М.
Adding Tons of Levels to My Indie Game
6:39
Goodgis
Рет қаралды 79 М.
Why Didn't He Get the Job? Let's Find Out! // Code Review
27:25
The Cherno
Рет қаралды 105 М.