Hope you all enjoyed the video! Sorry about Ghost Cherno 👻... have you made a Minecraft clone before? How did it go? Also don't forget to visit brilliant.org/TheCherno to get started learning STEM for free, and the first 200 people will get 20% off their annual premium subscription!
@张向乐2 жыл бұрын
Minecraft!😆
@TheShadoDragon2 жыл бұрын
I'd say Ghost Cherno has it's positives sides as well: You can see the code below the camera. ;)
@rob-8902 жыл бұрын
Why do you ask for comments and then not reply? 😋
@TL-Edu-r2 жыл бұрын
I want to ask how it is that for the video 3D Game Programming - Episode 4 - Drawing Pixels! when I run it I don't see anything there and I proceed exactly the same :(
@greatcesari2 жыл бұрын
Your tone sounded pretty harsh, considering the maker said they're just learning.
@not_herobrine37522 жыл бұрын
"the only design pattern a programmer needs to know is ctrl + c and ctrl + v" -sun tzu, the art of code
@adamhelberg92282 жыл бұрын
Hipity hopity your code is my property -Dani
@nakumjay2 жыл бұрын
Bruuuuuuuuuuuuuuuuuuuh
@ShredBird2 жыл бұрын
Sun "Microsystems" Tzu
@Highwind_2 жыл бұрын
@@ShredBird This would explain Java
@superscatboy2 жыл бұрын
Virgin copypaste Vs Chad *macros*
@toffeethedev2 жыл бұрын
love higher-level design talks like this, optimisations are usually specific to the 1 program, but knowledge about code architecture will never stop being useful
@lukefidalgo81542 жыл бұрын
I think every programmer that's interested in making games from scratch will always go through that phase where they want to make a Minecraft clone lol
@amadeusk5252 жыл бұрын
Minecraft is just a great concept, programming-wise. It's impossible not to have fun while trying to code it, or just trying to understand how one would do so
@makichiis2 жыл бұрын
Recreating Minecraft allows to you to explore many parts of the development process and touches a lot on optimization because of how performance-draining a voxel engine otherwise is.
@eucalypt4442 жыл бұрын
@@makichiis theres no voxel engine in minecraft lol
@makichiis2 жыл бұрын
@@eucalypt444 Is this supposed to be joke? Obviously, since Minecraft is engineless, it’s engine is *internal*.
@eucalypt4442 жыл бұрын
@@makichiis wrong. minecraft uses BrownEngine
@andrewcranston7802 жыл бұрын
When doing code reviews, its always good to keep personal 'feeling' or code style debates out. "I just don't like this" isn't a good reason, and doesn't go far in explaining why someone should avoid using singleton for the top level Application class. You could instead go the 'singleton is hard to test' route, and explain how you'd eventually want to write unit tests and instantiate the application inside a test harness.. if its designed to be statically instantiated that becomes hard to do.
@kukukudoes4582 жыл бұрын
Point It gets annoying when you tell to not do something but don’t point out why
@andrewcranston7802 жыл бұрын
@@kukukudoes458 usually if no actual explanation follows it's because the reviewer is a cargo cult programmer with no original ideas of their own.
@vladimirkraus14382 жыл бұрын
"explicit" is your friend. Unwanted or unexpected implicit conversions can cause a lot of troubles and hard to find bugs. I always use "explicit" unless I am really 100% sure that I want an implicit conversion for that type. Explicit conversion requires more writing but makes the code much more readable and simpler to reason about. It makes the code more type safe and less prone to errors.
@agfd56592 жыл бұрын
It's weird that they didn't make explicit the default now that I think about it.
@vladimirkraus14382 жыл бұрын
@@agfd5659 Yes, it is one the many wrong decisions when designing C++. But back in that time the language priorities were different than they are now. They probably believed that implicit conversions allow for more concise code (which they do) and did not think so much about language safety.
@doglitbug Жыл бұрын
@@agfd5659 I wonder if the author used CLIon and it suggested this all over the place
@noerlol6 ай бұрын
@@doglitbug He did
@doubledispatch66204 ай бұрын
Implicit conversions should be reserved for those that are entirely lossless and can never fail, e.g. an integer to a long integer or a fraction class.
@bloodgain2 жыл бұрын
Additional comments (and disagreements with Cherno's comments): - For a better understanding of the Application instantiation argument here, just look up why Singletons are considered a bad practice. If you're going to use a Singleton in C++, though, _always_ use the Meyers Singleton (thread safe), which you did. On this count, Cherno is wrong and going against widely-regarded best practice. He is right that it's subject to the Destruction Order Fiasco, but if you insist on a singleton, you live with that. Just don't have singletons that depend on other singletons -- as if singleton wasn't a bad enough design! There is another pattern called Leaky Singleton that avoids destruction entirely, but one, if you need that you have a bad design, and two, if you're going to go through the trouble of learning how make a good, thread safe, leaky singleton, you'd be better off spending the time re-architecting to get the singleton(s) out of your design. - While it's an architecture argument, I probably agree with Cherno's critique of your Ray class. However, passing the World into the function like that? That's _exactly_ how you avoid Singletons **and** tightly-coupled code. It's called Dependency Injection, one method of Inversion of Control -- aka coding to interfaces, not objects. Good instinct, if not the best use of it in this case. Still, way better than making World a singleton! - Cherno's argument against using explicit is simply wrong. You absolutely should mark all single-argument constructors as explicit. Not doing so can result in accidental implicit conversion, which adds runtime overhead. All such conversions should be made explicitly, usually by calling static_cast or dynamic_cast. Again, this is _widely_ considered best practice. - Why is it called main? Why not? This is an application, not a library. It's probably the IDE's default, and defaults are de facto patterns. Plus, it's just a learning project, and it could always be renamed later. Code reviews should not be nit-picking exercises. - Class layout is a little bit of a style nit-pick, but in this case, I actually agree. This is the standard layout that other developers expect to find. If you declare it as a struct (public access by default), this signals something a little different to another developer that this is more datatype than functionality, will probably be entirely public, and you can leave off the "public" declaration. Think of these as de facto standards. - Cherno doesn't call you out for not separating your code from your declarations, but I will. If you're going to enclose all your class's functionality in one file, it should be a header (.h) file. But still, separate your code from the declaration, either as "inline"d functions below the class declaration or in a code (.cpp) file. The _possible_ exception is simple one-liners like getters/setters that are only an assignment/return, but separate is better even then. This is another de facto standard, and most style guides enforce it. - If you have a destructor, either write the copy and move constructors and assignment operators, or remove them with "= delete". If you write any of these, you should write all of them. This is called the Rule of Five (formerly Rule of Three before move semantics were added in C++11). - Your "chunks" map is duplicated. Maybe that actually fits your design well, as long as you're not carrying 2 full duplicates of all of them in memory, but it does mean that *the map type is declared in more than one place.* Abstract that out. At minimum, use a typedef, but if "chunks" has responsibilities beyond what unordered_map provides, then it should be its own type with functions. A clue here would be if you're repeating code to operate on chunks in multiple places. - Overall, though, great job. Some of it is pretty clever, actually. Maybe read a style guide or two and check out some C++ best practices guides. Scott Meyer's "Effective" series of books is highly recommended, but there are some good free guidelines and talks out there, too.
@miguelguthridge2 жыл бұрын
That was really informative! Thanks for taking the time to write it. I'm gonna be learning C++ properly (messed around with it in high school) next term at uni so it's really interesting reading all the comments on how C++ code should be written from a stylistic standpoint.
@Bobbias2 жыл бұрын
@@miguelguthridge universities generally end up teaching horrible code style, so it's good to have a handle on what constitutes good code style before heading in :)
@andraskmeczo5752 жыл бұрын
@@miguelguthridge if you let me add to that the most you can learn is writing actual code, because then you'll encounter problems, look at other people's code, take the best of everything and have a good coding style after a while. Especially if you build a bigger project like a smaller but whole game or a game engine you'll inevitable follow the good practices because it will be easier to use than bad practices (or at least this was true for me)
@Astfresser2 жыл бұрын
Great explanation and I agree totally, but I think Cherno meant to avoid the singleton just put the object altogether on the main stackframe instead of having it lying around in global scope, which I would very much encourage. You can just pass your world object to every instance in a functional way and never have to worry about threadsafety.
@FokinDenis2 жыл бұрын
Thank's for information!
@jumpingjoy76892 жыл бұрын
The reason that there is a lot of "explicit" in the code is that the programmer is most likely using clion, which includes clang-tidy, which alerts you about single argument constructors. it is also why you see [[nodiscard]] aswell
@migueldejesustavares41682 жыл бұрын
You should 100% make your own Minecraft Clone tutorial series. It would be such a good learning resource.
@propov18022 жыл бұрын
16:16 C++ CoreGuidelines. "C.46: By default, declare single-argument constructors explicit Reason To avoid unintended conversions."
@neijiagongfu2 жыл бұрын
👆thats a good reason, not just a matter of taste.
@IONATVS2 жыл бұрын
I believe Minecraft Bedrock Edition (ie the modern version of Minecraft Pocket Edition, which is available on Mobile, Consoles, and Windows PCs) has a C++ codebase, as opposed to Java Edition (the Original, available on Windows, Mac, and Linux)’s use of Java (obviously, it’s in the modern name). Maybe it was C#, but in any case, Bedrock is already an entire rewrite of Minecraft in an entirely different language.
@Originalimoc11 ай бұрын
Yes, but most importantly its block algorithm is much more efficient resulting HUGE fps speed up. Not (mainly) because used C++.
@h.hristov2 жыл бұрын
Hi Cherno, could you create your own series on design patterns? I wonder what your take would be on them. Recommendations / pitfalls.
@Ezdiess2 жыл бұрын
He just made a rant over OOP and you expect him to make a video about desing patterns? Highly doubt it
@h.hristov2 жыл бұрын
@@Ezdiess Haha that was the reason I wrote this comment
@spikespaz2 жыл бұрын
He's pretty bad at design honestly, this whole ray casting thing in the constructor was explained horribly and he took too long to come to the conclusion it should be in the world class. Ideally it should be on a behavior interface that anything that can cast a ray can implement.
@Psykorr2 жыл бұрын
This is actually a good idea. Not because design patterns are that omnipotent as many think, but to set up a problem for which a design pattern COULD be a reasonable solution. For example, if you have a program that have different modes, perhaps in a game you have a start menu, some settings, game play, save screen etc. This could for example be done with the state machine pattern instead of a bunch of nestled if-statements. But every body should know that this could be done in many other ordered and 'clean' ways that are not formal design patterns
@DavidSpry2 жыл бұрын
I suspect he's using Clang-Tidy, which is fussy about the use of `explicit` for single-parameter constructors.
@bloodgain2 жыл бұрын
It's fussy about it because it's a widely-accepted best practice. Linters and other analysis tools should default to best practices, and if you decide to go against them, put the onus on you to disable that check.
@DavidSpry2 жыл бұрын
@@bloodgain Indeed, I agree.
@Ben-rc9br2 ай бұрын
@@DavidSprysonarqube also
@beastle9end4992 жыл бұрын
I actually do this with the explicit too if the constructor only has one parameter, because I think it's a better design to have everything explicit by default. This is exactly how you actually make every reference const at first, unless you already know you want to mutate it.
@pantsoff2 жыл бұрын
Yeah, this is very common. I'm not sure why such a big deal was made about this, especially right after he went over how he likes APIs to be clear
@bloodgain2 жыл бұрын
Both are considered best practices. Keep doing them!
@ShinQdan2 жыл бұрын
24:20 It's funny the actual Minecraft is written this way in Java as far as I remember - loads of passing the World object down to entities
@zxuiji2 жыл бұрын
16:07, another reason to put public stuff 1st is to reduce ABI issues when you change something in the private section, if the public stuff is 1st then it will remain in the same ABI spot so long as nothing changes in the public section (or what it inherits from)
@alexanderdonets53212 жыл бұрын
Glad you mentioned that, now I know the name of the general concept (ABI). Recently I've faced only with "binary compatibility" of assemblies in C#, but had a hunch that this is not a language-specific problem. P. S. hadn't got formal education in CS, guess that's why I'm learning this in a weird way :D
@zxuiji2 жыл бұрын
@@alexanderdonets5321 Good to he- er, read, for reference the 2 common terms I'm familiar with for any language is: 1. API, while I'm sure you know what this term means I'll clarify for those who are not, Application Programming Interface, all the functions, variables and constants that can access of a given library &/or system. 2. ABI, Application Binary Interface, what an API compiles down to for the computer to understand instead of humans, even the slightest mis-match can cause the computer to not understand where it should look for a given call, variable &/or constant when it is referenced in the compiled down code
@joelincz83142 жыл бұрын
It's inspiring to see what people are creating at the same time super insightful to hear an experienced person comment on it. Thank you to both!
@Jesus228FBI4 ай бұрын
16:50 "implicit constructors can simplify code a lot" - really cracked me up
@victornpb2 жыл бұрын
while I agree with most of the criticisms, I find that a lot in this video comes down to personal preference, and the author didn't do anything that is specifically bad. I think it's important to separate what are "do's and don’ts" from "there's this other way some people prefer", this discrimination is something very important I learned in code review etiquette.
@prezadent12 жыл бұрын
*distinction
@csisyadam2 жыл бұрын
I had the same feelings while watching this video. In a real world environment, colleagues wouldn't like Cherno's "blaming" :)
@victornpb2 жыл бұрын
@@prezadent1 define discrimination: The ability or power to see or make fine distinctions; discernment.
@prezadent12 жыл бұрын
@@victornpb So now you know. You're welcome.
@victornpb2 жыл бұрын
@@prezadent1 I don’t think you understand. they mean the same thing.
@sarahkatherine84582 жыл бұрын
30:46 I'm sorry if this is not Isti's case. This "MovementDirection" trick seems to be used by a lot of previous-generation teacher and programmer (or at least in my country). The idea is, instead of writing x += 0; y += 1; to move upward, they will create a "movement direction array" like this: dirX = {0, -1, 0, 1, -1, 0, 1, -1, 0, 1}; dirY = {0, -1, -1, -1, 0, 0, 0, 1, 1, 1}; Now to move upward, they will do x += dirX[8]; y += dirY[8]; because Num8 is up on your numpad (you are at Num5). They said it will saves a lot of if-else for all 8 directions, and makes it easier to tract the direction by looking at the numpad and array index.
@AntonioNoack2 жыл бұрын
Nice trick, but has nothing to do with the code in this video 😅. Lsti just defined what direction has which xyz coordinates without any tricks, and stored whether the key is pressed in there additionally.
@sarahkatherine84582 жыл бұрын
Yes, Isti's code is not any trick, just pre-defined direction vectors as Cherno said. I just borrowed the name because it reminds me of the mentioned trick 😅
@bluustreak65782 жыл бұрын
The thing that impresses me the most is how he's able to understand what the code does so fast
@temp50Ай бұрын
Yes, I'm pretty sure he didn't check the code previously and didn't make notes on it. :D
@bluustreak6578Ай бұрын
@temp50 i guess that is a possibility too... x)
@CediCore5 ай бұрын
I once made a Snake Clone, and it's still growing somwhere out there.
@DipsAndPushups Жыл бұрын
At 24:50 Yes, PLEASE! Those kinds of questions of OOP, questions of design, what class should do what is what I want to know so bad. I would like to watch videos on that topic in fact this very discussion about what the Ray and other objects should know about the world and which class should take care of collision detections is something that I am really interested to know. It is also interesting that you can build projects as big as Minecraft clones in OpenGL despite the fact that your design decisions are bad.
@DemetryRomanowski2 жыл бұрын
I use CLion with CLangTidy and the explicit comes directly from that, I changed mine to not constantly pester me to make constructors explicit.
@makichiis2 жыл бұрын
This is actually the same reason I use explicit constructors. As a general rule of thumb I will declare a one-argument constructor implicit just so CLang-Tidy doesn't yell at me, but I can also see how it would be good for consistency with other one-argument constructors that may benefit from it.
@bloodgain2 жыл бұрын
CLion and ClangTidy are correct. Cherno is wrong. Making single-argument constructors explicit is considered a best practice. You _don't_ want implicit conversion in most cases, and it can cost you performance even if it's not introducing errors.
@makichiis2 жыл бұрын
@@bloodgain Does implicit conversion occur even when your type matches the type the constructor accepts? I must admit that I am not as familiar with C++ under the hood as I should be. Thanks for the insight
@bloodgain2 жыл бұрын
@@makichiis In most cases, yes. Like all things in C++, the answer is "it depends" or "it's complicated". But if the compiler can determine a resolution for a call ("substitution"), in nearly all cases, it will insert that resolution unless it has been instructed not to, like with "explicit". Unfortunately, the way C++ determines substitution/resolution can lead to some weird corner cases and doesn't allow neat tricks like multiple dispatch, but it's also what makes some other neat tricks work, like complex template resolution (see: SFINAE).
@makichiis2 жыл бұрын
@@bloodgain Ah I see what you mean. It's good to *explicitly* (pun definitely intended) declare the constructor explicit since whether the resolution will actually take place when types match is not guaranteed by the standard (implementation-defined), only that "explicit" makes it so that it doesn't. Do I have that right? I also never considered how this is related to SFINAE. There's clearly still a lot I don't know! Thanks again for your input
@davidm2.johnston684 Жыл бұрын
This is the video that has spent the longest time in my "Watch Later" list. Years. Not that I don't clean it regularly, or that it's a place where videos go to die. But this video has survived there for all this time. And I finally watched it today. I needed to be ready. Ready to dive again into C++. And so yeah, good video! It made me want to try something like this too!
@davidm2.johnston684 Жыл бұрын
All jokes aside, I'm a Python programmer, have been doing that professionally for 3 years, in the animation industry. I've watched a lot of courses on C++, including yours, which made me familiar with the thought patterns, and the specific concepts and culture of the language. And of course the syntaxe. But every time I tried to start a project, I got stuck with other stuff. With configuring my project and my tooling. I guess I'm trying too hard to have the perfect setup, with an IDE that is well configured, the right build and build automation tools, etc, etc. And I can never understand all that or get everything to work. Same if I try to clone an existing project and build it. I've managed to do that for Blender and for Minecraft (with a modding API), but that's because everything has been perfectly automated for every single platform. With other projects, at the tiniest hiccup, I get stuck for whole days. Also working on Windows may not have been the best idea, as many projects are actually configured for Linux. Yeah, that's why I was putting that off for so long. But I will give it another go sometime. I'd like to write a ray tracer sometime, and I've saved your Ray Tracing series for when I'd get the courage again.
@aaron68072 жыл бұрын
I started learning OpenGl and C++ by making a minecraft clone too. It's interesting to see how others implemented the same systems
@anon19632 жыл бұрын
it just works
@cxlappsed154811 ай бұрын
link?
@rmt3589 Жыл бұрын
That's so exciting! Just started planning out my own Game Engine, and you're one of my recently found inspirations! Been watching a lot of your videos sense. To know that I can send it in for you to review, that's super exciting!!! Deffinately have my heart set on that now! Btw, you should totally make your own minecraft clone! Would love to see one done with hazel!!!
@randyprime2 жыл бұрын
that studio lighting is SEXY AF
@austin-m8r-w6d2 жыл бұрын
Thank you Randy (love you btw, come back soon but only if you feel like it)
@NewPlayer4U2 жыл бұрын
TheCherno! I remember your C++ series with these awesome memory checks! Smart Pointers was just BLAST! Where are those razors? ;] How are you even doing Cherno? Do you live well? Everything alright? Maaan, I wish we can drink vodka someday together ;] Thanks a lot for your time, I really appreciate it! You're the best!
@samarthtandale9121 Жыл бұрын
Love this review 🤩 learnt a lot !!! Huge fan cherno, wish I'll meet you some day!
@ronin29632 жыл бұрын
It's really Kool that you are doing this. It is one of the most positive aspects of the coding community
@vaanidel21172 жыл бұрын
30:54 A camera tutorial would actually be really nice 😅
@jcx57502 жыл бұрын
"I can do Unreal Engine 5 lumen tech in three months if I was free of work" -Does a code review of minecraft in c++
@szirsp Жыл бұрын
15:55 I heard a presenter say on some C++ conference that they changed their mind on public first. When I looked into it, I found a good argument against public API first: documentation. Read the documentation if you just want to see how to use it. If you want to see how it works, then you open the code, in which case you want to see the data first. You want to read from top to bottom, and you need to see declarations first and then their usage. So it's not really about public first or private first, it's about fields (member variables) first then methods (member functions). It just happens that in most cases data is private and methods are public.
@ale-lp2 жыл бұрын
There are so many cool things you could expand the Code Review series into... General review, optimization, architecture. I'd watch them all even if it's an hour long video per project per sub-series!
@crusaderanimation69672 жыл бұрын
1:35 Artists: Artist1: NOOOOO yOu stol My art ! Artist 2: No it's my ART ! ! Programmers: Programer1: I stole your code lol Programer2: This part of code isn't even mine code XD
@MaddGameMaker Жыл бұрын
Application::instance() does not do any lazy loading. In C++, all static variables (including local ones) get initialized before main() is called.
@cummins69458 ай бұрын
The C++ standards disagrees with you here (see [stmt.dcl]), but tbf you might have been thinking of C. However C doesn't do any dynamic initialization for statics and it's compile time only. Another detail is that the C++ initialization-on-enter is required to be thread-safe: "If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization." This means the compiler has to insert synchronization there when needed
@isodoublet3 ай бұрын
Not true. You can verify very easily that it will get loaded on the first call -- it's the entire raison d'être for this particular pattern (Meyers' singleton)
@marcsh_dev3 ай бұрын
And in fact they have a bool sitting in the initial static data area with the program (this isnt necessarily how they must implement it, just how the particular compiler did). I had to track down a "static" getting initialized twice, which ended up being an array being written to out of bounds, and resetting the bool to 0, and so, rerunning the code that set the function local static.
@ruddymolina70442 жыл бұрын
Master you have provide us with new knowledge... thanks master.
@charlestheanimator16762 жыл бұрын
15:40 I would agree with you to that point about class labels for private and public. That said I have pretty intimate knowledge of the Unreal Engine and their code is riddled with header files that have multiple private, public and protected sections. Upwards of sometimes 3 of each per class. AND, every single class has private data members in the top 'default' private section (of which is not labelled private).
@amayesingnathan2 жыл бұрын
I like to have multiple private, public, protected for members and methods and operators. This gives a clearer boundary between functionality and state in the class. It only ever really ends up applying to private/protected because I almost never have public data members.
@daithi0072 жыл бұрын
14:00 Moved the private data members to the bottom of the class implementation. You're complaining about it being first but you're looking at the implementation you're not looking at the header.
@Ezdiess2 жыл бұрын
What a brilliant brilliant plug
@user-dh8oi2mk4f2 жыл бұрын
Brilliant 👏
@TechEreb2 жыл бұрын
I really like this kind of video. It helps me learn better coding practices.
@LegoDinoMan2 жыл бұрын
I’d love for you to turn it into an optimisation series! Teach me the ways of speed
@atlantic_love2 жыл бұрын
I wouldn't, and that's not what he's about. There are optimization channels you can frequent.
@LegoDinoMan2 жыл бұрын
@@atlantic_love Would you recommended some please?
@kech-agmaio86202 жыл бұрын
love the chill background music
@szirsp Жыл бұрын
26:10 I think that Ray utility class might just needs a rename (something like WorldBlockColliderRay), or maybe moved into the World class. I mostly agree with Cherno here but I kinda disagree that the player and ray necessarily exist within the world. Minecraft has multiple dimensions/worlds. The ray belongs to the player. It can exist outside of a world (if you want to have a character creation/customization menu/screen... but then you wouldn't need the ray), or it can exist in multiple worlds simultaneously: like stepping or looking trough a nether portal or end portal (if you wanted to make them see-through, I saw a mod for that in MC). But you can achieve these as if the player existed in a void world or in multiple worlds all at once, call the world's ray collider function on multiple worlds. You could pass a collider object to the Ray and implement the world's collider, but the result is probably the same, that world specific code doesn't belong to a generic Ray class. You probably should ask the world for ray collision result, rather then a generic looking ray dig into the world internal structure. (The indirection makes this slightly less efficient, but you can still use this in the constructor.) I get why the work is done in the constructor, it's more efficient, the results take less space to store than the inputs, and called less frequently. I don't know if the world is holding only block data, but at some point you might want to implement entities (mobs, maybe chests), then ray collisions with those might be separate from world, and that might be a reason why not to implement this in the World class. Still Ray probably should receive a list of colliders (world's, entity's) and call those.
@abhinavjha30822 жыл бұрын
Could someone tell me which theme Cherno is using? I love it
@cole-nyc2 жыл бұрын
It's a theme you get with a payed VS extension called VisualAssist. You can, however, recreate this theme yourself with a color-picker on the colors you see in the video
@abhinavjha30822 жыл бұрын
@@cole-nyc ooh thanks bro
@NordicFrog2 жыл бұрын
18:16 that is a Linus Tech Tips level segway right there. Just perfect.
@awwastor2 жыл бұрын
25:00 You can just do cast_ray(Ray, World, ..context) to be completely neutral
@feschber2 жыл бұрын
But then this function would need knowledge about World, which only World itself should have. So imo having a World::intersect(Ray &ray) function is still the best approach (and our professor did it this way in a university assigment as well)
@awwastor2 жыл бұрын
@@feschber why should only World have access to itself, but Ray not?
@feschber2 жыл бұрын
@@awwastor its not about access, but why should Ray need to know anything about world? That just complicates things. Ray doesn't _need_ to know anything about the world.
@jan-lukas2 жыл бұрын
@@feschber my rule of thumb is: when two (or more) headers include each other, I've made a mistake and should move some things around
@pinguluk12 жыл бұрын
What's that menu at 7:42? It's a library that you can implement in C++ GUI projects? I've seen it in other C++ projects as well 🤔
@master_spike Жыл бұрын
Imgui
@m4rt_ Жыл бұрын
2:30 Jonathan blow is taking making it from scratch to the extreme. He is working on a game, in a programming language he is making, where it has no separate engine, just the game. Though I think he did copy over C++ code from his earlier games that didn't have a separate engine either.
@tomasofficial.2 жыл бұрын
Hello, how did you change the color scheme to be like that instead of the default?
@Erock6342 жыл бұрын
Really good advice! I love your coding style
@monetlarry84002 жыл бұрын
Thanks, Cherno! I learned a lot from this episode!!
@mike2000174 ай бұрын
The reason for using explicit constructors for single argument ctors is mostly to preserve strong type safety in function calls. Imagine you have a function that used to take a "string" parameter and later on you change the parameters and it just happens that where it used to take a string it now takes a "Persistence" object. Without the explicit ctor, this will still compile and might lead to a really annoying bug.
@kariakichernocherno22742 жыл бұрын
Hi cherno this is a great podcast love you man!
@adamhelberg92282 жыл бұрын
I have seen over a few videos that you dont like singletons, is there a reason ?, does it make it slower or use more memory?, I'm still learning so knowing might help for future.
@AntonioNoack2 жыл бұрын
Singletons can be bad for modularity, because you can only have one of them. On Android you're additionally told to avoid static references to your main UI class, because the system cannot garbage collect it then, when the classes shall stay in memory (e.g. so the app can restart faster).
@bloodgain2 жыл бұрын
Basically, it's a global that _forces_ you to only ever have one instance of it. Because it's global, it makes testing harder, because it's an undeclared dependency. Better design would be to declare all dependencies as parameters (either at construction time or use time). This is called Dependency Injection or Inversion of Control. While some things conceptually are globals, actually using global references should be done very sparingly, and avoided whenever possible. But this goes for _all_ globals. But worse, because it _enforces_ a single instance, it takes away the programmer's control over its lifetime. Thus, it has to be created at startup, live after shutdown or a least until static destruction time (leading to the Destruction Order Fiasco problem), or often both. This is a massive drawback that can be solved by simply not having a class control its own creation and destruction time. So, if you do decide to use a global, avoid making it a singleton pattern. You can have a global if you have to, fine. You can have only a single instance, also OK. But don't push those into the design of the type and adopt more downsides than necessary.
@DeathAtYourDoorStep2 жыл бұрын
Love the code review videos Cherno!! Keep them up thank you
@johnmccain30502 жыл бұрын
@The Cherno When you showed your Hazel code how you set up the "Application". Why didn't you use a smart pointer to wrap your "Application" object? you explicitly have to call "delete app".
@user-dh8oi2mk4f2 жыл бұрын
It doesn’t make any difference. There’s only one logical place to delete the app.
@moonhowler6676 ай бұрын
Four bits is a straight line, my dude. Or a 4x4 flat square. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 And a chunk is 16x16x256. Assuming you're not storing data for ANY cube not part of the surface mesh, and not storing the state of air blocks, you'd at best end up with 16x16 cubes, not 16. So that's 64 bits. Then you're not accounting for underground areas, which add more data to a chunk.
@emi6aston2 жыл бұрын
Idk why, but, Ghost Cherno made me have to pay attention to the code D:
@yoyo123452 жыл бұрын
waiting for java code reviews :)
@svens37222 жыл бұрын
then he have to do it in a pool that nobody sees him crying.
@yoyo123452 жыл бұрын
@@svens3722 sad, why do people hate java
@svens37222 жыл бұрын
@@yoyo12345 i started with c and c++. After that i got in school java and i was confused where all come from and i didnt liked it how it worked. but i have to admit that this opinion was kinda of my "beginner noob programmer" thinking builded.i didnt understand it fully. nowadays i think its quite handie and i would like to step into if i have to. but with my private stuff i prefer other languages.
@xerwinxpl2 жыл бұрын
8:04 like in minecraft alpaha or pre alpha
@teamcreative83022 жыл бұрын
I was waiting for this to happen!
@joschemd2 жыл бұрын
I disagree on the comment of having the main app being static vs instanced.. the context is predictable there should only be one and its just splitting hairs and really just a case of personal preference. And while you give alot of great points and recommendations almost all are what we used to call religious views.. they don't actually make the code better but they make it easier for the reviewer's ease of understanding. Re: ray scenario.. you're spot on. There's a reason game engines have a base type exactly for the lack of forcing a specific type, however the more you abstract the more work you have to do for specifics.. a trade off between versatility and utility.
@zxuiji2 жыл бұрын
20:33, I would not check for air, instead I would just have a null block that is treated as air whenever it's referenced, something like: typedef struct _FACE { float bends; vec3 emits; } FACE; typedef struct _CELL { FACE faces[6]; } CELL; ... CELL *cells = calloc( cell_types_count + 1, sizeof(CELL) ); ... fread( cells + 1, cell_types_count, sizeof(CELL), cell_types_file ); ... while ( ray.dist < 3.0 ) { ... cell = ... face = cells[cell->type].faces + (...) ... light += face->emits angle += face->bends ray.dist += ray_jumps_normalised_dist ... }
@zxuiji2 жыл бұрын
@@richardlyman2961 Did I ask if you cared?
@yearswriter2 жыл бұрын
@@richardlyman2961 the f dude is Just sharing very relevant opinion, lol, at least argue with proper argument on the subject
@zxuiji2 жыл бұрын
@@richardlyman2961 So? Normal people start conversations with anything they feel like talking about, do they ask if the person they started speaking to cared? No so I suggest you stop being a sheldon and quit complaining.
@Bonnie204022 жыл бұрын
@@richardlyman2961 When I ask for you to ask, that’s when you ask ;)
@adiaphoros68422 жыл бұрын
@@richardlyman2961 No one asked you to live. And no, your parents don’t count.
@lukesanford90262 жыл бұрын
I want to learn how to make games and programs from scratch, though I have no idea where to start. I have very minimal knowledge of the basics of programming and CS, I've worked in Java, Python, C++, and C#, though never beyond the point of basic baby stuff like...creating and calling functions. I don't even know what header files are or what any of those lines of code mean and while I don't want it to intimidate me, it does. Anyone have any advice on where to begin?
@Starchaser382 жыл бұрын
Header file is just a chunk of code, which can be embedded into another file by specifying #include "filename.h" directive. They are generally used when some specific code is widely reusable in many different projects or represents a completely different functionality (so a bunch of barely connected stuff won't make an unreadable mess in your main file). In basic stuff you probably didn't have a need for any of these (except for perhaps), but the concept is really simple and straightforward. As for beginning of programming... Well, if you're interested in understanding the syntax of C++ and it's basic functionality, there are some specialized books on the topic, like Straustrup's ones (he's the creator of this language after all). Also the internet is full of beginner level tutorials. In general though, I would recommend to set some pretty high goal for yourself (like creating a game, a useful app, a simple engine...) and to do your best to progress towards it. Even the path itself would be a great teacher.
@SerBallister2 жыл бұрын
11:15 Declaring "Application app;" in main() will allocate that class in stack, which might not be good idea if there a bunch of other classes, arrays and other large objects in there.
@TheCherno2 жыл бұрын
Yeah but his Application class was like 30 bytes, and in my experience you’d probably never have an Application class that was stack-heavy in most projects
@TheCherno2 жыл бұрын
@@SerBallister perhaps on certain systems, but otherwise I would just heap allocate most of those heavier classes within the Application class
@SerBallister2 жыл бұрын
@@TheCherno It's asking for trouble :)
@SerBallister2 жыл бұрын
@@TheCherno Yeah, either that or static/global, since I'm absolutely certain I only ever need one instance of that class
@samiam40392 жыл бұрын
Is the game engine a place where you abstract the device driver and direct connect drivers and the graphics pipeline from the real game code. In a way the game engine can be considered the compatibility code and gaming display conversion from the actual game specific code?
@atijohn81352 жыл бұрын
That's a graphics rendering API, like Direct3D or OpenGL. A game requires more elements than just graphics rendering (physics, UI, AI etc.)
@OperationDarkside2 жыл бұрын
I'm also doing a Minecraft clone, but it's nearly not as tidy as this guy's code and has a lot less features. I startet like 3 years ago and have less features than he does xD However, mine has more evolved into more of a experiment lab for graphics stuff. Just figuring out how to write a decent blur renderer took months and recently I ported the app to C++ modules, which ate another 2 weekends. And I'm guilty of getting lost in code optimization, despite running at 120 fps at 2% CPU load. GPU has been strange though. when I implemented a way to reduce vertices per chunk and draw calls in general the GPU usage jumped to 50% oO
@VioletGiraffe2 жыл бұрын
You're just teasing us with all these videos that are NOT about ray tracing, right? :)
@CodAv1232 жыл бұрын
Regarding the missing header files: I often see people using CMake not adding them to the targets, because technically that's not really required for building and CLion (which the author probably used) will show the directory structure instead of just the target files as VS does. Adding the headers is advisable for multiple reasons though. CMake will use all files added to the target - even non-code files - to determine if a target is out of date, depending on modification dates. So not adding headers might not retrigger a recompile of a target with some generators/build tools. Also adding headers will make them show up in project-based IDEs like VS. In addition to that, one should also set some additional CMake properties to properly sort targets and files into filters/subdirs to make them easier to browse.
@Garfield_Minecraft9 ай бұрын
Better than official bedrock version
@lunaerx20172 жыл бұрын
Hi Cherno! I want to ask you to make the review of WebGPU technology. I see it has some potential in the future not only for web, but also for desktop because it provides an abstraction over native APIs like Vulkan, Metal and DirectX. Unfortunately, I don't see the full picture of it because of a lack of experience working with graphics in general. So I would really like to hear thoughts and opinion from you as a very experienced graphics software engineer. Hope you'll see this message and eventually make the review! Thank you.
@BartKus2 жыл бұрын
16:16 explicit single-argument constructors are suggested by Google's style guide. "google-explicit-constructor" clang-tidy check can enforce this.
@danieloberhoff12 жыл бұрын
I disagree with the explicit constructor criticism. You can accidentally create an instance, even if the function has const& args. especially if the coinstructor takes only string.
@TheCherno2 жыл бұрын
You can’t really accidentally create a class from a string, since that would take two conversions (const char* to std::string to class). In my experience, in most cases where a conversion is possible (for most types, not all), the conversion is the intended behaviour
@frydac2 жыл бұрын
wrt the ray depending on the world: this code is highly, pretty sure unnecessarily, coupled to the world class. A ray class is normally something you want unnittests for to make sure it works correctly and it enables you to change/optimize the implementation without worrying about breaking it's functionality. When you write lots of unittests, and you should, then you notice that setting up a world class just to test the ray is quite annoying. If you ever start a new game and need a ray there, this class is also not usable as you probably want a different world (though this ray may be really specific to the minecraft block layout of course). I would strongly recommend trying to write unittests and think about the testability of building blocks like a ray. It will make it relatively easy to make your code less coupled, and thus more maintainable and reusable. This is kind of the idea behind TDD, imho it really works to think about testability all the time when designing, not necessarily writing tests first, though in some cases that works very well too. Same for the singleton, it really undermines testability: you want different testcases to be completely independent, but a singleton keeps existing between testcases so it makes it more error prone as you need to make sure to reset the singletons state between testcases.
@TheRealMangoDev Жыл бұрын
"Application is such a like important part of your application that like uh like why not you know just kind of create it here" - Cherno 2022
@Spongman2 жыл бұрын
yeah, look at the asm for local static instance. it has a memory barrier around it, which is going to kill multi-threaded performance, especially on something so central.
@spectrm60142 жыл бұрын
The series is going good so far :) Early btw 😀🙌 🔥
@pmcgee003 Жыл бұрын
Passing state (the world) into a function *is* a functional approach.
@b4ttlemast0r2 жыл бұрын
Can the code review code be in any programming language, even lesser known languages and engines?
@stephenyork73182 жыл бұрын
One of the most important things I've learned over the years with OO is to STOP inheriting and making classes do too much. It's so much more manageable to to have data classes which represent a thing (noun) and have the behaviour of that thing represented by other classes, which typically do only one thing and do it well. I don't actually mean never inherit, but the ability to inherit generally leads to problems and it's a fine art to know when you genuinely need to do it. But anyway, dependency injecting (the pattern not and IoC container) following SOLID keeping clases super simple was a revelation to me.
@alfredli40322 жыл бұрын
Cherno I like this review very much, learnt alot. by the way can you do a hazel version minecraft
@Astfresser2 жыл бұрын
27:00 best part. I would add that class objects are essentially only needed in two cases: When you do RAII-type lifetime management and when you define an interface. Otherwise I like it when code just feels like a todo list
@gravenviolet Жыл бұрын
Thank you for giving me a glimpse of how to make a minecraft bedrock
@stephenkamenar2 жыл бұрын
i like the performance reviews. the main point of writing your own engine is performance.
@thepurplepanda42 жыл бұрын
Or learning what happens under the hood. I'm not making an engine, but I am making a graphics program. My purpose is purely to learn and show a project for potential work.
@anirudhsilverking57612 жыл бұрын
What's the font you're using??
@matyasnyilas2 жыл бұрын
Woooaahh i didn't expect a Hungarian project! Let's goo! 🇭🇺
@nodecrasher49912 жыл бұрын
How many more of these mincraft clones are going to be there
@Caellyan2 жыл бұрын
vert_lighting (ln 46) of shader code can be optimized a lot with regards to number of instructions generated. min(max(..)) screams "replace me with clamp", and in this case the glsl compiler wouldn't replace it with min(max()) as the upper limit is a variable. Sending less data to shaders is good, but in case of a MC clone this might be unnecessary as the world doesn't change that often - so computing positions every frame in a shader is increasing amount of work that needs to be done per frame. This depends though on how much work you need your shaders to do I guess.
@tumaraigordai41572 жыл бұрын
Does anyone know the name of BGM at the start?
@Throckmorpheus2 жыл бұрын
From modding Minecraft, I'm pretty sure the thing of passing World into functions that feel like they should belong to World is being copied from the way actual Minecraft structures itself.
@DominikGuzowski2 жыл бұрын
Well now we need a HazelCraft 😂
@me-ld2gq2 жыл бұрын
Ayyo someone hungarian. Finaly.
@therabidpancake12 жыл бұрын
I have been learning to code for years now and I can barely even write a program . My goal is to write games but I am afraid if I learned how to write a game I would be stuck writing the same kind of game over and over again . Same thing with writing a program . I am learning python and I know about 25 maybe 40 percent of the language I am still struggling to make anything . there are a few programs that I have written but when I run the program it says everything is written correctly but I can not see anything written on the screen. I do know about turtle commands and I do know about the print and input commands . Guess I just have to get better about following tutorials .
@IntheFishtank2 жыл бұрын
Don't follow tutoials, read books.
@therabidpancake12 жыл бұрын
@@IntheFishtank okay are there any that you recommend ? I have a lot of books on programming as it is but I am will and anxious to learn more .
@brightwebltd28642 жыл бұрын
Cherno! Check out 4D Minecraft - that’s some crazy game design and math!
@mobslicer15292 жыл бұрын
In CMake, you have to explicitly include the header files in the targets
@Tachi1072 жыл бұрын
Or, even better, you can use target_sources(FILE_SET)
@nathan82452 жыл бұрын
What's the ide you're using ? Love the way it makes the != and
@TheCherno2 жыл бұрын
Visual Studio 2022, however this is part of the font I believe (Cascadia Code)
@Wilksey372 жыл бұрын
If you want a code review challenge, review the BUILD engine (Duke Nukem 3D) code....
@AntonioNoack2 жыл бұрын
Oh well, then he could review Unreal Engine, Blender or Godot as well, but that's waaaayyyy too much. or my engine, but that's still 100k lines 😅
@Wilksey372 жыл бұрын
@@AntonioNoack BUILD engine is notoriously bad and convoluted though...If you want him to review you engine then send it to him.
@zxuiji2 жыл бұрын
as for constructors vs destructors, I like to put the destructors 1st, even in the implementation file, it makes it easier to know what you need to initialise in the various constructors since I would normally just start writing the next constructor directly underneath the destructor so I can quickly reference it, also since the destructor has a shorter api it just looks nicer to go from short api to long api