Finalspace

Members
  • Content count

    373
  • Joined

  • Last visited

Community Reputation

1146 Excellent

About Finalspace

  • Rank
    Member

Personal Information

Social

  • Github
    f1nalspace
  1. Really micromanaged audio programming (C++)

    DirectSound is what you are looking for. Its fully lowlevel and you can create/modify your sound samples however you want. But you have to mix and video-syncronize yourself - compensate for bad latency. Also there are not much tutorials out there, the only thing i know is this (which is quite good): https://www.youtube.com/watch?v=UuqcgQxpfO8&list=PLEMXAbCVnmY4UakJTODzmY-6rSPKkuLr5
  2. There are a lot of reasons: - ECS is not a generic solution to solve all game programming problems! - It overcomplicates everything - especially for beginners because there are so many indirections it requires. Making it debug and follow a nightmare when you dont have the proper tools - It has runtime performance penalitities, some can be minimized some cannot: You need to be at least aware of that - Doing it right is hard. Doing it poorly/wrong is really easy. See @Kylotan answer.
  3. What am I not understanding about programming?

    Thats not true for several reasons: - He does use knowledge from other people but he use this very carefully (papers, libraries, articles) - He teaches everything from low to high level concepts, everything you need to know about game development: Keeping nothing left behind - He teaches how to solve unknown problems, including all the mathmatical concepts (In school / university you learn a ton how to solve existing problems very well, built on existing knowledge - but not much about solving totally unknown problems). - He teaches how to build up your own knowledge, so you dont have to rely on others for everything - He teaches you can rely others, including using existing engine/libraries but you need to understand the downsides/costs of that. - He teaches programming languages are just tools, tools should not limit you - it should help you get the job done. - He teaches the most important thing is: There is actual hardware running your game! Really there are just a handful people like casey out there which does these sort of things: Sharing its entire knowledge, showing people its not the programming language that matters, but rather what you do with it and really... you can do everything if you want. And lastly most important he teaches that: Its one way how to make games, but it may not be the best way for you - because its a teaching series after all. I personally like the series very much and can recommend it to everybody, even though i still disagree about some statements. Nothing more to say about that.
  4. What am I not understanding about programming?

    I dont understand why most people here, de-recommend the handmade hero series. Its the only series/man i know of teaching the core fundamentals from the very beginning without forcing himself to any programming paradigmas at all: - He simple doesn´t care about any programming rules, patterns, whatsoever. - He just writes it down in the simplest straightforward way and extend it or compress it as he goes. - He produces working code doing real work, while explaining everything he is doing. So just write it down in the most stupid simplest way you can imagine - without forcing yourself to restrictions, managers, classes, any patterns, whatsoever. Extend it when you need it, abstract it when there is actually a need for. Thinking about how should i design my classes, how should i interact with them, how i can extend them in the future, how to abstract X to solve problem Y is just a trap most programmers will fall in - always. Unfortunatly even the most talented ones falls into this trap as well.
  5. I wanted a class which produces a string which is like: Aquiring, Aquired, Initializing, Initialized, Building, Built, Copy, Copied etc. Just to write "less" code... i thought... why did i do that, i have no idea... maybe because i can??? AddLog(SubjectBuilder.Build("C", false, "file A to B")); AddLog(SubjectBuilder.Build("C", true, "file A to B successfully")); Anyway this is the result: /// <summary> /// Simple class for genering a message using a subject as prefix /// </summary> public static class SubjectBuilder { private static readonly Dictionary<char, string> _subjectLetterMap = new Dictionary<char, string>() { { 'A', "Aquire" }, { 'B', "Build" }, { 'I', "Initialize" }, { 'G', "Generate" }, { 'D', "Destroy" }, { 'M', "Make" }, { 'C', "Copy" }, { 'P', "Publish" } }; class SubjectRule { public bool CurCut { get; set; } = true; public string Cur { get; set; } = "ing"; public bool PastCut { get; set; } = false; public string Past { get; set; } = "d"; } private static readonly Dictionary<char, SubjectRule> _rules = new Dictionary<char, SubjectRule>() { { 'e', new SubjectRule() }, { 'd', new SubjectRule() { CurCut = false, PastCut = true, Past = "t" } }, { 'y', new SubjectRule() { CurCut = false, PastCut = true, Past = "ied" } }, { 'h', new SubjectRule() { CurCut = false, PastCut = false, Past = "ed" } } }; /// <summary> /// Returns a simple string starting with a subject - like create, generate, copy. /// The subject is modified to satisfy the past or current time (creat-ing, creat-ed, etc.) /// </summary> /// <param name="firstLetterOrSubject">Subject or just the first letter of the subject</param> /// <param name="past">Is it now or in the past</param> /// <param name="text">The actual text</param> /// <returns>Builded message startin with the subject</returns> public static string Build(string firstLetterOrSubject, bool past, string text) { StringBuilder s = new StringBuilder(); string subject = null; if (!string.IsNullOrEmpty(firstLetterOrSubject)) { if (firstLetterOrSubject.Length == 1) { // Single letter - lookup into the subject table char upperCh = firstLetterOrSubject.ToUpper()[0]; if (_subjectLetterMap.ContainsKey(upperCh)) subject = _subjectLetterMap[upperCh]; } else subject = firstLetterOrSubject; } if (!string.IsNullOrEmpty(subject)) { char lastChar = subject.Substring(subject.Length - 1)[0]; SubjectRule rule = _rules.ContainsKey(lastChar) ? _rules[lastChar] : new SubjectRule(); if (past) { if (rule.PastCut) s.Append(subject.Substring(0, subject.Length - 1)); else s.Append(subject); s.Append(rule.Past); } else { if (rule.CurCut) s.Append(subject.Substring(0, subject.Length - 1)); else s.Append(subject); s.Append(rule.Cur); } s.Append(" "); } s.Append(text); return s.ToString(); } } And yes this is used in a productive every day used application...
  6. My thoughts/idea about this: - A physics system should never need any graphical stuff at all (If you need debug rendering, then add a separate system for that) - There is no need to separate position / rotation aka transform into its own component, just put it into the entity directly (Unity and Unreal does this for a reason). It totally complicates everything when you separate it. - Physics engines have its own properties and transformations - so you have to syncronize with your entities/components anyway - Potential components like physics/render-component which should be processed contigously has its own vector, outside from entity, outside from a system. All systems have accesss to that vector, so it can just iterate over it. - Only systems which require a set of components use a internal list to keep track of entities they need to process, in this case you cannot ensure any contigously memory, because the entities/components may be just random in memory, but to make things easier on the system i would use a internal struct to store each component pointer and a entity pointer: struct PhysicsSystemItem { Entity *entity; PhysicsComponent *physicsComponent; }; std::vector<PhysicsSystemItem> _activeItems; - Systems gets notified when a components gets added or removed, so they can update this internal list as needed
  7. Break of game development

    I will stop doing any private game or software development for a while or will drop it entirely - depending on how i feel about it. Right now i dont feel like doing it and dont see any reason why i should do this anymore. I cant hardly find time and when i have one, it just isn´t fun. But i may do some trickjump mapping in reflex... when they fixed that broken editor :-( So bye guys, have a good life.
  8. I totally agree with Kylotan, you cannot make your game fit every screen resolution / monitor - either you show more/less of the world or you letterbox it. But locking down your maximum viewable game size is much better and more controllable. Also i think its a good idea to fully drop the idea about "pixels" altogether and use game units as metrics only, for example meters. But its fine to stick with pixels if you want to... All my games uses a fixed game width in meters and a target aspect ratio. Game height is calculated based on game width and aspect ratio. Only when you render your game, you calculate a scale factor based on your monitor screen width in pixels and the fixed game width in meters. This scale factor is used in the projection matrix and to calculate the letterbox offset and size. It looks something like this (Area means game world size visible on the monitor - Unproject means converting screen coordinates into world coordinates): external Vec2f RenderUnproject(RenderState *renderState, s32 x, s32 y) { Vec2f result = {}; if (renderState->areaScale > 0) { result.x = (r32)((x - renderState->viewportOffset.x) / renderState->areaScale) - renderState->areaSize.w * 0.5f; result.y = (r32)((y - renderState->viewportOffset.y) / renderState->areaScale) - renderState->areaSize.h * 0.5f; } return (result); } external void RenderViewportUpdate(RenderState *renderState) { // // Calculate target viewport based on area size, screen dimension and aspect ratio // Vec2i *viewportSize = &renderState->viewportSize; Vec2i *viewportOffset = &renderState->viewportOffset; renderState->areaScale = (r32)renderState->windowSize.w / renderState->areaSize.w; renderState->viewportOffset = V2i(); viewportSize->w = renderState->windowSize.w; viewportSize->h = (u32)(renderState->windowSize.w / renderState->aspectRatio); if (viewportSize->h > renderState->windowSize.h) { viewportSize->h = renderState->windowSize.h; viewportSize->w = (u32)(viewportSize->h * renderState->aspectRatio); renderState->areaScale = (r32)viewportSize->w / renderState->areaSize.w; } renderState->viewportOffset.x = (renderState->windowSize.w - viewportSize->w) / 2; renderState->viewportOffset.y = (renderState->windowSize.h - viewportSize->h) / 2; }
  9. C# What does good code look like?

    - First of all, please use long names of everything in any case. It does not hurt and is much more readable, because you can be more descriptive what something is. - Max iteration is it a count? A max index? A max value ? Its not clear, make it clear: MaxIterationCount - Use inheritance (Naive way): * Pattern is a abstract PositionGenerator with one abstract function "GeneratePosition" one parameter iterationIndex * New class: CircularPositionGenerator which inherits from PositionGenerator implementing just the generate position function * The Pattern data like radius, position can be part of the specialized positon generator or when all have the same properties, put it into the abstract class or if you want to have it separate just leave the pattern as it is but call it Settings or Config instead. Use inheritance (More useful because creating multiple positions is more common): * Pattern is a abstract PositionGenerator with one abstract function "GeneratePositions" with this signature (int iterationCount, ref List<Vector2> outputPositionList) * New class: CircularPositionGenerator which inherits from PositionGenerator implementing just the generate positions function - generating multiple positions * The Pattern data like radius, position can be part of the specialized positon generator or when all have the same properties, put it into the abstract class or if you want to have it separate just leave the pattern as it is but call it Settings or Config instead. * MaxIteration can be removed from the pattern settings - Forget about struct in C#, this is only needed if you want to store them in array, making them contiguously and more cache friendly.
  10. Vararg and how to use it?

    Please add at least a reference operator, right know you are copy the entire vector by value for each call. But regarding your original question - You have to pass the count along on every call, there is no safe-way to loop over a dynamic array, even when you know the type because when you iterated over the last item you dont know what memory comes after it: void manyWrite(const int x, const int y, const int lineCount, ...) { va_list vargs; va_start(vargs, lineCount); for (int lineIndex = 0; lineIndex < lineCount; ++lineIndex) { char *line = va_arg(vargs, char *); ... } va_end(vargs); }
  11. It seems that this library is the worst most useless garbage ever made for most people here, but i wont back down. For me its very educational and useful + a perfect replacement for glut/glfw, thats reason enough for me to continue. As a matter of fact, i started integrating linux support as well...
  12. - I added C++/11 nullptr support and renamed FPL_NULL to FPL_NULLPTR. Fallback is (void *)0
  13. Thanks, i already did that. Will commit that later
  14. Insomniac Games and EA for example do not use the C standard library, they even dont use the STL. Also there are others people in the industry who do not use the C standard library as well. For myself, i dont care but its great when you have the option to not need to ship the C Runtime with your game (VC++ redist for example). Static has more than one meaning, private scope for this file only, local persisting state, global variable, class field in c++, etc. Even though it just mean: Private in this file only. Techniqually there are no differences between all of them, but this way you see right away which scope its meant to be in. Right, there are no difference between header and source files. C++ has no definition of a file, you just have translation units which gets compiled to object files - thats it. I dont want to force users to have a separate translation unit, just for the library - if they want, they can have one but its not required.
  15. I tried FPL_NULL (void *)0 - but i had trouble with it, so i simply set it to zero. But yes i agree, using nullptr on C++/11 would be better, but how do i detect if C++/11 is available - through preprocessor directives? Btw. FPL_NULL is internal only, so its not meant to be used outside. That entire no CRT thing - i am not sure about this. Its a experiment to see if it works, because some people dont want to include even the C-Runtime Library at all. Also regards DLL´s and ExitProcess and need to think it more, as a matter of fact i havent created a library project yet - but this will come soon. When i see that no-CRT is support is too complicated, i will drop it. Right know i dont see any benefit disabling CRT, except for smalling out the executable size. Why header library only? Because its simple and works all the time. No linking madness, no dll´s needed - besides from the standard system operating stuff which is included anyway. Regards build-systems: I dont like build-systems at all, all i ever used was just awful: Slow, hard to configure, not working -> On any programming language the same bad experience. But what i will do for sure, is making several simple build scripts (Batch, Shell) which just builds the samples in the simplest possible way for a set of compilers/platforms.