You may have two problems when following this episode: 1. lots of unresolved external symbols 2. unresolved external symbols DwmExtendFrameIntoClientArea 1. For the first problem, you may notice that in GLFW project setting, go to C/C++ -> Code Generation, on the right hand side, the runtime library is Multi-threaded DLL (/MD), that means when compile this project, GLFW will use C++ dynamic library. And in the Hazel project setting, the runtime library however is Multi-threaded (/MT), that means when compile this project, Hazel will use static links of C++ runtime. Now we can have 4 combinations, and all of them are valid except GLFW use (/MD) and Hazel use (/MT). Therefore, you can have GLFW use (/MD) and Hazel use (/MD), or GLFW use (/MT) and Hazel use (/MD), or GLFW use (/MT) and Hazel use (/MT) Here, it is better to set this options in premake5.lua file, however I didn't find any method to change that setting. You can set it in Visual studio directly. And don't forget to set it each time after you regenerate the solution .sln file. 2. For the second problem, I guess that the new version of GLFW use this new function, and this function is in dwmapi.lib. Therefore, add this dependency into premake5.lua. links { "GLFW", "opengl32.lib", "dwmapi.lib" } And regenerate the solution. Don't forget to change the C++ runtime setting.
Thank you so much for the detailed clarification. I was struggling with older commits to figure out the problem for two whole days. I knew the problem had to do with the engine project output being changed from dynamic lib to static, but I couldn't pinpoint the issue.
@@willianwu4317 No problem, what I learned now is that the Libraries should be set to /MD or /MDd (debug) and Sandbox to /MT or /MTd (debug). I don't think premake does this well but it could be my setup file is wrong :) I keep changing it manually.
I have been pulling my hair out for about a week trying to figure out why it wasn't working...you probably just saved the rest of my head, thank you Btw do you know if there is a premake command I can add that will set this automatically?
@@electricn0va Yes he does set it up in a later video but I still have to manually change it from time to time maybe I implemented it wrong but (I think) it should be for Libraries: buildoptions "/MDd" filter "configurations:Debug" defines "HZ_DEBUG" buildoptions "/MDd" symbols "On" filter "configurations:Release" defines "HZ_RELEASE" buildoptions "/MD" optimize "On" filter "configurations:Dist" defines "HZ_DIST" buildoptions "/MD" optimize "On"
@@electricn0va in episode 17 Github and Hazel he explains to use runtime not buildoptions. This should be the fix I haven't tried it yet (just watching it)
I had a hard time following this one as i'm coding along and not just getting the resource from your git repos. I managed to make it work in the end and i have learn a lot of things so cheers as always.
I feel like this new way of going over the game engine is glossing over huge steps and being less efficient than before. I think a better method would be a video on heavy concepts such as windowing, event system, etc, be live coding. Then do a smaller 5-15minute video of review over that episode where you go over the changes you made to the code after reviewing it yourself (since not everything can be caught coding live), that follows the format you're doing now. When you did live coding episodes you explained why you did what you did where as this feels like a sparks note of the code, and doesn't explain much.
If anyone is having issues with unresolved externals related to glfw3 when building, I found the issue to be in properties -> C/C++ -> Code Generation -> Runtime library. Switching it from Multi-threaded debug (/MTd) to Multithreaded DLL(/MD) or Multithreaded Debug DLL (/MDd) did the trick. To make the premake file do what you want, they keywords are staticruntime and runtime. for /MD you want staticruntime "off" and runtime "Release", and for /MDd you want staticruntime "off" and runtime "Debug". You may also need to get rid of any buildoptions that override this (I had buildoptions "/MT" which overrode /MD). Hopefully this saves someone some time :)
More importantly, there are missing files currently. Check the forked GLFW repo for an updated premake file if you insist on mimicking on that level. (you can just copy the files for all platforms and windows)
Hey! I just wanted to make a comment about the teaching style and your comments at the beginning of the video. I am a Computer Science teacher who has taught courses on game programming / engines, and have spent a lot of time talking to other faculty members / industry programmers about how to teach game programming. I have found that for students / audiences with zero initial knowledge, it is much better to use a top-down approach then bottom-up when teaching game engine programming. Bottom up like you are doing is great for the more technically minded audience who already has some experience, because they can greater appreciate the context for why you are doing what you are doing. Despite your explanations, its really only something you can appreciate after you've already made a game and done a bunch of things wrong. For completely new students, I greatly prefer top-down. By doing things top-down, you can start with a very simple game example with controls, drawing the the screen, and get the students hooked on having an actual very simple game up and running. Now that they have this experience, you can start abstracting away parts of the engine into the systems that you are talking about here in your video series. Once they have dealt with things like hard-coded input handling, or tying their drawing system to a specific API, they can really start to appreciate Event systems or window abstractions. So I understand why you are teaching it this way, but just realize that you are probably going to either a) lose the interest of novice programmers, or b) only start to get a lot of views after the entire series has been completed. Please don't take this as criticism, I'm a huge fan of the series and don't want you to change anything. I was just giving another explanation of why you might find viewership not being as high as you'd like so far. Please keep up the great tutorials! I've pointed some students to your C++ videos in the past and they're a great resource. One other small thing: You probably don't need to spent 2-3 minutes at the beginning of each video apologizing for the previous video or explaining the context of this video within the series. Once the series is completed and people binge-watch the videos that will pretty much just be dead air. So while you're explaining it now and it makes sense, later on it might not be worth having those segments in the video. I think it might be a better idea to just get straight to the content of the video, and then maybe release a separate longer video explaining all of the other non-programming related things.
I don't want to blindly defend him as I have some concerns about the video structure too, but I don't mind this series being bottom-up as you put it. if you look at the channel playlists this is at least the third game engine series. The Sparky engine series and the OpenGL series are both top-down. My complaints are more towards the incomplete lessons. It's been three weeks since the event system planning video, two since the event system programming video and viewers likely still have no idea how to actually use it. There's no class to publish callbacks to, nothing to publish events to, just the events themselves. I hope I'm wrong, but I don't expect anymore videos for 2-3 weeks. Yan's gotta be doing Christmas/ New Years stuff just like everyone else.
I don't want him to change anything, his lectures are fantastic. I will stop following him if he did what you ask him to do. Technical viewership is the way to go. They can always learn from his other lectures.
My take on this is that what you are describing lives in several places on the internet already. I have found several of them, but never make it far in any of them simply because I cannot do the "just make this thing with all this magic" approach before understanding. This series is unique in part because it does what you are saying is the less effective method. To combat what you're describing, I would suggest he do a design video every 2 or three videos describing the overall big picture and the why behind the decisions, and then go on to implement them ground-up. PS: You're right the preamble is distracting.
Hmmm I get the sentiment and you are certainly correct in your conclusions for technically minded(aka very knowledgeable and/or experiences programmers) vs new(aka people who have a grasp of perhaps the language and some of the other constructs / hardware implementations used... [as an aside I would class myself as one of these] ). Having said all that I think that what Yan failed to make clear enough (my opinion) at the outset was that this series is FOR the first group... the second can give it a shot but it will require some VERY. DEDICATED. EFFORT. to get there (aka google is your friend... and UA-cam... [but also extremely frustrating because of the amount of unintelligible crap that you will have to sift on your way to understanding] but I digress...). To be fair he has droped many hints along the way... "go see this or that video", "if I was to explain (insert subject here) then we would be here 'til Xmas... aka known as a very polite form of RTFM. And TBH I think he has done an amazing job of making it as simple as it is... This is far from common in an advanced series... and this IS an advanced series, but in actual fact this is a lot easier than many others (lesser in difficulty than this) that I have seen over the years. Of course I think he needs his head read trying to teach a free course on engine design to the masses without stressing an encylopedia of before you start you must know...(insert a plethora of subjects) but then he is a far more talented and generous person than I can proclaim to be... :) jmtcw... digest with a healthy dose of scepticism or disagreement of your choice.
Hey Cherno. I understand why you made the switch to prewriting the code, and just reviewing it, but this way isn't really teaching. I really preferred the other style. I know it is probably more difficult to play to write everything, but I learn by coding along side you. I really miss the old format.
really self aware move. my two cents: i enjoy all the of the content and i'd be most excited to follow the logical structure for a game engine... im a beginner and doing foundation data structure stuff before i really move onto this though. realy brilliant videos man, youre a great teacher
My English is not very good, so I translate part of your words into a dictionary, write out unfamiliar words and teach them. I really want to understand everything that you say by ear. You're the best, thanks for your videos. P.S. This post is written in google translator
- Single responsibility principle: Your window class should not directly be responsible for the GLFW initialization - Constructor and destructor exist for a reason so there's no point to write Init() and Shutdown() functions at this stage and from a object point of view, there's never a need for those functions. If you want to reset the state, you just create a new object. - Returning a owning raw pointer from your Create-factory function is rather dangerous, as you now rely on the user of said function to a) know that this is an owning raw pointer and b) properly takeover ownership and destroy it. At zero cost, you can just have the factory function return a unique_ptr and call make_unique, that way the signature indicates that you're a) transferring ownership and b) as long as the user doesn't explicitly misuses the unique_ptr the destruction of the window is guaranteed. - To initialize your member variable, use the initialization list instead of doing it in the constructor.
It's a little hard to follow what is actually included in a file, because often the include is not explicitley in the file but in the pch or other files that include the current file, or is that just me ?
Don't use the most updated GLFW in Cherno's repository. That would give you error which I don't remember anymore. It's a quite long name and no where you can find help online. Instead go to the corresponding commit of this video "Added Window class and GLFW'" and click 'GLFW' in left side panel, then on the right side large panel you can find 'Submodule GLFW added at b4b431'. Click 'b4b431' and there is the right GLFW you need to finish this video. I am totally a starter so I can't find out what is the essential difference between this GLFW and the most updated GLFW in Cherno's repository, but any way, this solved my problem. Oh and don't forgest to change the 'systemversion "10.0.17134.0" ' to 'latest'( or whatever your Visual Studio have) sin premake5.luna file which Cherno mentioned in this video.
THANK YOU SO MUCH DUDE I SPENT SO LONG TRYING TO FIGURE THIS OUT I LOVE YOU SO MUCH ♥♥♥♥♥ IM NOT EVEN A BEGINNER AND I COULDNT EVEN FIGURE THAT OUT YOU'RE SO SMART THANK YOU
I had to go through all the videos till now twice to understand what was going on here. I don't think there is any such c++ intensive project on whole of UA-cam which not only teaches c++ but also helps visualize it. All hail @TheCherno
in the beginning I found premake quite difficult, but it's actually easier and more convenient to use than the visual studio property pages. Microsoft has outdone itself on that one.
I recommend using the latest branch of GLFW, it worked for me, as I think that branch is just more stable overall, and didn't give me any linking errors. And no, the format is fine, the tutorials still work. Stop leaving negative comments and binging about why you want to give up because you are not willing to look hard enough.
I know right, dude is giving us some really good information on his own time and people think its ok to talk crap because they need someone to hold their hand. Anyway, I did the same thing as you, but still ended up with linker errors. I forked a branch from the new one, but if I understand glfw's documentation right, you have to compile a second part to that. I didnt want to do that so I downloaded the precompiled 64 bit binaries and put the lib-vs2022 in the root of vendor/glfw and renamed it to lib. You still have to compile the main part of glfw, as well to create the other lib. I then added glfw3_mt.lib underneath opengl32.lib under links. And added a new section above that named libdirs with a link to vendor/gflw/lib in hazels main premake5 script. I dont know if this is the correct way but it worked after that.
I tried with the latest GLFW version 3.4, it didn't work, so I downloaded the version before that (which is 3.3.8) which should be the latest version when @shihaong2220 commented, and now the issue got fixed!! thank you for pointing that out.
For anyone watching this in 2021 who happened to create their own fork of GLFW for their project and is running into LNK2019 (linking) errors, specifically involving init.c and vulkan.c, I have found a temporary solution. Granted, this may not be the "right" thing to do, but seeing as (I believe) he changes this overall workflow later anyways, it may be worth doing in order to continue along with the series. So, within your submodule, run: git checkout tags/3.3 then add, commit, and push to your master branch. Hope this helps.
Had the same issue as you. I went through all the missing c functions in the GLFW project and added them to the premake5.lua. This worked for GLFW 3.3.6 (master branch as of writing this comment) in project files: files { ..., "src/platform.c", "src/null_init.c", "src/null_monitor.c", "src/null_window.c", "src/null_joystick.c" } in filter "system:windows": files { ..., "src/win32_module.c" }
@@SkyFallsLegion Thanks so much for the help!! I tried looking back through at the c files as well, but I’m a noob when it comes to a lot of this linking stuff. Your solution worked like a charm
@@matthewwhalen9585 Glad to hear! As someone who's new to c++, the linking issue was tough to debug. But as always, when you go down a debug hole, you learn a lot! Good luck with your engine!
I'm struggling with this, i'm still a c++ newbie, and have no idea how to fix this linking issue. I even dumped my repo and pulled the thecherno/hazel one on this specific commit and the same problem occurs, can't build due to the glfw linking issues.
glfwSwapInterval(x); if x = 0 >> FPS would've no limit. if x = 1 >> FPS would be set to the monitor's current refreshrate if x = 2 >> FPS would be half the monitor's refreshrate and so on...
So an inverse relation. Thus people can calculate the fps limit using this equation: *limit = refresh-rate/interval* And if you divide by 0 then it is obvious that there's no limit or it is set at infinity. Note: This comment's OP is actually me on my alt account and I'm just rewatching after +2 years due to high-school bottlenecking my progress in the series.
Tried compiling and linking but getting several errors such as "2>GLFW.lib(window.obj) : error LNK2019: unresolved external symbol __imp_strncpy referenced in function glfwWindowHintString" Anyone hit this and found a solution?
Ok so I'm obviously following this through nearly 3 years after it was done live. It seems the TheCherno version of GLFW has moved on a little, and a couple of commits back there were a some lines removed from the premake5.lua for GLFW. This may well work by the time I catch up with present day Cherno, however for now it does not... Therefore I have reinserted these 3 lines show in context below... and everything works... at least for now :) If you come up against this bug yourself... recreate the "system:windows" filter to include start as follows: filter "system:windows" buildoptions { "-std=c11", "-lgdi32" } systemversion "latest" staticruntime "On" I hope this is clear.
@@JohnLee-ef8lf Worth noting that @TheCherno alters his position in this area a few times as the series progresses. I'm up to the start of "Rendering Context" (EP 27 in the playlist) and things definitely got reassessed in the 25/26. All I'm saying is: don't get too attached to this :)
@@acelyon5221 Yah, this doesn't work for me either. In fact, this is exactly the code I had there before I first ran into this issue. Only difference from TheCherno's code is that it uses "latest" instead of some hardcoded Windows version number. So, I'm pretty much stuck :/
I'm a huge fan of this series and the new format! The series is all about how game engines are made seriously instead of what I feel like are kind of easier versions elsewhere on the internet. The new format is like a code review and helps the understanding so much!
I just wanted to post this in case anyone else had this problem and if someone could give me an explanation as to why this is the fix. When compiling the code after implementing the WindowsWindow class, the linker couldn't link to GLFW properly. I changed the static runtime option in the GLFW premake5.lua file to on and then it linked and ran properly. Why is this the case and what did this do?
Hey I looked this up actually. It has to do with multithreading. turning it off is for "Multithreaded DLL (/MD)", while turning it on is for static which is how we are linking, only the hazel engine library should be the DLL in this solution, GLFW will be static
Thank you for this. You've lived up to your name. I ended up submoduling (is that a word??) GLFW version 3.3.6 (latest) and still got linker errors although I wasn't having compilation errors anymore. Your suggestion fixed my linking issues with GLFW. Thank you, Yuno for explaining this.
Maybe a dumb question, but does anyone know why we forked glfw and have it as a seperate project in Visual Studio? Why didn't we just add it the same way we added spdlog? Why is it so complicated to handle dependencies in C++? :D
Event was unable to read the ToString and EventFn = std::function; had to include the precompile headers. I don't know if it should be done in that header, but at least it compiles now.
As the application.cpp creates a window using the Window class 'create' which WindowsWindow inherits from, if you have a LinuxWindow class that also inherited from Window, how would you control which class application.cpp uses?
When it comes to assertions, what happens if the glfw window isn't initialized in a release build on a user's computer? how would that be handled? this seems like a perfect use-case for exceptions imo, but I'm not sure if I'm missing something
it will likely crash unfortunately if it doesnt initialize properly once the engine is debugged that normally mans you dont have an opengl version which supports this game engine at that point no amount of failsafes will get the program to work. And opengl isnt just a program you can download its something thats native to your graphics cards
The purpose of the assert is different from the try/catch or if statement. The purpose of the assert is "This piece of code should never fail and if it did theres a bug in the code"
@@gaymerjerry so there's no case where initializing a glfw window would unexpectedly fail? Such as if a user's driver is bad? I understand the purpose for assertions
@@gaymerjerry it's not about "fail safes" to get the program to work. it's about the user being able to report the problem to the developer. an assert means the program will crash, as you said, and therefore the inability for the user to tell the developer that its because "window failed to initialized", which you can easily be alerted of with the exception mechanism. for me - assertions should be used to test programmer logic errors - code that WILL be tested, and is not computer/situation dependent, meaning WHEN it gets tested, if no assertions are hit. it HAS to be correct. this, for me, isn't a case for that - unless i'm missing something about the window initialization process
What should be the deciding factor between building third-party libraries from source as demonstrated in this video, versus downloading the pre-compiled binaries and linking them as dependencies?
Adding your libraries as submodules keeps your project up to date. If you will take just binaries, you will have to replace them one day with newest ones. That's the main reason in most projects. There are few more reasons, but it's rare cases.
Hi @TheCherno, I hope this could help, when u use an external lib in your project, like GLFW, I think that is better install it with CMake(the case of GLFW) rather than fork the repo, and create a premake file, because with this u only need to link the libs that u compiled by yourself
Because spdlog is a header-only library, it doesn't need to be compiled separately. When we include the header files into our Hazel source files, it gets compiled.
@@TheCherno Thanks a lot! I'm really enjoying this tutorial series. I'm trying to only use it as a loose guide for my own engine just so I can say that I wrote it myself, and its been incredibly helpful!
Note to self: Dont forget to add all the files in premake files { "%{prj.name}/src/**.h", "%{prj.name}/src/**.cpp", "%{prj.name}/src/Events/**.h", "%{prj.name}/src/Events/**.cpp", "%{prj.name}/Platform/Windows/**.h", "%{prj.name}/Platform/Windows/**.cpp" }
I'm getting Warning C4251 'WinWindow::m_data': struct 'WindowData' needs to have dll-interface to be used by clients of class 'WinWindow' I'm only loosely following the tutorial, and I'm using the same struct WindowProps (called WindowData) in both Window.h and WindowsWindow.h I tried adding the macro responsible for __decl(dllexport/dllimport) to WindowData, but I get similar error messages for each member of WindowData. I don't see why I'm getting the warning and Cherno isn't. I'd really appreciate anyone's feedback. Edit: Cherno is getting the same warnings (but he deselected warnings from the vs error list), it's fine since this project will be shipped with the source code. The warning signifies that there might be problems if you compile the .dll with one compiler and compile the .exe with a different one.
TheChernoProject :*Teaches how to make a game engine for free*. Dat guy: aCtUaLlY tHiS iS tHe cOrReCt WaY To cOdE.............................................
The Window doesn't have to be virtual. If you are determining the actual implementation at compile time you can use pimpl in the header and ifdef the actual implementation.
Not sure if this will be seen, but I've followed this series with no errors until now. The error specifically is "An internal error has occurred in the compiler.", produced from the spdlog file logger_impl.h, and I've narrowed the cause down to the 2 logging macros in the WindowsWindow.cpp file. Commenting out these macros avoids the problem and everything works, but it's annoying that I can't use the logging system in this file (and presumably more files in this Platform folder).
I love your videos! I'm wondering how you made spdlog output to a terminal when the application is a window application. On my computer visual studio (I think, or is it the os?) eats all output to cout or cerr, so I have to make spdlog write to a file if I want to read it xD
I don't know if this will be answered, but i hope... Why do you override virtual inherited functions? Isn't that what virtual does? Never really used override but since you haven't defined the virtual functions shouldn't it be ok? Or does it have to be a pure virtual in order to automatically override?
Maybe I will understand this later but at this stage, it's unclear to me why spdlog only needed a simple `includedirs` directive while GLFW requires that we include its build configuration in our premake file.
spdlog is a headers-only library, meaning all its source code is in headers. The consumer of the library includes those headers in their own project and both sources compile & link together. GLFW is a static library meaning it is compiled separately. The product of its compilation is a .lib file which the consumer of the library then links with their project. Including spdlog's sources is enough to use it, which is why adding it to includedirs is enough, while GLFW actually requires you to build it (produce the .lib file) which is why Cherno had to create a Premake script and build it independently.
The final code of the Hazel Engine on github is different from that in each episode. Can someone tell me how to get the source code in these videos? thanks a lot!!
There is a history button. You have to go back to the commit used in this video. Personally, I'm feeling like giving up on this series. It was good until the format change and now I can barely understand anything.
Hi thanks for this nice episode, keep it up! Guys can someone explains me how the system knows to create a WindowsWindow and not BlablaWindow ? I don't understand this part.
The Window::Create function is static and the WindowsWindow file includes Window.h. The fact that the function is static means that any instance of the Window class would be aware of that function and any of its implementations. Now I don't fully understand the structure used here myself but I presume that the reason why the system creates a WindowsWindow implementation is because there is not other implementation available. I think in future episodes he might use some macros to specify which Window::Create implementation to use (based on the platform).
great vid! I know this is kind of lost in time, but can anyone explain how we're able to use glfw without first downloading glad or glew or one of the function loading things? Because I thought glfw used OpenGL functions that you had to find in your GPU drivers using one of those, but I can't see any references to them?
Glad is an implementation of modern OpenGl, since we only use the old openGl we only need glfw's headers and the opengl32.lib file that is integrated in you GPU (go check the opengl series it will explain it all to you)
Everytime I run the code, it throws an error at WindowsWindow.h at including glfw3.h, I checked the premake file multiple times and it exactly is the same as the one in Hazel.. I don't understand what's going wrong.
Man, what I found usefull is to go to the github repo and look for the commit previous to the release date of the video, and compare my code with the code in the repo, sometimes I even copied and pasted it into my files, it solved a lot of errors, some other errors it doesn't.
@@JoseRodriguez-rx4ck Well I eventually found out something weird was going on visual studio. Had to re install and it ran fine. Till today I have no clue why that happened
I finally hit the wall. I realize something now as I watch these videos, the GitHut link in the description takes me to the current version of the files. Meaning, that there are things in there I haven't, or the Cherno hasn't done during the upload of the video. I was trying to find an older version that matches the video's version as the Cherno was making changes, but I couldn't. It wasn't until I had downloaded the file from GitHub that I realized I was looking into the future of what the Cherno would do later in the series. I ended up not having a "Platform" folder; I didn't even have a "Windows.h" file in the Hazel folder. Perhaps I did something wrong, at this point, I think I've lost the battle with this "wall" I hit, but hopefully not the war. I believe that if i were watching these videos as they were coming out, that I would be able to keep up, however, that's not the case. I will update on this comment once I've been able to solve this problem... if I am able to. I say this with a bit of hope that I can get past this "wall": I'll see you on the next video's comment section.... maybe :(
I did it! I was getting worried there for a moment or two. I realize that the folders and .h and .cpp files were added by the cherno and not automatically when downloading GLFW file. I was able to find the older version in GitHub that was used when the video was uploaded, and so i was able to follow along with the video just fine. In the end, I was able to create the pink window screen like he does at the end of the video. I'm happy to have gotten pass this video, and with confidence I can now say: I'll see u on the next video's comment section :)
@@obi1jim316 Yes, you are right, using the git repository to find the commit previous to the video release date is awesome, I got to fix almost all the errors (mine ofcourse) except for "cannot open file 'opengl32.lig.lib' " other than that your idea help me a lot.
@@JoseRodriguez-rx4ck it's "opengl32.lib", and also I'm getting linking errors when building Hazel project, like __imp__calloc, __imp__strncpy and others, I'm trying to fix this problem 😕
@@memeguy8185 Hey, i got the same problem you had, and i found a solution if you still need it, and just in case anyone else needs it :) In the premake5.lua script, on the configuration filters, I specified /MTd and /MT as build configurations for build and release respectively. This is the new piece of the script: filter "configurations:Debug" runtime "Debug" buildoptions "/MTd" symbols "on" filter "configurations:Release" runtime "Release" buildoptions "/MT" optimize "on" I hope it helps!
@@GDZenith Thank you!!!!!!!!!!! I was stuck on this for awhile, also if anyone else makes the same mistake as me, Zenith means to change the premake5.lua script for GLFW, not the one for Hazel!
Thanks as always for uploading Cherno, I love the series! Am I right in saying that member functions defined within a class definition don't need to be explicitly inlined? For example, WindowsWindow::GetWidth(). Not an issue obviously I'm just wondering whether you do that for increased clarity. Thanks again, can't wait for next episode!
yknow before I got into programming I thought I'd have big tabs vs spaces arguments I wouldn't care about. never happened. I haven't met anyone who cared one way or the other. has anyone been in a tabs vs spaces argument?
I had a lot of bad memories with SDL to be honest. Like there was that one time SDL was causing a lot of lag or not handling events correctly on my old laptop and GLFW just killed it so personally I prefer GLFW.
I honestly hate that he just looked through code in these parts. I can't follow anything and when I look at the github in order to follow along, its out of date. I've spent 2 days tryna get this one part working and its not, great.
Hello, I know that I am a few years behind; however, I am having a linking problem with GLFW. I thought I am doing it the same way as in the video. The issue is LINK2019 unresolved external symbol _glfwSelectPlatform referenced in function glfwInit ..... And a few other similar. Any help would be greatly appreciated.
Ok, I did figure out how to do it with premake, so I just linked it directly in the project for now to continue with learning. It is working now as a dependency.
Is "because it's made by MicroSoft for Windows" actually a valid argument? Every game I've played that's offered both DX (11 or 12) and Vulkan on Windows has run better on Vulkan. Clearly the programmers have to write different code to deal with that so there're uncontrolled variables there, but it still doesn't seem right.
You know you can tell visual studio to automatically insert spaces when you tab, right? Under Tools->Options->Text Editor->All Languages->Tabs. I currently have mine set to make 4 spaces when I tab. You may also have to go to Tools->Options->Text Editor->C/C++->Formatting and uncheck "Automatically indent when I type a tab"
On one video, I recall you saying that you would not use glfw and basically create the window yourself from scratch but since it was about "learning opengl" you said you did not care and just wanted it to work or something along those lines and then said that you would create your own if you were writing a game engine. Umm, you are writing a game engine currently?
Anyone know how to solve: Error LNK2019 unresolved external symbol DwmExtendFrameIntoClientArea referenced in function windowProc Hazel GLFW.lib(win32_window.obj 1 I've already tried changing the runtime library settings in project properties as per previous posts, but this error still remains. Thanks in advance.
The new video structure is a bit of a headache. My comprehension of your code was better before. This new structure feels rushed and seems like you are already getting bored/irritated with the lessons.
Thanks for watching guys, hope you enjoyed the video! Next episode is already available for Patrons at www.patreon.com/posts/23365701
You may have two problems when following this episode:
1. lots of unresolved external symbols
2. unresolved external symbols DwmExtendFrameIntoClientArea
1. For the first problem, you may notice that in GLFW project setting, go to C/C++ -> Code Generation, on the right hand side, the runtime library is Multi-threaded DLL (/MD), that means when compile this project, GLFW will use C++ dynamic library. And in the Hazel project setting, the runtime library however is Multi-threaded (/MT), that means when compile this project, Hazel will use static links of C++ runtime. Now we can have 4 combinations, and all of them are valid except GLFW use (/MD) and Hazel use (/MT).
Therefore, you can have GLFW use (/MD) and Hazel use (/MD), or GLFW use (/MT) and Hazel use (/MD), or GLFW use (/MT) and Hazel use (/MT)
Here, it is better to set this options in premake5.lua file, however I didn't find any method to change that setting. You can set it in Visual studio directly. And don't forget to set it each time after you regenerate the solution .sln file.
2. For the second problem, I guess that the new version of GLFW use this new function, and this function is in dwmapi.lib. Therefore, add this dependency into premake5.lua.
links
{
"GLFW",
"opengl32.lib",
"dwmapi.lib"
}
And regenerate the solution. Don't forget to change the C++ runtime setting.
set staticruntime "on" in every Premake file for every project
Thanks man!!
Thank you so much for the detailed clarification. I was struggling with older commits to figure out the problem for two whole days. I knew the problem had to do with the engine project output being changed from dynamic lib to static, but I couldn't pinpoint the issue.
For me, the first option resolved all errors
Thank you very much
Thanks! I finally got it to work after I changed GLFW project properties -> C/C++ -> Code Generation ->Runtime Library -> Multi-threaded (/MT)
Thanks Bro! I struggled a whold day and just can't make the program successfully run. You did save me!
@@willianwu4317 No problem, what I learned now is that the Libraries should be set to /MD or /MDd (debug) and Sandbox to /MT or /MTd (debug). I don't think premake does this well but it could be my setup file is wrong :) I keep changing it manually.
I have been pulling my hair out for about a week trying to figure out why it wasn't working...you probably just saved the rest of my head, thank you
Btw do you know if there is a premake command I can add that will set this automatically?
@@electricn0va Yes he does set it up in a later video but I still have to manually change it from time to time maybe I implemented it wrong but (I think) it should be for Libraries: buildoptions "/MDd"
filter "configurations:Debug"
defines "HZ_DEBUG"
buildoptions "/MDd"
symbols "On"
filter "configurations:Release"
defines "HZ_RELEASE"
buildoptions "/MD"
optimize "On"
filter "configurations:Dist"
defines "HZ_DIST"
buildoptions "/MD"
optimize "On"
@@electricn0va in episode 17 Github and Hazel he explains to use runtime not buildoptions. This should be the fix I haven't tried it yet (just watching it)
I had a hard time following this one as i'm coding along and not just getting the resource from your git repos. I managed to make it work in the end and i have learn a lot of things so cheers as always.
I feel like this new way of going over the game engine is glossing over huge steps and being less efficient than before. I think a better method would be a video on heavy concepts such as windowing, event system, etc, be live coding. Then do a smaller 5-15minute video of review over that episode where you go over the changes you made to the code after reviewing it yourself (since not everything can be caught coding live), that follows the format you're doing now. When you did live coding episodes you explained why you did what you did where as this feels like a sparks note of the code, and doesn't explain much.
its also difficult because his git diff tool does not show line numbers
even following along with the repo its not clear which commit is used for this video
For anyone attempting this in 2024 and getting lots of linking errors, the Cherno actually forgot to include some files in the premake file (of the GLFW), Here is my file which worked: (for windows)
project "GLFW"
kind "StaticLib"
language "C"
targetdir ("bin/" .. outputdir .. "/%{prj.name}")
objdir ("bin-int/" .. outputdir .. "/%{prj.name}")
files
{
"include/GLFW/glfw3.h",
"include/GLFW/glfw3native.h",
"src/internal.h",
"src/platform.h",
"src/mappings.h",
"src/context.c",
"src/init.c",
"src/input.c",
"src/monitor.c",
"src/platform.c",
"src/vulkan.c",
"src/window.c",
"src/egl_context.c",
"src/osmesa_context.c",
"src/null_platform.h",
"src/null_joystick.h",
"src/null_init.c",
"src/null_monitor.c",
"src/null_window.c",
"src/null_joystick.c"
}
filter "system:windows"
systemversion "latest"
staticruntime "On" --staticly linking the runtime libraries
files
{
"src/win32_init.c",
"src/win32_module.c",
"src/win32_joystick.c",
"src/win32_monitor.c",
"src/win32_time.h",
"src/win32_time.c",
"src/win32_thread.h",
"src/win32_thread.c",
"src/win32_window.c",
"src/wgl_context.c",
"src/egl_context.c",
"src/osmesa_context.c"
}
defines
{
"_GLFW_WIN32",
"_CRT_SECURE_NO_WARNINGS"
}
filter "configurations:Debug"
runtime "Debug"
symbols "on"
filter "configurations:Release"
runtime "Release"
optimize "on"
Thanks!
You're savior, god bless you
god bless ur soul mate
Legend!
You inadvertently started a tabs vs spaces war.
Good lord do people really give a shit? Seems as though if there is no fight you gottamake one. Sigh.
@@infinitesimotel you shouldn't take the comment at heart, it's a joke and a reference to a popular subjective topic.
@@codeorbs I think youre right. I took life seriously for a second... I don't normally do that.
Tabs are better.
@@humm535 Yup they're better unless you want your code to look pretty on every machine.
If anyone is having issues with unresolved externals related to glfw3 when building, I found the issue to be in properties -> C/C++ -> Code Generation -> Runtime library. Switching it from Multi-threaded debug (/MTd) to Multithreaded DLL(/MD) or Multithreaded Debug DLL (/MDd) did the trick.
To make the premake file do what you want, they keywords are staticruntime and runtime.
for /MD you want staticruntime "off" and runtime "Release", and for /MDd you want staticruntime "off" and runtime "Debug". You may also need to get rid of any buildoptions that override this (I had buildoptions "/MT" which overrode /MD).
Hopefully this saves someone some time :)
do you might know what buildoptions that could have override the /MD
tysm, i was about to loose my mind lol
More importantly, there are missing files currently. Check the forked GLFW repo for an updated premake file if you insist on mimicking on that level. (you can just copy the files for all platforms and windows)
I love you guy
thank you soo much you saved me sooooo much time
Hey! I just wanted to make a comment about the teaching style and your comments at the beginning of the video. I am a Computer Science teacher who has taught courses on game programming / engines, and have spent a lot of time talking to other faculty members / industry programmers about how to teach game programming. I have found that for students / audiences with zero initial knowledge, it is much better to use a top-down approach then bottom-up when teaching game engine programming. Bottom up like you are doing is great for the more technically minded audience who already has some experience, because they can greater appreciate the context for why you are doing what you are doing. Despite your explanations, its really only something you can appreciate after you've already made a game and done a bunch of things wrong.
For completely new students, I greatly prefer top-down. By doing things top-down, you can start with a very simple game example with controls, drawing the the screen, and get the students hooked on having an actual very simple game up and running. Now that they have this experience, you can start abstracting away parts of the engine into the systems that you are talking about here in your video series. Once they have dealt with things like hard-coded input handling, or tying their drawing system to a specific API, they can really start to appreciate Event systems or window abstractions. So I understand why you are teaching it this way, but just realize that you are probably going to either a) lose the interest of novice programmers, or b) only start to get a lot of views after the entire series has been completed.
Please don't take this as criticism, I'm a huge fan of the series and don't want you to change anything. I was just giving another explanation of why you might find viewership not being as high as you'd like so far. Please keep up the great tutorials! I've pointed some students to your C++ videos in the past and they're a great resource.
One other small thing: You probably don't need to spent 2-3 minutes at the beginning of each video apologizing for the previous video or explaining the context of this video within the series. Once the series is completed and people binge-watch the videos that will pretty much just be dead air. So while you're explaining it now and it makes sense, later on it might not be worth having those segments in the video. I think it might be a better idea to just get straight to the content of the video, and then maybe release a separate longer video explaining all of the other non-programming related things.
I don't want to blindly defend him as I have some concerns about the video structure too, but I don't mind this series being bottom-up as you put it. if you look at the channel playlists this is at least the third game engine series. The Sparky engine series and the OpenGL series are both top-down. My complaints are more towards the incomplete lessons. It's been three weeks since the event system planning video, two since the event system programming video and viewers likely still have no idea how to actually use it. There's no class to publish callbacks to, nothing to publish events to, just the events themselves. I hope I'm wrong, but I don't expect anymore videos for 2-3 weeks. Yan's gotta be doing Christmas/ New Years stuff just like everyone else.
@@marklinton4567 I didn't mean to say that what he was doing is wrong, but it may explain the viewership drop he mentioned, that's all :)
I don't want him to change anything, his lectures are fantastic. I will stop following him if he did what you ask him to do. Technical viewership is the way to go. They can always learn from his other lectures.
My take on this is that what you are describing lives in several places on the internet already. I have found several of them, but never make it far in any of them simply because I cannot do the "just make this thing with all this magic" approach before understanding. This series is unique in part because it does what you are saying is the less effective method.
To combat what you're describing, I would suggest he do a design video every 2 or three videos describing the overall big picture and the why behind the decisions, and then go on to implement them ground-up.
PS: You're right the preamble is distracting.
Hmmm I get the sentiment and you are certainly correct in your conclusions for technically minded(aka very knowledgeable and/or experiences programmers) vs new(aka people who have a grasp of perhaps the language and some of the other constructs / hardware implementations used... [as an aside I would class myself as one of these] ).
Having said all that I think that what Yan failed to make clear enough (my opinion) at the outset was that this series is FOR the first group... the second can give it a shot but it will require some VERY. DEDICATED. EFFORT. to get there (aka google is your friend... and UA-cam... [but also extremely frustrating because of the amount of unintelligible crap that you will have to sift on your way to understanding] but I digress...).
To be fair he has droped many hints along the way... "go see this or that video", "if I was to explain (insert subject here) then we would be here 'til Xmas... aka known as a very polite form of RTFM. And TBH I think he has done an amazing job of making it as simple as it is... This is far from common in an advanced series... and this IS an advanced series, but in actual fact this is a lot easier than many others (lesser in difficulty than this) that I have seen over the years.
Of course I think he needs his head read trying to teach a free course on engine design to the masses without stressing an encylopedia of before you start you must know...(insert a plethora of subjects) but then he is a far more talented and generous person than I can proclaim to be... :) jmtcw... digest with a healthy dose of scepticism or disagreement of your choice.
Line 22 here 12:00 *buildoptions { "-std=c11", "-lgdi32" }* is the reason for the problem here 14:32.
Thanks, it helps a lot.
Ayy my alt account! Long no see. (rewatching)
Hey Cherno. I understand why you made the switch to prewriting the code, and just reviewing it, but this way isn't really teaching. I really preferred the other style. I know it is probably more difficult to play to write everything, but I learn by coding along side you. I really miss the old format.
too bad, he's probably not gonna remake this entire series
really self aware move. my two cents: i enjoy all the of the content and i'd be most excited to follow the logical structure for a game engine... im a beginner and doing foundation data structure stuff before i really move onto this though. realy brilliant videos man, youre a great teacher
So, you've been following this series? How's it been going on for you, specially since you state you're a beginner?
My English is not very good, so I translate part of your words into a dictionary, write out unfamiliar words and teach them. I really want to understand everything that you say by ear. You're the best, thanks for your videos.
P.S. This post is written in google translator
I wonder if your english improved by now
@@abdelrahmanyasser4519 Me too :D
@@HappyHippo0609 oh wow I never expected anyone to reply in this comment section
this is better than my school education
you are a good man. thank you
- Single responsibility principle: Your window class should not directly be responsible for the GLFW initialization
- Constructor and destructor exist for a reason so there's no point to write Init() and Shutdown() functions at this stage and from a object point of view, there's never a need for those functions. If you want to reset the state, you just create a new object.
- Returning a owning raw pointer from your Create-factory function is rather dangerous, as you now rely on the user of said function to a) know that this is an owning raw pointer and b) properly takeover ownership and destroy it. At zero cost, you can just have the factory function return a unique_ptr and call make_unique, that way the signature indicates that you're a) transferring ownership and b) as long as the user doesn't explicitly misuses the unique_ptr the destruction of the window is guaranteed.
- To initialize your member variable, use the initialization list instead of doing it in the constructor.
15:35 This kind of code design is actually described by a design pattern named Abstract Factory for the once who are interested :D
It's just a Factory Method, I think. Abstract Factory is a bit more complex.
It's a little hard to follow what is actually included in a file, because often the include is not explicitley in the file but in the pch or other files that include the current file, or is that just me ?
Don't use the most updated GLFW in Cherno's repository. That would give you error which I don't remember anymore. It's a quite long name and no where you can find help online. Instead go to the corresponding commit of this video "Added Window class and GLFW'" and click 'GLFW' in left side panel, then on the right side large panel you can find 'Submodule GLFW added at b4b431'. Click 'b4b431' and there is the right GLFW you need to finish this video. I am totally a starter so I can't find out what is the essential difference between this GLFW and the most updated GLFW in Cherno's repository, but any way, this solved my problem. Oh and don't forgest to change the 'systemversion "10.0.17134.0" ' to 'latest'( or whatever your Visual Studio have) sin premake5.luna file which Cherno mentioned in this video.
THANK YOU SO MUCH DUDE I SPENT SO LONG TRYING TO FIGURE THIS OUT I LOVE YOU SO MUCH ♥♥♥♥♥ IM NOT EVEN A BEGINNER AND I COULDNT EVEN FIGURE THAT OUT YOU'RE SO SMART THANK YOU
@@goozjeesh46 Wow glad to hear I am not the only one studying Cherno series in 2023!
THANK YOU MAN ! 🎉 i also changed runtime library to multithreaded dll debug. That solved my problem completlly.
Thanks brother, was stuck on this for a day - nearly gave up going through a course so old
Thnx a lot.
I had to go through all the videos till now twice to understand what was going on here. I don't think there is any such c++ intensive project on whole of UA-cam which not only teaches c++ but also helps visualize it. All hail @TheCherno
in the beginning I found premake quite difficult, but it's actually easier and more convenient to use than the visual studio property pages. Microsoft has outdone itself on that one.
I recommend using the latest branch of GLFW, it worked for me, as I think that branch is just more stable overall, and didn't give me any linking errors.
And no, the format is fine, the tutorials still work. Stop leaving negative comments and binging about why you want to give up because you are not willing to look hard enough.
Hey, could explain how exactly you use the latest branch of GLFW? Does that mean I need to fork the repo from somewhere else?
@@fazzo5409 No offence like, but if you can't figure that out then you haven't been paying close enough attention to the videos.... Just sayin'
I know right, dude is giving us some really good information on his own time and people think its ok to talk crap because they need someone to hold their hand.
Anyway, I did the same thing as you, but still ended up with linker errors. I forked a branch from the new one, but if I understand glfw's documentation right, you have to compile a second part to that. I didnt want to do that so I downloaded the precompiled 64 bit binaries and put the lib-vs2022 in the root of vendor/glfw and renamed it to lib. You still have to compile the main part of glfw, as well to create the other lib.
I then added glfw3_mt.lib underneath opengl32.lib under links. And added a new section above that named libdirs with a link to vendor/gflw/lib in hazels main premake5 script.
I dont know if this is the correct way but it worked after that.
I tried with the latest GLFW version 3.4, it didn't work, so I downloaded the version before that (which is 3.3.8) which should be the latest version when @shihaong2220 commented, and now the issue got fixed!! thank you for pointing that out.
For anyone watching this in 2021 who happened to create their own fork of GLFW for their project and is running into LNK2019 (linking) errors, specifically involving init.c and vulkan.c, I have found a temporary solution. Granted, this may not be the "right" thing to do, but seeing as (I believe) he changes this overall workflow later anyways, it may be worth doing in order to continue along with the series.
So, within your submodule, run:
git checkout tags/3.3
then add, commit, and push to your master branch.
Hope this helps.
Had the same issue as you.
I went through all the missing c functions in the GLFW project and added them to the premake5.lua.
This worked for GLFW 3.3.6 (master branch as of writing this comment)
in project files:
files
{
...,
"src/platform.c",
"src/null_init.c",
"src/null_monitor.c",
"src/null_window.c",
"src/null_joystick.c"
}
in filter "system:windows":
files
{
...,
"src/win32_module.c"
}
@@SkyFallsLegion Thanks so much for the help!! I tried looking back through at the c files as well, but I’m a noob when it comes to a lot of this linking stuff. Your solution worked like a charm
@@matthewwhalen9585 Glad to hear! As someone who's new to c++, the linking issue was tough to debug. But as always, when you go down a debug hole, you learn a lot!
Good luck with your engine!
I'm struggling with this, i'm still a c++ newbie, and have no idea how to fix this linking issue. I even dumped my repo and pulled the thecherno/hazel one on this specific commit and the same problem occurs, can't build due to the glfw linking issues.
@@SkyFallsLegion Wow! Thank you. After five hours of struggling on this problem (but learning a lot) I've finally found a solution.
I have an error saying GLFW.lib is not a win32 application. How can I fix this?
Hey Cherno, ,You are doing amazing stuff please keep it up!
better use two commas
glfwSwapInterval(x);
if x = 0 >> FPS would've no limit.
if x = 1 >> FPS would be set to the monitor's current refreshrate
if x = 2 >> FPS would be half the monitor's refreshrate
and so on...
So an inverse relation. Thus people can calculate the fps limit using this equation:
*limit = refresh-rate/interval*
And if you divide by 0 then it is obvious that there's no limit or it is set at infinity.
Note: This comment's OP is actually me on my alt account and I'm just rewatching after +2 years due to high-school bottlenecking my progress in the series.
4:20 *Sad vulkan noises*
Tried compiling and linking but getting several errors such as "2>GLFW.lib(window.obj) : error LNK2019: unresolved external symbol __imp_strncpy referenced in function glfwWindowHintString"
Anyone hit this and found a solution?
Ok so I'm obviously following this through nearly 3 years after it was done live.
It seems the TheCherno version of GLFW has moved on a little, and a couple of commits back there were a some lines removed from the premake5.lua for GLFW.
This may well work by the time I catch up with present day Cherno, however for now it does not...
Therefore I have reinserted these 3 lines show in context below... and everything works... at least for now :)
If you come up against this bug yourself... recreate the "system:windows" filter to include start as follows:
filter "system:windows"
buildoptions { "-std=c11", "-lgdi32" }
systemversion "latest"
staticruntime "On"
I hope this is clear.
@@RoryBecker OMG!Thx!!!!!!
@@JohnLee-ef8lf Worth noting that @TheCherno alters his position in this area a few times as the series progresses. I'm up to the start of "Rendering Context" (EP 27 in the playlist) and things definitely got reassessed in the 25/26. All I'm saying is: don't get too attached to this :)
@@RoryBecker For some reason this doesn't work for me. I don't know why I been reading the comments and been finding nothing to help.
@@acelyon5221 Yah, this doesn't work for me either. In fact, this is exactly the code I had there before I first ran into this issue. Only difference from TheCherno's code is that it uses "latest" instead of some hardcoded Windows version number. So, I'm pretty much stuck :/
Just a small note: Ctrl + H (aka. find&replace) could be really helpful for changing tabs/spaces rather than finding them one-by-one.
Please go back to the old format & write it live! This is so much harder to follow!
Copy code from github. Link is in the description.
@@richardlighthouse5328 Half the time the repo hasn't even been updated.
@@bacontf2 Right now it is. That episode i meant.
"Here what's up guys, my name's *inaudible*. Welcome back to my game engine series".
It's like that in every video man!
Hey there, awesome video as always :)
A small request thou - could you show the diff changes at the start of the video?
I think that GLFW can return HWND window and you can also set NO_API in some method and then use DirectX.
I'm a huge fan of this series and the new format! The series is all about how game engines are made seriously instead of what I feel like are kind of easier versions elsewhere on the internet. The new format is like a code review and helps the understanding so much!
I just wanted to post this in case anyone else had this problem and if someone could give me an explanation as to why this is the fix. When compiling the code after implementing the WindowsWindow class, the linker couldn't link to GLFW properly. I changed the static runtime option in the GLFW premake5.lua file to on and then it linked and ran properly. Why is this the case and what did this do?
Yoo thanks!
@@luaa. You're welcome.
Hey I looked this up actually. It has to do with multithreading. turning it off is for "Multithreaded DLL (/MD)", while turning it on is for static which is how we are linking, only the hazel engine library should be the DLL in this solution, GLFW will be static
Thank you for this. You've lived up to your name.
I ended up submoduling (is that a word??) GLFW version 3.3.6 (latest) and still got linker errors although I wasn't having compilation errors anymore. Your suggestion fixed my linking issues with GLFW.
Thank you, Yuno for explaining this.
Thanks alot man!
Maybe a dumb question, but does anyone know why we forked glfw and have it as a seperate project in Visual Studio? Why didn't we just add it the same way we added spdlog? Why is it so complicated to handle dependencies in C++? :D
Event was unable to read the ToString and EventFn = std::function; had to include the precompile headers. I don't know if it should be done in that header, but at least it compiles now.
As the application.cpp creates a window using the Window class 'create' which WindowsWindow inherits from, if you have a LinuxWindow class that also inherited from Window, how would you control which class application.cpp uses?
When it comes to assertions, what happens if the glfw window isn't initialized in a release build on a user's computer? how would that be handled? this seems like a perfect use-case for exceptions imo, but I'm not sure if I'm missing something
it will likely crash unfortunately if it doesnt initialize properly once the engine is debugged that normally mans you dont have an opengl version which supports this game engine at that point no amount of failsafes will get the program to work. And opengl isnt just a program you can download its something thats native to your graphics cards
The purpose of the assert is different from the try/catch or if statement. The purpose of the assert is "This piece of code should never fail and if it did theres a bug in the code"
@@gaymerjerry so there's no case where initializing a glfw window would unexpectedly fail? Such as if a user's driver is bad? I understand the purpose for assertions
@@gaymerjerry it's not about "fail safes" to get the program to work. it's about the user being able to report the problem to the developer. an assert means the program will crash, as you said, and therefore the inability for the user to tell the developer that its because "window failed to initialized", which you can easily be alerted of with the exception mechanism. for me - assertions should be used to test programmer logic errors - code that WILL be tested, and is not computer/situation dependent, meaning WHEN it gets tested, if no assertions are hit. it HAS to be correct. this, for me, isn't a case for that - unless i'm missing something about the window initialization process
25:32 idk if i should see it as a chain reaction or a "i know a guy who knows a guy who knows a guy who...."
What should be the deciding factor between building third-party libraries from source as demonstrated in this video, versus downloading the pre-compiled binaries and linking them as dependencies?
Adding your libraries as submodules keeps your project up to date.
If you will take just binaries, you will have to replace them one day with newest ones.
That's the main reason in most projects. There are few more reasons, but it's rare cases.
Thanks for explaining, that makes sense with the use of submodules.
Thanks Feel nice to learn stuff
Does anyone know why he passed data from props AND m_Data into glfwCreateWindow()? I don't understand what the point of mixing the two is.
Why is "Init()" and "Shutdown()" inside WindowsWindow class virtual functions?
Hi @TheCherno, I hope this could help, when u use an external lib in your project, like GLFW, I think that is better install it with CMake(the case of GLFW) rather than fork the repo, and create a premake file, because with this u only need to link the libs that u compiled by yourself
Not really a fan of the new format, I don't have any problems following or anything, i just liked the other format better
I know that this video is old but I was hoping that someone could explain to me why he made a premake file for glfw but not for spdlog.
Because spdlog is a header-only library, it doesn't need to be compiled separately. When we include the header files into our Hazel source files, it gets compiled.
@@TheCherno Thanks a lot! I'm really enjoying this tutorial series. I'm trying to only use it as a loose guide for my own engine just so I can say that I wrote it myself, and its been incredibly helpful!
Note to self:
Dont forget to add all the files in premake
files
{
"%{prj.name}/src/**.h",
"%{prj.name}/src/**.cpp",
"%{prj.name}/src/Events/**.h",
"%{prj.name}/src/Events/**.cpp",
"%{prj.name}/Platform/Windows/**.h",
"%{prj.name}/Platform/Windows/**.cpp"
}
I'm getting
Warning C4251 'WinWindow::m_data': struct 'WindowData' needs to have dll-interface to be used by clients of class 'WinWindow'
I'm only loosely following the tutorial, and I'm using the same struct WindowProps (called WindowData) in both Window.h and WindowsWindow.h
I tried adding the macro responsible for __decl(dllexport/dllimport) to WindowData, but I get similar error messages for each member of WindowData.
I don't see why I'm getting the warning and Cherno isn't. I'd really appreciate anyone's feedback.
Edit: Cherno is getting the same warnings (but he deselected warnings from the vs error list), it's fine since this project will be shipped with the source code. The warning signifies that there might be problems if you compile the .dll with one compiler and compile the .exe with a different one.
no need to include glfw in the header file.
struct GLFWWindow; is enough
TheChernoProject
:*Teaches how to make a game engine for free*.
Dat guy: aCtUaLlY tHiS iS tHe cOrReCt WaY To cOdE.............................................
@@gage2560 I mean he is right.
The Window doesn't have to be virtual. If you are determining the actual implementation at compile time you can use pimpl in the header and ifdef the actual implementation.
Hey, I have a question. What is your opinion on SDL? It's my library of choice when it comes to making my game engine while watching this.
Not sure if this will be seen, but I've followed this series with no errors until now. The error specifically is "An internal error has occurred in the compiler.", produced from the spdlog file logger_impl.h, and I've narrowed the cause down to the 2 logging macros in the WindowsWindow.cpp file. Commenting out these macros avoids the problem and everything works, but it's annoying that I can't use the logging system in this file (and presumably more files in this Platform folder).
TheChernoProject: return of the magenta
Because his theme is like magenta?
I love your videos! I'm wondering how you made spdlog output to a terminal when the application is a window application. On my computer visual studio (I think, or is it the os?) eats all output to cout or cerr, so I have to make spdlog write to a file if I want to read it xD
I don't know if this will be answered, but i hope... Why do you override virtual inherited functions? Isn't that what virtual does? Never really used override but since you haven't defined the virtual functions shouldn't it be ok? Or does it have to be a pure virtual in order to automatically override?
Maybe I will understand this later but at this stage, it's unclear to me why spdlog only needed a simple `includedirs` directive while GLFW requires that we include its build configuration in our premake file.
spdlog is a headers-only library, meaning all its source code is in headers. The consumer of the library includes those headers in their own project and both sources compile & link together.
GLFW is a static library meaning it is compiled separately. The product of its compilation is a .lib file which the consumer of the library then links with their project.
Including spdlog's sources is enough to use it, which is why adding it to includedirs is enough, while GLFW actually requires you to build it (produce the .lib file) which is why Cherno had to create a Premake script and build it independently.
Thanks for explaining, it makes total sense.
The final code of the Hazel Engine on github is different from that in each episode. Can someone tell me how to get the source code in these videos? thanks a lot!!
There is a history button. You have to go back to the commit used in this video.
Personally, I'm feeling like giving up on this series. It was good until the format change and now I can barely understand anything.
Hi thanks for this nice episode, keep it up!
Guys can someone explains me how the system knows to create a WindowsWindow and not BlablaWindow ? I don't understand this part.
The Window::Create function is static and the WindowsWindow file includes Window.h. The fact that the function is static means that any instance of the Window class would be aware of that function and any of its implementations. Now I don't fully understand the structure used here myself but I presume that the reason why the system creates a WindowsWindow implementation is because there is not other implementation available. I think in future episodes he might use some macros to specify which Window::Create implementation to use (based on the platform).
I got an error " attempt to call a nil value (global 'inlcude')", plz how to fix it..
Hey, I realise this is incredibly late, but make sure your line is
IncludeDir = {}
& not
IncludeDir {}
This was the issue I had
great vid! I know this is kind of lost in time, but can anyone explain how we're able to use glfw without first downloading glad or glew or one of the function loading things? Because I thought glfw used OpenGL functions that you had to find in your GPU drivers using one of those, but I can't see any references to them?
Glad is an implementation of modern OpenGl, since we only use the old openGl we only need glfw's headers and the opengl32.lib file that is integrated in you GPU (go check the opengl series it will explain it all to you)
Everytime I run the code, it throws an error at WindowsWindow.h at including glfw3.h, I checked the premake file multiple times and it exactly is the same as the one in Hazel.. I don't understand what's going wrong.
Man, what I found usefull is to go to the github repo and look for the commit previous to the release date of the video, and compare my code with the code in the repo, sometimes I even copied and pasted it into my files, it solved a lot of errors, some other errors it doesn't.
@@JoseRodriguez-rx4ck Well I eventually found out something weird was going on visual studio. Had to re install and it ran fine. Till today I have no clue why that happened
Nowadays, I prefer CMake for project management, for me is easier to manage, I know that the learning curve is huge, but it worth the work
I finally hit the wall. I realize something now as I watch these videos, the GitHut link in the description takes me to the current version of the files. Meaning, that there are things in there I haven't, or the Cherno hasn't done during the upload of the video. I was trying to find an older version that matches the video's version as the Cherno was making changes, but I couldn't. It wasn't until I had downloaded the file from GitHub that I realized I was looking into the future of what the Cherno would do later in the series. I ended up not having a "Platform" folder; I didn't even have a "Windows.h" file in the Hazel folder. Perhaps I did something wrong, at this point, I think I've lost the battle with this "wall" I hit, but hopefully not the war. I believe that if i were watching these videos as they were coming out, that I would be able to keep up, however, that's not the case. I will update on this comment once I've been able to solve this problem... if I am able to. I say this with a bit of hope that I can get past this "wall": I'll see you on the next video's comment section.... maybe :(
I did it! I was getting worried there for a moment or two. I realize that the folders and .h and .cpp files were added by the cherno and not automatically when downloading GLFW file. I was able to find the older version in GitHub that was used when the video was uploaded, and so i was able to follow along with the video just fine. In the end, I was able to create the pink window screen like he does at the end of the video. I'm happy to have gotten pass this video, and with confidence I can now say: I'll see u on the next video's comment section :)
@@obi1jim316 Yes, you are right, using the git repository to find the commit previous to the video release date is awesome, I got to fix almost all the errors (mine ofcourse) except for "cannot open file 'opengl32.lig.lib' " other than that your idea help me a lot.
@@JoseRodriguez-rx4ck it's "opengl32.lib", and also I'm getting linking errors when building Hazel project, like __imp__calloc, __imp__strncpy and others, I'm trying to fix this problem 😕
@@memeguy8185 Hey, i got the same problem you had, and i found a solution if you still need it, and just in case anyone else needs it :)
In the premake5.lua script, on the configuration filters, I specified /MTd and /MT as build configurations for build and release respectively. This is the new piece of the script:
filter "configurations:Debug"
runtime "Debug"
buildoptions "/MTd"
symbols "on"
filter "configurations:Release"
runtime "Release"
buildoptions "/MT"
optimize "on"
I hope it helps!
@@GDZenith Thank you!!!!!!!!!!! I was stuck on this for awhile, also if anyone else makes the same mistake as me, Zenith means to change the premake5.lua script for GLFW, not the one for Hazel!
Thanks as always for uploading Cherno, I love the series! Am I right in saying that member functions defined within a class definition don't need to be explicitly inlined? For example, WindowsWindow::GetWidth(). Not an issue obviously I'm just wondering whether you do that for increased clarity. Thanks again, can't wait for next episode!
with this window can man see the data comes from VR Glasses ?
Man, you can convert all the tabs to the spaces with "Edit->Advanced->Untabify..." :)
What is the better way to learn all about opengl, directx and game engines? Are there some books or you can find everything on the Internet?
Game Engine Architecture
anyone come across the problem where glClear and glClearColor identifier not found? Any solution
你解决了吗
Did you solve it,i have the same problem.
Getting an Address boundary error trying to use those functions...
Neat stuff!
yknow before I got into programming I thought I'd have big tabs vs spaces arguments I wouldn't care about. never happened. I haven't met anyone who cared one way or the other. has anyone been in a tabs vs spaces argument?
At the end will you be able to make a 3d game in this
supposedly yes
Already happened. :)
I wonder why you use GLFW and not SDL, since SDL does support DirectX.
because sdl does not support 3d rendering and glfw does :)
I had a lot of bad memories with SDL to be honest. Like there was that one time SDL was causing a lot of lag or not handling events correctly on my old laptop and GLFW just killed it so personally I prefer GLFW.
I honestly hate that he just looked through code in these parts. I can't follow anything and when I look at the github in order to follow along, its out of date.
I've spent 2 days tryna get this one part working and its not, great.
What is actually windows specific at this point about the WindowsWindow?
Maybe someone also stumbles apon this. This works on Ubuntu as well (so far), as far as I can tell
@@joannam.170 I think he'll add Windows-specific code later.
Hello, I know that I am a few years behind; however, I am having a linking problem with GLFW. I thought I am doing it the same way as in the video. The issue is LINK2019 unresolved external symbol _glfwSelectPlatform referenced in function glfwInit ..... And a few other similar. Any help would be greatly appreciated.
Ok, I did figure out how to do it with premake, so I just linked it directly in the project for now to continue with learning. It is working now as a dependency.
@@dustinclark5620 hey can you tell me what you changed in the premake file, im heading this problem myself and cant figure out what to change
I have the same issue
@Dustin Clark Same issue, how did you solve it?
I checked out the older GLFW commit as a work around for now
Do I have to watch your OpenGL series first before getting into this? or can I just watch this series without doing so?
Not before getting into rendering I guess
Maybe call it a GLFWwindow? There are lots of other Windows windows...
Editorconfig is your friend and is supported by VS as well as many other IDEs XD
no idea why he took premake and not cmake, but it complicated the stuff a way more
Is "because it's made by MicroSoft for Windows" actually a valid argument?
Every game I've played that's offered both DX (11 or 12) and Vulkan on Windows has run better on Vulkan. Clearly the programmers have to write different code to deal with that so there're uncontrolled variables there, but it still doesn't seem right.
Quigley Valley
if (enabled)
glfwSwapInterval(1);
else
glfwSwapInterval(0);
could be
glfwSwapInterval(enabled);
You know you can tell visual studio to automatically insert spaces when you tab, right? Under Tools->Options->Text Editor->All Languages->Tabs. I currently have mine set to make 4 spaces when I tab. You may also have to go to Tools->Options->Text Editor->C/C++->Formatting and uncheck "Automatically indent when I type a tab"
Ralph Island
On one video, I recall you saying that you would not use glfw and basically create the window yourself from scratch but since it was about "learning opengl" you said you did not care and just wanted it to work or something along those lines and then said that you would create your own if you were writing a game engine. Umm, you are writing a game engine currently?
I get only errors
17:20
create a binary tree of patreons credit.
Please do a github and git tutorial series.
Anyone know how to solve:
Error LNK2019 unresolved external symbol DwmExtendFrameIntoClientArea referenced in function windowProc Hazel GLFW.lib(win32_window.obj 1
I've already tried changing the runtime library settings in project properties as per previous posts, but this error still remains. Thanks in advance.
please make videos more frequently one video/lecture in a week is not enough🙏
Will Hazel supports Android or iOS?
Ila Forges
😍😍
25 Errors and 43 Warnings...😎
You beat me by 6 errors!
@@averageturtlee Are they fatal error LNK1120: 6 ? How to fix them😩
@@bananas4jim Did you find a solution or not yet 😩
mwahahaha... The graphics phase shall soon begin
i just CAN NOT follow this :(
The new video structure is a bit of a headache. My comprehension of your code was better before. This new structure feels rushed and seems like you are already getting bored/irritated with the lessons.
How to fix it "LIBCMTD.lib(exe_main.obj) : error LNK2019" 😣.\bin\Debug-windows-x86_64\Sandbox\Sandbox.exe : fatal error LNK1120
@JIM BANANA I'm having the same problem, Did you solve it?
Why do we still use OpenGL instead of DirectX when 96% games on Steam run on Windows. For me, DirectX is better than OpenGL for the series.
He might make it cross-platform later on
Provide a source for the "96%"
Cross platform purposes, i like when my app runs on both Windows and Linux
This is a cross platform engine that will run on opengl, directx, vulkan. Please watch the intro episode
It's easier to learn. He said that on the OpenGL series. Once you learn openGL, then it's really easy to learn other graphics APIs