Transcription
So, as you all know, I've been using Cursor exclusively when I work on my side projects. I've been doing it for a while now, and I want to give you some of the tips and tricks that I've learned along the way to try to be the most productive that you can.
By the way, leave a comment if there's something else you have done that I haven't tried yet. For example, I haven't even tried this Bugfinder. I'm slow to try new things, right? So, leave a comment if you think I should try this out in a future video.
But what are some of the best ways to use this IDE? If you have used AI, you know that sometimes it gives you really bad results; other times, it gives really good results. I think there is a skill behind knowing how to prompt the AI to get some good results, and you'll learn that the more you start using it.
So, don't get discouraged if you ask it to do something and it's giving you some bad code. Just know that maybe you're just not prompting very well.
The best way to explain the features is, let's try to build out a feature in my game. So, let's go to my server and let's go to a tree. I have this tree entity, and let's just go ahead and copy this tree entity. Like I'm doing old school coding, you know, where I actually have to type up the code. I know it's a drag, but let's just go and say "grenade," and I'm going to put this in this items directory.
Right, so the most important feature of Cursor, honestly, is the tab completion. Typically, if you want to just change an existing file, like for example, I copied and pasted some code, Cursor is really good at just looking at your code and expanding upon it. So, I'm going to go ahead and just say "G" and just go ahead and tab complete all the way down the file.
Okay, sometimes you have to let it cook for a little bit because it has to wait for the LLM to be ready. But at this point, we now have a new type of entity in our game: a grenade. We can just go ahead and go into here, and the cool thing about the tab completion is that it seems to remember what it just put into your codebase.
So, if I go and click on the bottom here, click tab, we're good. Let's just open up this, and then this one. Oh, it looks like item key is missing a grenade. Let's add that in.
Okay, so now we have a brand new entity called a grenade, and you can pick it up and you can carry it.
Second thing, let's go to the front end. So, I'm going to go ahead and just say "client tree," and we're going to open up this one. I'm going to go ahead and copy and paste this, and we're going to say "grenade." Awesome! And then we're going to go ahead and just put a "g" here.
Okay, oh look at that, it's already tab completing. Okay, we are actually going to call this. Actually, let's go to the image loader, right? So, we have these assets here, and I can just go ahead at the top and I'm going to go ahead and just—sorry, the game is playing in the background. Let's just go ahead and let it bring in a grenade.
Then we're going to go over to my tile sheet and let's find where that grenade is. Now, I think I'm actually using a different type of location, so let's grab up here. Let's look here; it's 160, 160.
Okay, let's go back over to the grenade. I'll say 160, 160, and then we'll say sheet is items.
Okay, tab completion—this is your best friend. It kind of remembers what you just did, and if you are already in the mindset of knowing what files you need to change or how to implement a feature, this is just another copy and paste of another feature. Get good at knowing how to do this.
Okay, now let's check out our game. Let's go ahead and go to the entity factory, make sure I'm not missing anything here. Oh, looks like I'm missing a grenade here, so let's add this here. Let's go ahead and just import this, or you could also just tab complete to get the grenade client.
Okay, so hopefully I didn't miss anything. The way to verify this is working, we're going to go over here. I'm going to just spawn—I got a nice little admin menu down here. I'm going to say "grenade," and let's see what happens.
It didn't actually spawn a grenade. Okay, so I think there are some other places that we probably forgot to update. I think the entity manager in the server side has a create entity method, and this looks through here and it tries to find your entity from here. I didn't add it to this; I'll make sure I add that in.
All right, so now we have the grenade there. Let's try this again. I'm going to refresh the game, and then I'm going to spawn a grenade, and it crashed my server.
Okay, all right, so here is the first issue with using AI, and that is sometimes you'll just blindly accept stuff and you'll think it'll work, but it crashes.
Okay, so now you have to do a little bit of debugging. Right now, this is failing because it's trying to do position clone on something. But it turns out when I use this admin command, there's a recent refactoring in the codebase where we're using Vector 2. So, I think I actually need to say like new Vector 2.
Let's just go ahead and make sure that's imported, and then what we could do here is just say X and Y.
Okay, so again, tab completion—you see how quick that was? Once you type in the first couple of characters, it just kind of works for you, which is great.
So, let's try this again. Let's just spawn a grenade. Here we go. Now, right now, it's not showing up anything, but as you walk over it, you can see that it's actually having a grenade there.
Now, there's no image of the grenade, so we got to debug that. So again, if you go to the client and say "grenade," the front end is where that grenade is basically displayed.
Now, I'm going to assume what's happening here is that the grenade itself is not loading correctly. So, let's find grenade, and that's supposed to be loading from the items sheet, and that should have a grenade up here.
I think the issue is that for some reason I put 160 for the Y. This is like the top row, right? So, this should have been—oh, I copied the wrong thing. This should have been 640. That's just a human error.
Let's just go ahead and do that, and AI is not going to help you there. That's just—you got to know what you're actually typing in when you do some sprites.
Okay, there we got the grenade. It took me a while. Let's see if we can pick it up, though. Let's press "E." We can pick it up, but when we drop it, it actually crashes.
So, there are more places in this crappy codebase that I worked on where we are missing some stuff. So, create entity from item. If you look at the errors, which you probably should have read, the errors are failing because it looks like there's an item type that maybe we don't have set up somewhere.
Now, I need to do some refactoring on this codebase. I'll be honest with you because to add a single item, you have to change like five different places, and I think I remember where it is.
Okay, so I guess what I'm trying to show you right here is that even though I wrote most of this code and reviewed the code that was generated from AI, you reach a point where your codebase is so large you don't even understand all the places that you need to modify to get something working.
That's a code smell, honestly. My code's crap. That's a smell that I should have one centralized place for registering new items and weapons and consumables and stuff like that.
All right, so that is the tab completion. I don't know how much other things you could do with tab completion. You just need to have a good idea about what you want and then just slowly type what you're trying to get at and then just tab, tab, tab.
Now, let's move on to Command K. Command K is where you can highlight some code and you can actually prompt it to do something. I found this to be very good when you're dealing with larger JSON files or something where you have a bunch of repetitive code.
Like, for example, if I wanted to modify all these to add in a third parameter, I could just go and say "add a size param," and then that'll loop through and basically add in—hopefully, if it—
I ran out of fast credits, so now you guys have to basically wait for me to do something. But you'll see here that it quickly just adds in stuff to your existing code, and it can kind of do that very well.
Versus if I did that myself, I mean, I could do that, but I don't know if you guys could do it as fast as me, right? So, if I wanted to add like size over here, I could do this.
Was it faster for me to do it myself? Yes. Can you achieve that same level of proficiency? I don't know; that's up to you.
But I have just seen that when you have a bunch of stuff, you can literally like Command K this whole thing, ask it to do something, or like refactor the code a little bit better, and it just does it very well.
And like you don't have to do all this manual labor of like moving your cursor down and doing the select K's and stuff like that. So, very, very useful.
The second thing I think Command K is very good for is if you want to implement an algorithm that is very well known or if you want to implement a class that's very well known.
Like, for example, this Vector over here or a shape like a rectangle, you can basically just prompt it. I want to say like, "Okay, generate me a pathfinding algorithm that does DFS from the zombie position to the human position using the map, which is a 2D array."
Okay, let's just see what this does with a quick little Command K. It might take a little bit of time, but what this is doing is basically just looking on the internet for an algorithm. It's tweaking it to hopefully work with my data structures and my game context.
And now we have a depth-first search algorithm, which who knows if this works? Usually, it won't first try, so you kind of have to debug it and look through it.
But stuff like this, I find Command K very, very useful to use if you have something in mind that you think the AI would be very, very good at.
Okay, so again, highlighting and, you know, say "change to seal." Okay, quick little thing, take a sip of your coffee, and then you come back; it'll be done, especially if you got those fast credits that we all love to use.
Okay, now it's done. I can just go ahead and accept that, but I'm actually going to undo that.
Okay, now another thing I have done is when I write sloppy code, I would basically just highlight it and say "improve this."
Okay, is there a way we can improve this with AI? And then it's going to go ahead and just restructure my code to make it better. Or you can highlight something and say "dry this up."
So, your question is, is this cleaner code than what it was? If it's out of bounds or if it's a forest tile, that's more readable. That's definitely more readable.
And so hopefully that didn't break my game. We can go ahead and just try to see what happens, and it looks like I can still walk around and pick up stuff.
Okay, so again, those types of refactorings are very, very good for highlighting and just prompting something small, which I would definitely recommend doing.
Now again, leave a comment if there's another way that you like to use Command K. You can still reference stuff, so you can give it context.
So, like if you want to refactor this file in a particular way, you can do that. You can reference some other file in your context and say, "I want this function to look like that function over there," and it'll just do that.
So, these are really good things to keep in mind.
Listen up! If you're this far in the video, this is the most important advice I can give you coming from an engineer who has been doing this for a while. You need to understand from a high level if your code is converging towards garbage.
Right? You need to know if stuff is becoming too coupled, stuff is too unmaintainable, if you have a bunch of spaghetti coding. The only way to do that is by knowing how the code works.
Right? You can build out diagrams; you can draw little boxes and arrows that point in certain directions to show dependencies. So you know, "Okay, this is getting a little complex."
So, with that being said, I recommend that you understand your code as best as you can, and then you should probably try to use tab completion as much as possible and then Command K as much as possible.
Now, if you are very experienced and reading code is like reading a book, right? I can just glance through code and get a good understanding.
Okay, it's doing a loop; it's kind of doing this and that and whatnot. Okay, there's a little bug here; let's go ahead and fix that. It takes time to get to that level, right?
But when you feel like you're at that level—which you'll get there soon if you're not—so just keep on working on it, you can load up this prompt over here, right?
So, this is the Command L chat prompt, and let's talk about the chat prompt. I find it very, very useful if you have come into a new project and you don't really understand how stuff works.
Okay, you can ask it questions over your codebase, and it's going to answer you. So, I can basically say, "Can you help me find what files are related to playing sounds?"
And then I'm going to do a full codebase search, which I think my head is hiding, so let's just do that.
So, there's two types of submit buttons: there's like a normal submit, but there's a full codebase search, so I'm going to do that one.
So, it's going to search over our codebase and give us the files that are relevant, and then it's going to respond with a nice AI generic response that you can read and understand how the code's working.
Now, the cool thing about this is that it's going to give you references directly into your codebase. So, like we have a sound manager. If you click on this, it takes us right to the sound manager inside of the client.
So, to me, reading through this code, it looks like, okay, there are different events that fire over from the back end, and they play different MP3s.
Look at this; we have all these MP3s that are kind of named the same way. In fact, I could probably even refactor this.
I don't know if this is used elsewhere; let's use a couple of places. I think just in this file, though. So, I could actually refactor this and say sound types to MP3, right?
So, you could ask AI to refactor that, but again, it's going to be much faster if you just use the skills of your IDE to do an inline replacement, and now you just ref your code very simply.
All right, so again, we can kind of scroll through here. It's going to give us all the different files that are related to playing sounds in our codebase.
It looks like there is a sound listener that's listening to all these sounds that are sent from the server. I'm basically just binding to events and playing sound clips based on the event that comes over with the backend.
Okay, so I can register the different events on my backend when a player dies or when a zombie spawns, and I can do stuff on the front end when that happens. Event-driven systems—very, very good to understand.
So, read up on them. All right, looks like there's a debug thing about sounds here. That's probably good to understand. I can turn the sounds off whenever I want at a centralized place.
So again, the point of the chat is you can ask questions over your codebase, and it will answer you.
Okay, now another thing is I could say, "Walk me through how I would add in a new item called—uh, we'll do water."
Okay, let's just pretend like there's a water item that you can get to extinguish fires or something like a fire extinguisher.
Okay, so again, ask questions about your codebase, and it's going to walk you through the steps that you can take to implement this. This is very good.
I'd recommend using chat if you just want to have someone hold your hand about what I did earlier in this video. Right? What I did at the first section of this video—that's me knowing my codebase.
That's me opening up files, adding things, modifying things. I remember where different maps are set up. I forget where some are set up, obviously, as you saw.
But if you have a really, really strong understanding of your codebase, it's very quick to go through and just change stuff.
If you don't, or you just want that extra certainty that you're not missing something, using chat to help you implement a feature is very powerful.
So, this is going to tell you like, "Okay, there's an item type." Okay, I can't click on this to open the file for some reason. I don't know if that's a bug they need to fix.
I'm paying them good money, right? I should be able to click this and load up the file. But anyway, if I want to find this, let's just go ahead and go to the file because I know how to use my code editor.
You just do a Command P and then a hash symbol; you go straight to whatever variable definition you want.
Okay, so it's telling you if you want to add water, you probably got to update this water items list, right? And then it's going to tell you, "Well, you should probably also create a water file."
Anyway, so down here, you can create a new file called water. So, like if I were to reapply that, it'll create a file for me, and I can just go ahead and save that.
And then I can read through it again. It looks like I need to go over here and add a water asset or like a fire extinguisher asset or something.
And then it's going to tell me I need to create a server-side water event. Let's just go ahead and do this for the server one.
All right, if you look at this file, there's like a ton of issues in it. And I will say that if you were to compare this to any other thing in my codebase, you'll see that this is the way I'm doing extensions.
So, this suggestion wasn't the best, and that's something you need to keep in mind is that sometimes it's going to give you suggestions that just don't even work.
Like, why did it say "ADD extension" when it knows I have like 20 other files that look like this?
So, here's where Command K again comes into play. I could say, "Make this look like server wall."
Okay, let's just go ahead and submit that. Let AI refactor this file real quick, and then we can just keep on reading through about the next steps.
If you don't want to sit here and wait, at some point this thing will finish up with an approach that matches more of this one that I just kind of gave it as a suggestion.
Okay, there's still a little bit of TypeScript errors, and it's probably going to tell you how to get resolved those like assets.
It should update entity factory. I got to update entity factory on the server. I got to update—
But again, like if you don't truly know your codebase, you're just going to blindly accept this stuff, and it's just not going to work out very well.
Like, this is not something that I would do in my codebase, right? This is totally against how I'm doing stuff with the entity factory.
It already basically just takes the constructor and builds the entity. I don't need a switch statement.
So, be very careful with the chat. This is why I recommend start with the tab completion, and then start with the Command K, and then you move on to the chat when you feel like you truly understand your codebase.
Now, let's go ahead and take this to the next level. How do we actually use something called Composer?
So, if I were to go ahead and like remove the water from the front end and the back end, we're going to try to use Composer to implement this feature as well.
So, I would recommend that the more specific you are in your requests, like the more specific your prompt is, and you can give as much context as possible, typically the AI system does a very good job at modifying your current codebase to implement whatever you need.
So, in our case, I'm going to say, "I need you to add a fire extinguisher item, which a player can use next to a fire, and it should put the fire out if it is within a certain radius of the player."
Okay, so here is the prompt. I'm going to go ahead and just hide my face real quick, but again, I would recommend to give it suggestions.
So, like I'm going to say, "Please use the bandage." I have a bandage file. I'll just go ahead and say bandage as well on the client side.
Where is it? Bandage on the client. Okay, so I'm going to give it examples to build out the fire extinguisher. Don't forget to update all of the necessary maps in the front end and backend to get this working.
Also, there is a place you need to update to make it pickable and droppable. Good luck!
Okay, let's just go ahead and submit this. Now, first, Composer is something I use all the time. When I'm sitting in bed and I'm watching TV with my wife and I'm tired after work, I literally just type this prompt up with my right hand.
I let it go, and then I come back after five minutes. Sometimes you got to babysit it because it doesn't create files for you.
Like, you have to go and accept those files, but for the most part, if you give it the right amount of context, you can come back and, like, if the feature wasn't too difficult, it'll just add in your files.
It'll add in everything and have it look like your existing codebase, and it's actually pretty phenomenal, especially if you're just adding something kind of like a brain-dead implementation like the one we're adding now: a fire extinguisher.
I have an item that already does exactly this, but it heals the player, so I wanted to modify it to instead look within a radius of the player and just put out any fires that the player is standing next to.
Okay, so hopefully this goes well. We will see. I don't know if I even have a fire extinguisher icon.
I could go ahead and look over here. I highly doubt that I do. Is there even like a water icon?
Let's go ahead and grab this potion. This potion should be good enough, so we're going to go ahead and just paste that in here, and that's probably good enough now.
And then I'll save this. I think I need to re-export this, so let's go here. I'll export this as, and then we want to export it over the item sheet.
I'm sure there's an easier way to do that. I'm still learning Aspite, but now if I were to look at this location, it's 112 over Z.
So, what I've seen is even as it's like cooking, you can go ahead and just load up different files like this, and I can say fire extinguisher, and then we'll say 112 Z sheet items.
Okay, so again, you can code while this thing's going over here as long as you remember to check it, you know? So, keep that in mind. It's very useful when you just want to do some background refactoring, then come back and check it.
You can also have multiples of these going at the same time, I believe. I haven't tried that. That's kind of like more advanced that I don't know if I even want to try that. That'd be crazy.
But now we have this thing, this fire extinguisher asset, and if we're lucky, when it's trying to update my codebase, I might actually grab that asset already and just use it.
Now, unfortunately, this is a pay-to-win type of thing, so like when you run out of fast credits, it becomes kind of problematic.
I pay for like the $20 subscription to get like 500 credits of fast tokens or something, but honestly, it's probably worth paying to get more.
The amount of productivity gains you're going to get from using Cursor over just coding yourself—it's a lot.
Now, sometimes you have to figure out, is this stuck or is it actually just slow? So, I'm going to cancel it and I'll say "continue."
This is a really good trick—just type "continue," and it kind of builds off of where it was to generate the code again.
Okay, so I was trying to create a fire extinguisher on the client. I think up here it created one in items. There'll probably be an issue we got to resolve there.
It's creating two different files, so here it's actually trying to update the entity maps that I reminded it to do because, you know, that's something I just ran into, and I assume that the AI is going to forget about it too.
Again, the more context you can give it, the better it does. And I swear, if I had the fast credits, it would have been done by now.
But again, this is—I do this the most when I'm watching TV or I'm just too lazy to really implement it, or if I just want to roll the dice and see how far I can get with letting Composer do it.
It's a very good approach. I used Composer for implementing the pathfinding, which is probably why the zombies are getting stuck at this point when they try to walk around the map.
But I swear I've had some good results using Composer, and you'd be silly not to at least try this a couple of times.
Like, give it some solid tries because it does pretty well.
So, right now, it actually created—hopefully—the fire extinguisher. You kind of read through the code. This is important. I mentioned this at the start: read through the code, understand what it's doing, correct it, correct the AI if it's wrong.
If the code looks wrong, okay? But let's read this one.
So, the player, when you update it—this is totally wrong too. So, here's another thing I've seen: it basically deleted all of my code.
I don't know if this file got a little bit too large, but it's also trying to do the logic for the player inside of this. It should have done it inside the fire extinguisher.
So again, as you're reviewing the code, like when you see stuff that looks wrong, you can reprompt this and be like, "Hey, I actually need you to add a consumable type to the fire extinguisher."
So, I can say new consumable, and then I'll just say uses of one. Let's see what this is.
Okay, yeah, it doesn't even take a second thing. Okay, and then I can say "on consume," and then I can just go ahead and type that in.
Okay, so now I can say, "You implemented this wrong. Instead, I want you to add the logic that you put in the player. Move it to the consume method."
So, move the logic you put in the player's update method inside the fire extinguisher's consume method, please.
I don't think you even needed to modify the player. Something like this. Again, I'd be watching TV. I go ahead and just prompt that, and then I wait five minutes and I come back, and like, "Oh, it works!"
Okay, there you have it. You saw it come in here, and it basically modified this consume method.
And the cool thing about the Composer is that it sees that there's a TypeScript error, and it's going to reprompt and try to fix this file because the first iteration at implementing this, it did it wrong.
Recently, Cursor added this feature where it keeps on trying when it gets linting errors, and it looks like a refactor to say entity manager.getNearbyEntities.
It's trying to get anything that's a fire that's nearby, and then it's trying to mark those entities for removal.
Okay, so I think it's on the right track. I think most of this stuff is good, and it's going to say that, "Hey, now you can actually try this."
Let's just accept all these changes and let's go back to our game.
Okay, let's try to spawn an extinguisher. I don't know if this is going to work with this. So, fire extinguisher—there it is! Pick it up.
Now, also what I want to do is spawn a fire. Okay, let's just let the zombie catch on fire real quick. Oh, and he killed me.
Okay, so all right, let's try to do this real quick. I'm going to spawn a fire extinguisher, and I'm going to spawn—I'm G to pick this up, and I'm going to spawn a fire, and then I'm going to try to use it with G, and it actually crashed.
So, like, it looks like it crashed over here. Here's another good approach: you're going to try out the feature; it's going to crash.
Copy the entire stack trace, okay? And just say "add to Composer," and it's just going to fix it.
Okay, you keep on building upon the errors that Cursor spits out, and it'll eventually get through it.
Okay, now I'm going to say "fix this error" and just go ahead and paste that in, and it should kind of go through.
Now, if you're good, you can fix it yourself, right? Let's see if I can race to it.
So basically, it's saying that there's no item called fire extinguisher, but the good thing is that it's going to use all the context that we just went through, and it's going to fix the issue.
We tried to do fire extinguisher here, and I think I didn't register the item over here, so now it should probably be good to go.
All right, let's just go over here. I'll pick up the fire extinguisher, and then I'm going to go ahead and just like spawn a fire, and then I'm going to press "F," and then look at that! It extinguished it!
So, there you go. You have a feature that was added in. Had to kind of, you know, help it out along the way, but if you're not that great at coding, like you saw how easy that was.
I basically copied and pasted an error in it, added the feature, and now we should be good to go.
So, like, I'm probably going to commit this, right? I'm going to build upon that fire extinguisher, maybe make a nice sprite for it.
But those are some of the ideas about Cursor that I have learned when I want to use something over something else.
Typically, if I'm lazy, I'll use Composer. If it starts failing and I just cannot figure it out, that's when I kind of pull out the big guns and I try to implement it myself.
Back to the tab completion, the Command K, and then I'll use chat along the way to help me out.
So, I think Composer is really good to get you that starting point. Sometimes when you're coding, like you feel like you're overwhelmed; there's too much code you got to change.
Use Composer. It'll modify seven files for you. It might have one or two bugs in those modifications. You can go back and you can fix them, and then you already have that motivation because you're already 90% of the way there.
You just have to go and keep prompting it and just get it working.
And the better you know your codebase, the faster it is to fix the bugs that the AI generates for you.
And then you start getting used to the bugs that it generates because it typically falls with the same pitfalls that it does every single time, right?
And of course, having TypeScript—like, I don't know why you'd code without any type of typed language at this point—but having TypeScript just helps it even become better because it can actually see that it has a bunch of TypeScript errors, and then it just goes back and it fixes them.
All right, I know this was a long video, but I hope you learned something by watching this.
Maybe you were convinced and said, "Okay, maybe I'll give Cursor and Composer and chat another try. Maybe it's more useful than I thought it was."
Or you might look at this game like, "Bro, this is just like a silly 2D online game. No wonder why AI is doing so well against it."
Okay, so your mileage may vary on a large-scale project. Maybe Cursor won't do as well, but I have found it to be very useful on my Next.js applications that I work on, on side projects, and also on this game that's starting to get a little bit larger in size.
So, hope you guys enjoyed. Have a good day, and happy coding!