<![CDATA[Carrot Games]]> http://community.carrot-games.com Thu, 08 Oct 2026 17:11:49 +0000 Smartfeed extension for phpBB http://community.carrot-games.com/styles/carrotgames/theme/images/site_logo.svg <![CDATA[Carrot Games]]> http://community.carrot-games.com en-gb Thu, 08 Oct 2026 17:11:49 +0000 60 <![CDATA[Game Programming :: Snippets: The IDE feature from the 1990s nobody told you about :: Author celes]]> http://community.carrot-games.com/viewtopic.php?f=10&t=56&p=121#p121

In VSCodium snippets are quite easy. Browsing the docs today instead of guessing taught me a couple of cool tricks today so I think it's worth a read: https://code.visualstudio.com/docs/edit ... edsnippets

I never thought I'd be the kind of dev to get into snippets :blobcatthink: To me, what made them really click is how you can have a snippet config file under .vscode/snippets.code-snippets in your repository and every clone of the repo gets the same snippets. I'm sure every editor in existence has had this feature for over twenty years, it just didn't click until recently that snippets are more useful are a per-project thing, not a per-user thing. You can still have both of course.

So what do I use snippets for? One thing is to "remember" the boilerplate. It's not the kind of boilerplate I want to eliminate, that one goes away. :akko_smile: But sometimes you just want to type faster. For example: I always forget how to create new editor plugins. I can go look at another plugin and copy-paste the relevant bits, it takes a minute, so it's not like this saves a significant portion of my time, but being able to type editorpl and hit return to get my plugin boostrapped is nice. It keeps me in the zone, which is important.

Code: Select all

"New editor plugin ": {
	"scope": "cs,csharp",
	"prefix": "editorplugin",
	"body": [
		"public partial class $1: EditorPlugin {",
		"    public void EditorLoad(Editor e) { }",
		"",
		"    public void EditorUpdate(Editor e) { }",
		"}",
	],
	"description": "Create a new Game Singleton"
},
But the simplest snippets are actually the ones that I use the most and save the most time. These lil' fuckers I use daily, several times. Typing getass and instead of ass this gets me the assets singleton (I know, disappointing :pensivecat:). I don't even remember what the original line looked like. If you've caught any of the streams you've surely seen it, it's crazy how much typing this saves:

Code: Select all

"Get the asset manager": {
	"scope": "cs,csharp",
	"prefix": "getassets",
	"body": [
		"var assets = Singletons.Assets();"
	]
},
"Get the renderer": {
	"scope": "cs,csharp",
	"prefix": "getrenderer",
	"body": [
		"var renderer = Singletons.Renderer();"
	]
},
Then there's creative snippets covering up for missing language features. Here I wrote this because C# doesn't have a "prefill all the parameters to this function" helper and my particle struct has a bazillion fields:

Code: Select all

"Construct a particle": {
	"scope": "cs,csharp",
	"prefix": "newparticle",
	"body": [
		"Particle.New(",
		"    position: Vec2(0, 0),",
		"    lifetime: 1,",
		"    zIndex: DrawOrder.Particles.ToZ(),",
		"    rotation: 0f,",
		"    direction: Vec2(0),",
		"    gravity: Vec2(0),",
		"    speed: 0,",
		"    size: Vec2(1),",
		"    color: Color.White,",
		"    angularVelocity: 0f,",
		"    blendMode: BlendMode.AlphaBlend,",
		"    texture: null,",
		"    hFlip: false,",
		"    vFlip: false,",
		"    flipbookFrames: (numFrames: 4, fps: 12)",
		")"
	]
},
And perhaps the ones I feel the proudest for are the dialogue script ones. Writing dialogue gets tiresome really fast if you're typing anything other than the dialogue text. I could've built a streamlined imgui widget for that, but I like keeping my dialogue data as simple XML files, so I desperately needed something to avoid wrist pain from typing so much < and >.

