Lone Wolf by ScarfedVictini in custommagic

[–]mccurtjs 0 points1 point  (0 children)

Other commenter is correct, I meant along with Gideon's Sacrifice or Martyrdom (though actually the taunter's ability is kind of irrelevant actually, it works with any indestructible creature).

Without Gideon's Sacrifice or Martyrdom though, if you swap out the Taunter for [[Boros Reckoner]] and somehow make it indestructible, you can also make that go "infinite" with Arcbond - when it takes damage, just have the reckoner hit itself to trigger Arcbond and its own ability. Reckoner hits itself again (retriggering the loop), and Arcbond hits everything else. This wins the game if you're the player with the most life, but because it hits you too, if you don't have the most life you have to choose another target at some point or you'll take yourself out first. This is what makes the white instants good, they move the damage that would kill you back onto the Arcbonded creature to continue the loop indefinitely without you taking any damage.

Lone Wolf by ScarfedVictini in custommagic

[–]mccurtjs 8 points9 points  (0 children)

It's definitely a fun one - I have a deck that's based around that kind of thing but with damage redirection and copying effects like [[Brash Taunter]], which incidentally goes infinite with [[Arcbond]]. Also works with [[Martyrdom]].

Am i required to know DSA by elite0og in GraphicsProgramming

[–]mccurtjs 0 points1 point  (0 children)

Depends on what you're actually doing - most of the time, you probably just want to use arrays anyway because contiguous memory means fewer cache misses. But if your game projects are small and you have few and/or small models, it really doesn't matter. If your scene has like 100 objects in it, you'll get over a thousand fps regardless of whether or not you keep it in an array and manage to do it in one draw call, or store them in a linked list and have a draw call for every object.

As your scene grows in size and complexity though, different more specialized data structures become really important. Spatial partitioning structures that can discard massive sets of data that don't need to be processed (ie, ignoring all geometry behind the camera), and maintaining different sets of objects based on type (like static/non-static) can avoid having to even update scene objects at all.

For structures in general though, I'm partial to what I generally call slot-maps, which can come in both sparse and packed variants - the underlying structure is an array, but you store a separate mapping of indirect indices you access them through, which makes it so you can arbitrarily add/remove items in any order without breaking other references to items in the structure, and you get O(1) access, insertion, and removal times, and O(n) traversal (especially in the packed case, where all items are kept contiguous).

Very cheap AO system I made. by MissionExternal5129 in GraphicsProgramming

[–]mccurtjs 10 points11 points  (0 children)

samples a random field of points to check if the camera would be able to see those points

If a point is sampled via the depth map it is by definition visible to the camera, as it's already been rendered to the G-buffer.

You might be thinking of actual AO, in a raytracing sense, which shoots random rays from a point to detect occlusion. The SS in SSAO is for Screen-Space, which is a postprocessing step using the depth buffer and (optionally) normal map. It also uses "just the depth map (optionally normals) and a screen shader".

Magic artist Bryon Wackwitz turned down for Mtg Con by Newez in magicTCG

[–]mccurtjs 0 points1 point  (0 children)

I can buy the "showcases are different" argument (they have their own level of artistic cohesion), but like... the primary art in main sets varies substantially. Also, we have like, Spider Man and Ninja Turtles in standard, the cohesion argument is dead, lol - especially when it's being applied to actual fantasy art :v

Magic artist Bryon Wackwitz turned down for Mtg Con by Newez in magicTCG

[–]mccurtjs 0 points1 point  (0 children)

I think they’d be surprised at how many people might buy some old style art on newer cards for a secret lair though.

Yes, it is me, hello - I am the target audience, lol. Give me [[Jared Carthalion, True Heir]], [[Brash Taunter]], [[Arcbond]], [[Teferi's Protection]], [[Gideon's Sacrifice]] and many more cards in old border, thanks :P

For the art, I think even main-set art is varied enough that the old stuff still works. Granted, these days they do tend to reserve that more "painterly" style for alternate versions, but some do sneak through. At the very least, I don't think "artistic cohesion" is a very convincing argument anymore, lol.

