 Hi, hello, thank you for coming to my talk Maslow's particle system It's gonna be a little bit about Abraham Maslow pictured here and a lot about particle systems You probably know Abraham Maslow from his number one smash hit the hierarchy of needs But he also has this absolute banger Maslow's hammer also sometimes called the law of the instrument You've probably heard it paraphrased when all you have is a hammer Everything looks like a nail. But this full quote here is from this book the psychology of science. It's a truly lovely book in which he makes a kind of a plea to the psychoanalytical community for a more holistic more humanistic approach to the cycle psychoanalytical project but also to science in general I think and I'm gonna read this little excerpt that I think is kind of Irrally prescient I have been disturbed not only by the scientists and the dangers of their denial of human values in science Along with the consequent a moral Technologizing of all science just as dangerous are some of the critics of orthodox science who find it too skeptical To cool and non-human and then reject it all together as a danger to human values So that is a very lofty and philosophical introduction to what is really going to be a pretty silly talk about Using particle systems as a way of getting Very high-performance very natural feeling interfaces and also hopefully Bringing some joy to your users So this is me my name is Matt Hayes. You can find me as mystery command on the internet pretty much everywhere my pronouns are he him and The slides will be available online and the repository for all the code that we're going to look at will also be available online so let's look at the So this is my little sort of chatbot messenger app. I can Type a message here and it shows up I can tell it to say hello, and it will say hello back I can say be movie and it will begin reciting the be movie one line at a time every two seconds Now I'm just going to use this to sort of fill the window with some messages I can also say Congrats, and I get this cool fireworks particle effect and then if I Send it some love I get this other cool sort of sentiment, you know, like what you would see if you're live-streaming Facebook event or something like that I'm really sure what to call it. We'll get to that later one thing. I do want to point out here is that this Scrolling window of messages is its own kind of particle system where I'm using the bounds of the window to Filter messages that get shown or not. This is sometimes Referred to as virtualization or wind doing but modeling it as a particle system It gives us a pretty Efficient and like easy to reason about way of approaching the problem So that's what we're going to build. That's what we're going to sort of tour and Just get back to my slides here Nice a little bit of history about this talk the reason that I took inspiration from Maslow's hammer as a sort of a little self-criticism I've been thinking about particle systems and using and reusing them since sometime around 2007-2008 I saw Seb Lee Delisle give this talk as three particles a thousand percent extra free At I think it was flash belt in 2008 I was recently out of art school and Had found my way into the advertising world and was building a lot of banner ads and micro sites and looking for ways to Add pop and pizzazz and this was really inspirational to me Just as like a kind of clean clear concise way of organizing the problem the first implementation I ever did was an action script class called bedazzler and what it would do is take a color and Time duration and it would just sort of scan the flash movie for Pixels of that color and then put a little sparkle on them and kind of bedazzle it for some silly banner it I Gave a talk about the similar kinds of things this was more sort of canvas based and just looking at how to break up some of the some of the parts of these kinds of systems in forward JS in 2016 I was working at Yahoo, and then in 2017 I was working at tumblr And I got the opportunity to give another version of this talk at Liberty JS where I'd had a little bit more Sort of practical experience putting some of this stuff to work in some experimental UI For tumblr in that talk is the first time I really kind of introduced Sort of more practical Application some of the feedback I got from the first talk was it's really fun, but I need to like do work so in this second iteration I Focused a lot on a Google Developerist article called complexities of an infinite scroller Where I kind of looked at it as a one-dimensional particle system and that same kind of the inspiration from that is also in this This app that we're going to tour and then late last year Actually after the Liberty JS talk Some feedback I got was I think you're kind of building up towards an entity component system And that really set me off in the direction of entity component systems Unity the game engine Came out with a thing called project tiny and a thing called dots or the data-oriented tech stack Which are both any component system kind of rewrites of some of the core framework functionality with the goal of doing higher performance work and also being able to sort of Dynamically scale it down to what mobile devices can handle or like a web browser Being able to launch unity games as WebGL apps on your on your device So we're going to use some Patterns here. The first is just a handful of interfaces The main one being the the particle, right? I'm going to use Verlay integration if you've ever like looked into physics of any kind. It's just a way of Modeling physical behavior without needing to track velocity and now acceleration So you you wind up mostly doing addition and subtraction. So it's a little bit cheaper It's not quite as realistic as Euler or semi implicit Euler, but it is cheap and Very stable So it makes it a good candidate for for these kinds of like fun silly particle systems because it's using vectors for our position in previous position. We know the vec interface and The field here is a little bit hand wavy What I really need is some kind of like world state or global context There are sort of conditions under which you want to emit a new particle conditions under which you want to sort of deactivate or clean one up and those generally depend on some sort of World context you might in some other implementations see this described as a world or as a universe or As global state, then we have an object pool and a property initializer This we will get to sort of midway through the tour of the code, but it is just a sort of more memory efficient way of Keeping a keeping track of a fixed sized list of particles and recycling them when we're done instead of sort of just throwing them away and letting the garbage collector clean them up and then Effects and the command pattern the command pattern comes from Design patterns the gang of four book in the book They call it a reified method call They're kind of approaching it from a Java or C++ sort of background and in JavaScript all functions are reified We have these sort of first-class functions. So really the command pattern here is just Functions that we're gonna pass around callbacks essentially So this example is an updater, which is you which is basically an implementation of that verlay Integration scheme we get the current velocity by subtracting the previous position from the current position And we add the current velocity to the current position that to the current position to get the next position We cash the old position and move on in my actual implementation There's a sort of a gravity vector that we also add in there the two other kinds of effects that we're really gonna Make use of here are a kind of create or activate effect and a remove or a deactivate Effect and we'll see that In a minute. So let's look at some code if I check out 1.0. I really just want to Show you that this is a Pretty vanilla create react app setup. I'm using the type script Template oh, and I am adding some semantic release related stuff just so that I can get these these releases as tags in get hub and I Get this nice changelog that uses my commit messages to Sort of move things along But other than that, it's it's pretty much straight up just a just a react app, right? I use the component folder pattern CSS modules, but really nothing out of the ordinary in here So here I'm starting to build out mostly just the interface my app has a reducer for actions I have this kind of a knit which is sort of a measure the size of the Window an ad message and then a render message which also kind of just measures the size of the the message object itself and In here, you'll see I Have this effect which fires whenever it renders and if we don't already have a top and height for this message We're going to Generate one and render it and if we do have a top and height for this message We're going to scroll that message into view And I also think at this point that Yeah, in my sort of form my submit bar here What I'm doing is just echoing Everything I say so if we look at this Here I can say hello So it's it's got some jank right it's early But you get the kind of basics of the layout of the interface and kind of what we're Going for in 1.3 You see I sort of stub out my fireworks effect, but really I just I'm starting to kind of organize things a little bit better We see that this big reducer in the top, but now we have a messages component that kind of represents the window and here Here you see the actual sort of Filtering right so and we have a kind of an update effect that's being called as part of this on scroll event whenever of the whenever the messages window scrolls and We have this kind of cleanup effect happening here, which is just really just this Messages that reduce that filters out messages that are that have been rendered but are now outside of the windows Bounce so moving on if I go to 1.4 you can see where I am Implementing this fireworks thing. So here I have a new state Key called is showing fireworks and it just conditionally renders this fireworks Component the fireworks component if we look all the way down at the render is a canvas and If we just quickly look at the CSS It starts out at opacity zero and has an opacity transition of point four seconds or four hundred milliseconds that's going to come in handy for transitioning in and out when we Render this fireworks thing. Yeah, so there's an effect that fires the first time at render is right It's got no dependencies. It just gets a ref just grabs the the canvas ref And then creates a state variable for the rendering context It also does some measurement and width stuff and then sets the opacity to one so a Point four seconds after it's rendered. It is fully opaque And then this effect fires when the context changes And it really sets up our Frame handler, so we just kind of step through this We capture the frame ID so that we can cancel it if we on render for some reason We do some stuff with time to normalize it And then we have an emitter here, which just pushes on to Particles array then we have kind of some Context setup we have an updater which we'll look at is is just the the Verlet integration thing I described earlier and a renderer which takes the context and the particle And then finally we have this reducer which just Resets the the particle is a kind of mutable array at this point by Filtering out anything that's outside of the bounds So we scroll up. It's all just in this one kind of module at this point here you see our Beck and particle interfaces props for the component. I'm pulling some Stuff off the window just a shorthand it this character here You can get with option P It's Great. I love it. Here's our particles array. This is pre-object pool optimization It's just a list. We have some some configuration state here a P function which Generates a new particle or emits a new particle Some vector mass stuff an updater, which is the Verlet integration thing I described And a renderer call which draws them into the canvas context if we look at that Do I say congrats? Yeah, it's okay. I mean I think this is sort of as far as I can push it with the Performance characteristics. We have as you'll probably note here We're just creating new objects every time and and we're in the sort of create emit sort of step we're just pushing them on to this list and then We're pushing the ones we want to keep on to a new list and throwing the whole list and and everything We don't want to keep away. So we're creating a lot of references. We're creating a lot of objects that the potential for garbage collection is Very high at this point, but forward Yeah, so in 1.5. I add a Similar kind of a sentiment again. I didn't wasn't really sure what to call it and it's very similar to The fireworks display. I guess let's look at this too because we just Made some updates. So so here I've moved some of the interface stuff out into a little lib folder So I can focus on just the sparks and particle effect here I pee has become create spark and I have an update spark and a render spark and then I moved these Create many kind of functions Into their own functions, but it's it's pretty much just like moving it out of Out of being in line and in the frame callback. So So yeah, here you see the kind of setup Here is the create render and remove some optimizations, right that are kind of obvious at this point is that each of these Do something with many calls is is iterating over a list Every frame in fact the render sparks is iterating over the entire list and then Then we're reducing over the entire list in the very next call And if we look at the sentiment thing that lets us some get that heart effect. It's a very similar setup, right? It's a lot of copy pasted, but we have sort of unique Opacity and scale properties on the on the heart We don't have a render heart here because we're just going to set visible hearts as state And then let let react do the Do the diffing and the rendering and so we can check that out here I'm trying to overwhelm so this sort of limited in terms of the number of particles the effect and The performance I if we sort of throttled this up very much from where it is You would see Significant amounts of sort of jank and lag in the system whenever the garbage collector kicks in So let's see if we can clean that up here. Let's look back at our our fireworks Here so now inside of our frame handler. We have a single sparks dot for each So we're only going to loop over the list of sparks once and as a matter of fact if we are Looking at a spark that is currently Not active and we should emit we will do the kind of activating step and Otherwise we'll bail early and then we do this is kind of the new deactivator of the remover step and if we've Deactivated a spark in this step We're just going to return so that we avoid the update and render steps and kind of similarly in the sentiment thing We're just going to loop once over all of the hearts And bail as early as possible Throughout and I think also at this point. Yeah, we have the pool So if I go back here, I've moved the particles out to their own module So they kind of have their own domain So you see here we have the hearts are a pool of heart interfaces There is a fixed number of 50 They get their uuid ones at the beginning and it's kind of preset their Values and then the activate and update step are really what kind of like Resets them at the beginning, you know, if they're if they're sort of moved out of the frame they get become inactive and eligible for redrawing and then the update step adds gravity and moves everything along a similar setup in the fireworks display with the addition of render, right? We pass the context in and we draw it an optimization here as to use Phil wrecked. It's a little bit cheaper than ellipse and fill and we'll talk about some further optimizations that could be had there and the end so any other I Guess the only other really significant change here is that the reducer is kind of moved up into its own module and it is just Setting and and adding items in the state and we actually Have a wrapped dispatch callback that Handles the sort of special cases for us so that we can have that all in one place So again, you'll see if I do Congrats here. We get like a lot more particles and We can do a lot more hearts at the same time and it's pretty smooth Yeah, if I get a bunch of stuff in there, then I do Congrats, and then I do the heart And then I scroll You see we're not getting too much jank at all and I'm running a screen recorder, so this will like a lot going on and it's Highly amenable to kind of tuning to whatever performance characteristics you might be targeting So I think 1.7 is where I add the B movie enhancement And I'm actually I fixed a couple bugs this morning. So my extra credit branch And now we're we're back at the kind of full Full featured App and we get, you know pretty solid performance with just a little bit of a little bit of organizing our code and in a sort of Set of a particle system like patterns Okay, back to slides We are Almost done So where to go from here as I mentioned we're creating a lot of vectors those vector math operations are Immutables that they're returning completely new vector objects Every time they're run it might be an optimization to create a pool of vectors and do a kind of similar Activate deactivate sort of thing an optimization. I've made in previous incarnations of this of this Presentation which is kind of overkill for what we're doing here is a fixed time step Fixed time step would let you split the update and the render steps from each other Make it so that the update step can kind of play catch up if the render step takes too long Which means that the animation is smooth even if the rendering is not Yeah, you can ask me more about that if you have questions Another thing that's would be really interesting to me to explore and I'm still kind of working on is Message passing and how you do kind of interactivity and events In in a system like this, especially as it broadens out into an entity component system High-level overview of what an any component system means is if we're thinking about particles as kind of rows In a in a table like one column is the X position one column is the Y position one column is previous X previous Y active and so on an entity component system would be a way of organizing the code so you're dealing with columns and kind of running almost like queries on this Database of particles to get a certain set of like column our records and it is It is a very Efficient from a memory layout standpoint might be it might be need to explore in This sort of virtual machine that JavaScript gives us also. I think this is functional you might have noticed that a couple of instances were passing a particle instance and like some extra State along whether it's the field or the rendering context That is starting to feel to me like this reader monad pattern Functional programming is very new to me as I mentioned I came from art school So I have a pretty non-traditional path into engineering but a one really exciting possibility is that if you have a functional system that is Associative and closed over composition. It is parallelizable and maybe we could push all these particles into Multiple workers and just have them emit sort of Operations or positional updates or do something like that to you know run potentially You know ten times more something like that and then similarly on the rendering side, right? We're the real expense there is the draw calls thinking specifically of the the fireworks display It would be a cool optimization If we could batch all of the particles of one color draw all their rectangles and then fill one time I think that's it and finally black lives matter. It would be Weird and maybe even irresponsible to start a talk with the humanization of science and Abraham Maslow and not in these unprecedented times Mention that black lives matter if you find yourself thinking please keep Politics out of JavaScript. I have to say that silence is also a form of political speech And that inaction is action In the off chance that me talking about it is the thing that pushes you over the edge into action The equal justice initiative seems great and they accept recurring contributions so you can set up a Monthly donation black lives matter card and black lives matters card are both great highly Circulated just in case you haven't seen them this Twitter thread from Victoria Alexander is a sort of anti-racist reading list broken up into beginner intermediate special topics biographies, I mean, it's just a stupendous list there. I've read some of those books and they really moved me and I added all the rest of them to my Reading list on a more personal note this dismantling racism.org has a page on white supremacy culture if you Like me grew up in an almost exclusively white community Maybe rural or suburban Maybe in the Midwest and remember wondering well, what's what's my culture? I I regret to inform you that there is a strong chance that at least part of your culture Is white supremacy culture and I highly encourage you to Do some soul searching about that and finally If you're into indie games Humble bundle is doing a fight for racial justice bundle 100% of proceeds go to some great charities I have no affiliation with humble bundle whatsoever I just like indie games and think it would be cool if we lived in a just society That is my time. My name is Matt Hayes. Here are the slides. Here's the repo If there is anything I can do. I mean, I kind of only know JavaScript but If I can review your code or make some kind of connection for you I'm happy to try and help Thank you very much and I look forward to The rest of the conference. I hope you're having a great one