In the end, my dreams of a dedicated VSCode extension (which I actually have, for other more advanced use cases, but that's a story for another day) were stopped by these two lil' snippets:

Code: Select all

"Dialogue: Character": {
	"scope": "xml",
	"prefix": "character",
	"body": [
		"<character character=\"${1|lynchpin,renna,renna-hub,scientist,squatter,informant,messenger|}\" mood=\"${2|grin,happy,sigh,angry,laugh|}\"/>"
	]
},
"Dialogue: Talk": {
	"scope": "xml",
	"prefix": "talk",
	"body": [
		"<talk>$1</talk>"
	]
}
Crazy, right? Notice the ${1|one,two,three|} syntax? That thing gives me auto-completion for the placeholder value and it saved me a VSCode extension. Cool stuff.

And you'll say: But Celes, these snippets are not in sync with your code and need manual adjustment, surely we can do better? Macros perhaps? Code generation? Well, while you were doing better I was getting the code written. That's the point of snippets. Like the blue philosopher said: "Long as the voice inside drives me to run and fight, It doesn't matter who is wrong and who is right".

Anyway, I'm glad I took the time to introduce snippets into my workflow. It took a while for me to develop the neural pathways that make my snippet sense tingle when I've been typing a recurring pattern too much, but now they're finally there :blobcatnodfast:]]>
no_email@example.com (celes) http://community.carrot-games.com/viewtopic.php?f=10&t=56&p=121#p121 Mon, 14 Sep 2026 16:21:50 +0000 http://community.carrot-games.com/viewtopic.php?f=10&t=56&p=121#p121
<![CDATA[Game Programming :: Re: Snippets: The IDE feature from the 1990s nobody told you about :: Reply by Sugui]]> http://community.carrot-games.com/viewtopic.php?f=10&t=56&p=122#p122
Probably not many people realizes that, because for programming languages, it's easy to find an extension that gives you language snippets for a while loop, or a for-each loop. But for project specific snippets, no one would be doing the snippets except yourself :blobfoxthinksmart:

No one is giving you a getass*enter* for free :pensivecat:]]>
no_email@example.com (Sugui) http://community.carrot-games.com/viewtopic.php?f=10&t=56&p=122#p122 Mon, 14 Sep 2026 17:11:04 +0000 http://community.carrot-games.com/viewtopic.php?f=10&t=56&p=122#p122
<![CDATA[Game Programming :: Re: Snippets: The IDE feature from the 1990s nobody told you about :: Reply by celes]]> http://community.carrot-games.com/viewtopic.php?f=10&t=56&p=123#p123
Sugui wrote: Mon Sep 14, 2026 5:11 pm Probably not many people realizes that, because for programming languages, it's easy to find an extension that gives you language snippets for a while loop, or a for-each loop.
Yes!! This so much. I wrote this yesterday thinking: People will think I'm dumb and this is obvious because everybody already knows. But you're right! Programming language extensions giving you all those silly useless snippets prove how widespread the wrong minset is! Very good point :blobcatthink:]]>
no_email@example.com (celes) http://community.carrot-games.com/viewtopic.php?f=10&t=56&p=123#p123 Tue, 15 Sep 2026 17:37:35 +0000 http://community.carrot-games.com/viewtopic.php?f=10&t=56&p=123#p123
<![CDATA[Langdev :: I love nameof :: Author celes]]> http://community.carrot-games.com/viewtopic.php?f=21&t=57&p=124#p124
So, nameof(MyClass) returns the string "MyClass". And on first glance that's pretty useless, because if you have to type the name of the thing, why not type two quotes instead of the more unwieldy nameof?

The key is playing nice with IDEs! If you're referring to the name of a thing, that thing might get renamed, or you might want to find references to that thing. You surely don't want to misspell the thing! Your LSP typically helps you achieve all these worthy goals, but the LSP can't see inside your string. What it sees are any references you make inside the nameof operator!

If you use nameof, when you rename your class, the name of the class you printed will get updated instead of being hardcoded. And what's even cooler is that you can refer to things in scope, like variables in the current function or fields in the current class, and references will work as expected! You can even refer to some other class' field like MyOtherClass.someField and this will evaluate to the string "someField" and count as a reference for that field for the purposes of refactors!

For example, in my game I have mappings from my GameDb to C# structs written by hand (why didn't automate it? because there hasn't been a need to), and while I've been careful in my typing and disciplined in my renaming (so it never caused trouble), today I realized I could change all the lines that look like this:

Code: Select all

id: row.GetString("id"),
Into this nicer form, because id is a variable in scope (a class member, in this case). It was not immediately obvious to me you could do this with any symbol reference (classes, methods, fields, ...), and not just types!

Code: Select all

id: row.GetString(nameof(id)),
Full snippet looks like this:

Code: Select all

public static object FromRow(CsvRow row) {
    return New(
        id: row.GetString(nameof(id)),
        name: row.GetString(nameof(name)),
        description: row.GetString(nameof(description)),
        distance: row.GetFloat(nameof(distance)),
        spriteOffset: row.GetFloat(nameof(spriteOffset)),
        comboTree: row.GetString(nameof(comboTree)),
        sprite: row.GetAsset<Texture>(nameof(sprite)),
        attackPower: row.GetFloat(nameof(attackPower)),
        attackSpeed: row.GetFloat(nameof(attackSpeed)),
        speedBetweenCombos: row.GetFloat(nameof(speedBetweenCombos)),
        burnChance: row.GetFloat(nameof(burnChance)),
        bleedChance: row.GetFloat(nameof(bleedChance)),
        loadoutSlotTweaks: row.GetConEgg<LoadoutSlotTweaks>(nameof(loadoutSlotTweaks))
    );
}

Now I still need to adjust the names of the CSV columns if I ever rename one of these struct fields, so this does not give me 100% painless refactors, but it takes care of one more thing. It's a tiny improvement, but a substantial one!

A side effect (or perhaps, the main point!) of nameof is also that you can't misspell a field name. No "bledChance" will slip into your game causing runtime errors. It's an all-around great feature and I can't think of a good reason it shouldn't be on every language.

Some people would compare this to Rust's stringify! macro, but while they're related that's not the same feature at all. Unless I'm mistaken, stringify! works at the token level, so it will not save you from any typos and won't participate in "find all references" or renaname refactors from the LSP. The use case for stringify is authoring macros, which is a completely different (but useful!) thing.]]>
no_email@example.com (celes) http://community.carrot-games.com/viewtopic.php?f=21&t=57&p=124#p124 Tue, 15 Sep 2026 17:59:55 +0000 http://community.carrot-games.com/viewtopic.php?f=21&t=57&p=124#p124