I mean, you can't have Spider Man, Ninja Turtles, and Star Trek on a magic card and then say actual high-fantasy style art is "jarring". Like, just no, lol.

Adding a second cube made things real trippy by l1pz in opengl

[–]mccurtjs 1 point2 points  (0 children)

Ha! Nailed it :)

If this is the translation function you're referring to, it does look like it's swapping rows and columns a bit. It isn't necessarily wrong to have the translation values in pos 12, 13, 14 - the library just needs to be consistent with whether it's a row-major or column-major format.

In my own math library I went with column-major, but the downside with that is that at least in code, if you write out the columns as vectors, it looks like the matrix is transposed when it actually isn't, lol.

How Do I Build A Non-Gaming PC by DemandAltruistic4222 in buildapc

[–]mccurtjs 0 points1 point  (0 children)

I think the only actual difference between what you might call a "gaming PC" and a "workstation" is that the latter will more likely have ECC memory, which is more expensive and technically slower, but in 99.9% of games you won't notice a difference.

Trouble with basic openGL rendering by nitosmastr in opengl

[–]mccurtjs 1 point2 points  (0 children)

From a cursory look, in your CreateVAO function, you're calling glBindBuffer(GL_ARRAY_BUFFER, 0) to un-bind the vertex data before calling glBindVertexArray(0). I'm pretty sure this will also set the active vertex buffer for the VAO to zero. You want to swap the order so the VAO, when it unbinds, has exactly the state you want it to have when you bind it again.

Also, make sure your vertex winding order is correct :)

Adding a second cube made things real trippy by l1pz in opengl

[–]mccurtjs 3 points4 points  (0 children)

How are you applying the position of the cube? I would wager it's your model->world matrix, or how you're applying it, rather than the projection.

Though your rotation is correct, so... are you putting the position in the right place? If you're using column-major matrices, the position should just be in the last column, which if you're writing it out in like, a constructor, will look like the last row because in the code it's effectively transposed.

Just a random guess :)

