https://toffeee.com/ Zola en Sat, 16 Nov 2024 00:00:00 +0000 blog Sat, 16 Nov 2024 00:00:00 +0000 Unknown https://toffeee.com/blog/ https://toffeee.com/blog/ Tetrenga Retrospective Sun, 01 Sep 2024 00:00:00 +0000 Unknown https://toffeee.com/posts/tetrenga-retrospective/ https://toffeee.com/posts/tetrenga-retrospective/ <style> img { max-height: 300px; } </style> <div class="post-image"> <a href="results.png"> <img src="results.png" alt="the results for tetrenga, we came 33rd in Enjoyment and 192nd overall" title="the results for tetrenga, we came 33rd in Enjoyment and 192nd overall"> </a> </div> <p>tetrenga was probably the best ratio of work to good response ive ever experienced with a game, taking only a comfy weekend to make</p> <p><strong>we maintaned top 10 most popular in the entire jam for the full rating period</strong></p> <p><strong>we came #33rd in enjoyment out of 7,700 ENTRIES</strong>, that is the top 0.4%</p> <p>here's a list of things i'm very very glad we did:</p> <h1 id="1-ideated-explosively">1. ideated explosively</h1> <div class="post-image"> <a href="ideas.png"> <img src="ideas.png" alt="our ideas on our whimsical kanban board" title="our ideas on our whimsical kanban board"> </a> </div> <p>over time ive discovered that the best way to get good ideas is to just absolutely fart out 50 very terrible ideas</p> <p>this completely stops the "think of only 1 idea and then keep rotating it in your brain until it explodes in scope" issue. throw all of your judgement to the curb, don't think about scope, don't think about game design, just smash out the ideas. if the idea is bad, pinpoint why it's bad, then make an iteration. now you have 2 ideas. mash up two ideas youve already come up with to make a new idea. make gigantic leaps. and DO NOT think too hard about any 1 idea. don't try and mental gymnastics your way to justifying any idea - the reason you're making so many ideas is because you're fishing for what gives your gut instinct the best response. your gut is usually right!</p> <p><small>*(this is mean but.. this is also why ideas are a dime a dozen and generally why ideas guys aren't very valuable. they usually have 1 idea that they rotate in their heads and justify to themselves, rather than doing the work to explore and discover ideas that are organically exciting)</small></p> <p>me and miredly both came up with &gt;10 ideas, discussed them, ranked them, and mashed them up. our best mashup was "build a structure on a small platform and score based on how heavy it is". from there, the game easily grew into the tetris/jenga idea with the risk/reward random generation. out of all of the ideas we had, this one just felt the most intuitive and air-tight. we already drew similarities to it and popular games like Suika Game, so we knew it'd at least have an audience and we had examples to work from</p> <h1 id="2-we-didn-t-scope-small-we-scoped-tiny">2. we didn't scope small, we scoped TINY</h1> <p>to make a game as fun as it can be, you have to experiment. if you scope to the limit of your ability, you by definition don't have the time or skill to experiment. you WILL NOT get a game perfect in your first shot, you gotta give yourself breathing room to try out different stuff</p> <p>to give an idea of the scope, it took just 1 hour for miredly to make the core game. all we needed was the wobbly physics tetronimoes, the base, and the zone at the bottom which restarts your game</p> <div class="post-image"> <a href="original.png"> <img src="original.png" alt="the 1-hour prototype of tetrenga, no graphics just debug collision shapes" title="the 1-hour prototype of tetrenga, no graphics just debug collision shapes"> </a> </div> <p>that was fantastic, because that meant we could spend the rest of the time experimenting, polishing, making art and menus. you have no idea how important menus are and how long they take lol</p> <p>one thing im REALLY happy we got to experiment with is the randomly generated shapes. my original idea was for it to generate a random polygon, and you have to somehow incorporate it into the rest of the tower</p> <div class="post-image"> <a href="old.png"> <img src="old.png" alt="the tetrenga tower with strange triangular polygon rigidbodies slotted into the tower" title="the tetrenga tower with strange triangular polygon rigidbodies slotted into the tower"> </a> </div> <p>miredly instead really wanted to have randomly generated <strong>tetrominoes</strong>, following the same formula of having a connected set of squares but just in a random formation. i was actually averse to this idea and i didn't believe in it.</p> <p>"like, if they're all just squares, surely you could just stack them too easily"</p> <p>i was so so so wrong, having randomly shaped tetrominoes made this far more fun</p> <div class="post-image"> <a href="new.png"> <img src="new.png" alt="the new tetrenga tower with random tetrominoes" title="the new tetrenga tower with random tetrominoes"> </a> </div> <p>in the old version, it'd pretty much always be high-risk low-reward to try and stack a totally random polygon into your tower. miredly basically never pressed the button. i pressed the button at first, but found myself deciding against it when going for the high score, which basically meant i was just stacking regular pieces like i was playing regular tetris</p> <p>but in the new version, it's a lot more hopeful, and incorporating the strange shapes feels pretty similar to saving yourself when you missdrop in regular tetris. this, combined with the new way of thinking about tetris where you care about balacing your tower instead of clearing lines, really helped with how readable and approachable the game is</p> <p>im very happy we had the time to <strong>actually try out</strong> this idea rather than me being silly and dismissing it instantly. our game would have been far, far less fun if we didn't give ourselves time to try it out :3</p> <h1 id="3-added-a-gorl">3. added a gorl</h1> <p>im so happy we added tetrenga chan. she was inspired by Rhythm Heaven minigames and Nintendo's Nikky from Swapnote</p> <p>i think having her there made this game more addicting and emotionally interesting, because there's a girl Live Reacting to the stuff you're doing!! you feel empathy for her, if shes nervous im nervous, if she gets happy because you saved your tower or integrated a super heavy piece, it feels nice</p> <p>idk if this is just me, but she makes the game feel less like an abstract shape-puzzle game, and more like you're building an actual tower. the tower feels physically there, in tetrenga-chans world, and she's watching you piece it together and is cheering for you. ok i may be going insane do you understand what i mean</p> <div class="post-image"> <a href="tetrachan.jpg"> <img src="tetrachan.jpg" alt="a mockup drawing of tetrenga, with tetrenga-chan!" title="a mockup drawing of tetrenga, with tetrenga-chan!"> </a> </div><h1 id="4-didnt-do-pixel-art">4. didnt do pixel art</h1> <p>im quite happy with the art on this one. it feels a bit soft and approachable, like a medium-budget mobile game of olde a la Cut the Rope or Suika Game</p> <p>we were originally toying with the idea of making it look like Money Puzzle Exchanger for the Neo Geo <a href="https://www.youtube.com/watch?v=XhnZAy_CNlA">https://www.youtube.com/watch?v=XhnZAy_CNlA</a></p> <div class="post-image"> <a href="money.png"> <img src="money.png" alt="a very high definition screenshot of money puzzle exchanger for the neo geo" title="a very high definition screenshot of money puzzle exchanger for the neo geo"> </a> </div> <p>its silly but a lot of people really, really dislike pixel art. even beautiful, masterful pixel art. often, even the crappiest vector graphics would get the popularity vote over good pixel art, and i'm still not sure why. i straight up do not share that same taste, i don't understand it, but it's something ive witnessed</p> <p><small>(i actually wonder if it depends on if you were brought up on rasterized retro games vs vector flash games? i grew up with the SNES so i love some good pixel art..)</small></p> <p>i've always drawn pixel art because it's a very helpful limitation to stop yourself adding infinite detail, and its far easier to make every asset of your game harmonious.</p> <p>BUT, drawing scribbly high-res graphics in this style was SO much easier than drawing pixel art. and the audience felt it was higher quality for it. maybe i should try it more...</p> <h1 id="but-yeah">but yeah!</h1> <p>im just happy with this project! its teeny tiny was a lot of fun, and i'm very proud of the results</p> <p>for most of my jam games, i ask my friends to play it and they play it for that evening and are very lovely. but this game has literally got a life of its own. so many friends would join call like "toffee ive been playing this game for like 4 hours"</p> <p>people are STILL playing it weeks later and posting their screenshots</p> <p>its incredibly flattering, and this has been a huge success</p> <div class="post-image"> <a href="wow.png"> <img src="wow.png" alt="tetrenga love!!!" title="tetrenga love!!!"> </a> </div> quiet room Sun, 28 Jul 2024 00:00:00 +0000 Unknown https://toffeee.com/posts/quietroom/ https://toffeee.com/posts/quietroom/ Arcade Thang Retrospective 3 - Its shipped! Fri, 21 Jun 2024 00:00:00 +0000 Unknown https://toffeee.com/posts/arcadethang-retrospective-3/ https://toffeee.com/posts/arcadethang-retrospective-3/ <p>well its not shipped but its out in a week, but you can wishlist if youd like! im doing literally 0 marketing because ive left most social medias so my marketing strategy is to Manifest it into peoples heads and then im assuming 1000000$ will appear in my bank account</p> <p>🎉💥⚠️🩷 <a href="https://store.steampowered.com/app/3055780/PERMUTER/">https://store.steampowered.com/app/3055780/PERMUTER/</a> 🩷⚠️💥🎉</p> <p>wowww it actually only took 2 months instead of 3 months! this was made over 8 busy-ish weekends, so about 10-12 working days of time. making Permuter has been a breeze. i'm happy it's complete and shipped without much struggle, its got me feeling much more optimistic about gamedev as a hobby</p> <p>ive made an effort to talk about my games more with friends &amp; post about it more. ive always been a bit nervous to tell irl friends about my games but... they have been extremely supportive and have all wishlisted it &gt;:3 DESPITE it being poopyshit</p> <div class="post-image"> <a href="banner.jpg"> <img src="banner.jpg" alt="the game Permuter in my Steam library, there&#x27;s my sona over it saying &#x27;so official&#x27;" title="the game Permuter in my Steam library, there&#x27;s my sona over it saying &#x27;so official&#x27;"> </a> </div> <p>one thing i took very seriously on this project was playtesting WITH OTHER PEOPLE</p> <p>i playtested the 3-day prototype with dozens of people, every batch of new features i playtested again with another dozen, i released a shitty instantly-playable web version so people could playtest easier, and i took all feedback dead seriously</p> <p>playtesting has been completely indispensable.. this made me confident that my game was worth something, and also showed what part of the game to put the most work into. lots of people had lots of different ideas, but importantly, when testing with a lot of people, you notice <strong>trends</strong>. ideas and criticisms are good, but they don't hold much weight when the sample size is 1.. but when everyone agrees on something, you can be confident that it's the right thing to do</p> <p>another thing i took seriously was polish</p> <p>making a polished game is a neverending pile of minutia that you dont really think about when you make stuff for itch.io. like, i've never needed an accessibility settings menu for a jam game, nor had to care about controller support for menu-driven games, nor had to give a fk if the mouse is still visible on screen after you plug in your controller</p> <p>by making this game, i've learned a lot about polishing a game to a steam-acceptable standard, and the experience making it has been really worthwhile and id like to bring my other games up to this sort of standard. i think feel-good minutia goes a long way</p> <p>also - in getting this game shipped asap - ive made peace with not including everything i wanted. ive scrapped a whole narrative idea which i was quite attached to. telling myself "ill save that for Permuter 2" has got me through this project far easier and prevented going too far over the line of diminishing returns</p> <p>i also tried to take management seriously in this project, primarily to prevent project-killing scope creep, but also to maximise how good i feel about progress. my #1 killer lately has been my mental health (which is crushing <em>all</em> of my hobbies atm) so making this as easy and feel-good as possible is a priority, and it's done wonders</p> <p>a big proponent of that has been this one gigantic Whimsical whiteboard where i track every stage of the project with kanban boards <em>(i know its a meme but the physicality of it feels good)</em> and have progress bars for everything. every single task felt great to complete when i knew i could come back to my board, shuffle some cards to the "done" pile and inch the progress bar along. its a little instant gratification reward for my small brain, it all felt like forward momentum! and even better, since it was all in stages, if i scope-creeped and had new ideas, i would put them into the next stage. when the time came to start the next stage, i could filter down to just the best ideas and discard the rest, and then <strong>strongly stick</strong> to the tasks that i chose</p> <p>highly recommend setting up a silly feels-good system for your projects!!</p> <div class="post-image"> <a href="whim.png"> <img src="whim.png" alt="the final whiteboard for Permuter, full of kanban boards" title="the final whiteboard for Permuter, full of kanban boards"> </a> </div><br/> <p>but ya hm... my final thoughts on the game itself...</p> <p>i think its a bit unimpressive. im a little embarassed about this project because i know i can do much much better, which i think is a good feeling to have</p> <p>with this project being made so quickly, and with it being easy to manage and fun to work on, im confident my next project can be more ambitious</p> <p>mid-way through making this project, i made <a href="https://dollcorp.itch.io/a-story-about-love/">a love story about love</a> which has felt like wringing my brain thorugh a wire mesh to get all the gunk out</p> <p>i feel so much more secure after making this project and seeing the rly lovely reception (🩷 thank u). i think making it sorta re-centered my compass to the values i had before i started gamedev as a job..</p> <p>i have much more fun if i dont think about an audience when making games or art</p> <p>i mean that in a lot of senses - i want to be more self indulgent with what i make, be less frightened of being authentic, but also.. i want to give myself permission to make some totally derivative trash game, because theyre fun to make!!! all of the design problems are solved ahead of time by other people and you can just focus on making it look and feel good!! Permuter was set out to be a completely shameless clone at first for the sake of shipping something without worrying about innovation, but i ended up meshing so many ideas together i think it reasonably stands on its own..</p> <p>so in future..</p> <p>id like to make something more open-ended. my greatest value in games is making something which lets other ppl express themselves. not even just in a minecraft-way, but like, fighting games are also quite expressive. id like to figure that out..</p> <p>idk! ill keep experimenting, making more 3-day prototypes and see what's exciting</p> <p>yayaya!!! thank you all for being so supportive of this game! its inspired me to take it easy, have fun, and scope very very small</p> <p>have a nice one! 🩷</p> <div class="post-image"> <a href="sickos.png"> <img src="sickos.png" alt="the game Permuter in my Steam library, there&#x27;s my sona over it saying &#x27;so official&#x27;" title="the game Permuter in my Steam library, there&#x27;s my sona over it saying &#x27;so official&#x27;"> </a> </div> Arcade Thang Retrospective 2 Sun, 05 May 2024 00:00:00 +0000 Unknown https://toffeee.com/posts/arcadethang-retrospective-2/ https://toffeee.com/posts/arcadethang-retrospective-2/ <div class="post-image"> <a href="screenshot.png"> <img src="screenshot.png" alt="screenshot of a discord stream of my friend Jill playing this game" title="screenshot of a discord stream of my friend Jill playing this game"> </a> </div> <p>this is basically a devlog at this point but playtest 2 is done! im really feeling that playtest 3 will be the release canditate lol</p> <p>this process has been really nice. its made me realise how much of a back and forth games like this require</p> <p>i'm going to keep going until it's Steam-able but i've already got a lot of big takeaways from this project:</p> <p>1 - balancing is really really hard. for example, this game has a "merchant" upgrade, where enemies have a chance to drop an extra coin. enemies drop coins on death. one common <em>game feel</em> tip is to increase the amount of enemies but decrease their health. however, if i increase the amount of enemies but decrease their health, this makes the "merchant" upgrade soo much stronger, because its strength implicitly scales with how frequently an enemy death occurs. balancing one thing can throw something else out of balance. i kinda understand why balacing games are a constant effort years after a game's launch</p> <p>and 2... im never ready for how much time polishing takes. i made this game in 3 days and i estimate it's going to take more 3 months to get it to the level of polish i want. that's not even adding more features or making more content, just tuning what's already there</p> <p>i now understand that if you're making a systems-y game, it's just so unlikely that the first draft will be good. it'll probably go through many huge sweeping iterations. these iterations could touch every single facet of your game, so the more surface area your game has, it'll require exponentally more iterations</p> <p>in my case, taking on feedback and iterating on my game required so many changes, that the second pass of the game took way more effort than the first prototype</p> <p>i think this has put into perspective how impossible my other projects would be if i tried to continue them</p> <br/> <div class="post-image"> <a href="autoficer.png"> <img src="autoficer.png" alt="screenshot of my experimental game &#x27;Autoficer&#x27; and of my bunny factorio game" title="screenshot of my experimental game &#x27;Autoficer&#x27; and of my bunny factorio game"> </a> </div> <p>some of my previous first-iteration prototypes took months to make, e.g. Autoficer (left). and knowing what i know now, i can't imagine how long the timeline would be if i chose to complete it</p> <p>doing stupid probably-not-real math, if a 3 day prototype ends up taking 3 months to finish (1:~30 ratio), then a 2 months prototype would take ~5 years to finish. which actually sounds like it could be an accurate timeline for a game like this lol. that's not even accounting for the fact that Autoficer is a game with not many similar examples to pull from. i'd have spent a very very long time climbing over design walls</p> <p>since life is getting busier (which is a v good thing), i really dont want to keep spending months on something im going to throw away. this is fine if you're learning, but eventually you have to cash in what you've learned and actually make stuff, right? from now on im quite happy making things that are tiny</p> <p>so ya.. balancing is hard. polishing is hard. quality games take much, much longer than youd think</p> <p>i guess these ideas are obvious in retrospect, everyone says this, but in practice and planning, id never given them enough attention or took them seriously</p> <p>i will from now on!!! im going to make smaller experiences that are better and actually give them to wayyy more friends. my friends have definitely been the most helpful thing to happen to my game dev hobby. thats what its all about right! making something exciting for the girlies</p> <p>excited to keep working on this, i feel like i can see a finish line lol. all that's next is more upgrades, 2 small bosses and a nice art pass!! tysm</p> <div class="post-image"> <a href="https:&#x2F;&#x2F;media1.tenor.com&#x2F;m&#x2F;JoTEm6NZTXcAAAAC&#x2F;kaito-vocaloid.gif"> <img src="https:&#x2F;&#x2F;media1.tenor.com&#x2F;m&#x2F;JoTEm6NZTXcAAAAC&#x2F;kaito-vocaloid.gif" alt="kaito vocaloid cheering" title="kaito vocaloid cheering"> </a> </div> Arcade Thang Retrospective Sun, 21 Apr 2024 00:00:00 +0000 Unknown https://toffeee.com/posts/arcadethang-retrospective/ https://toffeee.com/posts/arcadethang-retrospective/ <iframe width="520" height="345" src="https://www.youtube.com/embed/J3AG0RDZ4HI"> </iframe> <p>here it is its basically geometry wars lol lmao</p> <p>im really happy with this, its polished, feels pretty tense and im really pleased it only took a single quiet weekend, it was very fun to make. ive still got game jam muscles babyyy</p> <p>comparing the experience of this to making my other larger projects woke me up to a sort of survivorship bias that my games have - all the stuff ive shipped is simple platformers, pixel art, etc, because anything more complex or demanding is just... impossible to make presentable or robust. ive had friends say its lazy, but its just reality. im realising it has to be simple simple simple, or it just wont exist. since trying to make games with deeper systems, i think i personally try too hard to make a game with a Twist or something that's Never Been Done, systems-wise. this ends up with me hitting design walls which i dont have the skill to overcome, then i scrap the game. for now, it might be more worth it to copy games i love, with some mild tweaks to bump the game in a direction that i wish it was bumped</p> <p>so!! ill keep it so much simpler from now on heehoo</p> <p>tho................... it is really getting to me how game-y all of my work is. there's like, serious games, and then there's game-y games, yknow? i think im biased towards systems-y games because im an engineer. but not <em>everyone</em> is an engineer, yknow? i barely think about narrative, purpose or motivation because a systems sandbox is more than enough. im making things just for myself, which is fun, but i want other people to actually play my stuff!!</p> <p>so, id like to put in more effort into figuring out what makes people want to play a game in the first place, and making a game that gives people something to talk about after playing it. this geometry game doesn't really inspire discussion, it's honestly just a fun not-too-challenging realtime reaction test with progression a la vampire survivors</p> <p>but im not sure if vampire survivors is really what i want to make lol.. ive had my itchio-front-pagers and ive sorta had enough of "fun game it has nice Controls and Game Feel you should add a boss and-" comments.. i am so thankful for that though and had fun. but i think im beginning to focus on what i really want, which is my art having some sort of meaningful effect, even if it's only for a tiny number of people</p> <p>which is hard!!!! im on step 0!!!!!!! i guess i can begin by giving my games any freaking story at all lol</p> <div class="post-image"> <a href="ideas.png"> <img src="ideas.png" alt="my ideas for future games. there&#x27;s a zero ranger screenshot, and 2 black and white drawings ive made. one of a fighter jet launching missiles at a huge geometric pyramid enemy, and another drawing showing a sketch of a giant woman boss heehoo" title="my ideas for future games. there&#x27;s a zero ranger screenshot, and 2 black and white drawings ive made. one of a fighter jet launching missiles at a huge geometric pyramid enemy, and another drawing showing a sketch of a giant woman boss heehoo"> </a> </div> <p>so for this geometry game, ive got a small idea for a fuller version if people enjoy the roughbox prototype. it's an old <small style="opacity: 0.5">(2020 old!! wtf i grew grey hairs looking through my folders to find my old mockups, i thought this was like 1 year ago)</small> idea i had about a pilot battling eva-style angels who invade earth. theres one pilot and shes terrified, barely putting up a fight against the angels and beating herself up over her failures. she slowly gets more powerful but not much more confident.. her friends are reassuring her on the intercom and explain to her - while yea she's failing, she's the only pilot who actually showed up, every other pilot was too scared. she's failing but failure is a part of trying. its a story of realising self worth!! idk!! its important to me!! i read and write at a 3rd grade level its actually so embarassing /srs</p> <p>anyway, i think ive got the whole bubbly polishy gameplay-y enjoying-ur-time-while-playing thing down i think, but i want to cultivate my art having a lasting effect, or just giving people something to talk about - even if the only thing to talk about is how Bad it is. ive been so scared of putting emotion into my games for those exact reasons, but i think id welcome it now.. thankfully, its something i can learn, given enough time and practice. i dont even know where to begin.</p> <p>which is very exciting!</p> <div class="post-image"> <a href="fantasy.jpg"> <img src="fantasy.jpg" alt="goodbye eri screenshot, &#x27;its missing a pinch of fantasy, dont you think?&#x27;" title="goodbye eri screenshot, &#x27;its missing a pinch of fantasy, dont you think?&#x27;"> </a> </div> a brief toffee 2023 wrapup Fri, 29 Dec 2023 00:00:00 +0000 Unknown https://toffeee.com/posts/wrap-up-2023/ https://toffeee.com/posts/wrap-up-2023/ <!-- <style>h2{border-bottom:1px solid #64524c;}</style> --> <p>takatakatakatakatakatakatakatakataka braindump post incoming</p> <p>this year was amazing for me. i've probably undergone the most amount of change ive experienced in a year &amp; become overwhelmingly friendpilled</p> <h2 id="feburary">Feburary</h2> <p>published ferra with tha lovely miredly whos always a pleasure to work with, felt more confident in my ability to make games. im so thankful this kicked me out of my love2d comfort zone, my c#/raylib projects have been very clean so far</p> <p><img src="https://toffeee.com/posts/wrap-up-2023/ferra.jpg" alt="" /></p> <h2 id="march">March</h2> <p>had a brain hemorrhage, went to hospital. became very stupid and struggled with basic tasks. my friends were so supportive and im very thankful. months later im functioning very well and back to my regular level of stupid</p> <p><img src="https://toffeee.com/posts/wrap-up-2023/brain.jpg" alt="" /></p> <h2 id="may">May</h2> <p>MCM!! i went to mcm london with a group of my closest friends and it was so much fun. i met brand new cool people who are now in da inner circle. i got this miku who is now the group mascot and comes everywhere</p> <p><img src="https://toffeee.com/posts/wrap-up-2023/mcmmiku.png" alt="" /></p> <h2 id="july">July</h2> <p>went to norway</p> <p><img src="https://toffeee.com/posts/wrap-up-2023/norway.png" alt="" /></p> <p>also got platinum 3 in street fighter 6</p> <p><img src="https://toffeee.com/posts/wrap-up-2023/plat.png" alt="" /></p> <h2 id="sep">Sep</h2> <p>went to alton towers with friends and daniel rustage of youtube fame who was really sweet</p> <p><img src="https://toffeee.com/posts/wrap-up-2023/alton.png" alt="" /></p> <h2 id="october">October</h2> <p>promoted at work, also kinda took up physical painting, its fun and relaxing even if im not very good</p> <p><img src="https://toffeee.com/posts/wrap-up-2023/paint.png" alt="" /></p> <h2 id="nov">Nov</h2> <p>moved house and moved in with my best friend!!!!!!!! we've moved back to the city i went to university in and couldn't be happier, feels much more homely</p> <p>going outdoors more, meeting up with new friends, becoming less alien</p> <p><img src="https://toffeee.com/posts/wrap-up-2023/newcastle.png" alt="" /></p> <h2 id="dec">Dec</h2> <p>working on more games, getting things actually on steam</p> <p>went to london and ice skated and did funny mini golf</p> <p><img src="https://toffeee.com/posts/wrap-up-2023/ice.png" alt="" /></p> <p>had a great new years party</p> <p><img src="https://toffeee.com/posts/wrap-up-2023/newyearmiku.png" alt="" /> <img src="https://toffeee.com/posts/wrap-up-2023/newyearkorean.png" alt="" /> <img src="https://toffeee.com/posts/wrap-up-2023/drip.jpg" alt="" /></p> <h2 id="2024">2024</h2> <ul> <li> <p>paint more</p> </li> <li> <p>get my shit together</p> </li> <li> <p>find a good creative scene</p> </li> </ul> <h2 id="final-notes">Final notes</h2> <img src="kim.png" style="margin: 0;"/> <audio controls><source src="kim.mp3" type="audio/mpeg"></audio> <p>its quiet i promise</p> blank canvas Sun, 15 Oct 2023 00:00:00 +0000 Unknown https://toffeee.com/posts/blank/ https://toffeee.com/posts/blank/ <div><style> h1 {display: none !important;} body {color: black; background: white} </style></div> <p><img src="https://toffeee.com/posts/blank/a.png" alt="" /> <img src="https://toffeee.com/posts/blank/b.png" alt="" /> <img src="https://toffeee.com/posts/blank/c.png" alt="" /> <img src="https://toffeee.com/posts/blank/d.png" alt="" /> <img src="https://toffeee.com/posts/blank/e.png" alt="" /> <img src="https://toffeee.com/posts/blank/f.png" alt="" /> <img src="https://toffeee.com/posts/blank/g.png" alt="" /></p> ferra retrospective Sat, 18 Feb 2023 00:00:00 +0000 Unknown https://toffeee.com/posts/ferra-retrospective/ https://toffeee.com/posts/ferra-retrospective/ <p>before ferra i was in a sink &amp; id not released anything in years. i came into this project with absolutely no expectations of making anything</p> <p>i just wanted to exercise the muscles required to work on something small while also having a full time job</p> <p>we used an entirely new framework with no past code to steal, so it was a challegne</p> <p>but watching friends mash replay on it was more than enough to make the work worth it</p> <p><img src="https://toffeee.com/posts/ferra-retrospective/gamers.png" alt="" /></p> <h1 id="starting-out">starting out</h1> <p>the vision was <strong>"frantic top down shooter"</strong></p> <p>i made a quick character controller &amp; gameobject system and then miredly made the first boss</p> <video controls> <source src="veryveryearly.mp4" type="video/mp4"> </video> <h1 id="steal-and-shuffle">steal and shuffle</h1> <p>miredly was doing an "ultimate" (some ffxiv thing idk) and showed me a boss fight. the loop looked cool, and we wanted to use the same idea and were dead set on huge floor attacks</p> <p>this turned out great and fit our vision of "frantic" perfectly</p> <p>if this were a pure bullet hell in an arena, you'd be making almost surgical micro-movements like touhou, which isn't frantic.</p> <p>however, with gigantic sweeping floor attacks, you're incentivised to zoom around. these floor attacks spawn right on top of you too, meaning you WILL have to get moving!!!!!!!!!!!!!</p> <p><img src="https://toffeee.com/posts/ferra-retrospective/ffxiv.jpg" alt="" /></p> <h1 id="explosive-scoping">explosive scoping</h1> <p>we had a lot of ideas, and we had to be ruthlessly subtractive. it almost felt like a bad decision at the time. but if we were not ruthless, we would have not made a good game, or maybe we never would have completed it at all</p> <p>to interpret the jam theme "makeshift" we really wanted makeshifty mechanics;</p> <ul> <li>huge chunks scrap falling off the bosses which u can use as a bullet shield</li> <li>different random ammo drops - the last 2 you pick up get combined to create a unique kind of bullet</li> <li>makeshift guns where you tape together multiple different guns and inherit the attributes of both (shotgun minigun!?)</li> </ul> <p>i drafted out the first 2 and they weren't fun. they sounded like good ideas, but in practice they don't add much</p> <p>that was a rly difficult thing to notice - "it doesn't add much"</p> <p>it's easy to notice if something's bad and makes your game worse, but if it's simply just "whatever", then it still doesn't need to exist. id much rather spend that bandwidth working on the things that do matter, and in this case that paid off a loooot</p> <p>a big number of dimensions to your game sounds good in your head, but even if you could pull it off, you'll have a thousand unrefined features that clash, confuse or dilute your game. id prefer a tiny set of mechanics that people can immediately understand, then surprise them with depth</p> <h1 id="agency">agency</h1> <p>i hate "easy" "medium" "hard" garbage so much i feel insane</p> <p>but, we wanted casual players and supergamers to both have fun</p> <ol> <li> <p>for casual gamers, the goal is to beat the bosses and finish the game. you have a huge health pool so it's very forgiving, but this means even casual players can see and experience the final boss and say they fully completed it. (in retrospect this was actually too casual, they had too much hp)</p> </li> <li> <p>for supergamers, the goal is to beat the dev times. getting hit increases your time hugely, so it incentivises never getting hit once - a very supergamer thing to do! this became a lot of people's reason for mashing replay</p> </li> </ol> <p>some absolute viking got this time:</p> <p><img src="https://toffeee.com/posts/ferra-retrospective/WR.png" alt="" /></p> <h1 id="art-direction">art direction</h1> <p>i had a few director-y moments which i was satisfied with</p> <p>art direction is hard, we talked about making the bosses huge scrappy mechs, but the ideas just weren't gelling with me.. i just don't have the big mech gene in me</p> <p>i had a meltdown and then just settled for something i always do, which is draw cute girls. i think leaning into things you unapologetically enjoy is good rather than going for.. whatever's sensible? or expected? and i love the juxtoposition of normal-looking characters being badass or having huge weapons</p> <p>i unashamedly love homogeneous color palettes - for ferra, every color on screen is color-picked from a pic of a molten iron crucible. i think it suited the vibe well</p> <p><img src="https://toffeee.com/posts/ferra-retrospective/coolness.png" alt="" /></p> <p><img src="https://toffeee.com/posts/ferra-retrospective/kai.png" alt="" /></p> <p><img src="https://toffeee.com/posts/ferra-retrospective/concept.png" alt="" /></p> <h1 id="music-direction">music direction</h1> <p>miredly carried the music department and got a stream of compliments for the music.</p> <p>my 1 contribution which was the sort of "seed" of the vibe we wanted for this game. i gave them this;</p> <p><a href="https://youtu.be/HD4dUMDWM58?t=182">https://youtu.be/HD4dUMDWM58?t=182</a></p> <p>the rhythmic, mechanical vibe of it just suited the idea of clunky mechs and big machinery so well</p> <p>they took that locus and made it way better than i imagined, the soundtrack rocks. having this one vibe-y point of reference kept the whole game singing in the same tune and made it feel coherent</p> <h1 id="but-yea">but yea</h1> <p>im so so so so stoked to have something released after so long. it was hard work, but it's almost given me more energy to work harder in future</p> <p>qiolp;578dfopa'u,t;klguedkl;jtg;t'asjtg'dashng'lah4tyl;dfe;hdk;lh;lkl;ghl;ksdhg;shdkghs yknow what i mean</p> superpermute at light speed!!!! Fri, 13 Jan 2023 00:00:00 +0000 Unknown https://toffeee.com/posts/light-speed-superpermute/ https://toffeee.com/posts/light-speed-superpermute/ <p>i made a quick 2hr clone of geometry wars 3 pacifist mode. i just wanted to get back into the swing of programming relatively finished games after spending a while making tech demos</p> <p>heres the first version:</p> <p><video src="bad.mp4" controls preload="metadata"></video></p> <p>it sucked really bad, it was not fun</p> <p>but the insidious issue with this game is that <strong>it seriously does implement every "core" feature of the game.</strong> it has enemies that spawn and chase you, it has gates that you move through, and they explode when you go through them. it is exactly what id consider to be a stripped-down-but-topologically-equivalent version of Geometry Wars 3 Pacficist mode</p> <p>if i were to make a prototype to show off my own game idea, id do the same thing - strip the game down to what i believe to be the "core", then implement those features, then see if its fun ive done this with multiple games, and discarded a huge amount of them because of this</p> <blockquote> <p>"if the games not fun even when stripped to its most barebone state, it likely wont be fun in future." <small>— Gaming Yoda</small></p> </blockquote> <p>but, i knew that the final polished version of geometry wars 3 was fun, so i had an absolute concrete example that this topology can be made fun. so i kept working on it</p> <p>i added things that seemed to me, completely worthless on paper.</p> <ul> <li>slowed the player down</li> <li>sped the enemies up</li> <li>make enemies drop points you can collect</li> <li>make the gates spin</li> <li>make enemies spawn from corners</li> </ul> <p>all of these things feel almost like "design bugfixes" to me. theyre tiny little things that make the game feel a little bit better, but ultimately are tweaks or minmaxing for a game that is already fun and has a solid core</p> <h2 id="however">however!!!</h2> <p>i implemented them, lets take a look now</p> <p><video src="geometry.mp4" controls preload="metadata"></video></p> <p>it still doesnt look like much, but suddenly the game was absolutely addictive. i wanted to add more polish but i couldnt stop playtesting, it really did become a game where you mashed replay as soon as you died</p> <blockquote> <p>so what the hell happened?</p> </blockquote> <blockquote> <p>i have no idea and i still dont</p> </blockquote> <p>though this left me with a very valuable practice; when prototyping, you really have to believe in the idea and try your best to make it fun and give it multiple shots; add one thing, take away another, shuffle the parameters around, add a timer, add points, pickups</p> <p>yknow? simple, game-y stuff that, and the best part is that these things are really really fast to code. if you add this feature and it becomes a little more fun, then you're heading in the right direction, and you can keep going</p> <p>after all, the reason you started prototyping a game is because you came up with a game idea that you want to play, right? the fun will be buried in there somewhere. i dont know about anybody else but i need to give more respect to my ideas and dig a little deeper</p> <blockquote> <p>"when looking for treasure, its no use just glancing over the shore and calling it a day, you gotta get your shovel and start digging bitch!!" <small>— Gaming Yoda again</small></p> </blockquote> failing to fail fast; prototyping Sun, 18 Dec 2022 00:00:00 +0000 Unknown https://toffeee.com/posts/failing-to-fail-fast/ https://toffeee.com/posts/failing-to-fail-fast/ <p><img src="https://toffeee.com/posts/failing-to-fail-fast/whatwentwrong.png" alt="" /></p> <p>this happens a lot!!</p> <p><a href="https://www.youtube.com/watch?v=GhTAoilsFUs">https://www.youtube.com/watch?v=GhTAoilsFUs</a></p> <p>the video is really good, watch it! it showcases what i think is the main incredible failure of most indies, studios and even a lot of AAA;</p> <p>a lot of devs when they start projects only have a reaaaaaally vague idea of what they want, and dive right in. this is especially bad in this case where he started out by making his own freaking c++ voxel engine for it!</p> <p>but this also coincides with the stories i hear from friends in the indie industry, where devs figure out a goal, and a mechanical genre, and just get to work on what will eventually be their final product. then they make it, find out it's not that fun, and try to permute it while it's pretty much carved in stone by method of unmalleable architectural patterns, which of course fails</p> <p>a lotta ppl treat the design for a game as a quick forethought, seeing game creation as purely a technical challenge and not a design one. "if i can just implement this, this this... then it'll be a fun finished game!"</p> <p>it's like the analogy that gamedev is like "exploring," but before you even know where you're going, you've started building a road</p> <p>this is how games used to be made - there actually wasn't even a "game designer" role, it was all thought out by the programmers, which of course there's a raph koster talk about all that</p> <p><img src="https://toffeee.com/posts/failing-to-fail-fast/raph.png" alt="" /></p> <p><a href="https://www.youtube.com/watch?v=Oua_fTlRf50">https://www.youtube.com/watch?v=Oua_fTlRf50</a></p> <p>(he mentions it somewhere in this talk but i forget where so guess youre gonna have to watch the whole thing!! ;P)</p> <h1 id="fucking-it-up-at-an-unprecidented-rate">fucking it up at an unprecidented rate</h1> <p><img src="https://toffeee.com/posts/failing-to-fail-fast/yoda.jpg" alt="" /></p> <p>because game design is a barely-charted and unironic graybeard hyperskill which literally nobody has a concise measurable grasp on yet, the easier way to arrive at something cool is to just make <strong>a ton</strong> of garbage using your gut instinct and seeing what sticks. but a huge emphasis on "a ton". make a lot of tiny garbage games and reflect deeply on what worked and what didn't <small>(which is why ive actually been making retrospectives! theyve helped)</small></p> <p>as such, you'll want to stick with tools that let you make things as fast as possible, so just work with what you're fastest with, and only once you've got a full functional and fun game, then you can make your C++ voxel engine or something <small>(*of course unless youre just learning and the game is secondary to the engine)</small></p> <p>this is similar to the "tracer bullet" paradigm described in the pragmatic programmer book by andy hunt &amp; dave thomas; make something which feels correct, test it with other people (!!!), and see if youre going in the right direction</p> <p>make your decisions based on one measurable facet; how quickly and shittily can you make this game and demonstrate the core experience, while spending as little time as you can on it knowing that you're going to throw the whole thing away</p> <p>the one thing a lot of people get wrong about <a href="https://www.youtube.com/watch?v=UvCri1tqIxQ">minimum viable products</a> is that they aren't making anything minimal, and theyre instead viewing it through a lens of "this is a demo" as in, a small slice of what will be their final game, which you really don't want it to be</p> <p>from my own experience and stories passed to me, prototypes best serve ONLY to be its own standalone piece of shit that happens to have the same soul as a brand new product you want to make in future. its designed to be thrown out at the end, and likely not extended upon. even if you <em>could</em>, it'd be so much better to re-write your code now knowing exactly what you're aiming for, and it'll be 100x neater, and you'll get it done super fast</p> <p>so ya thats why i have 1000 unfinished projects lol wowoow</p> deconstructed fighter retrospective Mon, 05 Dec 2022 00:00:00 +0000 Unknown https://toffeee.com/posts/retrospective-fighter-deconstruction/ https://toffeee.com/posts/retrospective-fighter-deconstruction/ <p>paosditygasfdio;yhtglkadfhtl;q3h4poghdfc</p> <p>this post doesn't really have much useful information on it but i want to log the creation of this game for prosperity, please bear with me!</p> <p><img src="https://toffeee.com/posts/retrospective-fighter-deconstruction/ex.jpg" alt="" /></p> <h2 id="hypothesis">hypothesis</h2> <p>i think fighting games rock, but it's 1v1 modes haven't diverged that far from the main formula discovered in street fighter 2</p> <p>raph koster made a really interesting point that fighters are essentially rock/paper/scissors played on an axis</p> <p><a href="https://youtu.be/zyVTxGpEO30?t=1430">https://youtu.be/zyVTxGpEO30?t=1430</a></p> <p><img src="https://toffeee.com/posts/retrospective-fighter-deconstruction/raph.png" alt="" /></p> <p>playing fighters since forever, this rock/paper/scissors analogy is totally true. pretty much every option has a well-defined way to beat it — you can anti-air jumps, you can jab slow overheads, etc. all that matters is having the gamesense to know what's coming out at what time and being proactive, or being fast enough to be reactive. it's an environment where you don't have time to sit and meditate on your response to an opponent's actions, so your body is constantly bordering conscious and subconscious operation which means you - human being - will play out predefined patterns, and your opponent can adjust their behaviour accordingly</p> <p>there's been many games that diverge from this formula and are incredible, like divekick, lethal league, and recently yomi hustle</p> <p>yomi hustle is godlike and a successful experiment in removing that immediate reactive time pressure, deconstructing the genre and reconstructing it into a turn-based game — it still has that insane fighting game spirit of prediction, learning what moves you can string together to optimize your output off of a correct read, and so on. it cuts the need for time-based execution and keeps a lot of fighting game ideas intact like combos and mindgames</p> <p><a href="https://ivysly.itch.io/yomi-hustle">https://ivysly.itch.io/yomi-hustle</a></p> <p><img src="https://img.itch.zone/aW1hZ2UvMTc4NTU1NS8xMDQ5Mzg2OC5naWY=/347x500/5nWKfg.gif" alt="" /></p> <p>divekick is also a nuts deconstruction of fighting games, you get literally 2 moves. its a distillation of the last few tense seconds of a match where both players are at 1hp</p> <p>it essentially becomes completely reaction, mindgames and each character's unique movement. this game made it super far, having regular tournaments of people who were doing stuff that looked insane, so this was a super successful experiment too</p> <p><img src="https://cdn.akamai.steamstatic.com/steam/apps/244730/ss_b8e37d450375530364b09ff034026a4f692af728.1920x1080.jpg" alt="" /></p> <p>so is it possible to make a new deconstruction that removes both intense timing-based execution and combos, but tries to keep realtime mindgames, and still be fun?</p> <h2 id="the-game">the game</h2> <p>i made a fighter that is quite literally rock/paper/scissors</p> <p>you have 3 moves: <strong>punch, parry,</strong> and <strong>grab</strong></p> <p><img src="https://toffeee.com/posts/retrospective-fighter-deconstruction/chart.jpg" alt="" /></p> <p>punch beats grab, grab beats parry, parry beats punch. this is the RPS, and the axis is the 2 dimensions of movement</p> <p>jumping in this game is a huge commitment. you can't change your direction during a jump, but you can still attack as a counter to a ground attack</p> <p>one thing i wanted to capture is an idea that comes from smash where characters can get a KO very very early. i wanted that same vibe, but sticking to the ground - so i wanted to go for a sumo-style game where you KO your opponent if you push them into a wall. rather than decrease health or increase knockback percent, all attacks push your opponent back closer to this wall, where they can take risk to get back to safety, or stay in this tense disadvantagious spot</p> <h2 id="playtesting-the-finished-game">playtesting the finished game!!!</h2> <p>the majority of the work for this game was the shift to 3D (!!! which is hard when you're working in a framework built for 2D lol), and a refactor of the rollback netcode container. the rollback rewrite was to fix an off-by-one issue. turns out that happened due to some internal game state not being serialized correctly but i reduced the size of the rollback container by 50%!! so big win regardless</p> <video controls> <source src="example.mp4" type="video/mp4"> </video> <p>big thanks to geni and ceroribi for playtesting this with me &amp; giving feedback!</p> <p>i was surprised that the game already felt pretty fun! on paper it feels like it should constantly be a game of random chance, but it's very clear that you can get good at this game and be better than the opponent, which is great. the slow-paced deliberate (and clunky) feeling is great. it rewards patience and mindgames over quick reflexes, execution and button-mashing. if you press a random button, you will very easily get punished for it</p> <p>the sumo-style works very well, you can safely control centre stage or hover around a wall to get a quick kill, while being at a huge risk yourself. you get used to the clunkiness, but it is missing some simple game-feely stuff, like vfx, sound, and animations that aren't terrible(!!!). i feel like if this game was given a budget, it could be a fun small argument-settler</p> <h2 id="feedback">feedback</h2> <ol> <li> <p>the game has traditional blocking where if you hold "back", you don't get hurt. this sucked, we already have a defensive option of parrying. blocking is too little risk. we can remove this</p> </li> <li> <p>crouching punch isn't worth anything, the focus definitely wasn't on mixing up high/lows. instead we can turn this crouch punch into an uppercut anti-air</p> </li> <li> <p>as a counter to the uppercut anti-air (and also an extension to the sorta limited options you have while you're airborne), we should be able to both parry and grab while in the air</p> </li> <li> <p>you should be able to dash while in the air</p> </li> <li> <p>charged attacks! if you anticipate your opponent reacting with a parry to your punch, you can charge it and wait for the parry to end to release it. if ur opponent anticipates your charge, they can grab you or wait out the parry. like smash!</p> </li> </ol> <p>im pretty happy with this project, which is nice, since partway through i was certain this idea didn't work at all and was pretty bummed about my efforts. im still unsure, but friends playing it and having a nice time was really reassuring, so im trying to power through that feeling a little more</p> <p>ill let it sit for a while before i refine it and apply these new ideas. thanks for coming!!</p> on not releasing a game in a while Mon, 21 Nov 2022 00:00:00 +0000 Unknown https://toffeee.com/posts/on-not-releasing-a-game/ https://toffeee.com/posts/on-not-releasing-a-game/ <p><img src="https://toffeee.com/posts/on-not-releasing-a-game/head.jpg" alt="" /></p> <p>i haven't released any kind of small game since 2020! it's mainly due to finishing my degree and going straight into working full time, but i still find the time. the most crippling issue now are my standards</p> <h2 id="analysis-poisoning">analysis poisoning</h2> <p>ive read a lot of books and watched a lot of lectures from the best minds in game design, and while its given me the tools to climb over walls when i run into them, its made my standard for myself skyrocket way past my ability. its almost like a re-introduction of paralyzing beginners-perfectionism</p> <p>now when im making a fun throw-away toy, it gets put through the thousand lenses of scrutiny given to me by great thinkers. lenses that should only be reserved for too-big-to-fail mass-appeal AAA game, and even then, most games that come out definitely don't go through that level of thorough thought. the designers make conscious sacrifices in some areas in order to elevate other areas - the important and most productive part is knowing what to chop.</p> <p>im still working hard on making a system deep enough for actual individual expression and that can be done with the most barebones of applied theories, so its really not helping to bog myself down in textbook methodologies and sciences applied only to games made to be a person's lifestyle, worth $60 upfront and a microtransaction-based subscription service thereafter</p> <p>so, how should indies think?</p> <h2 id="if-a-game-s-worth-making-then-its-worth-making-badly-albert-einstein">"if a game's worth making, then its worth making badly" - albert einstein</h2> <p>a lot of very productive people have an ethic of ignoring all academic-style* advice and going purely from gut instinct</p> <p><small>* this is what id describe textbook gamedev theory as, like jesse schell's lenses, or raph koster's theory of fun. or even anything that very clearly fits into a formula. you'd be able to describe some games as made literally by-the-book</small></p> <p><img src="https://toffeee.com/posts/on-not-releasing-a-game/tyler.png" alt="" /></p> <p><a href="https://twitter.com/TylerGlaiel/status/1555291147685113857">https://twitter.com/TylerGlaiel/status/1555291147685113857</a></p> <p>a lot of my very productive friends make cool stuff with this approach. even when ive recommended talks or books, theyve take it w a grain of salt because of a very specific sentiment that i see that a lot of artists share: they trust their gut, they want to have fun and explore, and they want to derive their own theory. innovate with a fresh mind, rather than hone on something they dont have a clear handle on yet</p> <p>this sorta mirrors a lot of artists journeys. you just start Drawing because there's ideas you want to express, and this just seems like the natural way to do it, yknow? this way its more likely you'll create stuff that comes from a pure, unfiltered place of passion. the gap between the spark and the reality you're trying to bridge is so incredibly thin and unobstructed that real art can almost spill out of you</p> <p>but theory is where the answers lie when you've ran into a problem you can't solve on your own, and solving that problem is important. its a bit of a common error to aliken it a recipe you need to know beforehand before starting to cook. its not a known routine to perfect and hone, its an area of innovation, you're trying to experiment, yknow?</p> <p>so, im going to try and kick myself out of this rut of feeling like im always working, but never having stuff to show for it. the hardest part of being in this situation is getting back into that "just make the damn thing shittily" mindset. so how can we do that?</p> <h2 id="how-to-make-things-that-suck-what-works-for-me-as-an-overly-self-judgemental-add-haver">how to make things that suck; what works for me as an overly-self-judgemental ADD-haver</h2> <ol start="0"> <li> <p>public hyper alpha. its even more alpha than alpha. it is barely the blurry thought of your game-to-be. but its something! if your game is mechanics-based, dont make art, make everything coloured blocks, and code it with no care for cleanliness - you'll likely scrap it later anyway. if your game is methodical, story-driven or heavily depends on art, dont code at all, look into making a paper prototype. even think to yourself - does it need to be interactive? could this game be a comic, or a book? can this meeting be an email? can this email be a Literally Nothing ?</p> </li> <li> <p>dont actually give yourself a deadline. it feels so bad and will make you sick of the game and incite panic-crunch. the unfinished game will always be looming over you until it's complete in its entirety and you'll have no idea when to put the pen down. instead, give yourself an exact set amount of time per day to work on this game, and accept you'll eventually get it done. the only thing you need to do today is that slot of time, then youre free.</p> </li> <li> <p>(1. cont.) doubling down on the first point. i cant stress this enough. i am talking in the realm of 10-30 minutes per day working on a game. you'll get it done faster than you think. draw a sprite or two, sketch out the design of a level, then call it a day and relax. my largest game project was done using this method and i did not feel the slightest bit burnt out on it, start to finish. i could work on it indefinitely.</p> </li> <li> <p>(1. cont. again) tripling down. if youre the kind of person that says "ugh thats so little time i could easily do more" NO!! *slaps your dick*. trust me its better than the 0 minutes you're doing. even if you become motivated and start doing sick all-evening sessions, you'll quickly fall back to doing 0 minutes a day again. you never burn out on brushing your teeth, right? so make it so small and effortless for yourself that you'll never burn out. motivation will never be an issue, because you dont need motivation to do a total pushover task like that.</p> </li> <li> <p>when i come up with a game, i very often play it in my head, and most often i get one recurring "clip" playing over and over. if you've got a very specific idea in your head, try and make literally exactly that thing first. the brain-to-reality process is usually very enlightening, and sometimes a little disheartening. at this point, you can probably tell if the game's worth continuing</p> </li> <li> <p>start before thinking about starting. if the thought "oh yea my game" even enters your head, immediately do the brain equivalent of blasting music so loud that you don't hear your brain trying to talk you out of getting work done. just open up aseprite or gamemaker or whatever and start doing stuff, its not hard once you're moving. fighting against your brain trying to talk you out of it is the hardest part of any task</p> </li> <li> <p>70% rule. when making decisions, choose one you know you'll be at least 70% happy with, and stick with it. be comfortable knowing that despite the fact it may not be the <em>best</em> choice, its a pretty good one for now.</p> </li> <li> <p>when its at all playable, get someone else to play it. even just the thought of someone else playing your game immediately brings you down to earth and you can tell if your game blows or not. if it's something you're embarassed to share, maybe its worth shuffling around a little more or figuring out why that is. all of my favourite games to this day did not have that initial embarassment of showing to friends.</p> </li> </ol> <h2 id="yea">yea!!</h2> <p>cool!!! im going to keep trying to make stuff. i still dont have answers for why i havent released anything in a while, but i think its due to my standards being higher. im sort of done with jam-sized minigames, they dont give me that much satisfaction anymore. but, a good game can still be technologically jam-sized. it all comes down to if you've made a system that is deep, explorable and talk-with-friends-about-it-able. vampire survivors hits this category and anyone could make a game like that - but the hard part was having the initiative to come up with something fun, then making the freaking thing, where so few people do.</p> <p>yayayayyayayayay</p> smash basketball retrospective Sun, 20 Nov 2022 00:00:00 +0000 Unknown https://toffeee.com/posts/smash-basketball/ https://toffeee.com/posts/smash-basketball/ <h2 id="the-game">the game</h2> <p>you're two stick guys fighting for control of a ball and have to dunk it in the other one's net. you can pick up the ball (and while you have it, you cant attack), and then release it as a throw or drop to put it in the other basket</p> <p>but! your opponent has to stop you. you have a full set of smash-style up/down/forward aerial and ground attacks, and a punchy parry system, which stuns the opponent for a second if you time it right. if you beat the other stick guy up enough to deplete their stamina, they're stunned on the ground for i think around 4 seconds</p> <p>that's it! that's the game so far. the ideal scenario would be a first-to-5-points type deal!</p> <h2 id="development">development</h2> <p>this game was so pleasant to make, no snags at all! just knuckled down for a few afternoons and re-used some old stuff. happy to do this several times over to refine the idea</p> <p>this was my first game where i absolutely swore off making any art for it at all until it's a complete game. i want there to be as little resistance as possible if i have to completely re-work the game at a fundamental level and throw out all the art assets</p> <h2 id="playtesting">playtesting</h2> <p>i played this with my friend (rei!) and it was hilarious, and the netcode feels AMAZING, she's in florida and im in the uk and it felt like there was no delay at all, even dashdancing didn't produce any typical rollback artifacts. im quite proud of it! the game itself needs a lot of work, but im happy! a successful alpha!!</p> <video controls> <source src="out.mp4" type="video/mp4"> </video> <h2 id="feedback">feedback</h2> <ol> <li> <p>the taunt was the best part of the whole game lmfao</p> </li> <li> <p>rei felt that when you get stunned, it lasts for way too long. you can score up to twice during that stun if you're quick enough!</p> </li> <li> <p>i felt the actual combat wasn't good, we just ran into each other spamming the attack button and any direction, since all attacks have a too-similar function my main thought is that a ton of these attacks are redundant - this isn't a game about combos or anything, it's primarily about movement, zoning, etc.</p> </li> </ol> <p><img src="https://toffeee.com/posts/smash-basketball/aaa.png" alt="" /></p> <h2 id="new-proposal">new proposal:</h2> <p>a game with a bigger focus on movement options and zoning and less on intricate attack options</p> <ol> <li> <p>twin-stick-shooter style ball throwing, where you can define the exact angle and power to throw at - which introduces a lot more skill and expression when hitting dunks (off the wall?! from THAT distance!? risky vs safe options etc)</p> </li> <li> <p>you can launch the ball at the opponent to knock them away</p> </li> <li> <p>but!! parrying a ball throw gives you control of the ball, so bait appropriately</p> </li> <li> <p>only one physical attack - a slash? punch? kick? knocks the opponent back. this one attack can change per character</p> </li> <li> <p>one special ability per character, which will lean into this "movement vs zoning" idea - like maybe a grapple hook, or fire-breathing which causes a hazardous area</p> </li> </ol> <p><img src="https://toffeee.com/posts/smash-basketball/tonky.png" alt="" /></p> <h2 id="concluzion">concluzion</h2> <p>i'll make a sketch for this another day but after having made and played this alpha, this idea seems like the right way to go, and seems way more fun. though, im getting much further away from a dream "fighting game" and more leaning into a quick 2-or-3-rounds party game im not sure how well that fits my vision of what i wanted to make or how confident i'd be releasing it, but i think it's an easy, fun thing to release as my first project</p> <p>though when it comes to network programming and making a game that is a little more complicated and exact than just scripting, Lua as a language is missing a lot.. I'd really like to have strong types and easier debugging. i might pull out all the networking logic into its own shared .dll and make two-way lua bindings for it, which might make things a LOT cleaner! it'd be a good amount of work, but definitely worth it if i'm going to make more networked games in future</p> <p>ive been working through ideas for this and i currently can't think of any permutation that isn't just Lethal League. i'll keep the networking code, but i think this idea needs a total re-do!</p> [Draft] Game Design - Hitstop in 2D Platformers Tue, 10 Dec 2019 00:00:00 +0000 Unknown https://toffeee.com/posts/gamedev-hitstop/ https://toffeee.com/posts/gamedev-hitstop/ <p>hitstop is this stuff:</p> <video controls loop autoplay> <source src="https://cdn.nulled.red/mastodon-nulled/media_attachments/files/002/765/675/original/c45bad978362e628.mp4" type="video/mp4"> Your browser does not support the video tag. </video> <p>&amp; youre probably sick of everyone talking about vlambeer talking about it -</p> <p>the little pauses when you land an attack on an enemy.</p> <p>Momodora has exemplarily punchy combat, and when viewing it in isolation it looks great.</p> <p>BUT, this method of <strong>gamefeel</strong> has one awful characteristic that people overlook a <em>lot</em>: it slows down the gameplay, and time-to-kill, to a crawl. i mean, it's <em>lag</em> by definition.</p> <p><em>NOT to mention the fact that in Momodora RUtM, enemies can APPROACH you during hitstop:</em></p> <p><img src="https://toffeee.com/posts/gamedev-hitstop/rdein.png" alt="" /></p> <p>BUT why did this error happen? this is actually.. a bit of a catch 22. And we'll discuss that later in this post</p> <h1 id="when-hitstop-is-great">When Hitstop is Great</h1> <p>hitstop is fantastic in lightning-fast games like 2d combo fighters t. skullgirls, blazblue. It even has the significant mechanical benefit of giving [whoever is popping off at the time] a leasurely few milliseconds to think out &amp; buffer their next attacks</p> <p><img src="https://toffeee.com/posts/gamedev-hitstop/blazblue.jpg" alt="" /></p> <p><em>but this isn't greatly needed when you have ONE attack, and the biggest decision you need to make is whether to hit or roll</em></p> <h1 id="when-hitstop-is-not-good">When Hitstop is Not Good</h1> <p>the main separator between games that benefit from hitstop and games that suffer from it are if the game is entirely reactive (fighting games) vs games that throw predefined patterns at you. An opponent in a fighting game does not follow a predefined pattern. Soulslikes <em>do</em>.</p> <p>most people would say that even in an overtly simple game like Momodora would benefit from hitstop, giving you better opportunity to buffer rolls or attacks</p> <p>BUT CONSIDER THIS:</p> <h3 id="learning-attack-patterns-to-press-ltrig-at-the-right-time-to-win"><strong>learning attack patterns to press Ltrig at the right time to win:</strong></h3> <p><img src="https://toffeee.com/posts/gamedev-hitstop/sekiro.jpg" alt="" /></p> <h3 id="learning-beat-patterns-to-press-lmb-at-the-right-time-to-win"><strong>learning beat patterns to press LMB at the right time to win:</strong></h3> <p><img src="https://toffeee.com/posts/gamedev-hitstop/osu.jpg" alt="" /></p> <p><span style="font-size: 4em">SEKIRO IS A RHYTHM GAME</span></p> <p>it's such a rhythm game that, it'd be UNDOUBTEDLY ruined by any form of hitstop.</p> <p>Imagine if in OSU, every time you Clicked Circle, the game and music would pause for a split second</p> <p>now Imagine in Sekiro, you've learned all the attack patterns, only for it to be chopped up and stuttered by vlambeer GameFeelBait and throwing you off completely</p> <p>THE SAME goes, even in small indie platformers. Unless a game uses a special kind of AI, ALL enemies and bosses in every game have patterns to learn.</p> <h1 id="humans-love-patterns-recognising-them">Humans Love Patterns &amp; Recognising Them</h1> <p>patterns are a lot of fun to learn for us. it's even more fun for your pattern-recognition to ascend beyond what we'd normally think of it; recognising a pattern in all patterns, and being able to predict - with a weirdly great level of accuracy - the following elements in a brand new pattern.</p> <p>this is what the dark souls "click" moment is. every boss you've bashed your head against &amp; every pattern you've learned so far suddenly overlap in your mind to form a Master pattern. and suddenly, dark souls is easy. you've gitted good. [&amp; i swear this is an actual phychological thing, i think it's called "thin slicing" t. past patterns infering future patterns]</p> <h1 id="optimisation-requires-constraints">Optimisation requires Constraints</h1> <p>AH, hitstop is great for fighting games, we know that.</p> <p>BUT, we're talkin bout Momodora, a single-player game. This opens up a lotta opportunities.</p> <h1 id="experiments-with-alternatives">Experiments with Alternatives</h1> <h2 id="minoria-freeze-the-world">Minoria: freeze the world</h2> <p>The issue with Momodora is that, to combat the feeling of lagginess, <strong>only the player and the enemy being hit is frozen in time.</strong></p> <p>In Minoria (the next game developed from the creator of Momodora RUtM), <em>EVERY</em> entity in the game is paused for a few frames.</p> <p>This tackled the problem of enemies approaching but a <em>lot</em> of people agree this contributed heavily to making the game feel clunky and unsatisfying.</p> <p><img src="https://toffeee.com/posts/gamedev-hitstop/minoria.png" alt="" /></p> <h2 id="freezing-only-the-hit-enemy">Freezing only the hit enemy</h2> <p>Stunning an enemy after an attack is classic soulslike, BUT what if you paused the enemy in time for a split second before applying your stagger animations and so on?</p> <p>This is something I'm planning to implement in my own game. Currently, I'm doing pretty normal hitstop stuff:</p> <video controls loop autoplay> <source src="https://cdn.nulled.red/mastodon-nulled/media_attachments/files/002/765/676/original/9f81091e7a6843f6.mp4" type="video/mp4"> Your browser does not support the video tag. </video> <h2 id="removing-it-entirely">Removing it entirely</h2> <p>Well, i'd take caution! Watch this video on Deaths Gambit:</p> <p><a href="https://www.youtube.com/watch?v=_jFbgoHyZnM">https://www.youtube.com/watch?v=_jFbgoHyZnM</a></p> <h2 id="other-forms-of-feedback">Other forms of feedback</h2> <ul> <li>particle effects on you and the enemy</li> <li>big punchy sounds (sekiro parry, street fighter parry, Doom big bassy badumf)</li> <li>flashing white (but actually DON'T do this!)</li> <li>making the damage dealt in your game intrinsically impactful. make an attack <em>do</em> something, make the baddy freakin fly across the room or something. using feel-tech like hitstop, screenshake etc on an attack that feels inherently unimpactful is worse than omitting it all together.</li> <li><strong>Touhou Luna Nights</strong> instead made characters SHAKE. <a href="https://www.sourcegaming.info/2015/11/11/thoughts-on-hitstop-sakurais-famitsu-column-vol-490-1/">Sakurai calls this damage vibration</a> and uses it in Smash bros!</li> </ul> <p>But, it's very context-sensitive.</p> <p>To tackle this problem properly, ask <em>yourself</em>, <strong>what is impact?</strong></p> <p>If I hit something with [weapon of choice], what would happen? In 2020, hit things. Deal damage and observe what it feels like.</p> <h1 id="conclusion">Conclusion</h1> <p>I love momodora</p> <pre style="background-color:#0f1419;color:#bfbab0;"><code><span>YATA - Today at 4:28 PM </span><span>and ohhh nice </span><span>idk how i feel about the uh </span><span>slow mo hit </span><span>i know momodora kinda did it </span><span>and its to simulate I guess impact? </span><span> </span><span>TOFFEE - Today at 4:29 PM </span><span>oh yeah, it&#39;s called hitstop </span><span>idk how to feel about it either, ive exaggerated it too much but also a game called Deaths Gambit DIDNT have it and it fkn sucked sometimes because of it </span><span> </span><span>YATA - Today at 4:29 PM </span><span>i&#39;ll be honest i didnt like it when i played momodora but thats just me personally lmao </span><span>and fair </span><span>i feel like it makes the overall combat kinda off{? </span><span> </span><span>TOFFEE - Today at 4:30 PM </span><span>huh yeah it sorta slows combat down a ton, dya think it&#39;d work better if it was a one-hit-kill? </span><span> </span><span>YATA - *logs off* </span></code></pre> Lumi Game Creator - Retrospective Thu, 29 Aug 2019 00:00:00 +0000 Unknown https://toffeee.com/posts/lumi-retrospective/ https://toffeee.com/posts/lumi-retrospective/ <p><em>Being burned out on this project means this post is pretty spruceless. Sorry in advance!</em></p> <!-- why i'm stopping development --> <h1 id="finished-ish">Finished-ish</h1> <p>So it's practically the end of the month hello! It's been fun to dive into a really large-scale project like this for the first time in a while.</p> <p><strong>Here's the result so far: (it's a video)</strong></p> <video controls> <source src="https://cdn.niu.moe/media_attachments/files/006/915/642/original/ced2fa4bfef74e27.mp4" type="video/mp4"> </video> <p>It's basic and doesn't look much but it does the things I want it to do!</p> <ul> <li><em>Loading and saving</em> a special .lumi filetype.</li> <li><em>Editing those files</em> to do <em>different stuff</em>.</li> <li><em>Running the game</em> straight from the editor!</li> </ul> <p>From here on out it's really just grunt work to add more Lua hooks in the engine, push more editor features and generally make things look prettier <strong>BUT I AM SO BURNED OUT</strong>. I did some not-good-praxis when working on this generally working in huge <em>10-hour sprints</em>, sleeping then dreading the idea of the next big <em>10-hour sprint</em>.</p> <p>(To bolster how not-good this is Stefan Mischook sensei recommends to work <a href="https://www.youtube.com/watch?v=g9Az2GdCImY">shorter amounts of time when doing studies.</a> Like "45mins/1h a day" shorter.)</p> <p>So I've dropped it for now and I felt pretty awful about it until my friend Josh told me (and I'm paraphrasing like crazy):</p> <blockquote> <p>It depends on if its a personal learning exercise or if it's something you seriously want people to use. If you started it to improve yourself once you learn what you set out to learn move onto something else.</p> </blockquote> <p>Thank you Josh ily.</p> <h1 id="design-flaws">Design Flaws</h1> <!-- design flaws --> <p>You know the tab system? It was awesome until I had to stop and think of where to put everything pertaining to sprites. I checked GMS for <em>&gt;inspiration</em> and a pretty solid argument for using windows over tabs sprung up.</p> <div class="post-image"> <a href=".&#x2F;gms1.png"> <img src=".&#x2F;gms1.png" alt="The Sprite Editor in the GameMaker Studio IDE, mouse hovered over &#x27;Modify Mask&#x27;" title="The Sprite Editor in the GameMaker Studio IDE, mouse hovered over &#x27;Modify Mask&#x27;"> </a> </div><div class="post-image"> <a href=".&#x2F;gms2.png"> <img src=".&#x2F;gms2.png" alt="Clicking on &#x27;Modify Mask&#x27; brings up a separate child window to modify the sprite&#x27;s collisions." title="Clicking on &#x27;Modify Mask&#x27; brings up a separate child window to modify the sprite&#x27;s collisions."> </a> </div> <p>Notice what happened? This is a very good method of abstraction. Users traverse through a tree-like-structure of editors and sub-editors. Start at the root (Sprite Properties editor) you can branch off into hitbox editing (Modify Mask) or subimage management (Edit Sprite) and so on.</p> <p>This wouldn't work with a tab system where concerns are completely separated like a list of single nodes where each of them can be modified in isolation. <em>Game assets do not lend themselves to this idea. They're much much too complicated.</em> You realize that it's not a list but a list of lists (which themselves contain lists (which might also have a list)). There's a LOT of nested abstraction because games are complicated and concerning yourself with <em>everything about a particular asset at once</em> is overwhelming.</p> <p>So do tabs suck? We chose them for a few pretty good reasons. There's always a solution without completely scrapping the idea, and while windows still seem like too much to me, GameMaker Studio 2 puts forward a pretty great solution:</p> <div class="post-image"> <a href="gms2_abs.png"> <img src="gms2_abs.png" alt="GameMaker Studio 2&#x27;s node system." title="GameMaker Studio 2&#x27;s node system."> </a> </div> <p>It's just like the window system but the window's parent and <em>branching</em> abstraction is much more explicit. Coupled with it's own tab system you can see us and the creators had similar ideas regarding tabs and ran into the exact same roadblock.</p> <p>But this doesn't really fix our <em>"there's too mdany got ddang windoes"</em> problem, so as an alternative (knowing the limits of what I can do with GUIs so far) I'd probably opt for a nested tab system like we had in the room editor:</p> <div class="post-image"> <a href="nested_tabs.png"> <img src="nested_tabs.png" alt="The room editor we made a few posts back displaying nested tabs." title="The room editor we made a few posts back displaying nested tabs."> </a> </div> <p>As for other UX flaws, there's already a lotta text here so I'll save the discussion on other much more complicated problems. Maybe another time!</p> <h1 id="what-i-learned">What I Learned</h1> <!-- what i learned --> <p>This was a surprisingly good practice in gang-of-four-style <strong>design patterns</strong> considering it was a GUI framework study. There's a pretty huge problem to solve when you're working with GUIs <em>for example</em> consider your main window has an instance of a class that manages a certain part of your GUI but those GUI components are only accessible from your main window.</p> <p>It might be obvious how to solve this at first such as subclass dependency injection but making it as maintainable as possible was my top priority so injections-in-injections seemed like something to avoid. This lead me to find out about a few patterns such as <strong>the Singleton pattern and before I say anything else oh my god don't use this pattern.</strong></p> <p>My main window UI was only going to have one instance and I need access to it from a lot of places right? A singleton pattern makes too much sense! Where's the problem?</p> <p>The problem: <strong>it <i>was</i> used in a lot of places</strong>. Many different subclasses modified a single part of the GUI which even if you're OK with violating the Single Responsibility Principle (for the sake of prototyping I swear) is something who's effects become more apparent only when you're in the thick of it. Common behavior kept being re-implemented and things got inconsistent.</p> <p>In short, in comes the Facade pattern <em>:tada:</em> wherein this facade is an ultra-simple toolkit to do anything you need with GUI elements. This is created by the main window (where it's given access to <em>certain</em> UI components with limited functionality) and is what gets passed into these subclasses.</p> <p>A bunch of other stuff was experimented with but I'm overstaying my welcome with this post enough already.</p> <!-- future plans --> <h1 id="future-plans">Future plans</h1> <p>I think I'm just going to stick with Löve2D for my game projects ahaha. The things I've learned here may or may not lead to a nice level editor, but for sure it'll be a great boon for my future code's architecture.</p> <p>Thanks for reading this BIG update.</p> <p><em>:fire:</em></p> Lumi Game Creator - Making the editor Sun, 11 Aug 2019 00:00:00 +0000 Unknown https://toffeee.com/posts/lumi-editor/ https://toffeee.com/posts/lumi-editor/ <style type="text/css"> </style> <p>*** it's actually been 1.5 months since i started the engine, the extra half-month was spent fixing a bunch of bugs with the engine, cleaning up the code a little and displaying some more user-friendly error messages.</p> <p>this month (or, the remainder of this month plus the first 10 days of September) will be dedicated entirely to <strong>the editor!</strong> (im excited for this part. engines ive done but native interfaces are still a whole new minefield to traverse for me)</p> <p><em>we're still using GameMaker as the notsosubtle inspiration for this, so the interfaces we're gonna start out with will bear a striking resemblance to pre-studio-era GameMaker</em> but my argument to that is that loads of good ideas have started out as clones followed by a series of <em>wouldn't it be cool if's</em>. (<a href="https://store.steampowered.com/app/253230/A_Hat_in_Time/">my favourite game ever</a> started out the same way.)</p> <p>this month, the goal is to arrive at a pretty solid <strong>starting point.</strong> something that barely functions, but functions nonthetneless. here's what i want it to look like:</p> <div class="post-image"> <a href="editor_concept.png"> <img src="editor_concept.png" alt="a concept mock-up for the visual editor, displaying a room-editor tab." title="a concept mock-up for the visual editor, displaying a room-editor tab."> </a> </div> <p>immediately, you can derive two pieces of info from this mockup:</p> <ul> <li>im not good at mockups</li> <li>its literally GameMaker but.. something's different</li> </ul> <p><strong>a couple of things are different lets unpack this.</strong> GM imo has a few but very potent frustration-machines, and this mockup proves that at least <strong>one</strong> can be eliminated: <em>GM's weird window system!</em></p> <div class="post-image"> <a href="ugh_windows.jpg"> <img src="ugh_windows.jpg" alt="a screencapture of gamemaker&#x27;s window system, which is fine but... uhh" title="a screencapture of gamemaker&#x27;s window system, which is fine but... uhh"> </a> </div> <p>i have no idea who actually enjoys this system but i respectfully disagree. when youre in the midst of making something, it can get out of control pretty fast (at least from my own experience). visual noise is <a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5579811/">actually pretty good to have</a> sometimes, especially in creative spaces (unintuitively, you wanna <strong>avoid</strong> <em>clear space clear mind</em>), but not so much when it can potentially stomp all momentum by unwillingly swapping yourself from salvador dali beast mode or whatever to everything being buried under a hundred windows looking like a windows xp crash askin urself "ok what the heck was i doing where am i"</p> <p><strong>so, tab system! it's all tabbed.</strong> every specialised editor dialog will be held in a tab, kinda like most code editors. people are pretty used to things like google chrome, but not so much for the idea of a bunch of windows open at once.</p> <p>other changes will be a lot more evident when the program's really being used, but more on that another time <strike>when i work out what those changes actually are</strike>. pretty substanceless post this week, thanks for bearing through it just letting you know where this project's at.</p> <p>thanks for reading!</p> SDL2/Native GUI - How to embed an SDL2 context into a QT application. Sat, 03 Aug 2019 00:00:00 +0000 Unknown https://toffeee.com/posts/sdlgui-qt/ https://toffeee.com/posts/sdlgui-qt/ <h2 id="note-for-people-who-just-want-the-source-code-it-can-be-found-here">Note: For people who just want the source code, <a href="https://github.com/tfcat/qt_sdl">it can be found here</a>.</h2> <h1 id="preface">Preface</h1> <p>A while ago I made a post talking about <a href="/sdl-wxwidgets-interface/">embedding SDL2 into a WxWidgets UI</a>. It worked well but performance was pretty horrible, so I experimented further with different libraries. Turns out <a href="https://www.qt.io/">Qt</a> <em>(pronounced 'cute')</em> works alongside SDL very well, with a few hacks. Unlike last time, these hacks give you pretty sturdy results and best of all; hardware accelerated rendering.</p> <p>Let's make a really simple implementation.</p> <h1 id="the-parent-class">The Parent Class</h1> <p>We'll inherit from this class for every custom SDL widget we want to make.</p> <p>Here's the definition for our parent class.</p> <p><strong><i>* Please see the comments in the given code for more detail. This just makes everything a little easier to read.</i></strong></p> <pre data-lang="cpp" style="background-color:#0f1419;color:#bfbab0;" class="language-cpp "><code class="language-cpp" data-lang="cpp"><span style="font-style:italic;color:#5c6773;">// sdlwidget.h </span><span style="color:#ff7733;">#pragma</span><span> once </span><span style="color:#ff7733;">#include </span><span style="color:#c2d94c;">&lt;QWidget&gt; </span><span style="color:#ff7733;">#include </span><span style="color:#c2d94c;">&lt;QTimer&gt; </span><span style="color:#ff7733;">#include </span><span style="color:#c2d94c;">&lt;SDL2/SDL.h&gt; </span><span> </span><span style="font-style:italic;color:#5c6773;">/* If you&#39;d like, you can just write </span><span style="font-style:italic;color:#5c6773;"> * `#define MS_PER_FRAME 17` here since that&#39;s all this is doing, </span><span style="font-style:italic;color:#5c6773;"> * but I like making sure that the math is right (by not doing it myself). */ </span><span style="color:#ff7733;">#define </span><span style="color:#59c2ff;">FRAME_RATE </span><span style="color:#f29718;">60 </span><span style="color:#ff7733;">#define </span><span style="color:#59c2ff;">MS_PER_FRAME </span><span style="color:#f29718;">1000 </span><span style="color:#f29668;">/</span><span> FRAME_RATE </span><span> </span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">SDLWidget </span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">public </span><span style="text-decoration:underline;color:#59c2ff;">QWidget </span><span>{ </span><span style="color:#ff7733;">public </span><span>: </span><span> </span><span style="color:#ffb454;">SDLWidget</span><span>(QWidget</span><span style="color:#f29668;">* </span><span style="color:#f29718;">parent</span><span>)</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ff7733;">virtual </span><span style="color:#ffb454;">~SDLWidget</span><span>() </span><span style="color:#ff7733;">override</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="font-style:italic;color:#5c6773;">/* A custom repaint slot, I&#39;ll explain this later */ </span><span>public slots</span><span style="color:#f29668;">: </span><span> </span><span style="color:#ff7733;">void </span><span style="color:#ffb454;">SDLRepaint</span><span>()</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ff7733;">protected</span><span>: </span><span> SDL_Window</span><span style="color:#f29668;">*</span><span> window</span><span style="color:#bfbab0cc;">; </span><span> SDL_Renderer</span><span style="color:#f29668;">*</span><span> renderer</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ff7733;">private</span><span>: </span><span> </span><span style="font-style:italic;color:#5c6773;">/* To be overridden by child classes */ </span><span> </span><span style="color:#ff7733;">virtual void </span><span style="color:#ffb454;">Init</span><span>() </span><span style="color:#f29668;">= </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ff7733;">virtual void </span><span style="color:#ffb454;">Update</span><span>() </span><span style="color:#f29668;">= </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ff7733;">virtual void </span><span style="color:#ffb454;">OnResize</span><span>(</span><span style="color:#ff7733;">int </span><span style="color:#f29718;">w</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">int </span><span style="color:#f29718;">h</span><span>) </span><span style="color:#f29668;">= </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">; </span><span> </span><span> </span><span style="color:#ff7733;">void </span><span style="color:#ffb454;">resizeEvent</span><span>(QResizeEvent</span><span style="color:#f29668;">* </span><span style="color:#f29718;">event</span><span>) </span><span style="color:#ff7733;">override</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ff7733;">void </span><span style="color:#ffb454;">showEvent</span><span>(QShowEvent</span><span style="color:#f29668;">*</span><span>) </span><span style="color:#ff7733;">override</span><span style="color:#bfbab0cc;">; </span><span> </span><span> </span><span style="font-style:italic;color:#5c6773;">/* Overriding this method prevents the </span><span style="font-style:italic;color:#5c6773;"> * &quot;QWidget::paintEngine: Should no longer be called&quot; error. */ </span><span> QPaintEngine</span><span style="color:#f29668;">* </span><span style="color:#ffb454;">paintEngine</span><span>() </span><span style="color:#ff7733;">const override</span><span style="color:#bfbab0cc;">; </span><span> </span><span> </span><span style="font-style:italic;color:#5c6773;">/* Timer used to call the re-render method every 1/60th of a second */ </span><span> QTimer frameTimer</span><span style="color:#bfbab0cc;">; </span><span>}</span><span style="color:#bfbab0cc;">; </span></code></pre> <h1 id="implementations-of-parent-class-methods">Implementations of Parent Class methods</h1> <p>The parent class constructor (setting up the widget ready to render onto):</p> <pre data-lang="cpp" style="background-color:#0f1419;color:#bfbab0;" class="language-cpp "><code class="language-cpp" data-lang="cpp"><span style="font-style:italic;color:#5c6773;">// sdlwidget.cpp </span><span style="color:#ff7733;">#include </span><span style="color:#c2d94c;">&lt;sdlwidget.h&gt; </span><span> </span><span>SDLWidget</span><span style="color:#f29668;">::</span><span style="color:#ffb454;">SDLWidget</span><span>(QWidget </span><span style="color:#f29668;">*</span><span style="color:#f29718;">parent</span><span>) </span><span style="color:#f29668;">: </span><span style="color:#ffb454;">QWidget</span><span>(parent) { </span><span> </span><span style="font-style:italic;color:#5c6773;">// These widget attributes are important. This lets SDL take over what&#39;s </span><span> </span><span style="font-style:italic;color:#5c6773;">// drawn onto the widget&#39;s screen space. </span><span> </span><span style="color:#ffb454;">setAttribute</span><span>(Qt</span><span style="color:#f29668;">::</span><span>WA_OpaquePaintEvent)</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ffb454;">setAttribute</span><span>(Qt</span><span style="color:#f29668;">::</span><span>WA_NoSystemBackground)</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ffb454;">setFocusPolicy</span><span>(Qt</span><span style="color:#f29668;">::</span><span>StrongFocus)</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="font-style:italic;color:#5c6773;">// HOWEVER, this important attribute stops the &quot;paintEvent&quot; slot from being called, </span><span> </span><span style="font-style:italic;color:#5c6773;">// thus we&#39;ll need to write our own method that paints to the screen every frame. </span><span> </span><span style="color:#ffb454;">setAttribute</span><span>(Qt</span><span style="color:#f29668;">::</span><span>WA_PaintOnScreen)</span><span style="color:#bfbab0cc;">; </span><span> </span><span> </span><span style="font-style:italic;color:#5c6773;">// Create an SDL window from the widget&#39;s native handle. </span><span> window </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">SDL_CreateWindowFrom</span><span>(</span><span style="color:#ff7733;">reinterpret_cast</span><span>&lt;</span><span style="color:#ff7733;">void</span><span style="color:#f29668;">*</span><span>&gt;(</span><span style="color:#ffb454;">winId</span><span>()))</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ff7733;">if</span><span>(window </span><span style="color:#f29668;">== </span><span style="color:#f29718;">NULL</span><span>) </span><span> </span><span style="color:#ff7733;">throw </span><span style="color:#c2d94c;">&quot;Can&#39;t create window: &quot; </span><span style="color:#f29668;">+ </span><span>std</span><span style="color:#f29668;">::</span><span style="color:#ffb454;">string</span><span>(</span><span style="color:#ffb454;">SDL_GetError</span><span>())</span><span style="color:#bfbab0cc;">; </span><span> </span><span> </span><span style="font-style:italic;color:#5c6773;">// Create a renderer from the window. We&#39;ll use this for drawing all our stuff. </span><span> </span><span style="font-style:italic;color:#5c6773;">// (NOTE this doesn&#39;t have the VSYNC flag. </span><span> </span><span style="font-style:italic;color:#5c6773;">// It&#39;d cause HEAVY flickering, so we&#39;ll do our own vsync.) </span><span> renderer </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">SDL_CreateRenderer</span><span>(window</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29668;">-</span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">,</span><span> SDL_RENDERER_ACCELERATED)</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ff7733;">if</span><span>(renderer </span><span style="color:#f29668;">== </span><span style="color:#f29718;">NULL</span><span>) </span><span> </span><span style="color:#ff7733;">throw </span><span style="color:#c2d94c;">&quot;Can&#39;t create renderer: &quot; </span><span style="color:#f29668;">+ </span><span>std</span><span style="color:#f29668;">::</span><span style="color:#ffb454;">string</span><span>(</span><span style="color:#ffb454;">SDL_GetError</span><span>())</span><span style="color:#bfbab0cc;">; </span><span>} </span></code></pre> <p>Every frame, we want to update and display the <code>renderer</code> so it shows on screen. What we want to render in a frame may change depending on the widget, so for now we need a generic method that simply clears and presents the renderer.</p> <p>We'll call the virtual method "Update" in between. This method must be overridden by the child with user-defined behavior such as drawing squares or images.</p> <pre data-lang="cpp" style="background-color:#0f1419;color:#bfbab0;" class="language-cpp "><code class="language-cpp" data-lang="cpp"><span style="font-style:italic;color:#5c6773;">/* Our custom slot that we call </span><span style="font-style:italic;color:#5c6773;"> every frame with the frameTimer. */ </span><span style="color:#ff7733;">void </span><span>SDLWidget</span><span style="color:#f29668;">::</span><span style="color:#ffb454;">SDLRepaint</span><span>() { </span><span> </span><span style="color:#ffb454;">SDL_SetRenderDrawColor</span><span>(renderer</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">255</span><span>)</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ffb454;">SDL_RenderClear</span><span>(renderer)</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ffb454;">Update</span><span>()</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ffb454;">SDL_RenderPresent</span><span>(renderer)</span><span style="color:#bfbab0cc;">; </span><span>} </span></code></pre> <p>Now we'll define our event overrides which are part of the <code>QWidget</code> class we inherit from.</p> <pre data-lang="cpp" style="background-color:#0f1419;color:#bfbab0;" class="language-cpp "><code class="language-cpp" data-lang="cpp"><span style="font-style:italic;color:#5c6773;">/* Called when the widget is resized. </span><span style="font-style:italic;color:#5c6773;"> Calls the child&#39;s &quot;OnResize&quot; method */ </span><span style="color:#ff7733;">void </span><span>SDLWidget</span><span style="color:#f29668;">::</span><span style="color:#ffb454;">resizeEvent</span><span>(QResizeEvent</span><span style="color:#f29668;">*</span><span>) { </span><span> </span><span style="color:#ff7733;">int</span><span> x </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">static_cast</span><span>&lt;</span><span style="color:#ff7733;">int</span><span>&gt;(QWidget</span><span style="color:#f29668;">::</span><span style="color:#ffb454;">width</span><span>())</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ff7733;">int</span><span> y </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">static_cast</span><span>&lt;</span><span style="color:#ff7733;">int</span><span>&gt;(QWidget</span><span style="color:#f29668;">::</span><span style="color:#ffb454;">height</span><span>())</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ffb454;">OnResize</span><span>(x</span><span style="color:#bfbab0cc;">,</span><span> y)</span><span style="color:#bfbab0cc;">; </span><span>} </span><span> </span><span style="font-style:italic;color:#5c6773;">/* This method is an event called when our widget is created. </span><span style="font-style:italic;color:#5c6773;"> It calls the child&#39;s &quot;Init&quot; method and starts our frame timer, </span><span style="font-style:italic;color:#5c6773;"> which will call &quot;SDLWidget::SDLRepaint&quot; every frame. */ </span><span style="color:#ff7733;">void </span><span>SDLWidget</span><span style="color:#f29668;">::</span><span style="color:#ffb454;">showEvent</span><span>(QShowEvent</span><span style="color:#f29668;">*</span><span>) { </span><span> </span><span style="color:#ffb454;">Init</span><span>()</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="font-style:italic;color:#5c6773;">/* frameTimer will send signal timeout() every 60th of a second, connect to &quot;repaint&quot; */ </span><span> </span><span style="color:#ffb454;">connect</span><span>(</span><span style="color:#f29668;">&amp;</span><span>frameTimer</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29668;">&amp;</span><span>QTimer</span><span style="color:#f29668;">::</span><span>timeout</span><span style="color:#bfbab0cc;">, </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29668;">&amp;</span><span>SDLWidget</span><span style="color:#f29668;">::</span><span>SDLRepaint)</span><span style="color:#bfbab0cc;">; </span><span> frameTimer</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setInterval</span><span>(MS_PER_FRAME)</span><span style="color:#bfbab0cc;">; </span><span> frameTimer</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">start</span><span>()</span><span style="color:#bfbab0cc;">; </span><span>} </span><span> </span><span style="font-style:italic;color:#5c6773;">/* Override default system paint engine to prevent errors. */ </span><span>QPaintEngine</span><span style="color:#f29668;">* </span><span>SDLWidget</span><span style="color:#f29668;">::</span><span style="color:#ffb454;">paintEngine</span><span>() </span><span style="color:#ff7733;">const </span><span>{ </span><span> </span><span style="color:#ff7733;">return reinterpret_cast</span><span>&lt;QPaintEngine</span><span style="color:#f29668;">*</span><span>&gt;(</span><span style="color:#f29718;">0</span><span>)</span><span style="color:#bfbab0cc;">; </span><span>} </span></code></pre> <p>And lastly, our deallocator for our renderer and window. To keep it simple, we're not using SDL_Textures yet, but once you start using them, destroy them at this point.</p> <pre data-lang="cpp" style="background-color:#0f1419;color:#bfbab0;" class="language-cpp "><code class="language-cpp" data-lang="cpp"><span>SDLWidget</span><span style="color:#f29668;">::</span><span style="color:#ffb454;">~SDLWidget</span><span>() { </span><span> </span><span style="color:#ffb454;">SDL_DestroyRenderer</span><span>(renderer)</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ffb454;">SDL_DestroyWindow</span><span>(window)</span><span style="color:#bfbab0cc;">; </span><span>} </span></code></pre> <hr> <h1 id="a-custom-child-example">A Custom Child Example</h1> <p>Now we have a generic SDL widget which we can inherit from and do whatever we want with, like drawing images, shapes or even embedding games (given you know how you can implement an event loop from here).</p> <p>All we need to do with this child class is:</p> <ul> <li>let it inherit from SDLWidget.</li> <li>override the three virtual methods defined in the parent and then populate the implementations with our own behavior.</li> </ul> <pre data-lang="cpp" style="background-color:#0f1419;color:#bfbab0;" class="language-cpp "><code class="language-cpp" data-lang="cpp"><span style="font-style:italic;color:#5c6773;">// example.h </span><span style="color:#ff7733;">#pragma</span><span> once </span><span style="color:#ff7733;">#include </span><span style="color:#c2d94c;">&lt;sdlwidget.h&gt; </span><span> </span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">Example </span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">public </span><span style="text-decoration:underline;color:#59c2ff;">SDLWidget </span><span>{ </span><span style="color:#ff7733;">public</span><span>: </span><span> </span><span style="color:#ffb454;">Example</span><span>(QWidget</span><span style="color:#f29668;">* </span><span style="color:#f29718;">parent</span><span>) </span><span style="color:#bfbab0cc;">: </span><span>SDLWidget(parent) {} </span><span style="color:#ff7733;">private</span><span>: </span><span> </span><span style="color:#ff7733;">void </span><span style="color:#ffb454;">Init</span><span>()</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ff7733;">void </span><span style="color:#ffb454;">Update</span><span>()</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ff7733;">void </span><span style="color:#ffb454;">OnResize</span><span>(</span><span style="color:#ff7733;">int </span><span style="color:#f29718;">w</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">int </span><span style="color:#f29718;">h</span><span>)</span><span style="color:#bfbab0cc;">; </span><span>}</span><span style="color:#bfbab0cc;">; </span></code></pre> <p>Now we'll implement our custom behavior for this example widget. All this does is draw a red rectangle at the top left of our screen.</p> <pre data-lang="cpp" style="background-color:#0f1419;color:#bfbab0;" class="language-cpp "><code class="language-cpp" data-lang="cpp"><span style="font-style:italic;color:#5c6773;">// example.cpp </span><span style="color:#ff7733;">#include </span><span style="color:#c2d94c;">&quot;example.h&quot; </span><span> </span><span style="color:#ff7733;">void </span><span>Example</span><span style="color:#f29668;">::</span><span style="color:#ffb454;">Init</span><span>() {} </span><span> </span><span style="color:#ff7733;">void </span><span>Example</span><span style="color:#f29668;">::</span><span style="color:#ffb454;">Update</span><span>() { </span><span> </span><span style="color:#ffb454;">SDL_SetRenderDrawColor</span><span>(renderer</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">255</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">255</span><span>)</span><span style="color:#bfbab0cc;">; </span><span> </span><span style="color:#ffb454;">SDL_RenderFillRect</span><span>(renderer</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">new </span><span style="color:#ffb454;">SDL_Rect</span><span>{</span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,</span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,</span><span style="color:#f29718;">300</span><span style="color:#bfbab0cc;">,</span><span style="color:#f29718;">200</span><span>} )</span><span style="color:#bfbab0cc;">; </span><span>} </span><span> </span><span style="color:#ff7733;">void </span><span>Example</span><span style="color:#f29668;">::</span><span style="color:#ffb454;">OnResize</span><span>(</span><span style="color:#f29718;">int</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">int</span><span>) {} </span><span> </span></code></pre> <h1 id="one-more-thing">One more thing...</h1> <p>In your main file, make sure to initialise SDL.</p> <pre data-lang="cpp" style="background-color:#0f1419;color:#bfbab0;" class="language-cpp "><code class="language-cpp" data-lang="cpp"><span style="color:#ff7733;">#include </span><span style="color:#c2d94c;">&quot;mainwindow.h&quot; </span><span style="color:#ff7733;">#include </span><span style="color:#c2d94c;">&lt;QApplication&gt; </span><span style="color:#ff7733;">#include </span><span style="color:#c2d94c;">&lt;SDL2/SDL.h&gt; </span><span style="font-style:italic;color:#5c6773;">// undefine main otherwise SDL overrides it. </span><span style="color:#ff7733;">#undef</span><span> main </span><span> </span><span style="color:#ff7733;">int </span><span style="color:#ffb454;">main</span><span>(</span><span style="color:#ff7733;">int </span><span style="color:#f29718;">argc</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">char </span><span style="color:#f29668;">*</span><span style="color:#f29718;">argv</span><span>[]) </span><span>{ </span><span> </span><span style="color:#ffb454;">SDL_Init</span><span>(SDL_INIT_EVERYTHING)</span><span style="color:#bfbab0cc;">; </span><span> </span><span> </span><span style="font-style:italic;color:#5c6773;">// Your main QT application code.. </span><span> QApplication </span><span style="color:#ffb454;">a</span><span>(argc</span><span style="color:#bfbab0cc;">,</span><span> argv)</span><span style="color:#bfbab0cc;">; </span><span> MainWindow w</span><span style="color:#bfbab0cc;">; </span><span> w</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">show</span><span>()</span><span style="color:#bfbab0cc;">; </span><span> </span><span> </span><span style="color:#ff7733;">return</span><span> a</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">exec</span><span>()</span><span style="color:#bfbab0cc;">; </span><span>} </span></code></pre> <p>And now your application is ready to have an embedded SDL2 context. Let's make a simple form and promote a basic <code>QWidget</code> to your new <code>Example</code> class.</p> <p>This example will be using Qt Designer. Create a <code>widget</code> (in the <code>containers</code> section on the left side) and place it where you want your SDL context to be.</p> <p>We want to promote this widget to our new Example class.</p> <div class="post-image"> <a href="ss1.png"> <img src="ss1.png" alt="Right click the new simple widget and select &#x27;Promote to ...&#x27;" title="Right click the new simple widget and select &#x27;Promote to ...&#x27;"> </a> </div><div class="post-image"> <a href="ss2.png"> <img src="ss2.png" alt="Enter &#x27;Example&#x27; into the promoted class name box and click Add." title="Enter &#x27;Example&#x27; into the promoted class name box and click Add."> </a> </div><div class="post-image"> <a href="ss3.png"> <img src="ss3.png" alt="Once added, select your Example class entry and click promote.&#x27;" title="Once added, select your Example class entry and click promote.&#x27;"> </a> </div> <p>And there you have it, that should be all you need to get started!</p> <div class="post-image"> <a href="example.png"> <img src="example.png" alt="A QT window displaying an SDL widget which contains a red square in the top left corner." title="A QT window displaying an SDL widget which contains a red square in the top left corner."> </a> </div> <p>If you want, you can try this out with more complex behavior in the child widget, such as rendering a texture or moving blocks around using the arrow keys (hint: SDL_PollEvent works in your Update function!).</p> <p>Thanks for reading! <a href="https://twitter.com/aks38d">Tweet</a> at me if you have any questions.</p> <p><span style="color: #789922;">:wq</span></p> Lumi Game Creator - in France! & progress update Sun, 28 Jul 2019 00:00:00 +0000 Unknown https://toffeee.com/posts/lumi-update-001/ https://toffeee.com/posts/lumi-update-001/ <div class="post-image"> <a href="france.jpg"> <img src="france.jpg" alt="The view from my gîte&#x27;s balcony in sceaux-du-gâtinais, France." title="The view from my gîte&#x27;s balcony in sceaux-du-gâtinais, France."> </a> </div> <p><small>(having beers on this ^ balcony at night listening to the river and the lil otters is the best feeling ever)</small></p> <p>Hey! Hope you're enjoying your summer. Figured I'd make a quick progess update. <strong>The game engine concept <a href="/0-0-1-in-a-month/">discussed last month</a> (now called Lumi) is COMPLETE!</strong></p> <p><small>sort of.</small></p> <p>For the most part, the engine is complete. Another 15 minutes of work to register a couple of functions to the Lua scope and it'll be ready for production. However, I missed out one thing: This engine is coming with an editor.</p> <p>The editor was the whole reason I made this new engine, right? Well, the editor is still in the works <sup>1</sup>. I'm not sure if I should call it a success. I <em>did</em> make an engine in a month, but just not the full package I intended. The engine + editor package would take well over a month to produce, so I'm glad progress is being made this quickly. It's a success to me.</p> <hr> <small><sup>1</sup> This is code for "hasn't been started."</small> <hr> <h2 id="and-here-it-is"><strong>And here it is!</strong></h2> <br/> <div class="post-image"> <a href="cap1.png"> <img src="cap1.png" alt="Underwhelming image of my 2D game engine in action." title="Underwhelming image of my 2D game engine in action."> </a> </div> <h2 id="what-this-is-trash">"What? ?? this is trash"</h2> <p>You're right it is trash! Despite its looks, this demo proves that every single facet of the engine works. You'll just have to trust me on this one. Here's something less ugly:</p> <div class="post-image"> <a href="cap2.png"> <img src="cap2.png" alt="The test results for my engine, all being successful." title="The test results for my engine, all being successful."> </a> </div><hr> <p>Anyway, doubts aside. Project "0.0.1 by the end of the month" is a success!</p> <p>After 2 weeks time when I'm back from vacation, the new goal will be to <strong>complete the engine's editor in less than a month.</strong></p> <p>Using the results of a couple of experiments, I'll make a usable editor for this engine. Level creator, sprite editor, a text editor for Lua code, the whole works. I'll make a post about this when I begin to sorta, concretise what my goal is. The "GameMaker but with Lua" idea is perfect but I'm afraid of taking it too literally and recreating the GameMaker editor in every sense.</p> <p>Anyway, I'll think about it! I'll catch you later.</p> <div class="post-image"> <a href="swans.jpg"> <img src="swans.jpg" alt="View from my balcony, 5 swans are swimming by." title="View from my balcony, 5 swans are swimming by."> </a> </div> Lumi Game Creator - A Game Editor Proposal Thu, 04 Jul 2019 00:00:00 +0000 Unknown https://toffeee.com/posts/lumi-proposal/ https://toffeee.com/posts/lumi-proposal/ <p>Hey!</p> <p>At the end of June I made a native interface with a custom embedded graphical widget where the goal was to make a level editor for <a href="https://github.com/tfcat/Lava">Lava</a>.</p> <p><em>"For now, I'll keep looking for simple (preferably not raw OpenGL) solutions with hardware acceleration."</em> - and I found one! Turns out QT and SFML work very well together.</p> <p><small>I'm not a fan of SFML's <strong>very</strong> <em>object-y</em> approach <em>(and a few nit-picks t. sprites)</em>, but I'm a big fan of how simple the API is as a whole. Getting started was very easy.</small></p> <p>I created a generic graphical widget (a SFML window which inherits from - and adapts to - a generic QT widget) to inherit from and add specific behaviour per widget, which allows me to do things like this:</p> <!-- fix this graphic, change to gif --> <div class="post-image"> <video controls> <source src="https:&#x2F;&#x2F;cdn.niu.moe&#x2F;media_attachments&#x2F;files&#x2F;006&#x2F;915&#x2F;640&#x2F;original&#x2F;119cc3c20044dd73.mp4" type="video/mp4"> Your browser does not support the video tag. </video> <p><p>A video of my QT/SFML interface showing a user selecting tiles from a set and placing them onto a canvas to create a level.</p> </p> </div> <p>This was coming along very well, but I knew this project wouldn't be fruitful even when it's completed:</p> <p><a href="https://github.com/tfcat/lava">Lava</a> is something I'm not a fan of in any pillar. It's written in D (by far my favourite language ever, but nobody uses it) and it's just a thick abstraction layer around SDL with a few game-domain logical systems thrown in.</p> <p>You can find hundreds of thousands of projects exactly like this (better or worse) on GitHub in any language you can think of, all created to fit the author's intuition. At the fear of making another project that is just my own personal engine bespoke to fit my own intuition, working on this level editor for Lava (alongside turmoil while making <a href="https://twitter.com/aks38d/status/1124350014027857920">my own game</a>) has inspired me to make one last stab at a simple game engine.</p> <h1 id="the-engine-plan">The Engine Plan</h1> <p>Something like GameMaker. GameMaker is brilliant, but there are a good handful of changes I'd make to it. First of all, I'd-</p> <h3 id="gamemaker-but-with-lua"><em>"GameMaker, but with Lua"</em></h3> <p>Well, yeah! GameMaker, but with the utility of Lua would solve 90% of the problems I have with GameMaker.</p> <p>My goal is to make a 0.0.1 prototype of "GameMaker but with Lua" by the end of the month. Pretty much recreating GameMaker gives me a great reference to work from and the result will give me a great starting point. We can refine from there.</p> <div class="post-image"> <a href="tweet.png"> <img src="tweet.png" alt="Tweeting that I&#x27;ll have a usable 0.0.1 by the end of the month. I&#x27;ve read the hundreds of &#x27;don&#x27;t share your goals&#x27; articles, I&#x27;ve found sharing goals is fantastic for getting things done. Peer pressure is a hell of a drug." title="Tweeting that I&#x27;ll have a usable 0.0.1 by the end of the month. I&#x27;ve read the hundreds of &#x27;don&#x27;t share your goals&#x27; articles, I&#x27;ve found sharing goals is fantastic for getting things done. Peer pressure is a hell of a drug."> </a> </div> <p>I'm not sure how possible this is, but deadlines and accountability are great motivators.</p> <p>There are two pillars in mind for this engine:</p> <ol> <li> <p>The enemy of art is the absence of limitations. People are really, really good at making a lot with a little. Small sets of tools or concepts force people to be creative. <i><small>(t. Minecraft, Scratch, Pico-8, every game jam ever, the human era since the stone age, etc.)</small></i></p> </li> <li> <p>Iteration time is everything. This is much truer with creative hobbies, especially something as intangible as experiences. When beginners make programs, they'll run it for every new line they add to make sure it still works. When artists are planning out a painting, they make <a href="https://conceptartempire.com/intro-to-thumbnail-sketching/">thumbnails</a>.</p> </li> </ol> <p>There's a couple of ways to make game prototypes (like <a href="https://www.gamasutra.com/blogs/MarcoMignano/20160725/277766/Use_Paper_Prototyping_to_design_your_games.php">paper prototyping</a>) but nothing really beats playing a demo. Which is why seeing results quickly is everything. Slow results kill projects, killed projects kill souls.</p> <p>This engine and editor will accomodate quick prototypes as well as it can.</p> <p>(I've produced a small <a href="GME_DesignProposal.pdf" target="_blank">PDF</a> to act as a semi-formal plan.)</p> <h1 id="why-lua">Why <a href="https://www.lua.org/">Lua</a>?</h1> <ol> <li> <p>Lua is a game-hacker's first language. It's primary adopted purpose is to be the embedded scripting language in games <em>(Tabletop Simulator, Garry's Mod, Roblox)</em>. Folks that want to get into this field has probably heard of Lua.</p> </li> <li> <p>It's famous for being <em>nearly</em> <small>(looking at you, metatables)</small> fully learnable in less than 2 hours for anyone familiar with beginner-basic coding concepts.</p> </li> <li> <p>Lua is a programmatic "small toolkit". All languages share the primative concepts that make it a language (functions, arrays, etc). <strong>Lua is that, and <em>only</em> that.</strong> There are no (or very very few) fancy gimmicks or flourishes. It is a minimal language like no other.</p> </li> </ol> <h1 id="final-words">Final Words</h1> <p>That's all I have for you now! This post is getting pretty long, I could talk all day about this. The best thing I can do for now is get to work. I'll catch you later with a product in my hands.</p> <p>Thanks for reading!</p> SDL2/Native GUI - Making a SDL2.0/WxWidgets interface Thu, 06 Jun 2019 00:00:00 +0000 Unknown https://toffeee.com/posts/sdlgui-wxwidgets/ https://toffeee.com/posts/sdlgui-wxwidgets/ <p>hi! sorry i don't post much, here's a bit of a rant to get me back into the swing of posting more often.</p> <p>so the past ~2 months i've been on-and-off trying to tackle one problem that's been a total bitch to me: integrating an sdl2.0 context in wxwidgets. i want to create a 2d level editor for my own toy engines</p> <p>i know there's a couple of good 2d level editors out there already, like tiled, gleed2d, and ogmo, but they are all still very... manual. this could be a great, or rewally awful idea, but i want a 2d editor to have a way to import entities etc in your own custom way, and to let you make your own export templates. small thing, but it'd be awesome, and it only needs to be as complex as gamemaker's room-editor dialog.</p> <div class="post-image"> <a href=".&#x2F;0.png"> <img src=".&#x2F;0.png" alt="gamemaker&#x27;s room editor" title="gamemaker&#x27;s room editor"> </a> </div> <p>(with the exclusion of the "views" and "physics" tab too. seems actually kinda easy right? <small><i>..if i didn't completely swear off using electron, i'd have probably made this already...</i></small>)</p> <p>maybe if i had better luck with this project, it could be entirely extended into a humble open-source version of gamemaker. my engine (or end-game vision of it) accomodates that style sorta well, using Lua as a scripting language and following the same entity-based init/step/draw idea.</p> <h2>inmplemrnentation</h2> <p>following the same idea shown in this-&gt;&gt; <a href="http://code.technoplaza.net/wx-sdl/part1/">http://code.technoplaza.net/wx-sdl/part1/</a> set of tutorials, (but heavily modified so i could access sdl's renderer api which is way more flexible) i could make a super super basic image viewer.</p> <div class="post-image"> <a href=".&#x2F;2.png"> <img src=".&#x2F;2.png" alt="two sweethearts" title="two sweethearts"> </a> </div> <p>i'm proud of it! but it works in a pretty ass-backwards way, the viewport is a single bitmap, where the bitmap's pixels are replaced by the pixels in an sdl surface, which we can render to. it's pretty slow, so anything real-time (like moving/placing tiles) would look a little janky.</p> <p>so instead i tried to do something else which was extremely ass-backwards, but it <i>may</i> have worked better.</p> <p>the idea:</p> <ul> <li>create a wxwindow and embed it into our main application frame</li> <li>pass the window handle/hwnd into sdl_createwindowfrom(handle)</li> <li>instantiate a rendering context in the newly created window</li> </ul> <p>this... this seemed to sorta work at first, but then it didn't. that's it that's this whole blogpost i'm sorry there's not a happy ending. on creating the window and binding a renderer to the window's surface, it draws a pure white onto the screen - which is a good sign! it's not the system's default kinda-light-grey!</p> <div class="post-image"> <a href=".&#x2F;3.png"> <img src=".&#x2F;3.png" alt="" title=""> </a> </div> <p>but, that's all it could draw. absolutely all attempts to draw images, squares, or even clear the screen with a color didn't work.</p> <p><i>and that's it~!</i></p> <p>that's all i really have to say. i tried to do the same thing (the surface/bitmap trick) in lua but getting lua-sdl2 to work on windows was a nightmare, so i might retry it one day when i have the energy to get out my seat and boot up my laptop.</p> <p>thanks for reading! ill work on more interesting stuff soon</p> Unfinished Projects - Dark City Temple? Sat, 06 Apr 2019 00:00:00 +0000 Unknown https://toffeee.com/posts/unfinished-citytemple/ https://toffeee.com/posts/unfinished-citytemple/ <p>Progress with Gamemaker Studio 1.2:</p> <video controls> <source src="https://iscute.moe/media/12ed9629-67ad-47a0-a102-d67aaadf8d89/cap.mp4" type="video/mp4"> Your browser does not support the video tag. </video> <p>Progress with Love2D:</p> <video controls> <source src="https://iscute.moe/media/5441b744-78b2-4cdb-9b1e-abc467f2eaf5/cap2.mp4" type="video/mp4"> Your browser does not support the video tag. </video> <p>This game was for a jam, taken place 2 years after my first game White for Eevee's Games Made Quick jam.</p> <img src="./a.png"> <p>I came down with a heavy case of <i>What Engine Do I Use</i> blues and then proceeded to get nowhere. </p> <img src="./b.png"> <p>This became an exercise in Love2D (I was in love with Lua at the time) and using my predefined boilerplate library, Gloop! It was pretty easy to get to the point shown in the video, but in the end it was <b><i>design</i></b> decisions that were blocking progress.</p> <img src="./c.png"> <p>The new way of animating characters was fun. I've always done frame-by-frame hand-drawn stuff, but in this, I wanted to try out something that'd look smoother. It's.. a weird derivation of skeletal animation, where all parts of her body are placed using some weird, hyper-specific formula. In the end, it was a little hard to get right. I'd love to play around with this idea more one day.</p> <img src="./d.png"> <img src="./e.png"> <p>My largest design block were enemies. I had no idea what sort of threat would exist in this world up until a final boss. </p> <img src="./f.png"> <img src="./g.png"> <img src="./h.png"> <p>I just scratched stuff out, and got these. I liked the plague-doctor look.</p> <img src="./k.png"> <p>The idea for the story was to seep back into the world left off in the original game, left completely dark, white grass and snow. This'd be, some huge arbitrary number of years (trillions?) after the fact. You regain your sword, travel forward and find another, much less hectic plagued world.</p> <img src="./j.jpg"> <p>The final boss, I've only got written concepts on paper. The idea was to have her in a room with a giant metronome (?) which pulsed light every tick through a garden of white flowers before a wall with archways of shattered stained glass.</p> <img src="./i.jpg"> <p>But! It didn't get finished. Or barely started. I really like the style though, so it could be something I make in future. Thinking about making it entirely 3D, kinda like Journey but with melee combat and 2 mins long. Thanks for reading!</p> Unfinished Projects - HolyWater! Fri, 29 Mar 2019 00:00:00 +0000 Unknown https://toffeee.com/posts/unfinished-holywater/ https://toffeee.com/posts/unfinished-holywater/ <p class="gt"> > has so many unfinished projects, could start a series about them<br> > does </p> <p>It sucks when projects are dropped for reasons beyond your control. It sucks more when even the journey isn't shared, or even reflected on.</p> <p>Anyway here's me oversharing:</p> <img src="./testing.gif"> <p>Working on this was cool. Little bit edgy, little bit cute. Cool themes. The jam asked you to make a Metroidvania game (fav genre) in a month (least fav amount of time).</p> <p> It was the first time I've ever worked on a game <i>with someone else.</i> We got a narrative put together pretty quickly.</p> <p><strong>BUT</strong>, double the people == double the scope creep, especially both being Ideas People and all of the ideas being too darn fun to not include. The total narrative we came up with would take waaay more than a month.</p> <p>It was cancelled when me and my friend got hit by huge sudden workloads (which was perfectly timed, as if the universe was charging up a bigass Donkey Kong punch and let it rip right when we were both finally excited to start something.) </p> <p>Anyway, here's some cool juice:</p> <p>Intro music:<br/> <audio controls> <source src="https://iscute.moe/media/d92482dc-da22-409f-a360-a11eb6815bfc/intro.oga" type="audio/ogg"> Your browser does not support the audio element. </audio> </p> <img src="./testing2.gif"> <img src="./menu.gif"> <img src="./map.png"> <img src="./map_small.png"> <img src="./concept0.png"> <img src="./concept1.png"> <img src="./concept2.png"> <img src="./concept3.png"> <img src="./concept4.png"> <img src="./concept5.png"> <img src="./concept6.png"> <img src="./concept8.png"> <img src="./concept9.png"> <p>All assets and concepts free to a good home!</p>