If you haven't been living under a rock then you've probably heard about ChatGPT. What's more is that the large language model is also capable of generating code. This post is about using the AI chat-bot to develop a particle system in P5JS, and test if it's capable of making adjustments to a simple sketch based on our prompt inputs.
What is ChatGPT? Can it generate code? Explain simply and briefly.
ChatGPT is an AI language model developed by OpenAI. It is designed to generate human-like responses to text-based prompts or questions. It has been trained on a vast amount of data from books, articles, websites, and other written sources to understand and generate natural language.
Regarding code generation, ChatGPT can assist with generating code snippets in various programming languages. You can provide descriptions or ask for specific code examples, and ChatGPT can generate code for you. [...] it may not always be perfect or error-free.
Arguably, the code generating aspect is the most intriguing part to me, and immediately makes me wonder about a number of things - how good is it really at writing code? Does it understand the code that it comes up with or is it just regurgitating things it has been trained on? Can we make adjustments to the code by guiding it with our prompts?
Here's what we'll try to create:
This post is intended as a lighthearted exploration of what we can do with ChatGPT in this regard. For the purposes of the examples in this post I used the GPT 3.5 version of ChatGPT. I was told that much better results might be possible with GPT4 - so if you have access to that you might just give it a spin.
What are Particle Systems?
You know what? We might as well ask ChatGPT while we're at it: What is a particle system? One short paragraph.
A particle system is a computer graphics technique used to simulate and animate large numbers of individual particles.
These particles have properties such as position, velocity, size, color, and lifespan, and can be manipulated to create various visual effects like fire, smoke, explosions, or fluid simulations.
Particle systems are commonly employed in video games, movies, and other visual applications to enhance realism and generate dynamic and interactive visual elements.
Actually one of the best resources to learn how to program a particle system is by none other than the creative coding OG Daniel Schiffman:
Additionally, there's a number of interactive widgets throughout the text for you to play with and that reflect ChatGPT's responses. To prevent this page from eating up too much memory I disabled auto-play on most of the sketches, to run them simply hit the play button at the top of each one.
Particle systems also involve a lot of loops, which might time out if they're left unattended - in that case simply restart them with their corresponding play button.
Let's start simple and just ask it straight away if it can generate a particle system in P5 👇
Can you program a particle system in p5js?
Kind of impressive! But hold on... that looks familiar! It's very similar to what Daniel Schiffman put together in his video tutorial on the same topic. The example from the corresponding chapter in his book Nature of Code is also very similar:
As we're going to see, it turns out that ChatGPT is actually pretty good at making P5JS sketches! Considering that GPT-3.5 was trained on a big chunk of the entire internet, it is likely that it has seen many thousands of P5JS sketches.
A good portion of this sketch corpus probably consists of particle systems, or particle-system-like systems, lots of them likely forks of Dan's example. So it probably didn't have much trouble piecing together the necessary code from it's internal representations. But that's just my assumption, we don't actually know exactly what GPT has been trained on.
The challenging part is yet to come though, let's see how good ChatGPT is at modifying and evolving the code from here on out!
The particle sketch that it provided doesn't implement any physics yet. The particles don't interact with each other, there's no collisions between them nor with the boundaries of the canvas. Let's ask chatGPT to make these changes one at a time:
Can you add physics to it? And make the particles stay within the canvas please.
Careful with these loops, they will slow down after a while due to too many particles being spawned.
Can you make the particles collide with each other?
This collision behavior is a bit odd, I'd like it if it was a little bit smoother actually such that the particles don't get stuck on each other. I also want there to be a maximum number of particles, so that it doesn't become very slow over time. Let's see if we can ask ChatGPT to fix that.
Make it such that there is a maximum amount of particles that shouldn't be exceeded. g vCan you also make the particles not get stuck on each other?
OK, not bad! Not bad at all, we asked for the changes and ChatGPT delivered. Note here that I didn't even look at the code when I made my requests, I simply based my suggestions off of what I saw when I copied the code over and ran it in the P5 editor.
Spawning Particles with the Mouse
Now let's see if we can spawn new particles with a mouse press!
Can you make the particles have different sizes and colors? Can you also add in a function that spawns new particles when the mouse is pressed?
You might notice here that the particles sink through the bottom of the canvas after they sit there for a bit, let's fix that. I also actually want the oldest particles to disappear and have the mouse continuously spawn new ones.
There's a problem where the particles sink through the bottom of the canvas, can you prevent that? Also when I spawn new particles with a mouse press, make it such that the oldest particles disappear to make space for new particles.
Sometimes ChatGPT doesn't get it right from the first try. Let's adjust the prompt and try to draw attention to what we actually want.
Can you also make it such that the particles don't leave the canvas from the sides or from the top? Can you make the collisions more accurate such that the particles don't overlap? Also mouse presses still don't spawn particles when the maximum amount of particles is reached, can you fix that as well?
Let's also see if ChatGPT can make this code run faster - in this aprticle system the number of collision checks grows exponentially the more of them are added, since each particle needs to be checked against every other particle to determine if they in fact collide.
Well, dang! Didn't expect ChatGPT to know about grid lookups! As it mentioned, a grid lookup is a method to speed up the collision procedure. Using an invisible grid in the background we check which cells the particles occupy and only check it against particles in neighboring cells that it overlaps, then we only need to make a fraction of the checks.
I wrote in depth about how to make such a grid lookup for a circle packing procedure in this article if you want to learn more about it:
Now let's see if the ChatGPT's grid lookup actually works - note I had to minify the code here for the widget to work:
Color me impressed! It works, and it works well! Here's also what it had to say about the changes:
The particles are however still overlapping a bit, let's see if we can ask it to fix that again. It's been a bit inconsistent in that regard.
Again, well done! But can you please make the collisions more accurate? Can you make it such that the particles don't overlap each other anymore?
Alright, alright - now I feel like it's just trying to flex on me. First time I hear about collision resolution, no idea what it is but let's see how it behaves:
Ok so this is also really cool! It's like the particles are a little bit elastic as well now. When you spawn a bunch of them it almost seems like there's a little sea of particles forming.
Next I asked it what other techniques there are to improve the sketch, and it answered with a bunch of stuff:
Let's see if it can actually implement the first one it suggested:
Thanks for the info, I didn't know about any of these! Can you modify the code and implement "Verlet Integration"?
Uh... OK interesting, but I don't think that's the correct behaviour. Now the particles are just jumping erratically all over the canvas. Can you fix that?
That's even worse. OK maybe no need for Verlet Integration, can you remove that from the code again and return to what we had before?
That is still broken. Can you go back to the exact version of the code that you provided in your 9th answer?
You'll notice that this isn't actually the code from the 9th answer LOL.
Ok - let's call it a day on this chat, and boot up a fresh one. It's just gotten stuck and doesn't want to go back to what we actually had before. I couldn't get it to go back to the working piece of code that we had.
Maybe there's some exact prompt with which we can achieve this, but I'm too impatient to keep waiting for it to regenerate the entire code on every question.
Adding an Attractive Force
Here I essentially started from a new chat and pasted in the code from before after the prompt:
I don't know what the best practice is pasting in code, if the back ticks are necessary or not or if they have any effect on ChatGPT's response.
In the following code can you add an attractive force to the cursor when I press the space bar? Such that the particles flock towards the cursor and follow it. Make it smooth please!
Ok that's working really nicely! There's an issue thought where the new particles don't collide with the old particles, can you fix that?
Again, the collision behavior wasn't very consistent, and kept changing over the prompts, but it was able to always make it work somehow - here I guess you gotta pick the one that you like the most.
Overall this entire prompting session took roughly 2 hours. I did however experimented for a couple of hours previously to get a feel for how things work. My main take aways here are:
- The initial prompt is incredibly important. If it provides something that already works well then you have a good chance at tickling something more out of it
- Choice of words is important. It is actually very sensitive to the words that you choose. For instance you get a different starting sketch if you ask it can you program instead of can you generate.
- Use clear language, avoid abstract terms. I had some fun prompting with before, telling it to create a beautiful p5 sketch, but that doesn't really work - the model doesn't know what beautiful actually means, it's a subjective thing. Asking for a particle system on the other hand, it knows exactly what we want.
- Don't ask too much of it. Simple improving questions to guide it in the right direction work well. Starting from a chunky and elaborate initial prompt is often too much for it.
- Asking again works sometimes! Sometimes you just need to ask it a second time and it'll make the correct changes.
- Going back doesn't really work. It doesn't really understand how to undo changes.
- When it's stuck, it's better to start from a new chat. It's a bit odd but it's ability to remember things from the current chat can sometimes also be a little bit detrimental. As if it has some sort of inertia that's a bit difficult to steer.
- Positive feedback like 'Well done!' and 'Good Job!' seem to somehow work? It's just based off of a feeling, but in my mind it's basically telling it that it did well and maybe it'll take note and conjure new answers in a similar manner to which it did before.
But those are just my thoughts after playing with it for a while. Would love to see what you can come up with.
Hope you enjoyed this little experimental post about sketching with ChatGPT! Now I'm actually really excited to write a little tutorial on how to code a Particle System from scratch, with physics and all that Jazz - especially with the grid lookup and the collision resolution method!
Cheers, happy coding ~ Gorilla Sun 🔆🐵