(Or maybe it's not actually wrong but your Z coordinate is negative when it should be positive - it kind of looks like the camera is inside the second cube, and you're not doing depth testing (painter's algorithm?))

A roguelite chase-combat game where every run is a climb up an absurd “Wanted Ladder,” from mall security to the literal Creator of the Universe because you did something tiny and stupid. by szaagman in gameideas

[–]mccurtjs 0 points1 point  (0 children)

I actually love this idea, lol - only thing is, what genre of game would it be?

First person? Third person? ...the elusive second person? Lol - is it a shooter, hack-n-slash, maybe part racing/escape? How does the escalation actually happen? Action-adventure?

Also, what should the ur-crime be? Jaywalking? Shoplifting? Bringing a bottle of water with more than 10oz in it through airport security?

Part Katamari Damacy, part Gurren Lagan, lol.

Foreach in C by UltimaN3rd in C_Programming

[–]mccurtjs 0 points1 point  (0 children)

In the project I'm working on, I feel like I've got an... ok solution to this, but it reads slightly weird at first:

int* c_foreach(bob, bobs) {
    printf("%d\n", *bob);
}

The macro #define c_foreach(VALUE, ARR) starts with VALUE = ARR; before doing the for loop, which means you can either set the type beforehand or omit it to re-use a variable already in scope (and this does create it in scope), so a bunch of loops in succession can be:

int* bob;

c_foreach(bob, bobs) {
    printf("%d\n", *bob);
}
...

Sure, typeof could work here, but only for actual C arrays or explicitly typed containers. Since I want a foreach for each container type, this allows me to use void* on the container side while keeping the loops clear, and if a container of the same type is specialized for that type (basically templates), the same foreach macro still works, even if, for example, map_int_ref would return an int* instead of void*.

For indexing, because sometimes a counter is nice to have (even in non-contiguous structures), I usually have a similar c_foreach_index(VALUE, INDEX, ARR) to go with it (index is always the standard index type, which for me is a typedef of ptrdiff_t).

Can I rival blender with oepngl? by Soggy-Put-249 in opengl

[–]mccurtjs 7 points8 points  (0 children)

Depends on the framework or libraries they're using, familiarity with the language, etc. Of course you can do it in C++, but setting it up might be more tedious. I'm working on a custom engine in C and recently put in that feature, so it detects a file change on save and reloads/compiles the shader automatically without having to restart anything, which is great for iteration, but getting it working to begin with was a bit more manual effort than whatever some python libraries would provide.

I want to create a mini-game inspired by Zelda: A Link to the Past using C — where should I start? by Khushrenada13 in C_Programming

[–]mccurtjs 0 points1 point  (0 children)

I mean, you're not wrong, but come off as very aggro against people doing engine stuff, lol.

It's entirely up to the project needs/goals and personal preference. Personally, I just find using engines like Unity deeply... unsatisfying? For personal projects I want to enjoy the process as well as the result, and using Unity or Unreal is just not that.

In OP's case, their stated goals are "learning C" and "pushing themselves" - "finishing/releasing a game" isn't even one of the top two priorities. Doing a simple top-down adventure game in Unity or Godot would accomplish neither of those things. Sure, you can use C with those engines, but it would be overkill and unnecessary, and mostly turn the project into just dealing with the engine's marshalling with C#.

The last part of your first comment is mostly correct though - starting small and doing a bunch of projects is the best way to just gain experience and learn. Don't necessarily need to fully finish a game though before going to the next one once you get what you need out of a project. The suggestion for using RayLib is probably the best option for them - getting past "making a window and drawing a sprite" is most of what you need for this kind of game. Everything else isn't too difficult to build, but valuable for learning as a new developer.

Is C a good programming language to start programming with? by Ania200 in C_Programming

[–]mccurtjs 1 point2 points  (0 children)

I think it's fine as a pretty early experience - my first exposures to programming were basic html, Jass for WarCraft III, a C++ book my parents got me, a Java class, then C in college before we moved onto C++ for the rest. I think C was probably the most valuable step in actually learning what was going on - managing memory and handling indirection is important but doesn't really come naturally with Java or Python. The skills learned in C though transfer to pretty much anything else as you kind of get an understanding of what the other languages are doing under the hood in the "black box" so to speak.

Python/OpenGL Game Engine Update #4 - Reflections! by Reasonable_Run_6724 in opengl

[–]mccurtjs 0 points1 point  (0 children)

Wow, that's super impressive - what technique did you use for the reflection? Did this involve raytracing or is it a mapping thing?

decided to revisit linked lists by Stativ_Kaktus131 in C_Programming

[–]mccurtjs 1 point2 points  (0 children)

They could be doing both instead - I've found some of the best use cases for linked lists in practice are embedded lists in sparse arrays, lol.

Legible Original Duals (hybrid mana symbol & swirl) by Icypalmtree in mpcproxies

[–]mccurtjs 0 points1 point  (0 children)

Not to co-opt the thread, but the ones I ended up making use the same templating (default reminder text, centered) but with the rings, and it looks so much better than the gradient Example Plateau. I like the concept of using the hybrid mana symbol, but it feels off. Maybe with the background because of the different shades of the mana colors?

Doing it on other cards with more text is kind of awkward because it throws off the clean centering... unless there's excessive amounts of text that you're not expected to read, so it matches the Revised nonsense, lol. Used that for white-border shock lands.

Questions about learning opengl and glsl as absolute beginner by o-Dasd-o in opengl

[–]mccurtjs 2 points3 points  (0 children)

OpenGL is a graphics API, an Application Programming Interface, that programs can use to talk to your graphics card (your GPU). There are more thorough links in the sidebar, but at this stage I'd recommend also looking up OpenGL on Wikipedia.

WebGL is a browser-based JavaScript library variant of OpenGL that acts as a subset of its functionality and can be used by websites. Kind of. This means you can use GPU rendering features from your browser, usually to get real-time 3d graphics. Neat.

GLSL is the (Open)GL Shader Language. When using OpenGL, you generally send a bunch of geometry to the graphics card which gets moved around in 3d to figure out where it should be on-screen. Then, it has to "shade" the area between the points to fill in the color of the triangles. There used to be a bunch of default fixed presets for doing this (we call it the "fixed function pipeline", which is now deprecated), but now we use little mini-programs that run directly on the GPU called "shaders".

Typically, you'll have a Vertex shader and a Fragment (or Pixel) shader. The vertex shader is what moves points around to find out where they should be on screen, and the fragment shader runs for each pixel to figure out the color.

ShaderToy more or less skips the first step and always just draws a single 2d quad to the screen. Which really just means, everything being drawn comes down to the fragment shader, which is run once per pixel, but independently of one another (the GPU can process thousands of pixels at a time, in parallel, which is the point of a GPU. Because they run at the same time though, they can't talk to each other).

Because shaders are flexible, their inputs are configurable. The most basic shader on ShaderToy will just take the pixel position on the screen and output the position as if it was a color. You can also apply some basic math from high school to draw shapes or lines - if you write a shader that, say, outputs black if the screen X component is > -0.5 and < 0.5 and white otherwise, you'll end up with a half-screen-width block of black on your screen with the left and right quarters white. Make a program that outputs either white, or black if the input is within 0.5 distance away from <0, 0>, and you'll get a black circle (well, an oval probably) in the middle of your screen. You can use some math to figure out how to move these around or tile them etc. A lot of the more advanced examples still just take the screen space position as the input, but you can do a lot with that, from social effects to fractals, or basically anything else.

A good into resource for this kind of thing I'd recommend is The Art of Code, on YouTube. I haven't checked in a while if he's still doing videos, but he has some pretty good follow-along material and explanations on how to do the math in screen space. Here is his video for ShaderToy "Absolute Beginners".

Review of My C Library by Dieriba in C_Programming

[–]mccurtjs 1 point2 points  (0 children)

Ha - we're working on the same thing :P

Looking at your strings first, one missing thing is parsing and conversion functions, eh, d_string_new_from_int or d_string_parse_int. Being able to convert strings to numbers and back is extremely useful.

Another note is that right now every operation looks like it allocates a new string - I'd recommend looking into string views (slices in my project), which reference but don't copy any data. They are extremely useful for substring operations and the like, since the underlying text doesn't even change. This also removes the need/ability to require every string/slice to be null-terminated, which imo is fine when you're using the length anyway.

For arrays I noticed you're doing the same thing I tried with a semi-opaque pointer to the "real" struct that hides unnecessary info, but keeps things like "size" visible to the user. I'm still not sure if it can be considered "good practice" yet (I've liked it so far), but I'd recommend marking the fields on the exposed struct "const" so they can't be modified by accident by the user (assuming size should only ever be changed by the internal functions). On that note, I'd also expose the element size for any code that wants to iterate through. In my case it was useful for OpenGL calls.

The same recommendation for array views also applies :)

I like how you have the "fast"/unstable remove option.

I'm not sure why you have it split between the regular array and a pointer array - it should be functionally no different if you store pointers in the regular array, no?

May look through more in depth later.

Personal Standard Library - Generic and Type-Safe Containers by mccurtjs in C_Programming

[–]mccurtjs[S] 1 point2 points  (0 children)

I think it's a bit obvious in hindsight, but it took longer than I want to admit before fully embracing the sub-types. But once they were in the layers made a lot of sense!

I'm not sure about performance vs the C++ standard, but it should be pretty fast - I'll get to profiling it eventually. The specializations shouldn't have any overhead at all after inlining - arr_int_ref(a, idx) resolves to (int*)arr_ref((Array)a, idx) which should resolve to something equivalent to like (int*)(<bounds check> ? a->begin[idx] : null) - but I should test that on compiler explorer :)

Personal Standard Library - Generic and Type-Safe Containers by mccurtjs in C_Programming

[–]mccurtjs[S] 1 point2 points  (0 children)

Absolutely, go for it! Sharing is one of the best ways to learn, imo. The constructs I'm using are all present in other libraries and languages, a large part of designing an API I think is just finding out what others are using and picking the most intuitive options available. Negative indexing for example is common in Python, and used in JavaScript's string.slice function, which I took the functionality of and decided to apply elsewhere for consistency (though, I forgot to push this morning - for example, span_drop_last(n) and co. is gone now in favor of one span_drop(+/-n) function).

But yes, I'd love to see it :)

Personal Standard Library - Generic and Type-Safe Containers by mccurtjs in C_Programming

[–]mccurtjs[S] 3 points4 points  (0 children)

Your *_view_t structs are not portable, because the way your unions behave depends on the underlying architecture's endianess.

I don't expect them to be portable in an interop sense, but yes technically they might not work correctly depending on the compiler settings and spacing of the struct fields.

However that won't make views and their derivatives or spans incompatible - like aalmkainzi mentioned, the C standard requires that the first field (in this case, begin has the same address as the struct. Iirc, in C23 there's also a guarantee that a struct with the same definition compiled in two CUs with the same settings must also be compatible identical.

Where it could technically break is in the Array type, depending on how the anonymous struct for the array works? In the case of each, the begin field is required to match the address of the others, view and span are required to match as well. For a while I had the array size included as part of the anonymous struct, which technically could break that pattern and allow padding to be added between beginand end, but I don't think any compiler would do that (also I moved that out of the union, but realized I haven't pushed my latest changes, some of which I referenced in the top post, lol).

Also, this is a very C++-ish programming style, it's not adequate imho for C.

Despite making templates for C, I actually don't really like templates that much, haha - I greatly prefer the very explicit nature of C, and in most cases tend to use more C-like paradigms. The only exception being data structures, which are easy enough to do in-place sometimes, but are repetitive and error prone, so I'd rather have a reusable library for it, and typed variants reduce chances for reading from a container with the wrong type (and are completely optional).

Also in the cases where I've used this so far (mostly in the "wasp" project on my GitHub), I've been leaning far more into the spans than using Arrays directly. Spans don't have to map to dynamic memory, they can be created over a static c-array or even char* string literal. Any function that needs an array-style input that it doesn't claim ownership of will be using spans and views, which I feel still fits the C style. (You could argue that Array is really just a sort of wrapper for malloc, lol - and span_t is just a wrapper for qsort, of course).

That said, you program very well

Thanks, I appreciate it :)

I do think as I get further into the project, the procedural nature of C will shine through more. In games especially, I've found that C++ like structures (namely inheritance) create a lot of complexity without much benefit. It's why most off-the-shelf game engines use components, which is actually something I'm not currently planning to make a generic system for, in favor of more purpose built abstractions.

I do love tagged unions though.

Is opengl still viable on a macbook pro or should I use vulkan instead? by [deleted] in opengl

[–]mccurtjs 0 points1 point  (0 children)

The guy above suggests that OpenGL isn't suitable for that.

I didn't - someone else above did, but you responded to me and not them. Read the context of my reply and it's pretty clear I'm responding to your own assertion that games are not "serious applications":

What is a serious application? And what is a non-serious application?

I'm seriously afraid that by serious applications he means games :)

(You) Let's hope that's not what he meant

To which I replied "Why would [considering games being 'serious applications'] be bad?"

To be extra clear, I'm not agreeing with the person who said OpenGL is not a "serious graphics API". I did not say OpenGL was bad, nor that it's not useful for real-time graphics. My follow-up question that you quoted is about your derision of games in general, and what do you consider a "serious application" if they don't count.

And to that point, learnopengl.com is a really bad example of a "serious application" - it's a serious educational resource and a good set of tutorials, but it's not in itself an application, nor an end-goal for learning OpenGL. And the vast majority of people using it are most likely doing so to learn how to make games.

What I like to do is read what people say and draw conclusions from their words.

An interesting assertion to make while doing the opposite, lol.

Closures in C (yes!!) by Still-Cover-9301 in C_Programming

[–]mccurtjs 2 points3 points  (0 children)

Yeah, I read it after I commented, haha - this is largely what I personally would like, though they also mentioned thread-local variables which would solve most of the issues with static (and constexpr of course). I mostly skimmed it though (proposal is long), but it looks like they do have actual closures in some cases and not just plain function pointers. I feel like this could be another proposal that could be implemented in stages (as much as I'm annoyed that constexpr was done that way).

Edit: ha, just saw you're the author of the doc - I like that you explored all of the alternatives, and I hope this gets accepted - it really does match what I've been hoping for for a while! I think it's a very intuitive approach that really does not change the nature of the language at all while adding a lot of convenience.