1(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[938],{2861:(e,t,o)=>{(window.__NEXT_P=window.__NEXT_P||[]).push(["/interviews/hendrik-mans",function(){return o(687)}])},687:(e,t,o)=>{"use strict";o.r(t),o.d(t,{default:()=>c,useTOC:()=>d});var a=o(5893),i=o(7812),n=o(1304),s=o(8925),r=o(835);let l=()=>(0,a.jsx)("iframe",{style:{width:"100%",borderRadius:4,overflow:"hidden",height:450,margin:"30px 0 -12px"},src:"https://vfx-composer-examples.vercel.app/examples/scenes/asteroid"}),h=()=>(0,a.jsx)("iframe",{style:{width:"100%",borderRadius:4,overflow:"hidden",height:400,margin:"30px 0 -12px"},src:"https://space-scene-sandbox.vercel.app/"});function d(e){return[]}let c=(0,i.c)(function(e){let t={a:"a",em:"em",h1:"h1",hr:"hr",p:"p",strong:"strong",...(0,s.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.h1,{children:"\uD83C\uDF99 Interview with Hendrik Mans"}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.em,{children:(0,a.jsxs)(t.strong,{children:["For our first interview on WebGameDev.com, we welcome ",(0,a.jsx)(t.a,{href:"https://github.com/hmans",children:"Hendrik Mans"}),", a German developer who works full-time on open-source game development tools. Thank you Hendrik for being our first interviewee! Could you tell us about your background and what led y
1ou to decide to go full-time with open source?"]})})}),"\n",(0,a.jsx)(r.n,{src:"/interviews/hendrik-mans/hendrik-mans.jpg",alt:"Hendrik Mans",height:250,wifth:250}),"\n",(0,a.jsx)(t.p,{children:"Hello and thanks for having me! Ironically, my background is actually something entirely different from game development â Iâve spent most of my professional life building business applications, designing databases and APIs, architecting complex systems, things like that. But Iâve also always been interested in game development, itâs the usual story really where, like many others like me, building a game on my first computer was the gateway drug to programming, and then it just never really let me go."}),"\n",(0,a.jsx)(t.p,{children:"Over the decades, Iâve always tried to keep up with the latest tools and engines, and more than once, Iâve told the people I work with: go build a game, not an app, youâll learn new skills and gain new insights that you will be able to use in your day job, too. For me personally, building games has always been about balancing out the type of work for which Iâd need to put on a good business shirt with something varied and colorful where I could allow myself to go a little crazy."}),"\n",(0,a.jsx)(t.p,{children:"Funny thing is, though, that very often the kind of tools that would otherwise be your first choice when building a game never fully clicked with me. Having spent so much time in web and server application development, I at some point understood that I really wanted to build games code-first, too, and on the web, because not only itâs a platform that Iâm familiar with, but also because I feel that there are a lot of valuable properties to building on the web that are just waiting to be applied to game dev. Hence my focus on this specific section of our trade."}),"\n",(0,a.jsx)(t.p,{children:"And so, early in 2022, I decided to ramp down my activities as a consultant to focus more, and eventually fully, on my open source work in this space. Thereâs a whole collection of libraries that Iâm working on now, and Iâm getting paid by people who enjoy my work enough to want me to produce more of it. Itâs a really cool setup thatâs not without its own set of challenges, but my mind is still blown that itâs possible to work this way."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.em,{children:(0,a.jsx)(t.strong,{children:"What do you think of the current state of web game development?"})})}),"\n",(0,a.jsx)(t.p,{children:"I think from a technical point of view, what we can do on the web today is super impressive, but games that make full use of the webâs capabilities are still quite rare. To some extent this is probably due to the libraries and engines still trying to catch up with the sort of feature sets of the big engines they aspire to imitate, but I think mainly itâs because not enough people are building games on the web yet."}),"\n",(0,a.jsx)(t.p,{children:"Building games on the web isnât anything new, and itâs had many names, but just stop and consider the sort of connotation âHTML5 gamesâ or âFlash gamesâ have â something that needs to happen more is to have people build full games that are more than just a quick hyper casual diversion or, worse, a front for a real-currency coin stores. This is unfortunately a really hard to sell idea right now, because nobody will go for bigger projects unless thereâs a clear path towards monetizing them. Weâre seeing some interesting platforms popping up that try to provide this, so I think thereâs going to be some good developments in this space in the next few years."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.em,{children:(0,a.jsx)(t.strong,{children:"It seems like there is a trend to use UI libraries like React, Vue, and Svelte, to wrap WebGL libraries like Three.js, Pixijs, or Babylon.js. While they certainly help make our code more declarative, some people argue that these are not the right tool for the job. What is your take on this matter?"})})}),"\n",(0,a.jsx)(t.p,{children:"Well, Iâm going to give you the textbook answer first â these things donât really matter all that much. If you sit down with the intention to build a game, the best stack you can choose is the one youâre familiar and comfortable with. No matter what that stack
1is, youâll always find at least one person whoâll tell you that youâve made an utterly terrible choice. Donât listen to them. There are advantages and disadvantages to every of the many engines and libraries available, and none of them will ever be more important than your own familiarity and enjoyment of them."}),"\n",(0,a.jsx)(t.p,{children:"I wrote one of my earlier web games with CoffeeScript, a language that is now pretty much universally hated among modern web developers. I think it was already hated a lot back when I used it! I certainly remember being mocked for it. But the simple truth is that that particular game only ended up existing because I enjoyed making it, and that would quite possibly not have been the case with another stack at the time."}),"\n",(0,a.jsx)(t.p,{children:"Having said that â I know youâre also asking because I now use React in almost all of my game projects, have a lot of React- or React-Three-Fiber-specific libraries, or at least make sure that my libraries can be used in React environments. I love using React for game development. You wouldnât believe how much people have mocked me for that choice, too, but, well, I can take it. In the end, React and other frameworks like it are really just tools that convert one state into another, and possibly run side-effects, which is a large part of what youâll be doing in your game code either way. If youâre not using a framework like that, youâre guaranteed to write your own, it might work differently, have another set of features, but youâre still writing one. Itâs not like there is a pure, lightweight, everything-is-peachy frameworkless game development model and the fatty framework-poisoned one that lazy people like me use. Iâm just choosing to use someone elseâs code to solve a specific problem instead of inventing things from scratch."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.em,{children:(0,a.jsxs)(t.strong,{children:["You created ",(0,a.jsx)(t.a,{href:"https://github.com/hmans/miniplex",children:"Miniplex"}),", a framework-agnostic ECS library, which has been very well received in the React Three Fiber ecosystem. Could you summarize what ECS is and how this approach can help developers architect their code? Do you have recommendations for people who would like to get started with ECS?"]})})}),"\n",(0,a.jsxs)("div",{style:{margin:"24px auto",textAlign:"center"},children:[(0,a.jsx)("a",{href:"https://github.com/hmans/miniplex",target:"_blank",rel:"noopener",children:(0,a.jsx)("img",{src:"/interviews/hendrik-mans/miniplex.jpg",style:{borderRadius:4,width:"100%",maxWidth:450,display:"inline-block",marginBottom:-12}})}),(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.a,{href:"https://github.com/hmans/miniplex",children:(0,a.jsx)(t.strong,{children:"Miniplex"})}),", Hendrikâs gentle ECS library"]})]}),"\n",(0,a.jsx)(t.p,{children:"ECS is short for Entity Component System, a code architecture pattern that cleanly splits things into separate components, which are usually just representations of state, and systems, which is the code that operates on them. Entities are composed from multiple of these components."}),"\n",(0,a.jsx)(t.p,{children:"The benefits this pattern provides are some very enticing performance properties, but also keeping complex codebases nicely maintainable, and testable, too. Most people who choose ECS for their projects do it for its performance benefits, but Iâm really a fan of it because of its structure, which is why Miniplex fully commits to that aspect of the pattern."}),"\n",(0,a.jsx)(t.p,{children:"Thereâs a whole bunch of JavaScript ECS libraries out there, but I felt that what was missing was one that very specifically was as easy to understand and use as possible, and was a perfect match for frameworks like React, without being exclusively designed for them. I let myself be inspired by the typical approach to state in JavaScript and React, where things usually are just boring old objects with specific properties on them, and ended up adapting that pattern to the idea of ECS."}),"\n",(0,a.jsx)(t.p,{children:"Miniplex will feel familiar to anyone whoâs ever used a state management library like, say, Zustand, but gently push them away from the typical reactivity-leaning focus, and towards ECS. You know, itâs funny how we take libraries like React-Three-Fiber and React and, when building non-trivial games with them, actively avoid their reactive properties for the sake of performance, and Miniplex fully embraces that. I think thatâs what makes it one of a kind."}),"\n",(0,a.jsx)(t.p,{children:"As to recommendations â I think the one I do have for newcomers to the pattern is to relax and not overthink things. The truth is, an object-based ECS library like Miniplex is really just a big array of things, with some tools that let you get a subset of that array to iterate over in your game loop. It doesnât really matter if these things are âplayersâ and âenemiesâ, or âmovablesâ, âhittablesâ, âkillablesâ and âpickupablesâ. Just like with the choice of stack weâve discussed before, start with something that feels comfortable and fun â youâll be surprised by how quickly the pieces will inevitably start falling into place by themselves."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.em,{children:(0,a.jsxs)(t.strong,{children:["You have also been working on the ",(0,a.jsx)(t.a,{href:"https://github.com/hmans/composer-suite",children:"Composer Suite"}),", a suite of standalone libraries for Three.js, React, and React Three Fiber. Could you tell us about the libraries and what developers can start using now?"]})})}),"\n",(0,a.jsx)("div",{style:{margin:"24px auto 30px",textAlign:"center"},children:(0,a.jsx)(h,{})}),"\n",(0,a.jsx)(t.p,{children:"Oh yeah, good old Composer Suite. The big thing I wanted to achieve last year was an easy-to-use API for visual effects, you know, particle systems, noise texture effects, and the likes. After doing a little prototyping, I quickly understood that these had to be driven by the GPU, not CPU, so I ended up building a library that came with a custom GLSL shader that you could customize through a series of parameters."}),"\n",(0,a.jsxs)(t.p,{children:["Then I got drunk with power and figured itâd be great to have something node-based that would fully let me build shaders using JavaScript, and thus ",(0,a.jsx)(t.a,{href:"https://github.com/hmans/composer-suite/tree/main/packages/shader-composer",children:(0,a.jsx)(t.strong,{children:"Shader Composer"})})," was born. I liked the theme of composers doing composition, so I eventually added Material Composer, which adds a layers-based API to Shader Composer, and ",(0,a.jsx)(t.a,{href:"https://github.com/hmans/composer-suite/tree/main/packages/vfx-composer",children:(0,a.jsx)(t.strong,{children:"VFX Composer"})}),", which implements an optimized particle systems engine based on instanced rendering."]}),"\n",(0,a.jsxs)("div",{style:{margin:"24px auto",textAlign:"center"},children:[(0,a.jsx)(l,{}),(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.a,{href:"https://github.com/hmans/composer-suite/tree/main/packages/vfx-composer",children:(0,a.jsx)(t.strong,{children:"VFX Composer"})})," examples"]})]}),"\n",(0,a.jsx)(t.p,{children:"All of these are ready to use, but sadly still need to receive meaningful documentation, something Iâve been holding off on because I wanted the development to settle first. And Iâm glad I did because I will give at least the latter two of these libraries a little do-over and restructuring to make them more compact and easier to use."}),"\n",(0,a.jsx)(t.p,{children:"I think that was a lot of words to basically say that yeah, these libraries are still under heavier development than Iâd like to admit, and youâd be crazy to use them in production projects, even though I know of some people who didnât let that stop them from doing so anyway."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.em,{children:(0,a.jsx)(t.strong,{children:"Are you planning any other things for 2023 that web game developers should know about?"})})}),"\n",(0,a.jsx)(t.p,{children:"Iâve been jotting down my plans for 2023, and thereâs probably a long blog post waiting to be written about what itâs like to work on open-source software full-time, and the kind of traps that this mode of working lays out for you. I probably stepped into most of them! So part of my focus this year is to learn from those little accidents and iterate on how I work, and what I spend my time on."}),"\n",(0,a.jsx)(t.p,{children:"Which mostly means that the big theme this year is going to be simplicity. I want to make the things Iâve already built simpler to use. The Composer Suite is currently looking a little too daunting, I think, so there will be some restructuring. I plan on integrating the functionality that Material Composer provides directly into Shader Composer, and rebranding VFX Composer to better reflect what it is doing, which is GPU-based particle systems. Some of my libraries like Miniplex are really tiny and cute, and theyâre really my favorites, so I want more of my stuff to be like that."}),"\n",(0,a.jsx)(t.p,{children:"Other than that, Iâm currently exploring an idea for a lightweight framework for Three.js apps and games that, if I can make it work the way that Iâm envisioning, might be pretty fun. But not talking about things too early is another thing Iâm trying to do in 2023, so youâll hopefully read more about this some other time, haha."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.em,{children:(0,a.jsx)(t.strong,{children:"Thank y
1ou, Hendrik, for taking the time to answer these questions and helping push this web game developer community forward with your tools! In closing words, would you like to share any advice with aspiring web game developers?"})})}),"\n",(0,a.jsx)(t.p,{children:"Thank you, itâs been excellent!"}),"\n",(0,a.jsx)(r.n,{src:"/interviews/hendrik-mans/hendrik-mans-2.jpg",alt:"Hendrik Mans",height:180,wifth:180,style:{borderRadius:999}}),"\n",(0,a.jsx)(t.p,{children:"To aspiring web game developers, I think I have the following to say: building games on the web, and elsewhere, is incredibly fun, so do not let others ruin this for you. Game development can be heavily opinionated. Donât build games the way that someone else tells you to. Donât build them to become rich and famous. Maybe donât even build them to finish and release them. Build them to have fun. Not only because having fun is great, but also because if youâre having fun, it typically means youâre learning. Enjoyment and knowledge will always be yours to keep."}),"\n",(0,a.jsx)(t.p,{children:"\uD83D\uDCC6 2023-01-10"}),"\n",(0,a.jsx)(t.hr,{}),"\n",(0,a.jsxs)(t.p,{children:["If you would like to support Hendrikâs work, you can ",(0,a.jsx)(t.a,{href:"https://github.com/sponsors/hmans",children:(0,a.jsx)(t.strong,{children:"sponsor him on GitHub"})}),", follow him on ",(0,a.jsx)(t.a,{href:"https://norden.social/@hmans",children:(0,a.jsx)(t.strong,{children:"Mastodon"})}),", watch his code ",(0,a.jsx)(t.a,{href:"https://www.twitch.tv/HansVonMans",children:(0,a.jsx)(t.strong,{children:"live streams on Twitch"})}),", and join the ",(0,a.jsx)(t.a,{href:"https://www.webgamedev.com/discord",children:"Web Game Dev Discord"})," if you have questions!"]})]})},"/interviews/hendrik-mans",{filePath:"src/pages/interviews/hendrik-mans.mdx",pageMap:n.v,frontMatter:{},title:"\uD83C\uDF99 Interview with Hendrik Mans"},"undefined"==typeof RemoteContent?d:RemoteContent.useTOC)},835:(e,t,o)=>{"use strict";o.d(t,{Y:()=>n,n:()=>i});var a=o(5893);let i=e=>{let{src:t,alt:o,height:i,width:n,style:s}=e;return(0,a.jsx)("img",{className:"float-img",style:{float:"right",height:i,width:n,borderRadius:4,marginLeft:24,marginTop:24,marginBottom:24,...s},src:t,alt:o})},n=e=>{let{src:t,alt:o,height:i,width:n,style:s}=e;return(0,a.jsx)("img",{className:"float-img",style:{float:"left",height:i,width:n,borderRadius:4,marginRight:24,marginTop:24,marginBottom:24,...s},src:t,alt:o})}},8925:(e,t,o)=>{"use strict";o.d(t,{a:()=>l});var a=o(1151),i=o(5675),n=o.n(i),s=o(7294);let r={img:e=>(0,s.createElement)("object"==typeof e.src?n():"img",e)},l=e=>(0,a.a)({...r,...e})},7812:(e,t,o)=>{"use strict";o.d(t,{c:()=>h});var a=o(5893),i=o(3665),n=o(8644);let s=(0,o(7294).createContext)({}),r=s.Provider;s.displayName="SSG";var l=o(8925);function h(e,t,o,a){let n=globalThis[i.ud];return n.route=t,n.pageMap=o.pageMap,n.context[t]={Content:e,pageOpts:o,useTOC:a},d}function d({__nextra_pageMap:e=[],__nextra_dynamic_opts:t,...o}){let s=globalThis[i.ud],{Layout:l,themeConfig:h}=s,{route:d,locale:m}=(0,n.t)(),u=s.context[d];if(!u)throw Error(`No content found for the "${d}" route. Please report it as a bug.`);let{pageOpts:p,useTOC:g,Content:f}=u;if(d.startsWith("/["))p.pageMap=e;else for(let{route:t,children:o}of e){let e=t.split("/").slice(m?2:1);(function e(t,[o,...a]){for(let i of t)if("children"in i&&o===i.name)return a.length?e(i.children,a):i})(p.pageMap,e).children=o}if(t){let{title:e,frontMatter:o}=t;p={...p,title:e,frontMatter:o}}return(0,a.jsx)(l,{themeConfig:h,pageOpts:p,pageProps:o,children:(0,a.jsx)(r,{value:o,children:(0,a.jsx)(c,{useTOC:g,children:(0,a.jsx)(f,{...o})})})})}function c({children:e,useTOC:t}){let{wrapper:o}=(0,l.a)();return(0,a.jsx)(m,{useTOC:t,wrapper:o,children:e})}function m({children:e,useTOC:t,wrapper:o,...i}){let n=t(i);return o?(0,a.jsx)(o,{toc:n,children:e}):e}}},e=>{var t=t=>e(e.s=t);e.O(0,[1304,2888,9774,179],()=>t(2861)),_N_E=e.O()}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.