Advertise with Googlier.com LÖVE • Community Blogs - The official community LÖVE blogs. http://blogs.love2d.org/ en Lövely Interviews - Midipixel on Warlock's Tower http://blogs.love2d.org/content/l%C3%B6vely-interviews-midipixel-warlocks-tower <div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/interview">interview</a></li><li class="taxonomy-term-reference-1"><a href="/blog-terms/ygor">ygor</a></li><li class="taxonomy-term-reference-2"><a href="/blog-terms/werther">werther</a></li><li class="taxonomy-term-reference-3"><a href="/blog-terms/midipixel">midipixel</a></li><li class="taxonomy-term-reference-4"><a href="/blog-terms/warlock">warlock</a></li><li class="taxonomy-term-reference-5"><a href="/blog-terms/tower">tower</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><div>In Lövely Interviews, I interview developers of LÖVE and LÖVE games. Today the LÖVE game <a href="http://store.steampowered.com/app/530370/">Warlock's Tower</a>&nbsp;by <a href="http://site.midipixel.com/en/">Midipixel </a>was released on Steam. I interviewed Ygor and Werther from Midipixel on the development of Steam's newest LÖVE game.</div> <div><img alt="" src="http://i.imgur.com/nRZOH2Z.png" style="font-size: 14px; width: 220px; height: 220px;" /><img alt="" src="http://i.imgur.com/QByy92g.png" style="width: 220px; height: 221px;" /></div> <div> <hr /></div> <div>&nbsp;</div> <div><strong>Tell us a bit about yourself. Who are you and what do you do?</strong></div> <div>We're <a href="http://site.midipixel.com/en/about/">Werther and Ygor</a>, two guys in their thirties, a musician/artist and a programmer, respectively. With our powers combined we make Midipixel, a Brazilian indie game company now existing for three years in a row. We make indie games, obviously, although we've done client work in the past. We participate in game jams as well (<a href="https://twitter.com/GBJAMofficial">GBJam </a>is our favorite) and the occasional experiment here and there. We're also part of a Rio de Janeiro collective of indie game developers called RING.</div> <!--break--> <div>&nbsp;</div> <div>&nbsp;</div> <div><strong>How did you learn about LÖVE, and what was it that made you start using it?</strong></div> <div>&nbsp;</div> <div>I first heard about it while I was doing my Computer Science M.Sc. at <a href="http://www.puc-rio.br/index.html">PUC-Rio</a>. PUC-Rio is where Lua was created, and having fell in love with the language there, LÖVE seemed a pretty easy to get into framework. I started doing some prototypes while working at my previous company (Nano Studio, which Werther was also a part of) and things always moved fast. I quickly discovered to be really productive using Lua and LÖVE.</div> <div>&nbsp;</div> <div><img alt="" src="http://i.imgur.com/jAB6sg1.png" style="width: 460px; height: 215px;" /></div> <div>&nbsp;</div> <div>&nbsp;</div> <div><strong>Congratulations on releasing Warlock's Tower! Where did it all begin, and how long did it take you to make it?</strong></div> <div>&nbsp;</div> <div>Thank you! By the time of this writing, Warlock's Tower is not yet released, so here's hoping nothing bad happens until then! It all began in October, 2014. Having just been released from a two-month hospital stay and feeling like life is short, I decided to use some of my recovery time to hack one of our old ideas. The first prototype was done in a week, I guess. We were pretty happy with it, sent it around to friends and family and everyone seemed to be having fun solving its puzzles. During 2015, however, we started doubting the project's potential and almost dropped it for another prototype of ours, but then November came and Warlock's Tower won two <a href="http://sbgames.org/">SBGames</a> awards, one of Brazil's major game development festivals, one for "Best Game Design" and another for "Best Developing Game". That was the sign we needed. We resumed working on the game and 2016 came and went as we spent most of it dealing with publishers (we talked to two of them before signing with <a href="http://www.whippering.com/">Whippering</a>, who currently publishes us), finishing the game's content, mobile ports and adding a Twitch integrated play mode. Whew!&nbsp;</div> <div>&nbsp;</div> <div>&nbsp;</div> <div><strong>What is the most important thing you've learned when creating Warlock's Tower?</strong></div> <div>&nbsp;</div> <div>Jeez, there are a lot of important things I learned while making this game! But I guess the most important one is: be an active part of the whole. I used to foolishly think that just by making something I was entitled to receive attention and praise for it. That by the sheer amazingness (if only!) of the thing I was creating, people would discover my work and recognize my effort and throw money at me. People will pay you attention, they will give you their time, but you need to reach out to them. Share screenshots, show how your game is evolving. Go to events and festivals, be a part of your local game developer gatherings (or start one yourself.) All the opportunities that came our way started with us making some sort of reaching out. If we hadn't submitted Warlock's Tower for the SBGames, we wouldn't have won. If we hadn't being posting screenshots of the game on Twitter, we wouldn't have been found by publishers, and pretty much no one would know about our game by now.</div> <div>&nbsp;</div> <div><img alt="" src="http://i.imgur.com/ObybtSm.jpg" style="width: 500px; height: 281px;" /></div> <div>&nbsp;</div> <div>&nbsp;</div> <div><strong>Was there a part/feature you really struggled with when creating Warlock's Tower?</strong></div> <div>&nbsp;</div> <div>Sure. One of the big ones was making the controls work for the mobile platforms. At first we tried a touch and drag approach, but the game's so movement focused that we couldn't avoid adding an onscreen directional pad. We also struggled to make our players understand the game's rules through the GUI. Warlock's Tower's interface was overhauled twice during development. A single (but very important!) rule regarding how gems restore your character's health was the sole reason for the second remake. We do have an incredibly better GUI today, but the sad part is that, honestly, we haven't felt that it particularly improved player's comprehension. It's a tough rule to explain through the GUI without having it heavily interfering with the game's experience. &nbsp;&nbsp;</div> <div>&nbsp;</div> <div>&nbsp;</div> <div><strong>Warlock's Tower is your biggest game yet. Did the scale of the project change your approach on programming or design?</strong></div> <div>&nbsp;</div> <div>Yes! Maybe every new project should challenge one's old, tested approaches, be it in programming or design. Warlock's Tower evolved in a more organic fashion, as I imagine happens in some way or another for every larger software project. Programming-wise, maybe due to LÖVE's lightweight, more library receptive architecture, I included more external libs in this project than I'm used to, which wasn't so much a deliberate change of approach but a production necessity. However, this proved fruitful, and I'd feel inclined to do this again working with LÖVE. Using Lua for a longer project certainly changed the way I code and think about code, somehow, and I'm sure many of its cool features will be sorely missed as soon as we start working again with more constrictive technology. In the end, it seems that Warlock's Tower changed me more than I changed for Warlock's Tower.</div> <div>&nbsp;</div> <div>&nbsp;</div> <div><strong>Do you already have plans for your next game, and if so what can you tell us about it?</strong></div> <div>&nbsp;</div> <div>All game developers (all creatives, really) have piles of ideas towering around, and we're no different in this sense. We have a favorite idea which we have been discussing for some time, but since it would lead us to another longer project, we most likely aren't going to be able to tackle it right away. We also need to evaluate Warlock's Tower's response, learn from its release before we can decide on where to go next. We have several jam games which certainly could become full projects in the future. We also had an interesting time implementing Warlock's Tower's Twitch features, and both Werther and I fondly consider making our next game a stream first game.</div> <div>&nbsp;</div> <div><img alt="" src="http://i.imgur.com/ENTZMt2.png" style="width: 500px; height: 355px;" /></div> <div>&nbsp;</div> <div><strong>Is there anything you really wish would be added/changed to LÖVE?</strong></div> <div>&nbsp;</div> <div>When I talk to people about LÖVE I usually say that its two weaknesses are 3D and cross-platform support. The first one is obviously not a weakness (since the framework is also called Love2d), but the second one really makes a difference nowadays when selecting a framework/engine. I'd love if making mobile LÖVE games were easier and if there were console ports available.</div> <div>&nbsp;</div> <div><strong>Thanks for answering all the questions, is there anything you would like to tell the readers?</strong></div> <div>&nbsp;</div> <div>Well, if any of you want to contact us, feel free to do it! Check out Warlock's Tower's <a href="http://midipixel.com/warlockstower">website </a>if you wanna know more about the game. Oh, and we're really active on Twitter, so if you wanna keep in touch, follow us there: <a href="https://twitter.com/ysperanza">@ysperanza</a> and <a href="https://twitter.com/w_midipixel">@w_midipixel</a>. We're constantly talking about games and we'll love to meet you there!</div> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/l%C3%B6vely-interviews-midipixel-warlocks-tower"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Tue, 31 Jan 2017 19:13:48 +0000 Sheepolution 53 at http://blogs.love2d.org Lövely Interviews - bartbes http://blogs.love2d.org/content/l%C3%B6vely-interviews-bartbes <div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/interview">interview</a></li><li class="taxonomy-term-reference-1"><a href="/blog-terms/bartbes">bartbes</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>In&nbsp;Lövely Interviews&nbsp;I interview developers of LÖVE and LÖVE games. And this time we interview bartbes. Together with <a href="http://blogs.love2d.org/content/l%C3%B6vely-interviews-slime">slime</a> he is one of the main developers of the LÖVE framework.</p> <p><img alt="" src="http://i.imgur.com/hthrHtF.jpg" style="width: 90px; height: 81px;" /></p> <hr /> <p><strong>Tell us a bit about yourself. Who are you and what do you do?</strong></p> <p>Starting off with the hardest question, I see. I'm <a href="http://me.bartbes.com/">Bart</a>, a long-time LÖVE<br /> developer — since <a href="https://www.love2d.org/wiki/0.6.0">0.6.0</a>, if memory serves — and otherwise boring student.</p> <!--break--> <p>&nbsp;</p> <p><strong style="line-height: 1.5;">H</strong><strong style="line-height: 1.5;">ow did you learn about LÖVE?</strong><strong style="line-height: 1.5;">&nbsp;</strong></p> <p>I'm not really sure, but I <em>think</em>&nbsp;this happened as a result of the game Crysis. See, Crysis came with an editor for the <a href="http://www.crytek.com/cryengine/cryengine2/overview">CryENGINE 2</a>, which used Lua. After playing around with the existing code, tweaking it a bit, and generally messing around with the editor, I googled for game engines using Lua. Yes, it was that simple.</p> <p>I should probably mention that it wasn't my first foray into programming, I started with QBasic on MS-DOS, and then later went on to (primarily) C++ programming. Using LÖVE was like a breath of fresh air, since all "games" I had made until then were text-based, and in 3 lines of Lua I had a window displaying "Hello, world".</p> <p>&nbsp;</p> <p><strong>Together with slime you're the biggest contributor to the LÖVE framework. Why did you start contributing and what kept you going?</strong></p> <p>I started contributing because... I'm not sure, actually. I think I heard <a href="http://blogs.love2d.org/content/l%C3%B6vely-interviews-rude">rude</a> and/or mike saying they were looking for help coding, and considering I knew C++, LÖVE was (and is) written in C++, and I was a cocky teenager, I volunteered. And it worked, I guess.</p> <p>As for what kept me going, I'd say it was probably a combination of free time (I was in high school at the time), fun and necessity. It was quite interesting to go from knowing how to get a compiler to accept your C++ code to knowing how a game engine works, I suddenly got to see everything from graphics to input to audio on a clean, readable codebase. I feel like these days I'm familiar with what goes on in most of LÖVE, but I've read ahead and will go into that in the next question. I also mentioned necessity, which I'm using fairly loosely here, but that was about the time that mike stopped contributing, and when rude had less and less time to work on LÖVE. I'm sure LÖVE would have been fine without me, but knowing I could easily become a driving force behind the project was a good motivator.</p> <p>&nbsp;</p> <p><strong>Are you and slime both specialized in certain modules/features or can you find your way through the whole codebase?</strong></p> <p>I'd say I could probably read and modify everything, and I have probably read most code at some point. Partially this is because I have modified or authored a decent part of it, or have worked on code that interacted with it, partially it's because I've been doing this for years, and LÖVE's codebase isn't actually that big. That said, I know slime knows OpenGL much, much better than I do, so I'd say I know love.graphics the least, and I usually leave graphics-related things to her. Don't tell her, but it's also because I'm lazy.</p> <p>From what I can tell, slime feels the same, she's had her fingers in a lot of pies too, including the SDL pie. I'm not sure how she feels about modules I've written from scratch, like love.thread and love.video, but she is not someone to back away from a challenge.</p> <p>&nbsp;</p> <p><strong>Does LÖVE still have lots of work left or are you at the point where you really have to seek for what you could work on next? What are you currently working on?</strong></p> <p>That's a hard question. As most people know, it feels like your work is never done, it's just "good enough". Though with love.video, and the upcoming microphone input (see <a href="https://bitbucket.org/rude/love/pull-requests/68">raidho's pull request</a> for more information), there's nothing major that comes to mind.</p> <p>I never have to look for what to do next, since I don't think the bug tracker has been empty in <em>years</em>, and in the limited time I spend on coding, I try to tackle whatever bug seems interesting at the time.</p> <p>&nbsp;</p> <p><strong>Is there a feature that is currently not in LÖVE simply because none of the developers so far have an understanding on how to implement it? Have you ever searched for help to get a feature made?</strong></p> <p>Audio input has (had) that problem: if I remember correctly <a href="https://bitbucket.org/bmelts/">bmelts</a> had a working prototype a few years ago, but it turned out it only worked on his machine.</p> <p>I think love.video used to be a prime example, but we've persevered! I don't think Twitch still has them archived, but I did a lot of research and experimentation for love.video on <a href="https://www.twitch.tv/">twitch.tv</a>. I didn't necessarily reach out to a person, but I ended up looking at a lot of example code, bad documentation and even library source code to get that working. Most of the time when I can't solve something myself, there's two resources that help: Google and slime.</p> <p>That's not to say it has never happened, ports are a good example. meric (then appleide) ported LÖVE to OSX, and I'm sure that played a role in asking him to join, though that was before my time. Similarly, <a href="https://bitbucket.org/MartinFelis/love-android-sdl2/wiki/Home">fysx' android port</a> was something we probably wouldn't have done ourselves, and he too was asked to join. Come to think of it, maybe that's the secret to joining… I'm sure those rituals had nothing to do with it.</p> <p>&nbsp;</p> <p><strong>When working on LÖVE, was there a bug that you had a special grudge on?</strong></p> <p>No specific ones, but garbage collections or race conditions are always fun. Especially garbage collection race conditions! Any bugs we can't reproduce are also up there.</p> <p>Interestingly, I kind of like the extremely specific bugs, the weird edge cases. Those usually expose some flaw in your logic, where you were sure that value can't have been 3 at that point, but your tests undeniably prove it can.</p> <p>&nbsp;</p> <p><strong>Is there a LÖVE feature that you are extra proud of?</strong></p> <p>When I read this question, love.video was my first thought, but I've talked about that enough and there's something else that I think is actually really cool: love.run.</p> <p>Why love.run? Because it shows the simple and customisable nature of LÖVE. If you use the default love.run, you get a hello world in 3 lines. But there's no reason you need to use the callbacks as we defined them. There's no reason you need to handle events in the main thread. You can change LÖVE's main loop without a problem. boot.lua — which is the file love.run lives in in the repository — shows to me that in essence LÖVE is a library. You can pick and choose, modules are fairly loosely coupled, and you can load it into an existing lua program. And somehow we tie this together into a coherent framework/engine using lua, rather than C++.</p> <p>&nbsp;</p> <p><strong>D</strong><strong style="line-height: 1.5;">o you have any plans or hopes for the future of LÖVE?</strong></p> <p>"Plans? Where we're going, we don't need plans!" pretty accurately describe LÖVE development. There are bugs, intentions and release dates.</p> <p>What I would like to see is more users. It still feels wrong that media and industry seems to ignore us. Obviously I live in a LÖVE bubble, and it's probably fair, but I'd like to be at the point where LÖVE <em>is</em>&nbsp;well-known. Something <em>completely</em>&nbsp;unrelated: if you work for a big games company, and you like LÖVE, spread the word!</p> <p>&nbsp;</p> <p><strong>Anything you would like to tell all lovers (LÖVE users)?</strong></p> <p>Don't fall in the engine-making trap, you'll never release games again!</p> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/l%C3%B6vely-interviews-bartbes"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Wed, 26 Oct 2016 13:55:55 +0000 Sheepolution 52 at http://blogs.love2d.org Lövely Interviews - Maurice from Stabyourself.net http://blogs.love2d.org/content/l%C3%B6vely-interviews-maurice-stabyourselfnet <div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/mari0">mari0</a></li><li class="taxonomy-term-reference-1"><a href="/blog-terms/stabyourself">stabyourself</a></li><li class="taxonomy-term-reference-2"><a href="/blog-terms/interview">interview</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>In Lövely Interviews, I interview developers of LÖVE and LÖVE games. This time I'm interviewing Maurice from <a href="http://stabyourself.net/">Stabyourself.net</a>, who is known for creating the Mario/Portal mashup: <a href="http://stabyourself.net/mari0/">Mari0</a>.</p> <p><img alt="" src="http://i.imgur.com/eyPXuoP.jpg" style="width: 140px; height: 147px;" /></p> <hr /> <p><strong>Tell us a bit about yourself. Who are you and what do you do?</strong></p> <p>We are a two-man developer team, that is Sašo and me, Maurice. Sašo does anything website and hosting related while I program all the games. He also helps me with bouncing off ideas.</p> <p>We make games for fun that you can download from our website for free. It's not about making money but instead creating something that people will enjoy and maybe be surprised by.</p> <!--break--> <p>&nbsp;</p> <p><strong>Mari0 was actually how I learned about LÖVE! How did you learn about LÖVE, and what was it that made you start using it?</strong></p> <p>I think someone in the <a href="https://facepunch.com/forumdisplay.php?f=240">Facepunch programming forums</a>, which I used to frequent, was making a project with LÖVE, and I was looking for a more capable game engine than <a href="https://www.autoitscript.com/site/autoit/">AutoIt3</a> or the Warcraft 3 Map Editor at the time. A good friend of mine was a very skilled Lua programmer working a lot with <a href="http://www.garrysmod.com/">Garry's Mod</a> so I figured it might be a good idea to learn more about LÖVE and Lua.</p> <p>&nbsp;</p> <p><strong>Mari0 might be the most popular LÖVE game to date. Where did it all begin, and how long did it take you to make it?</strong></p> <p>It began like a lot of prototypes, where you go "Hey, I wonder if I can program a platformer". I started programming away in January 2011 on it using Super Mario Bros as a base because historically it was one of the first games to really nail the movement mechanics.</p> <p>After some time when the game was starting to resemble SMB, I started looking into what can be made out of it, thinking of making a multiplayer game like the recent .io games (<a href="http://agar.io/">agar.io</a>&nbsp;and&nbsp;<a href="http://slither.io/">slither.io</a>) or turning it into an HD port like Sonic 2 HD.</p> <p>Neither really got anywhere because of my inexperience with netcode and unsuccessful attempts at finding an artist.</p> <p>But then <a href="http://www.dorkly.com/">Dorkly </a>made a video about <a href="http://www.dorkly.com/video/14583/dorkly-bits-mario-with-a-portal-gun">SMB with a portal gun</a> and I thought "Hey I can actually make that!". That was in April 2011.</p> <p>A couple of months later in March 2012 Mari0 was released, so it took just over a year of on-and-off programming.</p> <p>&nbsp;</p> <p><strong>What is&nbsp;the most important thing&nbsp;you've learned when creating Mari0?</strong></p> <p>It's difficult to please everyone, especially when you make the development process as open as we did. People have different ideas of what should be in the game and you have to be able to maintain your own vision.</p> <p>If I had listened to every idea we got, Mari0 would be an mmo with guns and Sonic side characters.</p> <p>&nbsp;</p> <p><strong>Was there a part/feature you really struggled with when creating Mari0?</strong></p> <p>Probably the most requested feature, partly due to my fault of showing an unfinished version of it, online multiplayer. Combining a lack of experience with netcode and an already far into development game made adding network play a real pain for us. Someone I know actually offered to write the online part into the game but ultimately failed due to the client heavy way the game was written. In the end we had to completely abandon the idea, much to the dismay of youtube commenters.</p> <p>I think online play in a complex game such as a platformer has to be included from the very beginning, otherwise you set yourself up for rewriting half your game.</p> <p>&nbsp;</p> <p><strong>You have a <a href="http://forum.stabyourself.net/viewforum.php?f=13">Modding board</a> on your forums.&nbsp;Was Mari0 programmed to be mod-friendly? And if so what did you do different to achieve this?</strong></p> <p>There's nothing in Mari0's code that makes it particularly mod friendly. It's just the openness of the code and engine that inspired people to mod the game.</p> <p>There was going to be an update to Mari0 which included moddable enemies and entities which was actually pretty cool&nbsp;(There's a short blogpost about it <a href="http://blog.stabyourself.net/post/35343642433/custom-enemies-for-mappacks">here</a>).</p> <p>I think the best idea is to program things as modular as possible and then allow elements to be loaded from a folder. Anyone interested in modding will figure out how to use it to their advantage.</p> <p>For more advanced types of modding, I assume you'd have to put hooks into your game like Garry's Mod does it, but I have no experience with that. It's definitely something that's worth looking into though.</p> <p>&nbsp;</p> <p><strong>With LÖVE you also created Ortho Robot, a game where you "bridge the gap between 2D and 3D games". Wouldn't it have been easier to create this game with a 3D framework/engine?</strong></p> <p>Probably. It would also add more features; my crudely programmed 3D engine allows no roll-rotation on the blocks and I had issues with the draw order when the player moves between blocks. Like many of my games it was a "Can I program something like that?" thing.</p> <p>I'd love to get into a new "more serious" engine such as Unreal or Unity, but I just can't find the time or motivation to do so.</p> <p>&nbsp;</p> <p><strong>Is there anything you really wish would be added/changed to LÖVE?</strong></p> <p>I think with the recent Android and iOS ports, the only platform left for LÖVE to support is web. It would be really cool if I could upload quick prototypes (or full games) on the internet and allow people to play them without any installation or download.</p> <p>Other than that I'm very happy with the way the LÖVE-team is handling development of the engine.</p> <p>&nbsp;</p> <p><strong>I</strong><strong>n my interview with rude he talked about one of your games, <a href="http://stabyourself.net/trosh/">Trosh</a>. Is there a story behind this explosive game?</strong></p> <p>Trosh is actually one of the users from our forums, and at some point I got into a kind of exchange with him where he'd send me something in the mail, I'd send something back and so forth. At some point I decided to send him a link to a game that I was gonna program while the mail was underway, which put me under some time pressure but I think the game came out alright. And that's how Trosh was made.</p> <p>&nbsp;</p> <p><strong>Are you working on a new game at the moment, and if so what can you tell us about it?</strong></p> <p>I have one project that I think has potential, but I'm not nearly far enough to show anything. I'm trying to get back into actively making games because making Mari0 and the other games was a lot of fun, but it's hard to find the motivation to do so next to my regular programming job.</p> <p>The past few months I've also been working on a game we showcased at our yearly Gamescom appearance, <a href="http://stabyourself.net/superbattlearcade/">Super Battle Arcade</a>. You can watch a video of an older version <a href="https://www.youtube.com/watch?v=mPS2SXLBV_8">here</a>.</p> <p>&nbsp;</p> <p><strong>Thanks for answering all the questions, is there anything you would like to tell the readers?</strong></p> <p>I think games are something really special, as there's no other hobby I can think of that allows you to share your work as easily and accessible as game programming. So don't be afraid to show what you've made and don't be afraid to try out new things.</p> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/l%C3%B6vely-interviews-maurice-stabyourselfnet"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Thu, 08 Sep 2016 16:05:32 +0000 Sheepolution 51 at http://blogs.love2d.org Lövely Interviews - slime http://blogs.love2d.org/content/l%C3%B6vely-interviews-slime <div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/interview">interview</a></li><li class="taxonomy-term-reference-1"><a href="/blog-terms/slime">slime</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>In&nbsp;<strong>Lövely Interviews&nbsp;</strong>I interview developers of LÖVE and LÖVE games. And this time we interview slime, who is the&nbsp;biggest contributor of LÖVE, with over <a href="https://bitbucket.org/rude/love/commits/all?search=slime">1300 commits</a>.</p> <p><img alt="" src="http://i.imgur.com/IDLbg6J.png" style="width: 90px; height: 90px;" /></p> <hr /> <p><strong>Tell us a bit about yourself. Who are you and what do you do?</strong><br /> <br /> Hello! I’m <a href="http://twitter.com/slime73">Sasha</a>. I’m a software developer currently working in the <a href="http://www.hb-studios.com/">games industry</a> in Nova Scotia, Canada. I’ve been contributing to LÖVE’s development in my free time since around the end of 2012. I’ve also made a few games using LÖVE, and I’m a regular contributor to the <a href="https://www.libsdl.org/">SDL library</a>, which is used extensively by LÖVE.</p> <!--break--> <p><br /> <strong>How did you learn about LÖVE?</strong><br /> <br /> I first heard about LÖVE back in 2010. I believe there was a post on the programming subreddit about LÖVE 0.6.2, which caught my interest because at the time Lua was the only programming language I knew. I had been making Lua addons / scripts for <a href="https://www.vendetta-online.com/">Vendetta Online</a>, an indie space MMORPG.&nbsp;<br /> <br /> I actually knew the LÖVE developer <a href="https://love2d.org/forums/memberlist.php?mode=viewprofile&amp;u=317">bmelts </a>from the Vendetta Online community before I knew about LÖVE, but I didn’t know he was one of LÖVE’s developers until after I joined the LÖVE IRC channel!<br /> <br /> I hadn’t done any sort of game development or real programming outside of my Vendetta addons before starting with LÖVE. The first thing I made with it was a Pong clone which wasn’t very visually impressive, but I had a lot of fun learning about the basics of games when making it.<br /> <br /> <br /> <strong>With over 1300 commits you've become the biggest contributor to the LÖVE framework. Why did you start contributing and what kept you going?</strong><br /> <br /> I wanted to learn C++ and I had an interest in OpenGL, and I was also very active in the LÖVE IRC channel at the time. I had some ideas about feature and performance improvements that I wanted to see in LÖVE, so I learned bits and pieces of the LÖVE codebase and submitted a few patches and pull requests… and now here we are.<br /> <br /> I ended up really enjoying the combination of several things that contributing to LÖVE’s codebase provides: learning and writing code that interacts with system-level APIs such as OpenGL and SDL (and OS APIs since I also contribute to SDL’s development now), designing functionality that fits in with LÖVE’s preexisting philosophy, working with graphics APIs like OpenGL, and working on something which gets feedback and use from a large community.<br /> <br /> That last point is probably the most important to me. I definitely would not have put so much time into LÖVE if it weren’t for the community, so, thank you!<br /> <br /> <br /> <strong>When working on LÖVE, was there a bug that you had a special grudge on?</strong><br /> <br /> I think bugs inside graphics drivers have been the most frustrating for me, since I have practically no control over when (or if) they’re fixed, I can’t rely on them being fixed on a user’s machine even if a new driver comes out, they’re usually annoying to debug, and they generally require ugly workarounds in LÖVE’s code... if a workaround is possible at all.<br /> <br /> <a href="https://love2d.org/forums/viewtopic.php?f=4&amp;t=81496">Here’s one example</a> of a graphics driver bug which I had to figure out a workaround for.<br /> <br /> The issue of stutters when in windowed mode on some systems (especially when using Windows) is also annoying, since I don’t know of a way to solve or work around it in LÖVE’s or SDL’s code. You’re probably seeing a pattern in my frustrations by now.&nbsp; :)<br /> <br /> <br /> <strong>Is there a LÖVE feature that you are extra proud of?</strong><br /> <br /> The OpenGL ES 2 graphics backend code I wrote unofficially for 0.9 and officially for 0.10 ended up enabling a lot of other people to port LÖVE to other platforms, which has been really cool to see.<br /> <br /> Some examples of LÖVE ports that rely on it are <a href="https://love2d.org/forums/viewtopic.php?f=12&amp;t=33357">LÖVELINESS </a>(a now-defunct NaCl / Chrome port of 0.8.0 created by a Google employee), fysx’ unofficial Android port of 0.9 which is now part of 0.10, my iOS port of 0.9 which is also now part of 0.10, <a href="https://love2d.org/forums/viewtopic.php?f=12&amp;t=80038">T-Bone’s port</a> to Metro / WinRT / Windows Phone, and <a href="https://love2d.org/forums/viewtopic.php?t=81736">Tanner’s web port</a> of 0.10 via Emscripten.<br /> <br /> <br /> <strong>You seem like a very skilled programmer. Do you have any advice for people who want to become a programmer, or programmers who want to improve?</strong><br /> <br /> There are many different ways to learn and improve at programming. I think it’s important to figure out the most enjoyable and best way for you (the reader) to do that, which may be different from someone else’s preferred way. Some people thrive by seeking out information and experimenting completely on their own. Others learn best within the type of environment that schools and universities provide. Or anything in between those two extremes.<br /> <br /> A lot of people, myself included, have a hard time committing to and following through on a completely self-developed project - whether it be for learning or otherwise. As I mentioned earlier I started contributing to LÖVE partly to learn, and I think finding an open source project, preferably one you already know about as a user, and figuring out ways you can contribute to that is a very good way to improve your programming skills.<br /> <br /> You’ll have an existing codebase written by others you can look to, there will often be plenty of opportunities to tackle small problems in order to get your feet wet, and most importantly an active open source project will have other people who can help you and whose own goals are similar to yours.<br /> <br /> All that said, following a self-developed project through to completion is a skill of its own. There is a lot to be learned after the first 90% of a project’s development… when you’ll be doing the final 90%. &nbsp;;)<br /> <br /> <br /> <strong>Do you expect to see LÖVE 1.0.0 happen in your lifetime?</strong><br /> <br /> Personally the “1.0” version tag doesn’t actually mean a whole lot to me, it’s all pretty arbitrary. 0.10.0 could have been labelled 1.0, or 2.0, or 10.0 if we had decided – and maybe a future major release will skip 1.0 entirely and/or change versioning schemes, who knows!<br /> <br /> I consider LÖVE to have been ready for use in complex 2D commercial games since around 0.8.0 or so, and 0.10 has been very stable so far. All of the minor (0.X.0) version releases in the past few years have had breaking changes but not complete overhauls of LÖVE at a fundamental level, and I don’t see that changing in the future.<br /> <br /> <br /> <strong>Do you have any plans or hopes for the future of LÖVE?</strong><br /> <br /> I have outlined some of my ideas <a href="https://love2d.org/forums/viewtopic.php?f=3&amp;t=81457">on the forums</a>&nbsp;and on the <a href="https://bitbucket.org/rude/love/issues?status=new&amp;status=open">Bitbucket issue tracker</a>, plus I have some more far-fetched and less fleshed out ideas knocking around in my head – I often think about how various APIs (especially in love.graphics) might be changed to provide better performance or to make them more powerful or more intuitive to use. Only some of those thoughts ever come to fruition or end up being worthwhile ideas, though.<br /> <br /> Beyond that, It would be super awesome to see more people contribute to LÖVE’s development. Since I currently have a full-time job in the games industry, I have a lot less free time than I used to that I can spend programming (and I usually split that time between LÖVE and SDL too). I also consider my own thoughts on LÖVE’s features and code pretty limited in terms of perspective, so having more people from different backgrounds working on LÖVE could only improve it in my opinion.<br /> <br /> I think LÖVE has already been extremely successful at carving out a niche for itself that isn’t filled to the same degree by anything else, but it still has room to grow and improve and I hope there are more people out there who want to help make that happen.<br /> <br /> <br /> <strong>Anything you would like to tell all lovers (LÖVE users)?</strong><br /> <br /> Don’t forget to like, subscribe, and comment… wait a minute.<br /> <br /> Seriously though, thank you for using LÖVE and being a part of this community! I hope everyone enjoys using it as much as I enjoy working on it.<br /> <br /> The forums are a great place to ask questions and post about what you’re working on. I and many other knowledgeable folks are active in the IRC channel at #love on irc.oftc.net as well - don’t be afraid to hang out there and chat about LÖVE things. I bounce ideas for new features off of other people there all the time!</p> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/l%C3%B6vely-interviews-slime"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Thu, 01 Sep 2016 12:32:10 +0000 Sheepolution 50 at http://blogs.love2d.org Garbage Collection in LÖVE http://blogs.love2d.org/content/garbage-collection-l%C3%B6ve <div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/technical-lua-gc">technical lua gc</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>I recently got a message on the forums asking me about the way LÖVE does garbage collection on its objects, and I figured they probably aren't the only ones interested, so here's an expanded answer.</p> <p>As some of you may know, LÖVE is written in C++, which features manual memory management, and Lua has garbage collection. How do we solve this mismatch? Why, with another way to manage memory, of course! I'll start off by explaining the Lua GC (Garbage Collector), then quickly discuss C++'s model, followed by LÖVE's solution.</p> <h2>Lua's GC</h2> <p>As you may have realised if you've ever used another language, in Lua you don't need to worry about allocating and freeing memory. You create an object, and it stays available as long as you can refer to it. If you remove all references, it gets freed transparently. So how does this work?</p> <p>I'll try to give a high-level overview of the Lua GC, to spare you reading a few books' worth of academic papers. First of all, the GC can be tweaked, <a href="http://www.lua.org/manual/5.1/manual.html#2.10">the manual</a> has some more information about the subject, but for the most part we can assume the GC runs automatically, at regular intervals. It stores a list of all objects, and by finding all reachable objects, it can then delete the rest, the unreachable objects. To determine which objects are reachable, it has a couple of starting points: the global environment, and any running functions. And yes, I mean functions, or really, coroutines.</p> <p>Let's consider a simple example, we have some globals, a suspended coroutine and, of course, the main "coroutine". This means we have 3 places to start looking for values. Now, we can obviously reach all globals, we can reach the locals of the function we're currently running, and we can reach all values they contain. So if we can reach the <code>math</code> table, we can also reach <code>math.sqrt</code>. Similarly, if we can reach the suspended coroutine, we can also reach anything its locals can reach. Additionally, if we are currently in a function <code>g</code>, that was called from <code>f</code>, then we can also reach anything <code>f</code> can reach, and so on. Needless to say, there are usually quite a lot of values you can reach.</p> <p>Thankfully, the GC doesn't need to run it all at once, since that would introduce significant delays. Instead, it's an <em>incremental</em> garbage collector, which means it can divide the work into multiple smaller steps.</p> <p>As a final piece of the puzzle, in Lua all external objects are classified as <code>userdata</code>. There is both <code>lightuserdata</code>, and what is sometimes referred to as "full userdata", but Lua calls it <code>userdata</code>. As LÖVE uses an unmodified Lua (or LuaJIT), all of LÖVE's objects, in Lua, are <code>userdata</code>. Whereas in Lua you can't do cleanup when an object gets collected, the Lua developers know that this would cause all kinds of issues if the same were to happen with userdata. To circumvent this, Lua calls the <code>__gc</code> metamethod on userdata when it is garbage collected. As you can imagine, LÖVE then uses this metamethod to determine when to free its objects, but we'll see that later.</p> <p>As an aside, if you've ever watched the memory usage of LÖVE whilst running the GC manually, you may have noticed something peculiar: The memory usage only goes down 2 cycles after userdata became unreachable. The reason for this is the aforementioned metamethod. If the metamethod somehow creates a new reference to the object, it can't be collected straight away. Rather than trying to solve this by trying to keep track of what it does, the GC does something simpler. On the first pass, it calls the metamethod, then "detaches" it. The next time it comes across the userdata, it knows the metamethod has already been called, and only then is it actually removed.</p> <h2>C++ memory management</h2> <p>There's very little to say on this point, since C++ memory management consists of the programmer doing it all by themselves. Specifically, if you want to allocate a new Image, you could write <code>Image *image = new Image(file);</code>, and when you're done with it, you delete it, using <code>delete image;</code>. Between those points the value of <code>image</code> is valid, after delete is isn't. So, if you refer to <code>image</code> after deleting it, your program could crash (or worse, it could <em>not</em>). Similarly, you are responsible for making sure you delete it exactly once, if you don't delete it, you won't notice you're leaking memory. If you delete it twice, you'll crash. Fun.</p> <p>As may be obvious, this isn't the most programmer-friendly paradigm. The upside is that it is fast, and it allows you to do all sorts of crazy things. Even though that may include shooting yourself in the foot. Another benefit is that it's predictable. When dealing with Lua, if you remove all references to an object, it may live on for a very long time before it is finally removed. If you delete something in C++, it gets removed right then. Since removing objects takes time, you can thus plan when this happens. You could spread it out or you could delete batches of objects at a time. Even though Lua's GC can be tuned, you'll never get precise timing control. If you're creating lots of garbage, you could see lag spikes, and there's very little you can do about it, except create less garbage.</p> <h2>LÖVE's reference counting</h2> <p>We've seen two completely different ways to manage memory, Lua's fully automatic GC, and C++'s fully manual new/delete. This leaves LÖVE somehow having to reconcile these two worlds. The answer is clearly to introduce yet another model!</p> <p>Now, not all LÖVE objects are the same, but we'll focus on those that you can use from Lua, which all derive from the <code>love::Object</code> base class. This base class supports (manual) reference counting. In our case, we use two methods for this, <code>retain</code>, which increases the reference count, and <code>release</code>, which decreases it. The basic concept behind these is simple: Once the reference count reaches 0, the object deletes itself! This also means that when the object is created (using new) it has a reference count of 1.</p> <p>Unfortunately, this is still a manual system, if we ever forget to retain an object we store, or release an object when we stop storing it, we will still run into issues. Thankfully, it's usually fairly easy to know when to call retain, and when to call release, and C++ allows us to write helpers to manage it for us in a lot of cases.</p> <p>I've now explained how LÖVE deals with those objects internally, and how it relates to C++ model of new and delete, but that still doesn't explain how it cooperates with Lua's GC. This is where the <code>__gc</code> metamethod comes into play again. Whenever an object reaches Lua, which is roughly whenever a function returns it, the LÖVE wrapper code calls <code>retain</code>. Then, when the <code>__gc</code> metamethod gets called, it calls <code>release</code>. What this means is that Lua holds 1 reference for every "copy" of the object it has. When one becomes unreachable, the GC will collect it, and the reference will be released.</p> <p>If you're now wondering why it has to be this complex, that's because object lifetimes are complex in LÖVE! Say you create a blank ImageData in your code. At that point Lua holds 1 reference, and nothing else does. Then you fill it with some data and call <code>love.graphics.newImage</code> on it. At that point Lua holds 1 reference, and the newly created Image holds another. If you then remove all references to the ImageData, Lua will no longer hold its reference, and the only reference will be the one from the Image. If you then remove all references to the Image, both the Image and the associated ImageData will get deleted, which is exactly what we'd expect. If we were to simply trust the Lua GC, we'd have deleted the ImageData whilst the Image was still using it. If we had "trusted" C++, we'd have deleted it when we LÖVE longer held it, but when Lua still did. This reference counting solution allows both models to work together, without leaking memory, nor deleting it prematurely.</p> <p>Similarly, this also works across threads. Since love.thread gives every thread its own separate Lua state, they also run independent GCs. Using this reference counting mechanism, this means each thread can have their own reference, and an object only gets deleted when all threads are done with it.</p> <h2>Want more?</h2> <p>In this article I've tried to give a glimpse into the LÖVE internals, if you want to know more about memory management, if anything was unclear, or if you would like to see more posts on other subjects, let us know!</p> <p>Of course, since LÖVE is open-source software, you can look at the implementation yourself, if you're interested. <a href="https://bitbucket.org/rude/love/src/0.9.0/src/common/Object.cpp">The 0.9.0 version of <code>love::Object</code></a> is a simple, straight-forward implementation of the <code>retain</code> and <code>release</code> primitives. <a href="https://bitbucket.org/rude/love/src/0.10.0/src/common/Object.cpp">The current, 0.10.0 version</a> is more thread-safe, at the cost of readability.</p> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/garbage-collection-l%C3%B6ve"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Sat, 16 Jul 2016 19:18:54 +0000 bartbes 49 at http://blogs.love2d.org Lövely Interviews - rude http://blogs.love2d.org/content/l%C3%B6vely-interviews-rude <div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/interview">interview</a></li><li class="taxonomy-term-reference-1"><a href="/blog-terms/rude">rude</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>In <strong>Lövely Interviews&nbsp;</strong>I interview developers of LÖVE and LÖVE games. We start off this series with <strong>rude</strong>, the creator of LÖVE.</p> <p><img alt="" src="http://i.imgur.com/3HWjypS.png" style="width: 90px; height: 90px;" /></p> <hr /> <p><strong>Tell us a bit about yourself. Who are you and what do you do?</strong><br /> <br /> Yes, well, I am <a href="http://love2d.org/wiki/User:Rude">rude</a>, the original creator LÖVE. These days I don't actually work on the code anymore (though I might resume at some point), but I still do all the design related work, e.g. the new icons, the no-game screens (e.g. Super Toast), the website design, etc. At least I do that eventually, after I get enough harassment from <a href="http://love2d.org/wiki/User:Bartbes">bartbes</a> and <a href="http://love2d.org/wiki/User:Slime">slime</a>.</p> <!--break--> <p><br /> I do definitely exist in real life as well, but I prefer not to talk about that. I must remain shadowy and mysterious. The menace must remain phantom.<br /> <br /> <strong>Can you tell us about how LÖVE came to exist?</strong><br /> <br /> Actually, I don't remember how it started. Possibly it was just a challenge to myself. If someone forced me to make up a story, however, it could be something like:<br /> <br /> Well, I was looking for a free 2D-centric game framework that was easy to get up and running, and that would work on all platforms without too much hassle, but I couldn't find any. There were many engines and frameworks available, but they were too focused on 3D, which made the API unattractive for use in 2D games. So I began to work on my own API; a glorious world blissfully ignorant of the z-axis, where the children could finally laugh and play freely, both as in beer, and as in freedom. *single tear*<br /> <br /> And so forth.<br /> <br /> <strong>What was Mike's role, and why did he leave?</strong><br /> <br /> Yes, he was (well, is, since he's not dead) the co-author of the original code. He worked on lots of stuff all over the place, like fonts (ImageFonts were his idea), ParticleSystem, and other stuff. He also worked on the love.gui module, which ultimately wasn't released.<br /> <br /> He didn't exactly "leave" in some dramatic incident, his interest just faded I guess. Or his interest faded because I was too bossy. Although you should probably ask Mike about that.<br /> <br /> <strong>How did you decide on the name LÖVE?</strong><br /> <br /> Software at the time (2006-ish) seemed either very serious (Visual Studio Professional), or attempted be all badass (UNREAL ENGINE). I hated that, so I wanted to come up with a very non-serious and anti-badass name that evoked fuzzy warm feelings of fun, happiness, etc.<br /> <br /> After a brainstorming I no longer remember clearly, "Love" (umlautless) surfaced somehow, and thought it was a perfect fit right away. I assumed, of course, that there was already some game-related software called Love out there (because every name is already taken in every context, no matter how ridiculous), but I couldn't find any. There wasn't even a Debian package called "love", which amazed me.<br /> <br /> When I understood that I could be the one responsible for making this a reality:<br /> <br /> $ make love<br /> $ man love<br /> $ apt-get install love<br /> <br /> There was of course no turning back.<br /> <br /> Later, when I designed the logo (the curvy LÖVE text), I added the umlauts on a whim since I decided that something was missing from the logo. That's how it became LÖVE. I also added a sarcastic copyright symbol to the logo, although that is removed now.<br /> <br /> <strong>Why did you choose Lua as the framework's language?</strong><br /> <br /> The main reason was that it was easy to embed the VM.<br /> <br /> Initially, LÖVE used <a href="http://www.swig.org/">SWIG</a>, which is a way to generate a scriting API from C/C++ code. There was a vague plan to allow multiple languages (i.e. generate multiple scripting APIs using SWIG), but that was dropped eventually, since the API produced by SWIG was too ugly. Today the API/bindings are made by hand.<br /> <br /> I vaguely remember trying to embed some other JS-like scripting language, but I don't remember the name, and it doesn't seem to exist anymore. The name had "Monkey" in it, I think.<br /> <br /> <strong>LÖVE doesn't have tilemaps, UI, Camera, etc. The Animation object was even removed. Why do you choose to keep LÖVE to the basics like that?</strong><br /> <br /> "High level" things are (for me) mostly just in the way, and never work quite the way I need for a specific case. It's really easy to create a high level component which seems nice, but in reality is too inflexible for many cases, leaving lovers to develop their own e.g. tilemap component anyway, feeling sad that the built-in component is just uselessly standing there. So it's better if such things are made as third-party Lua libraries, so they're easier to modify or extend.<br /> <br /> Also, there is an unwritten "emergent" guideline, which says that things which can be easily done in pure Lua should be done in pure Lua. This is affecting the API a bit, I think.<br /> <br /> By the way, I don't exactly closely oversee LÖVE development at the moment, so it's not like I vigilantly enforce some principle in the LÖVE API, like your question might imply. It's the consensus of the LÖVE-dev hivemind that takes care of that.<br /> <br /> <strong>Your last code-related commit was in 2014. Why did you stop working on LÖVE?</strong><br /> <br /> Hmm ... I don't know!<br /> <br /> You would perhaps expect me to answer that I don't have time anymore, but actually, I do have time. So I should totally get back into it.<br /> <br /> Of course, I don't really need to, since dem young'uns (bartbes, slime, <a href="http://www.fysx.org/">fysx</a> and others) got it covered.<br /> <br /> <strong>Do you have any plans or hopes for the future of LÖVE?</strong><br /> <br /> LÖVE is already way more popular than I ever thought it would be. And also 'apt-get install love' is a reality now, so I don't see where we could possibly go from here.<br /> <br /> <strong>Is there anything you would like to tell all lovers (LÖVE users)?</strong><br /> <br /> I regularly lurk the Games and Creations (formerly Projects and Demos) subforum (and other places), and it's so cool and impressive to see what people are making. I often think: "what?! I didn't know that was possible in LÖVE!".<br /> <br /> Some games also really make me laugh, like that game where you are first flying horizontally, battling unicorns or something, then flying vertically battling your way through stuff until you get to space, and finally explosively landing (back on the ground) in a cinematic pose, wearing sunglasses. Unfortunately I don't remember the name of this game (if anyone does, please post a link in the comments).<br /> <br /> So, definitely keep it coming, lovers.</p> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/l%C3%B6vely-interviews-rude"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Thu, 16 Jun 2016 10:52:34 +0000 Sheepolution 48 at http://blogs.love2d.org In the making - have a look at running LÖVE projects http://blogs.love2d.org/content/making-have-look-running-l%C3%B6ve-projects <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>I asked on Twitter "Are you making a game with LÖVE? Show us what you're making!"</p> <p>And these are the replies I got:</p> <hr /> <p><a href="http://www.wanderer-game.com/"><strong>Wanderer</strong></a> by&nbsp;<a href="https://twitter.com/wanderer_game"><strong>@wanderer_game</strong></a></p> <p><a href="http://i.imgur.com/OVd9hHp.gif"><img alt="" src="http://i.imgur.com/OVd9hHp.gif" style="width: 500px; height: 257px;" /></a></p> <blockquote> <p>A 2D adventure game blending cinematic platformer and RPG, and LÖVE is perfect for it!</p> </blockquote> <p>When asked why LÖVE is so perfect for it, the <a href="https://twitter.com/selages">developer</a> responded</p> <blockquote> <p>Lua power and flexibility + great documented API + multi platform + warm community = development going very fast!</p> </blockquote> <p>Wanderer had&nbsp;both a succesful <a href="https://www.kickstarter.com/projects/1231806848/wanderer-2">Kickstarter</a> and <a href="http://steamcommunity.com/sharedfiles/filedetails/?id=514749367">Steam Greenlight</a> campain!&nbsp;</p> <p>​You can check out their devlog <a href="https://forums.tigsource.com/index.php?topic=46548.0">here</a>.</p> <hr /> <p>&nbsp;</p> <p><a href="http://teampiquant.com/"><strong>ZombieGame</strong></a> by <strong><a href="https://twitter.com/Jeffrey_W23">@Jeffrey_W23</a></strong></p> <p><img alt="" src="http://i.imgur.com/ZLiatsBg.png" style="line-height: 1.5; width: 500px; height: 281px;" /></p> <blockquote> <p>I'm building a game called ZombieGame (I'm told I'm good with names).</p> <span style="line-height: 1.5;">&nbsp;</span></blockquote> <hr /> <p>&nbsp;</p> <p><a href="https://twitter.com/Ulydev/status/736280140393631744"><strong>DOS </strong></a>by<strong> <a href="https://twitter.com/Ulydev">@Ulydev</a></strong></p> <p><img alt="" src="http://i.imgur.com/UWjgn0Q.gif" style="height: 309px; width: 500px;" /></p> <blockquote> <p>A psychedelic rhythm runner</p> </blockquote> <hr /> <p>&nbsp;</p> <p><strong><a href="https://twitter.com/rm_code/status/736320438918389761">"An ASCII XCOM-Like game"</a>&nbsp;</strong>by <a href="https://twitter.com/rm_code"><strong>@rm_code</strong></a></p> <p><img alt="" src="http://i.imgur.com/fI6PfNw.jpg" style="width: 500px; height: 374px;" /></p> <blockquote> <p>Still very early WIP though</p> </blockquote> <hr /> <p>&nbsp;</p> <p><strong><a href="https://twitter.com/enemyspeak/status/736323074107133952">"A&nbsp;game about cats and stuff"</a>&nbsp;</strong>by <strong><a href="https://twitter.com/enemyspeak">@enemyspeak</a></strong></p> <p><img alt="" src="http://i.imgur.com/nl4tF9V.gif" style="width: 500px; height: 281px;" />&nbsp;</p> <hr /> <p><a href="https://twitter.com/foodshipnine/status/736482948711514114"><strong>"A game where you're walking around in the dark"</strong></a> by &nbsp;<strong><a href="https://twitter.com/foodshipnine">@foodshipnine</a></strong></p> <p><img alt="" src="http://i.imgur.com/KLvCPTR.jpg" style="width: 500px; height: 335px;" /></p> <blockquote> <p>And there are some trees i guess. and a buggy map editor!</p> </blockquote> <hr /> <p>&nbsp;</p> <p><a href="https://forums.tigsource.com/index.php?topic=53776.0"><strong>Traveler</strong></a> by <strong><a href="https://twitter.com/Sheepolution">@Sheepolution</a></strong> (me!)</p> <p><img alt="" src="http://i.imgur.com/1L5KHsB.gif" style="width: 500px; height: 281px;" /></p> <blockquote> <p>A game where you fly through space, meeting and fighting interesting creatures</p> </blockquote> <hr /> <p><span style="line-height: 1.5;">Really cool games! But surely there's more out there, right?</span><span style="line-height: 1.5;">&nbsp;If you're making a game, send a tweet to </span><a href="https://twitter.com/obey_love/status/736122183747932160" style="line-height: 1.5;">@obey_love</a>&nbsp;or place it in the comments here<span style="line-height: 1.5;">, and I</span><span style="line-height: 1.5;">'ll include your game the next time I'll make one of these. Whenever that is.</span></p> <p>Thanks for reading and I hope you have a lövely day!</p> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/making-have-look-running-l%C3%B6ve-projects"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Sat, 28 May 2016 22:56:13 +0000 Sheepolution 47 at http://blogs.love2d.org A Beginner's Guide to Shaders http://blogs.love2d.org/content/beginners-guide-shaders <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p><span style="line-height: 1.5;">Ever since </span><a href="http://www.love2d.org/wiki/Shader" style="line-height: 1.5;">shaders</a><span style="line-height: 1.5;">&nbsp;were introduced in&nbsp;Löve (previously called </span><a href="http://www.love2d.org/wiki/PixelEffect" style="line-height: 1.5;">Pixel Effects</a><span style="line-height: 1.5;">) they have been shrouded in mystery and myth. The only way to learn these&nbsp;mystical black arts was to scour the </span><a href="http://love2d.org/forums/viewtopic.php?f=4&amp;t=3733" style="line-height: 1.5;">examples</a><span style="line-height: 1.5;">&nbsp;others have made in hopes of learning by tweaking enough code.&nbsp;</span></p> <p>Hopefully, we can change that! By providing a straightforward guide, more people can learn and integrate shaders into their own projects!</p> <p>&nbsp;</p> <p>This tutorial will teach you how to set up a basic pixel shader as well as attempt to explain what&nbsp;everything does.</p> <p>&nbsp;</p> <h1>What is a shader? (background info)</h1> <p>All the code you normally write runs on the CPU. As a general purpose unit, that works great for&nbsp;<em>most&nbsp;</em>things. The problem with your CPU is that it is sequential. It runs the instructions it''s given in the order they are written. Even with multi-core computers and multi-threaded applications, you have a limited number of cores and if they are processing the same data, they have to wait until the other is finished with it anyway.</p> <p>Your&nbsp;<strong>GPU</strong> on the other hand has&nbsp;<em>thousands&nbsp;</em>of cores. It''s built specifically to be able to run instructions thousands or millions of times in parallel. The catch is, it can only run <strong>the same piece of code&nbsp;</strong>on all these cores at any one time. (This isn''t&nbsp;<em>exactly&nbsp;</em>how it works, but for all intents and purposes, it''s a good way to think about it)</p> <h1>What can I do with shaders?</h1> <p>Shaders can be immensely useful when making games or any sort of graphics work. You only need to look through the <a href="http://love2d.org/forums/viewtopic.php?f=4&amp;t=3733">Share A Shader thread&nbsp;</a>for a few moments to see all the impressive work.&nbsp;</p> <p>If you want to do any sort of realistic/dynamic lighting, you''ll need shaders.</p> <p><img alt="" src="http://blogs.love2d.org/sites/default/files/u185/LoveShadow.gif" style="width: 320px; height: 240px; float: left;" /><img alt="" src="http://blogs.love2d.org/sites/default/files/u185/LoveShadow2.gif" style="width: 320px; height: 240px; float: right;" /></p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>Screens taken from PriorBlue''s <a href="http://love2d.org/forums/viewtopic.php?f=5&amp;t=77418">Love vs Shadow engine</a></p> <p>Learning how to use shaders in&nbsp;<span style="font-size: 14px; line-height: 21px;">Löve will also teach you how to use them in any other application/platform, since the fundamentals are the same. Just look at all the <a href="http://glsl.heroku.com/">stuff you can do!</a></span></p> <p>Not only that, but you can potentially leverage the awesome parallel processing power of GPU''s to crunch more than just graphical data, but we''ll discuss that later on.&nbsp;</p> <h1>Let''s make a shader!</h1> <p>There are two kinds of shaders. A pixel shader (sometimes referred to as a fragment shader) whose code runs on all the pixels, and a vertex shader which runs on the vertices of your primitives. We''ll start with the <strong>pixel shader.</strong></p> <p>To set everything up, here''s a standard main.lua you can use.</p> <pre class="brush: lua"> function love.load() &nbsp; myShader = love.graphics.newShader[[ &nbsp; &nbsp; vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ &nbsp; &nbsp; &nbsp; vec4 pixel = Texel(texture, texture_coords );//This is the current pixel color &nbsp; &nbsp; &nbsp; return pixel * color; &nbsp; &nbsp; } &nbsp; ]] end function love.draw() &nbsp; love.graphics.setShader(myShader) --draw something here &nbsp; love.graphics.setShader() end</pre> <p>Now let''s step through this.&nbsp;</p> <p>The first thing we do is create a shader using the function <a href="http://www.love2d.org/wiki/love.graphics.newShader">love.graphics.newShader</a>. This will return a <a href="http://www.love2d.org/wiki/Shader">Shader</a> object.&nbsp;</p> <p>To apply this shader, we call <a href="http://www.love2d.org/wiki/love.graphics.setShader">love.graphics.setShader </a>in our draw function. Calling the same function with no arguments will disable any shaders. In the above code, only things drawn between the two function calls will be affected by our shader.</p> <p>Try loading in a simple image and drawing it (or just draw a circle or anything).</p> <p>This is the example image I''m using, and this is how it looks like when rendered.</p> <p><img alt="" src="http://blogs.love2d.org/sites/default/files/u185/Standard%20Shader.png" style="width: 700px; height: 546px;" /></p> <p>You should see it exactly as if there was no shader. To understand, let''s look at the actual shader we wrote.&nbsp;</p> <h1>What language are shaders written in?</h1> <p>We can see that we''re passing a big string to the newShader function. It doesn''t look like Lua. Shaders in&nbsp;<span style="font-size: 14px; line-height: 21px;">Löve are written in <strong>GLSL</strong> (OpenGL Shading Language) but with a slight variation. This is important to note because the resources you can look up don''t have to be&nbsp;Löve-specific (or you can try porting shaders from other platforms for practice!)</span></p> <table cellpadding="5" style="color: rgb(40, 70, 92); font-family: sans-serif; font-size: 13px; line-height: normal;"> <tbody> <tr> <th>GLSL</th> <th>LÖVE shader language</th> </tr> <tr> <td>float</td> <td>number</td> </tr> <tr> <td>sampler2D</td> <td>Image</td> </tr> <tr> <td>uniform</td> <td>extern</td> </tr> <tr> <td>texture2D(tex, uv)</td> <td>Texel(tex, uv)</td> </tr> </tbody> </table> <p>These are the only differences. You can look up the <a href="http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.20.8.pdf">documentation of GLSL</a>&nbsp;(<span style="font-size: 14px; line-height: 21px;">Löve uses version 1.20)&nbsp;</span>to learn more about any function.&nbsp;</p> <p>Now let''s look at the shader code in more detail:</p> <pre class="brush: lua"> vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ &nbsp; vec4 pixel = Texel(texture, texture_coords );//This is the current pixel color &nbsp; return pixel * color; }</pre> <p>We know that everything gets passed through this shader before it is drawn, and this code here will run on every pixel in parallel.</p> <p><strong>GLSL syntax is more akin to C/C++ than Lua, so don''t forget your semicolons!</strong></p> <p>The entire job of the pixel shader is to return the final color of this pixel. The return type is a vec4, which means it''s a vector with 4 values. These correspond to the red,green,blue and alpha channels, each taking a value from <strong>0 to 1.</strong></p> <p>Let''s try something even simpler. Remove all that and just return a new, custom color.&nbsp;</p> <pre class="brush: lua"> vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ &nbsp; return vec4(1.0,0.0,0.0,1.0); }</pre> <p>Try to guess what this will look like before running the code.</p> <p>It returns a red color with full alpha, so regardless of what you draw, or what color you set with love.graphics.setColor, it will appear red.&nbsp;</p> <p><img alt="" src="http://blogs.love2d.org/sites/default/files/u185/RedBlockShader.png" style="height: 550px; width: 700px;" /></p> <p>You might also notice that, if you try to draw any external image (as in, not a circle or polygon with the built in drawing API) it will come out as a red rectangle. This is because you''re also overriding the transparency of each pixel.</p> <p>Each pixel&nbsp;<em>will&nbsp;</em>get this specific color.&nbsp;</p> <p>So far, this isn''t very useful. It would be more benificial if we had access to information about each pixel so we can better manipulate the image. Let''s look at the arguments passed to us.</p> <p><strong>What do the arguments mean?</strong></p> <p>The first argument, a vec4, is the color set during love.graphics.setColor.&nbsp;</p> <p>The second argument is the image itself being drawn.</p> <p>The third is a vec2, of the <u>normalized</u> coordinates of the current pixel, <u>relative to the image.</u></p> <p>The fourth is a vec2, of the coordinates of the current pixel, <u>relative to the screen.</u></p> <p>&nbsp;</p> <p>Let''s try to make use of the last two coordinates to illustrate how they work.</p> <p>Say we want to make a shader, that will turn the right half of the image red, and the left half blue.</p> <pre class="brush: lua"> vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ &nbsp; if(texture_coords.x &gt; 0.5){ &nbsp; &nbsp; return vec4(1.0,0.0,0.0,1.0);//red &nbsp; } &nbsp; else &nbsp; { &nbsp; &nbsp; return vec4(0.0,0.0,1.0,1.0);//blue &nbsp; } }</pre> <p>Since the texture_coords are normalized. This means that x=0 is the leftmost point, x=1 is the rightmost, and x = 0.5 is just at the center (you can see how convenient this is).</p> <p>So regardless of where you draw your image, the right half will be red and the left half will be blue.</p> <p><img alt="" src="http://blogs.love2d.org/sites/default/files/u185/HalfHalfShader.png" style="height: 548px; width: 700px;" /></p> <p>What if we wanted to do the same thing, but <em>relative to the screen.</em></p> <p>In other words, we want anything drawn on the right side of the screen to be red, and anything on the left to be blue.&nbsp;</p> <pre class="brush: lua"> vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ &nbsp; if(screen_coords.x &gt; 400){ &nbsp; &nbsp; return vec4(1.0,0.0,0.0,1.0);//red &nbsp; } &nbsp; else &nbsp; { &nbsp; &nbsp; return vec4(0.0,0.0,1.0,1.0);//blue &nbsp; } }</pre> <p>Given that the screen_coords are not normalized (and assuming your screen width is 800), this will make the image completely red if it''s drawn on the right side, vice versa for the blue, and between will work as expected.</p> <p><img alt="" src="http://blogs.love2d.org/sites/default/files/u185/MovingShader.gif" style="height: 520px; width: 700px;" /></p> <h1>How can I get the color of the current pixel before changing it?</h1> <p>This is probably the most useful information you can use. Let''s say we want to give our game a monochromatic feel. All you''d have to do is average out the 3 color channels. (Or something simpler, removing the blue channel from everything will also give it an interesting tinge)</p> <p>These all sound simple, but how do you get the color of the current pixel?</p> <p>That''s where the <strong>Texel</strong> function comes in.&nbsp;</p> <p>It''s pretty straightforward, it takes the texture (image) and the coordinates of the pixel relative to that texture, and returns the color. You conveniently have both passed as ready arguments, so all you have to do is plug them in.</p> <pre class="brush: lua"> vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ &nbsp; vec4 pixel = Texel(texture, texture_coords );//This is the current pixel color &nbsp; number average = (pixel.r+pixel.b+pixel.g)/3.0; &nbsp; pixel.r = average; &nbsp; pixel.g = average; &nbsp; pixel.b = average; &nbsp; return pixel; }</pre> <p>And there you go! We just made a shader that transforms everything into black and white in real-time!&nbsp;</p> <p><img alt="" src="http://blogs.love2d.org/sites/default/files/u185/BlackWhite.png" style="height: 550px; width: 700px;" /></p> <p>&nbsp;</p> <h1>Combining our knowledge</h1> <p>Now let''s try making it&nbsp;<em>gradually&nbsp;</em>go from full color to black and white across its width. I''ll wait here if you want to try figuring this out yourself.</p> <p>Go on, I''ll wait!</p> <p>&nbsp;</p> <p>When the r,g and b all have the value of the average, it''s black and white. The farther away it is from the average, and the closer it is to its original value, the image becomes full colored. Given this, we can make these simple equations:</p> <pre class="brush: lua"> vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ &nbsp; vec4 pixel = Texel(texture, texture_coords );//This is the current pixel color &nbsp; number average = (pixel.r+pixel.b+pixel.g)/3.0; &nbsp; number factor = texture_coords.x; &nbsp; pixel.r = pixel.r + (average-pixel.r) * factor; &nbsp; pixel.g = pixel.g + (average-pixel.g) * factor; &nbsp; pixel.b = pixel.b + (average-pixel.b) * factor; &nbsp; return pixel; }</pre> <p>We use the normalized x coordinate as our gradient factor, and we get a gradual black and white image!</p> <p><img alt="" src="http://blogs.love2d.org/sites/default/files/u185/GradientBlackWhite.png" style="height: 546px; width: 700px;" /></p> <p>It should be very easy to make it go to black and white gradually over the entire screen instead of per-image, we''ll just change the factor into <strong>screen_coords.x</strong> divided by however wide our screen is.</p> <p>This sounds annoying though. Do we really have to hardcode in the width of the screen in our shader?</p> <h1>How do I send variables to my shader?</h1> <p>Of course there''s a way! And that is, <a href="http://www.love2d.org/wiki/Shader:send">Shader:send</a></p> <p>The first thing is to set up the shader to receive the variable. In this case, it''s our screen width. So it''s only 1 number. External variables need the prefix "extern" (note: in normal GLSL, that would be "uniform")</p> <pre class="brush: lua"> extern number screenWidth; vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ &nbsp; vec4 pixel = Texel(texture, texture_coords );//This is the current pixel color &nbsp; number average = (pixel.r+pixel.b+pixel.g)/3.0; &nbsp; number factor = screen_coords.x/screenWidth; &nbsp; pixel.r = pixel.r + (average-pixel.r) * factor; &nbsp; pixel.g = pixel.g + (average-pixel.g) * factor; &nbsp; pixel.b = pixel.b + (average-pixel.b) * factor; &nbsp; return pixel; }</pre> <p>External variables are declared outside the function, as you can see in the above example.&nbsp;</p> <p>Then you can run the command</p> <pre class="brush: lua"> myShader:send("screenWidth",800) &nbsp;</pre> <p>From anywhere in the code. &nbsp;(I''m using 800 for simplicity but you can of course get the width dynamically through <a href="http://www.love2d.org/wiki/love.window.getWidth">love.window.getWidth</a>&nbsp;)</p> <p>It is worth noting two things about the send technique:</p> <ul> <li>Communication between CPU and GPU is generally expensive. You don''t want to be sending hundreds of variables per frame</li> <li>What goes to the GPU, stays in the GPU. This is very convenient because it means you don''t have to send everything every frame. You can send the screen width once when you create the shader, and again if it ever changes.&nbsp;</li> </ul> <p>And you''ve just made a snazzy gradient monochromatic shader!</p> <p><img alt="" src="http://blogs.love2d.org/sites/default/files/u185/MovingMono.gif.gif" style="height: 521px; width: 700px;" /></p> <p>&nbsp;</p> <h1>Built-in variables</h1> <p>There''s a special note about the screen size. Since it''s such a common thing to use,&nbsp;<span style="font-size: 14px; line-height: 21px;">&nbsp;Löve has provided it as a built in variable. You can use it by accessing&nbsp;<strong>love_ScreenSize.x</strong> or&nbsp;<strong>love_ScreenSize.y</strong> at any time in your shader. <a href="http://www.love2d.org/wiki/Shader_Variables">This is only available since 0.9.1</a></span></p> <p>Another common thing to send to a shader is a time variable. Let''s say you want your image to slowly become black and white over time. It''s the same idea, except the factor will be an extern time variable instead of x or y coordinate.&nbsp;</p> <p><a href="http://blogs.love2d.org/sites/default/files/u185/ShaderTutorial.love"><strong>Here's a .love of the effect I just mentioned.</strong></a></p> <p>&nbsp;</p> <p>&nbsp;</p> <h1>Parting Thoughts</h1> <p>I hope you''ve enjoyed this guide! That should be everything you need to know to have a basic grasp of how shaders work, and get started. Please let me know what parts were helpful and&nbsp;what were confusing so we could improve this guide.&nbsp;</p> <p>There''s a lot of other things we could discuss in future tutorials, such as vertex shaders, ways to send larger amounts of data to the GPU (or using it for general purpose calculations as we hinted at earlier), live-updating your shader code so you don''t have to recompile to see changes.</p> <p>One of the biggest challenges for me in shaders was figuring out how to do self-propagating shaders. By that I mean, all the manipulations that you do to the screen are not saved. What if you wanted to make something that continually distorted an image, building onto its previous iterations?</p> <p>A very common use for this is a smoke/fluid shader</p> <p><img alt="" src="http://blogs.love2d.org/sites/default/files/u185/Smoke.gif" style="width: 700px; height: 522px;" /></p> <p>These are all things we could discuss in future posts, but for the time being, you can see the code for the smoke shader <a href="http://love2d.org/forums/viewtopic.php?f=4&amp;t=3733&amp;p=167865#p167865">here.&nbsp;</a></p> <p>&nbsp;</p> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/beginners-guide-shaders"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Sun, 29 Jun 2014 12:45:53 +0000 OmarShehata 46 at http://blogs.love2d.org Let it glow! - Dynamically adding outlines to characters http://blogs.love2d.org/content/let-it-glow-dynamically-adding-outlines-characters <div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/outline">outline</a></li><li class="taxonomy-term-reference-1"><a href="/blog-terms/shader">shader</a></li><li class="taxonomy-term-reference-2"><a href="/blog-terms/outline-shader">outline shader</a></li><li class="taxonomy-term-reference-3"><a href="/blog-terms/graphics">graphics</a></li><li class="taxonomy-term-reference-4"><a href="/blog-terms/pixel-effect">pixel effect</a></li><li class="taxonomy-term-reference-5"><a href="/blog-terms/glsl">glsl</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>Hello everyone,</p> <p>I'm Micha, aka "Germanunkol". I recently took a course at university on image manipulation and was thrilled by the possibilities - fourier and hugh transformations, filters, noise - there are so many ways to make graphics look better. At the same time, so few Löve projects use shaders - and I want to contribute to changing that.</p> <p><img alt="Preview of outline shader" src="/sites/default/files/u105/Teaser.png" style="width: 400px; height: 115px;" /></p> <!--break--> <p>I decided to try implementing some of the algorithms in Löve and noticed that many of them were quite simple to write and made for great effects in a game.</p> <p>So this article aims to do two things:</p> <ol> <li><a href="#theory">The first part</a> will give an introduction to some outline-filters and some of the maths behind them.</li> <li><a href="#code">The second part</a> is more of a tutorial on how to actually create an outline shader, with the goal to get people deeper into shader programming.</li> <li>If you want to skip it all, you can download the final example from <a href="/sites/default/files/u105/Outline.love">here</a>.</li> </ol> <p>For the second part you should have some basic experience with Löve and Lua. Having used a shader before won't hurt either. I will try to cover everything you need to know about shaders in this post, but your reading the<a href="https://love2d.org/wiki/Tutorial:Introduction_to_Shaders"> introduction to shaders</a> would be a good thing as well.</p> <p>I go into a lot of detail - but don't be scared off! The final shader is relatively simple and very short.</p> <p>So let's get started!</p> <h1>Outlines? Outlines!</h1> <p>Remember when Age Of Empires II introduced unit-outlines? It was one of those great new features - being able to see your units when they're behind buildings, or behind other units.</p> <p><img alt="Age Of Empires2 Outlines - Source: http://www.moddb.com/games/age-of-empires-2-the-conquerors/downloads/xomicron-userpatch-v11" src="/sites/default/files/u105/AoE.png" style="width: 531px; height: 306px;" /></p> <p>But there's other great uses for outlines as well: You could display an outline when the mouse is hovering over a unit, showing that the player can now select this unit. Or display an outline to highlight an important UI feature. Or you could outline a power-up when the player gets close to it. You could even use it to create a hit-effect for your space ship - the number of possibilities is endless.<br /> So how could we go about creating outlines?</p> <p>The first method that might come to mind is what I'd like to call the "traditional" way:</p> <ul> <li>Fire up the GIMP, open your "skeleton.png" spritesheet or similar (which should have an alpha channel), duplicate the layer.</li> <li>Add a blur to one layer: (<em>Filters-&gt;Blur-&gt;Gaussian Blur</em> - choose a blur size of 5 by 5 pixels and blur the layer)</li> <li>Change the color: With the blurred layer selected, go to <em>Colors-&gt;Curves</em>. Play with the red, green and blue channels until you have the color you'd like for your outline. Then go to the alpha channel and increase alpha in the middle range (see image below).</li> <li>Move the outline layer below your normal layer and you have an outline!</li> <li>Save as "skeleton_outline.png"</li> </ul> <p><img alt="" src="/sites/default/files/u105/Screenshot%20from%202014-04-05%2013%3A05%3A39.png" style="width: 372px; height: 568px;" /></p> <p><img alt="Outline sample, made in the GIMP" src="/sites/default/files/u105/OutlineGimp.png" style="width: 441px; height: 150px;" /></p> <p>This is neat and pretty fast. But there are major disadvantages:</p> <ul> <li>You'll need to do this for <em>every</em> image which you want to have an outline</li> <li>"Combining" outlines will never work this way. For example: If you give the skeleton a weapon (or a bunch of flowers, for that matter), the attached object's oultine will cover parts of the skeleton - instead, what I'd like is a combined outline for the two.</li> <li>Changing color for the outline dynamically only works if you store it in a seperate image.</li> <li>Growing/Blinking/fading of the outline won't work.</li> </ul> <p>So - the traditional method won't cut it. Let's use shaders instead!</p> <h1>Part 1. The Theory<a id="theory" name="theory"></a></h1> <p>First of all: What is an outline, really? Drawing a rectangle around a rectangular image is trivial in Löve. That's not what we want to do. Instead, we want to highlight the area where there's a transition from "transparent" to "non-transparent". This area can have all kinds of shapes and will very rarely resemble a primitive which we can draw using the love.graphics functions.<br /> Since we want to highlight the <em>changes</em> of the transparency (or alpha value), we'll ignore the red, green and blue channels for now - changes in color should not affect our outline.*</p> <h5>* Using the filters on the color channels can have some neat effects as well, try it!</h5> <p>Now, to get these "changes in alpha", consider the following image:</p> <p><img alt="" src="/sites/default/files/u105/Function.svg" style="width: 400px; height: 150px;" /><br /> The left image shows some object being drawn on the screen. If we move from left to right through the image, following the red line, and note down the alpha value of every pixel we pass, then we get the plot on the right - the alpha is first 0 (transparent) and then jumps to a high value, stays at that high value while we're moving through the image and then falls back down to zero. There's two areas where the function on the right changes - these are the two areas we're interested in. Now, remember how to get the changes in a function? Exactly - we simply need to calculate the derivative:</p> <p><img alt="" src="/sites/default/files/u105/Derivative.svg" style="width: 400px; height: 150px;" /></p> <p>The plot on the right shows the derivative. It's zero where there are no changes in the function and non-zero where there are changes - just what we wanted.</p> <p>When working with images, we only have descrete coordinates, so we don't need to worry about actually calculating the derivative. Instead, there's a neat trick:<br /> For every pixel, take the alpha value of the pixel to the right and subtract from it the alpha value of the pixel to the left. Consider these two examples:</p> <p><img alt="" src="/sites/default/files/u105/Points.svg" style="width: 400px; height: 150px;" /></p> <p>In the left image, subtracting the alpha value at 9 from the alpha value at 11 yields (1-0) = 1. In the right image, (1-1) = 0. So we have a high value (1) when there's a change and a low value (0) when the alpha stays the same.<br /> The next thing we'll do is represent this equation as a filter kernel.</p> <h2>Kernels</h2> <p>A kernel is a grid, or matrix of (often 3x3) values. It is used when doing a convolution over the image.</p> <p>To calculate the convolution, you place the kernel onto the image and line it up with the pixels. Then you multiply the values which the pixels hold (in our case, only the alpha values are considered, but others can be used as well) by the values written in the kernel entries right above them, and add the results together:</p> <p><img alt="" src="/sites/default/files/u105/Filter1.svg" style="width: 450px; height: 250px;" /></p> <p>Green is the pixel we're currently looking at. The filter-kernel has an entry for each pixel surrounding our current pixel, and for the current pixel as well - so 9 altogether. For the simple derivative, we'll only need two entries, the ones to the left and the right of the current pixel. All the others will be set to zero.<br /> Each entry in the kernel tells us by how much we need to multiply the corresponding pixel before we add the results together - in our case we need to multiply the left and right neighbouring pixels by -1 and 1, respectively, and then add them together.<br /> Let's try this in the GIMP.</p> <ul> <li>Open up the GIMP, load any image file you want to process (make sure it has an alpha channel).</li> <li>Go to <em>Filters-&gt;Generic-&gt;Convolution Matrix</em>. If you enter our kernel into the pop up, you'll get the derivative (in horizontal direction) of the image. Make sure only the alpha channel is checked to get the same results as I do.</li> </ul> <p><img alt="" src="/sites/default/files/u105/Screenshot%20from%202014-04-05%2018%3A49%3A38.png" style="width: 374px; height: 569px;" /></p> <p>Result:</p> <p><img alt="" src="/sites/default/files/u105/DragonSobel.png" style="width: 400px; height: 147px; margin-left: 0px; margin-right: 0px;" /></p> <p>There is a horizontal and a vertical version for this filter:</p> <p><img alt="" src="/sites/default/files/u105/Filter2.svg" style="width: 450px; height: 250px;" /></p> <p>These kernels are often used to get to the so-called <a href="http://en.wikipedia.org/wiki/Sobel_operator">"Sobel Filter"</a> for edge detection. All we need to do is blur this matrix, which I might explain in another post one day.</p> <p>While this filter works, there's are a few drawbacks...</p> <p>You'll notice that only the edges on the left side are being shown. That's something I didn't mention before: If you go back to the above image of the alpha-function, you'll notice that at the right edge, when applying our formula, you'll get (0-1) = -1. Since this value is negative, the GIMP will ignore it (or clamp it to zero). This can be fixed by simply taking the absolute value of the derivative instead:</p> <p><img alt="" src="/sites/default/files/u105/DerivativeAbs.svg" style="width: 400px; height: 150px;" /></p> <p>However, even when having done that we still don't have any of the edges in vertical direction - and this is where this method fails. The only way to fix this is to also calculate the derivative in y direction and then add the two together.<br /> There is, however, a better method: The <a href="http://en.wikipedia.org/wiki/Laplace_filter#Image_Processing">Laplace-Filter</a><br /> Before, we calculated the derivative, a'(x). Now, we'll consider the second derivative instead, a''(x). This looks approximately like this:</p> <p><img alt="" src="/sites/default/files/u105/Derivative2.svg" style="width: 400px; height: 150px;" /></p> <p>(A note of caution here: Our original function was piecewise linear. Off course this means that the second derivative is technically zero throughout the whole image, with the exception of a few infinitifely high spikes where there are jumps in the derivative. However, the way we're calculating it makes the whole principle work, because of the way we're approximating it.)<br /> The Laplacian can be approximated by using the kernels (horizontal and vertical again):</p> <p><img alt="" src="/sites/default/files/u105/Filter4.svg" style="width: 450px; height: 250px;" /></p> <p>To get the final Laplacian, we'll add the two kernels together into one. This results in the image on the left here. There's another approximation which is commonly used, which also takes into account the diagonal values, that's the kernel on the right:</p> <p><img alt="" src="/sites/default/files/u105/Filter3.svg" style="width: 450px; height: 250px;" /></p> <p>Trying both of these in the GIMP again gives us some nice results:</p> <p><img alt="" src="/sites/default/files/u105/DragonLaplace2.png" style="width: 400px; height: 147px;" /></p> <p>This looks good. So this will be the filter we'll use.<br /> Enough theory, let's get coding...</p> <h1>Part 2: The Shader<a id="code" name="code"></a></h1> <h2>Tutorial Framework</h2> <p>To speed things up, I've created a quick n' dirty tutorial framework. It creates two animated characters and lets them walk in an endless loop.</p> <p><strong>Download the framework from <a href="/sites/default/files/u105/TutorialFramework.love">here</a>.</strong></p> <p>Alternatively, you can also clone the repository on your command line using:</p> <pre> git clone https://github.com/Germanunkol/ShaderTutorialFramework.git</pre> <h2>The Shader:</h2> <p>We'll need a new file called "outline.glsl". Create the file in the same folder as main.lua.<br /> Into this file, put the following code:</p> <pre> vec4 effect( vec4 col, Image texture, vec2 texturePos, vec2 screenPos ) { // simply return the color at the current coordinates: return texture2D( texture, texturePos ); }</pre> <p><br /> Short explanation:</p> <p>Whenever the shader is active, the "effect" function will be called once for every pixel which is drawn. So if we draw a 32x32 pixel image, it'll run for each of the 32*32 = 1024 pixels.<br /> The "col" argument gives us the currently set color, which we won't need for this shader.<br /> The second argument is the image being drawn.<br /> The third argument holds the coordinates for the pixel we're currently drawing - in texture-space (i.e. "Which pixel of the texture are we drawing"), ranging from 0 to 1.<br /> The last argument holds the coordinates of the pixel on the screen (i.e. "Where on the screen are we drawing the pixel") - again something we won't need for this shader.</p> <p>Inside the function, all we do for now is a texture-lookup: texture2D is a function that simply returns the color of the pixel in the given texture, at the given coordinates. So the shader does not modify anything at the moment - it simply draws the image.<br /> To make sure it's all working, though, let's try setting the shader:<br /> Open up character.lua and add this to the Character:new() function (before the "return o"):</p> <pre class="brush: lua"> o.shader = love.graphics.newShader( "outline.glsl" )</pre> <p>This creates a new shader for every character which is created.**<br /> Go down to Character:draw() and modify it to look like this:</p> <pre class="brush: lua"> function Character:draw() love.graphics.setShader( self.shader ) love.graphics.draw( self.img, quads[self.frame], self.x, self.y ) love.graphics.setShader() end</pre> <p>This enabled the shader before drawing the character, and disables the shader again after drawing it.<br /> Run the project (using "love ." or similar) to test if it's working. You should see two characters walking side by side.</p> <h5>** This is probably not an ideal solution if you have loads and loads of characters or units. In that case, you should create only one shader, globally, and then re-use it whenever you need it. That's not really more difficult, but if you want to assign custom values to the shader for your different units (green outlines for friendly units, red for enemies and blue for drunk skeletons?) you'll need to send them every frame before using the shader - that's why I didn't choose this method here.</h5> <p>To see if the shader is working, modify your outline.glsl to this:</p> <pre> vec4 resultCol; vec4 textureCol; vec4 effect( vec4 col, Image texture, vec2 texturePos, vec2 screenPos ) { textureCol = texture2D( texture, texturePos ); resultCol = vec4( 1.0f, 1.0f, 1.0f, textureCol.a ); return resultCol; }</pre> <p>We perform the texture lookup as before, but then instead of returning that color, we return a modified color where the red, green and blue channels are set to white and only the alpha channel is perserved (textureCol.a gives the alpha of the textureCol color, textureCol.r would give the red value and so on). Run the code - what you should see now is the two characters walking, but they should be plain white. That's what the 1.0, 1.0, 1.0 does.</p> <p>Now let's create the outline!</p> <p>The outline should be composed of two things:</p> <ul> <li>The alpha of the outline (i.e. where it is showing) should be given by the second derivative (more precisely the laplacian) of the input image.</li> <li>The color of the outline should be a fixed color for now.</li> </ul> <p>Let's focus on the first point for now.<br /> Remember, what we need to do is: For every pixel we add together the alpha of the 4 nearest surrounding pixels. Then we subtract the result from 4 times the alpha of the current pixel.<br /> The math is simple. Imagine the function alpha(x, y) can get the alpha of the pixel which is found at an offset of x and y from the current pixel (alpha(0,0) being the alpha of the current pixel) then we can calculate the new alpha as:</p> <pre> alpha = 4*alpha(0,0) - ( alpha(-1,0) + alpha(0,-1) + alpha(1,0) + alpha(0,1) )</pre> <p>In GLSL, we can do this by adding to the texture coordinates, before we do the texture-lookup:</p> <pre> ... { number alpha = 4*texture2D( texture, texturePos ).a; alpha -= texture2D( texture, texturePos + vec2( 0.001f, 0.0f ) ).a; alpha -= texture2D( texture, texturePos + vec2( -0.001f, 0.0f ) ).a; alpha -= texture2D( texture, texturePos + vec2( 0.0f, 0.001f ) ).a; alpha -= texture2D( texture, texturePos + vec2( 0.0f, -0.001f ) ).a;</pre> <p>Note that we're adding small values like 0.001 to the position for now - this is because the texturePos values range from 0 to 1 (not from 0 to 64 as in our image). If we'd add 1 (or subtract 1, for that matter), we'd move the coordinates not by one pixel, but by the width of the whole image!<br /> Now let's calculate the final color:</p> <pre> // calculate resulting color resultCol = vec4( 1.0f, 1.0f, 1.0f, alpha ); // return color for current pixel return resultCol; } ...</pre> <p>If we run the game now, we'll see our first outline - hooray!</p> <p><img alt="" src="/sites/default/files/u105/Screenshot%20from%202014-04-06%2009%3A27%3A49.png" style="width: 219px; height: 116px;" /><br /> However if you look closely, you'll see that the outline is a bit thicker at the top and bottom than it is at the right and left - why is that?<br /> Well, to get the coordinates of the "neighbouring pixels", we used a very naive approach: we just added "0.001" to the coordinates, both in x and y direction. Since these are texture coordinates, what that means is "go 0.001 of the image width into the x direction and 0.001 of the image height into the y direction". Since image width and image height of the spritesheet image we're using are <em>not</em> the same (open up skeleton_3.png and you'll see), we're actually moving further up and down than right and left when we try to get "neighbouring" pixels. This effect would be even more noticable if the width and height of our image went more into the extreme - a 20x400 image, for example, would not look good any more.<br /> Instead, we should try to go exactly one pixel left and right.<br /> To do that, let's add a new variable, called "stepSize". This variable will tell us how much we should go left and right, or up and down, in order to move by exactly one pixel. Since we need two different values for horizontal or vertical movement, we make it a "vec2", which holds two values. Add this line at the beginning of the shader (outside the effect funtion):</p> <pre> extern vec2 stepSize;</pre> <p>We add the keyword "extern" to make sure this variable can be modified from within our Lua code.<br /> Now, instead of the previous fixed value of 0.001, let's use stepSize in our code:</p> <pre> number alpha = 4*texture2D( texture, texturePos ).a; alpha -= texture2D( texture, texturePos + vec2( stepSize.x, 0.0f ) ).a; alpha -= texture2D( texture, texturePos + vec2( -stepSize.x, 0.0f ) ).a; alpha -= texture2D( texture, texturePos + vec2( 0.0f, stepSize.y ) ).a; alpha -= texture2D( texture, texturePos + vec2( 0.0f, -stepSize.y ) ).a;</pre> <p>But how do we calculate the correct step size?<br /> Open up characters.lua again, and jump, once again, to the Character:new() function. After the creation of the shader, add this line:</p> <pre class="brush: lua"> o.shader:send( "stepSize",{1/o.img:getWidth(),1/o.img:getHeight()} )</pre> <p>What we do is: We send two values to the "stepSize" variable of the shader. By using 1/width and 1/height, we get exactly distance between two pixels. (If you're confused by that, think of is this way: If the image is 4 pixels wide and 4 pixels high, then stepSize will now hold the values {1/4, 1/4}, or {0.25, 0.25}. Now imagine we're running the effect function for the pixel 1,2. In the effect function, the texturePos variable will now hold {0.25, 0.5}. So adding and subtracting the value 0.25 from it, we'll get the coordinates shown in the following picture:</p> <p><img alt="" src="/sites/default/files/u105/TextureCoords.svg" style="width: 450px; height: 250px;" /></p> <p>These are exactly the neighbouring pixels which we want. So the 1/width, 1/height thing did just what we wanted - it calculated the distance in horizontal and vertical direction between pixels in GLSL's texture coordinates.)</p> <p>Now run the program again - and voilà, we have a pretty outline!</p> <h2>Making it prettier:</h2> <p>To change the color of the outline, you can try changing the line which calculates the resultCol to something like:</p> <pre> resultCol = vec4( 0.2f, 1.0f, 0.1f, alpha );</pre> <p>To add the outline ontop of the original image, simply draw the image twice, once without and once with outline shader applied:</p> <pre class="brush: lua"> function Character:draw() love.graphics.draw( self.img, quads[self.frame], self.x, self.y ) love.graphics.setShader( self.shader ) love.graphics.draw( self.img, quads[self.frame], self.x, self.y ) love.graphics.setShader() end</pre> <p>And, most importantly: To make it thicker, play with the stepSize values. Higher values create thicker lines:</p> <pre class="brush: lua"> o.shader:send( "stepSize",{3/o.img:getWidth(),3/o.img:getHeight()} )</pre> <h1>Closing remarks:</h1> <ul> <li>You can download the final example <a href="/sites/default/files/u105/Outline.love">here</a>.</li> <li>If you want to display the outline even when the character is behind a wall or similar, simply draw the character first (without shader applied), then draw the walls and then draw the outlines above the walls.</li> <li>We can make the outline shader even prettier if we blur the image using a shader before rendering the outline, or if we blur the outline after creation. I'll leave both of these methods for a possible future blog post, though.</li> <li>If you have any questions or comments, feel free to <a href="https://love2d.org/forums/memberlist.php?mode=viewprofile&amp;u=54284">write me a pm</a> in the forums.</li> </ul> <h2>Sobel filter:</h2> <p>For completeness' sake, here's the approach mentioned above, using the plain derivative (in horizontal direction - it can easily be modified to the vertical direction). Here, no blur is being applied, but you can add that as well by using the Sobel filter kernels above.</p> <pre> vec4 resultCol; extern number stepSize; number alpha; vec4 effect( vec4 col, Image texture, vec2 texturePos, vec2 screenPos ) { // get color of pixels: alpha = texture2D( texture, texturePos + vec2(0,-stepSize)).a; alpha -= texture2D( texture, texturePos + vec2(0,stepSize) ).a; // calculate resulting color resultCol = vec4( 1.0f, 1.0f, 1.0f, 0.5f*alpha ); // return color for current pixel return resultCol; }</pre> <p>The skeleton and spearman images used in this post come from OpenGameArt.org and are licensed under the creative commons license. See the following link for authors and copyright information. Thanks to the authors for making these accesible!</p> <ul> <li><a href="http://opengameart.org/content/lpc-skeleton">lpc-skeleton</a></li> <li><a href="http://opengameart.org/content/spear-walk">spear-walk</a></li> </ul> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/let-it-glow-dynamically-adding-outlines-characters"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Sat, 05 Apr 2014 17:43:07 +0000 Germanunkol 37 at http://blogs.love2d.org Lövely Code #01 - Ternary Operations http://blogs.love2d.org/content/l%C3%B6vely-code-01-ternary-operations <div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/lua">lua</a></li><li class="taxonomy-term-reference-1"><a href="/blog-terms/ternary">ternary</a></li><li class="taxonomy-term-reference-2"><a href="/blog-terms/lovely-code">lovely code</a></li><li class="taxonomy-term-reference-3"><a href="/blog-terms/elegance">elegance</a></li><li class="taxonomy-term-reference-4"><a href="/blog-terms/flow-control">flow control</a></li><li class="taxonomy-term-reference-5"><a href="/blog-terms/expressions">expressions</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>Hello world, err, lövers! My name is Dale James and I'm writing to introduce you to one of my favourite things you can do in Lua, which is called a <em>Ternary Operation</em>.</p> <p>I grew up playing video games - my first gaming machine was a <a href="en.wikipedia.org/wiki/Commodore_64" title="C64">Commodore 64</a> (which I still have, somewhere, with a neat collection of tapes). The more games I played, the more I dreamed of being able to produce my own games. Still to this day whenever I play a game I consider how it was built, what works well and how I could improve it. I have no formal education in programming of any sort, except maybe those 2 lectures I attended for ActionScript, but I'm not sure they count as I remember correcting the lecturer several times. I spent countless hours after school messing with lots of (what I now consider to be) awful frameworks and engines, so you could imagine the rush I got when I first discovered the <strong>pure awesomeness that is Löve</strong>. No other 2D framework comes close to it in terms of <em>elegance</em>, <em>ease of use</em>, and <em>documentation</em> (oh, <a href="https://www.love2d.org/wiki/Main_Page" title="that wiki!">that documentation!</a>).</p> <p>This series of articles, dubbed <a href="/blog-terms/lovely-code" title="Lovely code tag.">Lövely Code</a>, is intended to focus on the elegance that blossoms from Löve and Lua. Writing elegant code is very rewarding, fun, and it just looks so darn cool! So, on to Lövely Code #01:</p> <p><em>This article assumes that you have a basic knowledge of Lua concepts, particularly data types and expressions.</em></p> <h1>Ternary?</h1> <p>Many readers may not be aware of the concept of a ternary operator or operation. In Lua we have access to several types of operation - unary, binary and ternary.</p> <p>A <em>unary</em> operation is an expression with a single operand, or a single 'input value'. According to <a href="http://www.lua.org/manual/5.1/manual.html#2.5" title="Lua 5.1 Ref Manual">the Lua 5.1 Manual</a>, Lua features three types of unary operators:</p> <pre class="brush: lua"> a = -1 --negation b = not x --logical negation c = #"purple" --length, works with tables & strings </pre> <p>A <em>binary</em> operation is an expression with two operands. I bet you can see where this is going. There are lots of binary operators so I'll just list a few of them:</p> <pre class="brush: lua"> a = 1000 + 337 --need I explain this? b = a or 1337 --if a is nil or false then b becomes 1337 c = b > 9000 --c becomes true if b is over 9000 d = a --also binary! e = "some" .. "thing" --concatenation is actually a binary operator </pre> <p>Now here's the fun part.</p> <p>As you may have guessed, a <em>ternary</em> operation is one that has <strong>three</strong> operands. <em>"Three?!"</em> you say? <em>"How does that work? "</em>, you ask, or <em>"Prey tell how this most elusive of operations achieves its resolution, old chap"</em>, if you're English like myself, of course I wrote this article whilst wearing my best top hat and monocle, curling my mustache, and eating a lime.</p> <p>It's actually rather simple. A ternary operation is often used as a substitute for an <code>if/then/else</code> statement.</p> <h1>Delve Into the Secrets</h1> <p>In C-like languages there does exist an operator for ternary expressions, but Lua being Lua, we are treated to a much more elegant and human-readable method for creating these most wondrous of wonders; a combination of <code>and</code> / <code>or</code> operators makes for a beautifully simple ternary operation.</p> <pre class="brush: lua"> --a simple if/then/else... if a then x = b else x = c end --is equivalent to: x = a and b or c --three operands! </pre> <p>Whoah! What's going on there?! It's actually pretty simple if you break the expression down and evaluate it in the same manner as the Lua VM. If we check the manual for <a href="http://www.lua.org/manual/5.1/manual.html#2.5.6">order of precedence</a> we find that <code>and</code> is always evaluated <em>before</em> <code>or</code>. We also know that an <code>and</code> statement outputs the rightmost operand if the left is <code>true</code>, and that <code>or</code> outputs the left unless is it <code>false</code>. Sound confusing? Let's look at this in a way we can all understand.</p> <h1>To The Terminalmobile!</h1> <p>I recommend opening up a Lua console and following along. Start a new Lua session and try each line in sequence.</p> <pre class="brush: lua"> x = a and b or c print(x) </pre> <p>Our original statement. This would actually always evaluate to nil since we have not specified <code>a</code>, <code>b</code> or <code>c</code>, so let's give ourselves some sample values to work with.</p> <pre class="brush: lua"> a = 11 b = "variable b" c = "variable c" </pre> <p>Now, we're going to use the same expression as above. Before you run the command, take a moment to consider what the output will be...</p> <p>Ready? Then let's try it!</p> <pre class="brush: lua"> x = a and b or c print(x) </pre> <p>You should see the output <code>variable b</code>. What happened is that we said <em>"if <code>a</code> is <code>true</code> then <code>x</code> is equal to <code>b</code>, otherwise it is equal to <code>c</code>"</em>. We did <code>a = 11</code>, which in Lua means that <code>if a then</code> will evaluate to <code>true</code>. Just like a basic <code>if/then/else</code>!</p> <p>So what happens if <code>a</code> is not <code>true</code>? Go ahead, try it:</p> <pre class="brush: lua"> x = not a and b or c print(x) </pre> <p>This time you should see the output <code>variable c</code>. Similarly to before, this is because we said <em>"if <code>not a</code> is <code>true</code> then <code>x</code> is equal to <code>b</code>, otherwise it is equal to <code>c</code>"</em>. This time, <code>not a</code> evaluates to <code>false</code>. Allow me to demonstrate what is going on here (<strong>there is no need to input this block into your terminal</strong>):</p> <pre class="brush: lua"> x = not a and b or c --equivalent to x = false and "variable b" or "variable c" --equivalent to x = (false and "variable b") or "variable c" --equivalent to x = false or "variable c" --equivalent to x = "variable c" --tada! </pre> <p>Got it now? This is how a ternary expression works. As you can see, it's actually very simple once you understand the nature of <code>and</code>/<code>or</code>.</p> <p>Let's try another example:</p> <pre class="brush: lua"> x = a < 10 and b or c </pre> <p>Oh my science. Just what is going on there?! Now we have a <em>binary</em> expression embedded in our <em>ternary</em> expression........! Don't be fooled: this is simple stuff. <em>"How can you say that?!"</em> you yell at me. Well, if we consider that our ternary expression is rather like an <code>if/then/else</code> we see that it is indeed simple stuff (<strong>no need to execute this block either</strong>):</p> <pre class="brush: lua"> if a < 10 then x = b else x = c end </pre> <p>That wasn't so painful was it? So now if we go back and output our new <code>x</code>, what would we see?</p> <pre class="brush: lua"> print(x) </pre> <p>You should see <code>variable c</code> again. This is because our value <code>a</code> is greater than 10: <code>a &lt; 10 = false</code>. Go ahead and change the binary expression to use greater-than:</p> <pre class="brush: lua"> x = a > 10 and b or c </pre> <p>We are all over this now! We know what's going happen here! Our <code>x</code> is going to equal <code>variable b</code>, just like you expected.</p> <h1>The Cave(at)</h1> <p>One important thing to note when writing ternary operations is that <strong>the 'middle' operand cannot be <code>false</code>/<code>nil</code></strong> (<code>b</code> in our example) ! This is because of the nature of <code>and</code>/<code>or</code>. Try it and see what happens.</p> <pre class="brush: lua"> x = nil and nil or true x = nil or true x = true --or x = true and nil or true x = nil or true x = true </pre> <p>However, if you need this type of operation, you can simply 'invert' the operands:</p> <pre class="brush: lua"> x = a == nil and b or a --solved. x = a == nil and b == false or a --don't do this! </pre> <h1>A Winner Is You</h1> <p>Congratulations, you just learned how to write ternary expressions!</p> <p>Throughout this article I have repeatedly stated that this is a simple concept. In reality, it can be hard to understand at first, but once you get it, it becomes a beautifully simple, elegant way to form expressions in your code.</p> <p>So where exactly should you be using these <a href="http://www.youtube.com/watch?v=xrGWooNDPiE" title="adventure">most excellent</a> operations?</p> <p>There is no universal answer. Fear not though, for there are guidelines! Try to avoid convoluted ternary statements, after all we write them for our own sake; use them to make your programs more readable, more elegant, more lövely. An interesting example could be for setting a variable based on whether another exists or not (or setting a default), the condition is also the 'middle' operand:</p> <pre class="brush: lua"> --if statement basis if a then x = a else x = b end --could also be x = a and a or b --this can be further simplified to (and avoids the caveat!) x = a or b --this binary operation tastes great with functions </pre> <p>Code to die for.</p> <p>For further reading, as always I recommend <a href="http://lua-users.org/wiki/TernaryOperator" title="Lua-Users Ternary Operator Tutorial">lua-users.org</a> which is where I learned how to write these, and many other Lua concepts. You may find there that more complex forms of the ternary operation can be written, but they truly are complex and are (waaaaay) beyond the scope of this document.</p> <p>I hope you have enjoyed this article, the first in the Lövely Code series.</p> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/l%C3%B6vely-code-01-ternary-operations"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Mon, 15 Apr 2013 23:34:58 +0000 Lafolie 34 at http://blogs.love2d.org Using Noise in Pixel Shaders http://blogs.love2d.org/content/using-noise-pixel-shaders <div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/glsl">glsl</a></li><li class="taxonomy-term-reference-1"><a href="/blog-terms/shader">shader</a></li><li class="taxonomy-term-reference-2"><a href="/blog-terms/pixel-effect">pixel effect</a></li><li class="taxonomy-term-reference-3"><a href="/blog-terms/pixel-shader">pixel shader</a></li><li class="taxonomy-term-reference-4"><a href="/blog-terms/perlin-noise">perlin noise</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>Note: this was written for LÖVE 0.8.0, since 0.9.0 the semantics for shaders have changed with the addition of vertex shaders. I have updated the code snippets so they hopefully with work in 0.9.0 but the downloadable examples will be incompatible.</p> <p>My name is Mark Wonnacott and I’m a Computer Science student at the University of Bristol in the UK. I’m a hobbyist game developer and I am enamoured with the ease and accessibility of LÖVE and its accompanying libraries.</p> <p>Like a lot of game development amateurs, I got into programming because I wanted to make games. I’m not an artist, game designer, or audio guy, but I like to have a go at it all. Lately I’ve been playing around with visual effects in LÖVE and having a lot of fun.</p> <p>In this post I’m going to give a very practical start to playing with visual effects in LÖVE, especially using noise. So many things are possible and so much work has already been done, but hopefully this post will give you a starting point for your own exploration.</p> <!--break--> <h1>Pixel Effect Primer</h1> <p>Pixel effects are one of the most powerful features of LÖVE, allowing you to create advanced per-pixel visual effects that exploit hardware acceleration. They’re fairly simple to pick up, and are really fun to play around with.</p> <p>Setting up a LÖVE pixel effect is really easy: compile the effect when you load, optionally send data to the effect when you update, and then turn the effect on before you draw things.</p> <p><a href="http://blogs.love2d.org/sites/default/files/u54/noise-ex-1.love">Download Example 1</a></p> <pre class="brush: lua"> function love.load() screen = love.graphics.newShader([[ vec4 effect(vec4 colour, Image image, vec2 local, vec2 screen) { // red and green scale with proportion of screen coordinates vec4 screen_colour = vec4(screen.x / 512.0, screen.y / 512.0, 0.0, 1.0); return screen_colour; } ]]) texture = love.graphics.newShader([[ vec4 effect(vec4 colour, Image image, vec2 local, vec2 screen) { // red and green components scale with texture coordinates vec4 coord_colour = vec4(local.x, local.y, 0.0, 1.0); // use the appropriate pixel from the texture vec4 image_colour = Texel(image, local); // mix the two colours equally return mix(coord_colour, image_colour, 0.5); } ]]) image = love.graphics.newImage("love-logo.png") end function love.draw() love.graphics.setShader(screen) love.graphics.triangle("fill", 0, 0, 0, 512, 512, 0) love.graphics.triangle("fill", 256, 256, 256, 512, 512, 256) love.graphics.triangle("fill", 384, 384, 384, 512, 512, 384) love.graphics.setShader(texture) love.graphics.draw(image, 256, 256, 0.5, 3, 3, 44.5, 44.5) end</pre> <p><img src="http://you.mongle.me/love/noise-post/001.png" style="width: 192px; margin-left: 5px; margin-right: 5px;" /><img src="http://you.mongle.me/love/noise-post/002.png" style="width: 192px; margin-left: 5px; margin-right: 5px;" /></p> <p><em><strong>Left:</strong> A pixel effect that colourizes the image based on the texture coordinates; the closer x is to 1, the redder the pixel, the closer y is to 1, the greener the pixel. <strong>Right:</strong> Three triangles with colour entirely determined by screen coordinates; the closer x is to the screen width, the redder the pixel, the closer y is to the screen height, the greener the pixel (notice that screen coordinates count from the bottom in pixel effects).</em></p> <p>In simple terms, a LÖVE pixel effect is a function for choosing the colour and transparency of each pixel of a polygon when it is drawn (when you draw an image, you are actually drawing a rectangle where the colour and transparency of pixels is determined from the image data as well as the draw colour). Effects can base that choice on the current draw colour, the screen coordinates of the pixel, and any data sent from the LÖVE program itself; if a sprite is being drawn, then the full image data and the texture coordinates of the pixel are also available. This might seem a little difficult to understand at first, but when you start playing around with effects based on these variables, you can quickly get a feel for how they work.</p> <p>Pixel effects are written in a language called GLSL, and <a href="https://bitbucket.org/vrld/love-glsl">LÖVE adds some aliases</a> to make things a little more friendly. It’s really not very difficult to learn, the syntax is a lot like C and there are many helpful functions to help you do common things.</p> <h1>Introduction to Noise</h1> <p>Noise is unpredictable data, and is used in computer graphics to generate natural looking structures, patterns and textures. By incorporating noise into pixel effects you can create visual effects that don’t have obvious repetition or geometric pattern but also don’t depend on pre-made textures and images; you can also very easily animate the effects.</p> <p>Nearly all noise used in computer graphics is gradient noise, which is very different to value noise found in random number generators. Value noise is what you see in visual static; every pixel having a completely random brightness independent of any other. Gradient noise has inherent structure that makes neighbouring pixels similar, giving a smooth noise that is much more suited to creating interesting effects.</p> <p>The most popular type of noise in computer graphics is Perlin; it is also often used in terrain generation because it has the appearance of random hills. Another type of noise is Worley noise, which is also known as cellular noise because it has the appearance of being divided into cells.</p> <p><img src="http://you.mongle.me/love/noise-post/003.png" style="height: 192px; width: 192px; margin-left: 5px; margin-right: 5px;" /><img src="http://you.mongle.me/love/noise-post/004.png" style="height: 192px; width: 192px; margin-left: 5px; margin-right: 5px;" /><img src="http://you.mongle.me/love/noise-post/005.png" style="height: 192px; width: 192px; margin-left: 5px; margin-right: 5px;" /><br /> <em><strong>Left:</strong> Uniform value noise. <strong>Middle:</strong> Perlin gradient noise. <strong>Right:</strong> Worley gradient noise (also known as cellular noise).</em></p> <h1>Using Noise in Pixel Effects</h1> <p>Using noise in LÖVE pixel effects couldn’t be easier; there are some GLSL implementations of various types of noise online, but better yet I have collected a lot of them together for you. Using noise is as simple as loading the GLSL into a string, prepending it to your existing effect and then calling the noise function within the effect. The noise functions take a vector of inputs; typically spatial dimensions, but you can put in anything you like, and you can get some really great animation by using time as an extra dimension.</p> <p><a href="http://blogs.love2d.org/sites/default/files/u54/noise-ex-2.love">Download Example 2</a></p> <pre class="brush: lua"> function love.load() -- load the noise glsl as a string local perlin = love.filesystem.read("perlin2d.glsl") -- prepend the noise function definition to the effect definition noise = love.graphics.newShader(perlin .. [[ vec4 effect(vec4 colour, Image image, vec2 local, vec2 screen) { // scale the screen coordinates to scale the noise number noise = perlin2d(screen / 128.0); // the noise is between -1 and 1, so scale it between 0 and 1 noise = noise * 0.5 + 0.5; return vec4(noise, noise, noise, 1.0); } ]]) end function love.draw() -- draw a full screen rectangle using the effect love.graphics.setShader(noise) love.graphics.rectangle("fill", 0, 0, 512, 512) end</pre> <h1>Cool Things to Try</h1> <p>People have been using gradient noise to create cool effects for a long time and so there is a wealth of stuff to find online on the subject. I have put a little effect browser together using Quickie to make it easy to play around with different pixel effects.</p> <p><a href="http://blogs.love2d.org/sites/default/files/u54/noise-browser.love">Download Effect Browser</a> (Zoom with the mouse wheel, pan with right click, press space to move to the next effect, press enter to toggle the stencils)</p> <p><img src="http://you.mongle.me/love/noise-post/007.png" style="width: 192px; margin-left: 5px; margin-right: 5px; margin-bottom: 5px;" /><img src="http://you.mongle.me/love/noise-post/009.png" style="width: 192px; margin-left: 5px; margin-right: 5px; margin-bottom: 5px;" /><img src="http://you.mongle.me/love/noise-post/006.png" style="width: 192px; margin-left: 5px; margin-right: 5px; margin-bottom: 5px;" /><img src="http://you.mongle.me/love/noise-post/010.png" style="width: 394px; margin-left: 5px; margin-right: 5px;" /></p> <p><em><strong>Left:</strong> Using Worley noise as the saturation for a blue hued surface to create a water effect (it looks great when animated in the time dimension). <strong>Middle:</strong> Stencils can be used to draw the effects onto polygons. <strong>Right:</strong> By continually adding scaled Perlin noise together you can create a smokey effect. This fractal noise is often used for terrain generation because of the varied scales of natural-looking detail. <strong>Bottom:</strong> I combine the first two techniques in a game I'm currently working on.</em></p> <h1>Conclusion</h1> <p>Pixel effects aren’t too difficult to learn, and noise can be easily used to detailed and interesting effects; the real magic is finding new ways to use it. Play with effects and see what you can come up with; my effects browser makes it easy to observe the of effect changing different variables, so modify it for your needs.</p> <p>If you have any problems, questions comments, or make any cool effects: please comment!</p> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/using-noise-pixel-shaders"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Tue, 02 Apr 2013 14:31:43 +0000 Ragzouken 32 at http://blogs.love2d.org LÖVE 1.0 "Moar Bacon" Released http://blogs.love2d.org/content/l%C3%B6ve-10-moar-bacon-released <div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/love3d">love3d</a></li><li class="taxonomy-term-reference-1"><a href="/blog-terms/new-release">new release</a></li><li class="taxonomy-term-reference-2"><a href="/blog-terms/moar-bacon">moar bacon</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>LÖVE 1.0 "Moar Bacon" Released</p> <p>The dev team, after months of secrecy, are proud to announce the newest release of LÖVE; "Moar Bacon". Here are some quotes that were recorded from <code>#love-supersecretclub</code>;</p> <pre><code>&lt;Bartbes&gt; I've been working day and night on this release, and it was totally worth dropping out of school to meet this deadline. I just love everyone that much! &lt;Slime&gt; I am disappointed with everyone so far. I have been popping caffeine pills for the last two months, 24 hours a day, seven days a week to meet this deadline. In my free time, I've been preparing for love 0.9.0 as well. &lt;VRLD&gt; I have decided to approach the 1.0 release like Grand Theft Auto. If I can kill everyone and get away with it, I know I will have won. &lt;Bmelts&gt; ... &lt;Rude&gt; My hands are bleeding! I can't take it any more! This is the end! </code></pre> <p>Some new features that are available to you right now!</p> <ul> <li>Full sandboxing including mice and keyboard usage.</li> <li>Complete 3D rendering.</li> <li>Full iOS integration.</li> <li>Renaming <code>love.graphics</code> to <code>love.stuff</code> to improve clarity.</li> <li>Added <code>--obfusicate</code> flag to get rid of those pesky hackers!</li> <li>Added full HTML rendering</li> <li>Added in-game internet browser, Internet Explorer 5.5</li> <li>Automatic facebook and twitter integration.</li> <li>Updating the Lua 5.1 interpreter with PHP 5.4.13</li> <li>Every single module available within the luarocks community.</li> <li>MySQL, PostgreSQL, MariaDB and MSSQL.</li> <li>Removed the illusive <code>love.setColor</code></li> <li>SVN, CVS and Mercurial integration.</li> <li>All cute characters have now been replaced by occult lovecraftian artwork.</li> <li>Three new networking libraries.</li> <li>Moar bacon.</li> <li>Apple Newton branch.</li> <li>All that crappy 2D stuff has been removed.</li> <li>Adding the Qt GUI framework.</li> <li>love.filesystem now can use ImageData instead of file locations.</li> <li>New exciting proprietary license.</li> <li>Dropping support for crappy OS's like linux.</li> <li>Added linux man page.</li> </ul> <p>And to top things off, the developers have gone through the issue tracker, and <strong>added every single feature requested</strong>!</p> <p>Get the source code now!: <a href="https://bitbucket.org/rud3/love3d">https://bitbucket.org/rude/love3d</a></p> <p>UPDATE:</p> <p>Upcoming changes that the love community administration has informed me about;</p> <ul> <li>Replacing the forums with <a href="http://en.wikipedia.org/wiki/Imageboard">imageboard software</a>.</li> </ul> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/l%C3%B6ve-10-moar-bacon-released"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Mon, 01 Apr 2013 13:32:28 +0000 josefnpat 33 at http://blogs.love2d.org Quick Snips: Delta Time http://blogs.love2d.org/content/quick-snips-delta-time <div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/dt">dt</a></li><li class="taxonomy-term-reference-1"><a href="/blog-terms/delta-time">delta time</a></li><li class="taxonomy-term-reference-2"><a href="/blog-terms/delta">delta</a></li><li class="taxonomy-term-reference-3"><a href="/blog-terms/time">time</a></li><li class="taxonomy-term-reference-4"><a href="/blog-terms/timesteps">timesteps</a></li><li class="taxonomy-term-reference-5"><a href="/blog-terms/step">step</a></li><li class="taxonomy-term-reference-6"><a href="/blog-terms/timestepping">timestepping</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><address>This is a new series I want to work on called "Quick Snips". These are articles that are short and quick, and covers mainly the small stuff that people mostly ignore and take for granted that it is a required thing to create good games.</address> <address>&nbsp;</address> <p>In this article, we will talk about one (slightly mysterious)&nbsp;variable in love.update(), known as dt or Delta Time.</p> <h1>What is DT?</h1> <p>Delta Time, also known as dt,&nbsp;is how much time has passed between 2 frames, hence the "delta" part of the word. Delta Time is also&nbsp;approximately equal to the reciprocal of the current frames per second (FPS), and consequently, FPS is approximately equal to&nbsp;the reciprocal of Delta Time:</p> <pre class="brush: lua"> dt = 1/fps fps = 1/dt </pre> <p>Let's look at one way to use DT.</p> <h1>Counting seconds</h1> <p>One way to use DT is to count&nbsp;time, as DT multiplied by FPS is approximately equal to 1 second. You can do that by adding a global timer variable and adding the DT variable to it.</p> <p>Here's an implementation of a simple timer using love.update(dt).</p> <pre class="brush: lua"> timer = 0 function love.update(dt) -- this adds dt every frame, adding 1 every second timer = timer + dt -- this checks if timer is greater than the time interval (in seconds) if timer &gt;= timeInterval then -- subtract timer by interval timer = timer - timeInterval -- event end end </pre> <p>You can use this to fire events, for example, fire bullets every 1 second, or reload a gun every 5 seconds.</p> <p><em>Note:</em> Do <b>not</b> declare timer inside the love.update(dt) function! That will reset the timer every frame, which is not what we wanted.</p> <h1>Constant speed</h1> <p>Another way to use DT is to make objects move at constant speed. By&nbsp;<em>constant</em> I mean that it ideally looks the same at any framerate (I said ideally because DT isn't exact, but it's okay for most purposes). You can do that by multiplying the speed by DT. This has the effect of the object moving at that speed&nbsp;every second.</p> <pre class="brush: lua"> function love.update(dt) -- this has the effect of moving at a set speed every second, for example, 500 pixels every second object.x = object.x + speed*dt end </pre> <h1>Constant Acceleration</h1> <p>Another way to use DT is to add constant acceleration. Like before, by&nbsp;constant I mean it looks the same at any machine, slow or fast. You can do this by adding speed by acceleration multiplied by dt.</p> <pre class="brush: lua"> function love.update(dt) speed = speed + accel*dt object.x = object.x + speed*dt end </pre> <h1>Why use Delta Time?</h1> <p>So, why do you want to use DT? Well, here are the 2 main reasons:</p> <ul> <li>So that the movement of your objects looks, ideally, the same at any machine, slow or fast.</li> <li>Because it is easy to keep track of time using DT other than&nbsp;LÖVE's other timing functions.</li> </ul> <p>Well, that's pretty much the reasons why you would want to use DT.</p> <p>Alright, I'm done with this article, I hope you learned why many lovers (pretty much every non-beginner) use DT. Any typos or suggestions? Comment here, or send me a PM in the&nbsp;LÖVE Forums!</p> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/quick-snips-delta-time"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Fri, 29 Mar 2013 22:03:53 +0000 substitute541 21 at http://blogs.love2d.org First-class Functions http://blogs.love2d.org/content/first-class-functions-0 <div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/lua">lua</a></li><li class="taxonomy-term-reference-1"><a href="/blog-terms/functions">functions</a></li><li class="taxonomy-term-reference-2"><a href="/blog-terms/first-class">first-class</a></li><li class="taxonomy-term-reference-3"><a href="/blog-terms/concepts">concepts</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p><em>This is part one of a two-part blog post on taking advantage of first-class functions in Lua. Part one explains the inner workings of first-class functions from both a generic computer science perspective, and how you implement that within Lua. Part two puts all the theory together to create a lean version of an Entity Manager.</em></p> <!--break--> <h2>First-class boarding, now available!</h2> <p>Beyond the simplest of problems, a program needs variables in order to store, manipulate, and maintain some important value. Typically, we think of variables as some number value, or a string of characters. When dealing with programs of greater complexity, we begin to think about collections of these atomic units (in Lua, this is accomplished through the monolithic table). Part of being a variable usually requires that you must have some guarantees:</p> <ul> <li>You must be able to be stored;</li> <li>You must be able to be passed as a parameter to a subroutine <em>(function)</em>;</li> <li>You must be returnable by a subroutine;</li> <li>You must be able to be created at runtime <em>(during the actual execution of your program)</em>;</li> <li>You must have an intrinsic identity <em>(This is a bit harder to understand, but, philosophically, this means that you have an identity beyond some identifying characteristics. For example, am I, Michael Kosler, definable beyond my name, age, weight, etc.?)</em>.</li> </ul> <p>If you are able to provide these guarantees, then you are considered a <a href="http://en.wikipedia.org/wiki/First-class_citizen">first-class citizen</a> in programming parlance. All common variables in Lua, i.e. <code>number</code>, <code>string</code>, and <code>table</code>, are first-class citizens. Obviously, a <code>number</code> is stored as a variable, can be passed as an argument to a function, and can be returned from a function.</p> <p>Functions themselves, however, often did not have this same status. In C, I cannot directly pass a function as a parameter to another function (I can fake it through a function pointer, but I am just passing through something that <em>points</em> to the function, rather than the function itself). In Java <em>(until Java 8 comes out)</em>, I cannot store a function inside a variable.</p> <p>Lua, and many other scripting languages, elevate functions to first-class citizen status. This means that anything I could do with a <code>number</code>, I can do with a function.</p> <h3>Storing a function in a variable</h3> <p>In Lua, we often create functions like this:</p> <pre class="brush: lua"> local function foo(a) print(a) end </pre> <p>Turns out, when Lua interprets the code, it is kind of, <em>but not exactly</em>, looking at it like this:</p> <pre class="brush: lua"> local foo = function (a) print(a) end </pre> <p>I can even re-assign <code>foo</code> to now be a new function.</p> <pre class="brush: lua"> local foo = function(a) print(a) end foo = function(a, b) print(a, b) end </pre> <h3>Passing a function as a parameter</h3> <p>Since I can store a function in a variable, I can just as easily pass a function as a parameter. Suppose I have a table of strings that I want to make all uppercase, print, and then make all lowercase.</p> <pre class="brush: lua"> local function map(t, f) for i = 1, #t do t[i] = f(t[i]) end end local text = { 'The', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog.' } print(table.concat(text, ' ')) map(text, string.upper) print(table.concat(text, ' ')) map(text, string.lower) print(table.concat(text, ' ')) </pre> <p>This <code>map</code> function is a powerful and widely used function in functional programming languages like <a href="http://www.haskell.org/haskellwiki/Haskell">Haskell</a>, so much so that it is built into its core library.</p> <h3>Returning a function from another function</h3> <p>Since functions are first-class citizens, I have no problem returning them from other functions. Suppose I have an adder function, that rather than adding a bunch of numbers together, creates specialized adder functions.</p> <pre class="brush: lua"> function add(n) return function (m) return m + n end end local addThree = add(3) print(addThree(5)) -- 8 </pre> <h2>Closuring us out</h2> <p>The first two examples are pretty straight-forward. The adder <em>factory</em> function is a bit weirder if you really pay attention to it. Try tracing the execution path, keeping in mind how <a href="http://blogs.love2d.org/content/scope-within-lua">scope</a> works:</p> <ol> <li>Lua identifies the function <code>add</code> and the variable <code>addThree</code>.</li> <li>Lua calls the right-hand side of the assignment statement, <code>add(3)</code>.</li> <li>Lua creates a new, <em>anonymous</em> function that takes in a argument <code>m</code>, returning the expression <code>m + n</code>, and returns the anonymous function from <code>add</code>.</li> <li>Lua calls <code>print(addThree(5))</code>, which calls <code>addThree(5)</code>, which returns 8.</li> </ol> <p>But why does it return 8? Once I have left <code>add</code>, the value of <code>n</code> (in our case 3) is out of scope. Furthermore, it looks like I have no guarantees that if I call <code>add(4)</code>, that <code>addThree(5)</code> will not suddenly give me 9.</p> <p>What Lua and other languages that have first-class functions do is create something know as a <a href="http://en.wikipedia.org/wiki/Closure_(computer_science)">closure</a>, which takes a snapshot of the variables that are not within the enclosing functions <em>immediate local scope</em> (i.e. the value of <code>n</code> in our example), and carries that state with it for later use. So, the value of <code>n</code> when I created <code>addThree</code> will, within <code>addThree</code>, will always and forever remain 3.</p> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/first-class-functions-0"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Wed, 20 Mar 2013 23:14:17 +0000 MarekkPie 25 at http://blogs.love2d.org Scope within Lua http://blogs.love2d.org/content/scope-within-lua <div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/lua">lua</a></li><li class="taxonomy-term-reference-1"><a href="/blog-terms/scope">scope</a></li><li class="taxonomy-term-reference-2"><a href="/blog-terms/global">global</a></li><li class="taxonomy-term-reference-3"><a href="/blog-terms/local">local</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>Far too often, while opening up a LÖVE file that someone posts on the forums, I see the telltale signs of someone who does not understand the concept of scope. In their <code>player.lua</code> file, they will be referring directly to some variables inside their <code>wall.lua</code> file, which itself refers directly to some tables within the <code>main.lua</code> file.</p> <p><!--break--> Granted, there are some instances when polluting the global scope has a few benefits, but you need to truly understand what it means before you can safely do so.</p> <h2>About Me</h2> <p>My name is Michael Kosler, and I'm a college student currently attending Texas A&amp;M University, earning a bachelor's in Computer Science. I previously got a BA in Mathematics from Texas A&amp;M University, and taught high school mathematics for about four months (couldn't even last a year :)). I'm hoping to break into the game industry professionally, and have been using Lua and LÖVE since 2011 to help build out my online portfolio.</p> <h2>What is scope?</h2> <p>Ripped from Wikipedia:</p> <blockquote> <p>In computer programming, a <strong>scope</strong> is a context within a computer program in which a variable name or other identifier is valid and can be used, or within which a declaration has effect.</p> </blockquote> <p>While Wikipedia often gets the definition technically right, it also assumes you probably know what scope is before you begin reading up on scope - a backwards proposition.</p> <p>Scope, in the most general case, can be distilled down to one question: "Who knows I exist?" This is an important question to ask in programming, because rarely does a program not need to communicate with either other programs or other parts of itself. If you share everything, then you might end up clashing with other parts of your program that need similarly named variables.</p> <h3>Globe Trekking</h3> <p>The global scope is probably the simplest to understand. If I have a variable within the global scope, then it is visible to the entire program. For example, consider two files: <code>a.lua</code>, and <code>b.lua</code>.</p> <p><strong><code>a.lua</code></strong></p> <pre class="brush: lua"> -- x is defined in the global scope x = 10 -- foo is defined in the global scope function foo() -- Since x is global, the function foo can refer to it x = x + 5 print(x) end </pre> <p><strong><code>b.lua</code></strong></p> <pre class="brush: lua"> -- Bring the global scope from a.lua into b.lua require 'a' -- bar is defined in the global scope function bar() -- This x is still referring to the x we created in a.lua x = x + 10 foo() end bar() </pre> <p>Running <code>b.lua</code> prints <code>25</code> onto the screen.</p> <h3>I only buy Local Scope</h3> <p>Local scope refers to pretty much all other situations of scoping. Generally, however, to be in the local scope usually means that a variable is visible only to those other variables that share the same scope. I will get to some examples on what local scope looks like in code in a bit, but first I have to steer you away from a common problem.</p> <p>If you are familiar with other programming languages, then this so far has felt fairly familiar to you. Local scope, however, is where Lua starts acting differently. Consider the following program:</p> <pre class="brush: lua"> x = 10 function foo() y = 20 end function bar() print(x, y) end foo() bar() </pre> <p>In most other languages, this will give you an error. Why? Because in most other languages, the variable <code>y</code>, defined within the function <code>foo</code>, is local to that function, so when <code>bar</code> tries to print <code>y</code>, it has no understanding as to what <code>y</code> is, and balks.</p> <p>Lua, on the other hands, happily prints <code>10, 20</code>. Why? Because, in Lua, all variables are, by default, global. Why would it do that? Ask <a href="http://en.wikipedia.org/wiki/Roberto_Ierusalimschy">Dr. Ierusalimschy</a>. All we care about is how we take advantage of local scoping.</p> <p>Turns out its fairly easy: just append <code>local</code> to any variable that you wish that be inside its local scope. Given that, let us fix the above code snippet to work like other programming languages:</p> <pre class="brush: lua"> x = 10 function foo() local y = 20 end function bar() print(x, y) end foo() bar() </pre> <p>Now, while this does not quite give us the error we would get in many other programming languages, Lua prints <code>10, nil</code>, showing that <code>y</code> has no current meaning within the scope of <code>bar</code>.</p> <p>We can extend this idea of local scope between files as well. Suppose I have three files:</p> <p><strong><code>player.lua</code></strong></p> <pre class="brush: lua"> -- some other player functions function draw(o) love.graphics.setColor(o.color) love.graphics.rectangle('fill', o.x, o.y, o.width, o.height) end </pre> <p><strong><code>enemy.lua</code></strong></p> <pre class="brush: lua"> -- some other enemy functions function draw(o) love.graphics.setColor(o.color) love.graphics.circle('fill', o.x, o.y, o.radius) end </pre> <p><strong><code>main.lua</code></strong></p> <pre class="brush: lua"> require 'player' require 'enemy' local p = { x = 10, y = 10, width = 20, height = 50, color = { 0, 255, 0 }, } local e = { x = 50, y = 50, radius = 15, color = { 255, 0, 0 }, } function love.draw() -- Which one is which? draw(p) draw(e) end </pre> <p>Clearly, I want different functions for drawing my player and my enemies. But, both the <code>draw</code> function in <code>player.lua</code> and the <code>draw</code> function in <code>enemy.lua</code> pollute the global scope. So, which draw was used? It actually depends on the order of the <code>require</code> statements, so in our case, the <code>draw</code> in <code>enemy.lua</code> is the <code>draw</code> within the <code>main.lua</code>, so we get an error when we call <code>draw(p)</code>, since <code>p</code> does not have <code>radius</code>.</p> <p>The fix is fairly easy:</p> <p><strong><code>player.lua</code></strong></p> <pre class="brush: lua"> -- declare draw as local local function draw(o) love.graphics.setColor(o.color) love.graphics.rectangle('fill', o.x, o.y, o.width, o.height) end -- return the local version of draw return draw </pre> <p><strong><code>enemy.lua</code></strong></p> <pre class="brush: lua"> -- declare draw as local local function draw(o) love.graphics.setColor(o.color) love.graphics.circle('fill', o.x, o.y, o.radius) end return draw </pre> <p><strong><code>main.lua</code></strong></p> <pre class="brush: lua"> -- Assign the return value of the two files to variables local playerDraw = require 'player' local enemyDraw = require 'enemy' local p = { x = 10, y = 10, width = 20, height = 50, color = { 0, 255, 0 }, } local e = { x = 50, y = 50, radius = 15, color = { 255, 0, 0 }, } function love.draw() playerDraw(p) enemyDraw(e) end </pre> <h2>Why should I care?</h2> <p>Think of scope as a directory or folder inside your computer. If you exclusively use the global scope, then your computer has simple one directory, with all files shoved inside. In this flat structure, anytime you attempt to save a new file, you would have to be on guard against accidentally overwriting a previously saved file. Luckily, most modern operating systems warn you before you accidentally save over some previous work. Lua, and most other programming languages, do not give you that extra level of protection.</p> <h2>What are you leaving out?</h2> <p>Lua provides quite a few interesting tricks to meddle with the scope of the language. If you are interested, here are a few advanced topics on scope within Lua:</p> <ul> <li><a href="http://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scoping_and_dynamic_scoping">Lexical scoping</a></li> <li><a href="http://www.lua.org/pil/6.1.html">Closures</a></li> <li><a href="http://www.lua.org/pil/8.1.html">The <code>require</code> function</a></li> <li><a href="http://www.lua.org/pil/14.html">The Environment</a> <em>NOTE: as of Lua 5.2, this topic has changed significantly</em></li> </ul> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/scope-within-lua"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Wed, 13 Mar 2013 17:14:30 +0000 MarekkPie 19 at http://blogs.love2d.org Circle Collisions http://blogs.love2d.org/content/circle-collisions <div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/circle">circle</a></li><li class="taxonomy-term-reference-1"><a href="/blog-terms/collisions">collisions</a></li><li class="taxonomy-term-reference-2"><a href="/blog-terms/reaction">reaction</a></li><li class="taxonomy-term-reference-3"><a href="/blog-terms/resolution">resolution</a></li><li class="taxonomy-term-reference-4"><a href="/blog-terms/collision">collision</a></li><li class="taxonomy-term-reference-5"><a href="/blog-terms/detection">detection</a></li><li class="taxonomy-term-reference-6"><a href="/blog-terms/physics">physics</a></li><li class="taxonomy-term-reference-7"><a href="/blog-terms/new">new</a></li><li class="taxonomy-term-reference-8"><a href="/blog-terms/ball">ball</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p><br /> Hello I'm Phoenix Enero, and in this article&nbsp;(also my first) we will talk about Circular Collisions. But first, let me introduce myself.</p> <p>I am a programmer in the Philippines. I originally programmed in a programming language called ActionScript 3.0, the programming language used in Flash, and made some pretty cool stuff with it, like a plotting program. After that, I stumbled on&nbsp;<span style="font-size: 14px; line-height: 21px;">LÖVE through a ROBLOX (google it) group called "Love2D Fans". It was a great game engine, partly because it uses a simple programming language called Lua, and I made some games that I, erm, never finished. Okay, I think that's all I need to say about that. So anyways, let's get on with it!</span></p> <p><span style="font-size: 14px; line-height: 21px;">And, before you comment here about that the code is not working, notice that I fixed most of my careless typos. If you have some problems, re-copy-and-paste the code.</span></p> <!--break--> <h1>Detecting Circular Collisions</h1> <p>First we need to find a way to detect circular collisions. The best way is to use distance checking. It checks if the distance between two circles' centers are less than the sum of their radii (plural of radius). The code will look like this.</p> <pre class="brush: lua"> function checkDistColl(circleA, circleB) local dist = math.sqrt((circleA.x - circleB.x)^2 + (circleA.x - circleB.x)^2) return dist &lt;= circleA.radius + circleB.radius end</pre> <p>However, if you want to optimize your code, you can square both sides, thus getting rid of the math.sqrt function on the left side, and squaring the sum of the radii on the right side.</p> <pre class="brush: lua"> function checkDistColl(circleA, circleB) local dist = (circleA.x - circleB.x)^2 + (circleA.y - circleB.y)^2 return dist &lt;= (circleA.radius + circleB.radius)^2 end</pre> <h1>Collision Resolution</h1> <p>Now we want to know what will happen if they actually collide. But first, let's take a detour and find where&nbsp;the collisions occur.</p> <h2>Calculating the point of collision</h2> <p>This isn't really required for the collisions, but it can have some uses, for example, you can add an explosion effect at the point of the collision.</p> <p>There are two ways to find the point, the right and the wrong way.</p> <p>The wrong way, which many tutorials use, is averaging the two center points.</p> <pre class="brush: lua"> collPointX = (circleA.x + circleB.x)/2 collPointY = (circleA.y + circleB.y)/2</pre> <p>That works <strong>only</strong>&nbsp;if the circles have the same radius.</p> <p>The right way that we want to use is a bit more complicated, but it works for circles of any radius:</p> <pre class="brush: lua"> collPointX ((circleA.x * circleB.radius) + (circleB.x * circleA.radius))/(circleA.radius + circleB.radius) collPointY ((circleA.y * circleB.radius) + (circleB.y * circleA.radius))/(circleA.radius + circleB.radius)</pre> <p>This gives the true x/y coordinates for the collision point. If you don't bother finding the collision point, try finding the midpoint of both circles, as it will be needed later on.</p> <h2>Bouncing Apart</h2> <p>Now, we know when our circles collide into each other, and we know their velocity and their x/y coordinates. How do we work out where they travel next?</p> <p>There are two ways to do collisions;&nbsp;<em>elastic collisions</em> and&nbsp;<em>inelastic collisions</em>. Elastic collisions, in layman's terms, are collisions in which the objects do not "stick". Think billard balls colliding. Inelastic collisions are when they "stick". Think a bullet penetrating a block of wood. We will do elastic collisions here.</p> <p>Explaining it in words can be difficult, so I'll add a gif image from Wikipedia. If you would like to learn, in detail, how the formula is derived, click the link in the caption of the image.</p> <p><img alt="Wikipedia illustration of 2 coins colliding" src="http://gamedevtuts.s3.amazonaws.com/031_whenWorldsCollide/wikigif.gif" style="width: 350px; height: 200px;" /></p> <address class="rteindent1">Image taken from <a href="http://en.wikipedia.org/wiki/Elastic_collision">http://en.wikipedia.org/wiki/Elastic_Collision</a>, was created by<font color="#000000" face="sans-serif"><span style="line-height: 19.1875px;">&nbsp;Simon Steinmann</span></font></address> <address>&nbsp;</address> <p>Usually, there are a lot of factors that influence collision, such as spin, mass, mass distribution, etc. but in this collision reaction, we will only use the mass factor. If you don't need that much realism, you can substitute mass for the radius of the circle.</p> <p>The formula has something to do with&nbsp;the&nbsp;<em>conservation of momentum</em>. Momentum is expressed as this:</p> <p><img alt="momentum = mass times velocity" src="http://upload.wikimedia.org/math/c/a/2/ca2b01dfa919a34a0c9364110797aa36.png" style="width: 68px; height: 13px;" /></p> <p>In words: momentum is mass times the velocity.&nbsp;The conservation of momentum says that, the sum of the momentum of 2 objects before the collision is equal to the sum of the momentum of the 2 objects after the collision. Assuming that the initial velocities are&nbsp;<em>u</em>, and the final velocities are&nbsp;<em>v</em>,&nbsp;the equation of the conservation of momentum is this:</p> <p><img alt="conservation of momentum" src="http://upload.wikimedia.org/math/d/c/c/dccfa0969fdbd08e06981e85f2813970.png" style="width: 251px; height: 16px;" /></p> <p>Now you have an equation with two unknowns,&nbsp;<em>v<sub>1</sub></em> and&nbsp;<em>v<sub>2</sub></em>. To solve an equation with two unknowns, you need to find another equation with the same two unknowns in it. That happens to be dealing with&nbsp;<em>kinetic energy</em>. Kinetic energy is half of the mass times the magnitude of the velocity&nbsp;squared.</p> <p><img alt="formula for kinetic energy" src="http://upload.wikimedia.org/math/1/1/e/11e6fc84bb2641d36b09c5a6359f7c08.png" style="width: 94px; height: 25px;" /></p> <p>Now, it just so happens that, the sum of the kinetic energies of 2 objects before and after the collision remains the same. I have seen no equation-style image for that yet, so I'll just express it in code.</p> <pre class="brush: lua"> KE1 + KE3 = KE1Final + KE2Final</pre> <p>Expanding it, and factoring out the 1/2's in the kinetic energies&nbsp;(by multiplying both sides &nbsp;by 2) yelds:</p> <pre class="brush: lua"> (m1 * v1^2) + (m1 * v2^2) = (m1 * v1Final^2) + (m1 * v2Final^2) </pre> <p>Now you have a different equation with the same two unknowns. If you like algebra quite a bit, I invite you to sit down and try to solve both equations for both unknowns. In the mean time, I'll add Newton's Cradle here.</p> <p><img alt="" src="http://upload.wikimedia.org/wikipedia/commons/d/d3/Newtons_cradle_animation_book_2.gif" style="width: 480px; height: 360px;" /></p> <address>Incidentally, that represents the conservation of momentum. Haven't I hypnotized you yet?</address> <p>&nbsp;</p> <p>You done? The equations, solved for both unknowns, is this:</p> <p><img alt="Final Formula 1" src="http://upload.wikimedia.org/math/2/f/9/2f9b6fcd36cd25f6e4f563a7c08e9f54.png" style="width: 317px; height: 45px;" /></p> <p><img alt="Final formula 2" src="http://upload.wikimedia.org/math/e/3/b/e3b6a72306f7ccbfc078034ce8e833d0.png" style="width: 324px; height: 45px;" /></p> <p>In code, that will look like this, after adding both fractions in each equation:</p> <pre class="brush: lua"> local newVelX1 = (circleA.vx * (circleA.mass - circleB.mass) + (2 * circleB.mass * circleB.vx)) / (circleA.mass + circleB.mass) local newVelY1 = (circleA.vy * (circleA.mass - circleB.mass) + (2 * circleB.mass * circleB.vy)) / (circleA.mass + circleB.mass) local newVelX2 = (circleB.vx * (circleB.mass - circleA.mass) + (2 * circleA.mass * circleA.vx)) / (circleA.mass + circleB.mass) local newVelY2 = (circleB.vy * (circleB.mass - circleA.mass) + (2 * circleA.mass * circleA.vy)) / (circleA.mass + circleB.mass)</pre> <p>But, if you have seen it, those values for newVelX1/Y1 and newVelX2/Y2, almost have the same fractions. Is there some way to optimize it? Yes there is. I won't explain the solution in detail, but basically, you find the total velocities of both objects. After getting the final velocity of objectA, you then add the total velocity and the final velocity of objectA to find the final velocity of objectB.</p> <p>You can actually find the total velocity by&nbsp;<em>subtracting</em> both of the initial velocities. That may seem weird but think of it in the viewpoint of the system. Suppose you have a 40kph and 50 kph cars in a freeway, moving in the same direction. Depending on which car you are at, you can see one going at 10kph, or going at -10kph. In other words, it's either going away from you, or falling behind you.</p> <p>So first, you find the total velocity&nbsp;<em>before</em> the collision. In code, for both axes, it will look like this:</p> <pre class="brush: lua"> local vxTotal = circleA.vx - circleB.vx local vyTotal = circleA.vy - circleB.vy </pre> <p>Then, you find the final velocity of circleA:</p> <pre class="brush: lua"> local newVelX1 = (circleA.vx * (circleA.mass - circleB.mass) + (2 * circleB.mass * circleB.vx)) / (circleA.mass + circleB.mass) local newVelY1 = (circleA.vy * (circleA.mass - circleB.mass) + (2 * circleB.mass * circleB.vy)) / (circleA.mass + circleB.mass)</pre> <p>Now, &nbsp;you find the final velocity of circleB, using the method I told earlier:</p> <pre class="brush: lua"> local newVelX2 = vxTotal + newVelX1 local newVelY2 = vyTotal + newVelY1</pre> <p>Well that's better than the double formula. You can actually make this more optimized by using the normal vector, but I won't cover it here.</p> <p>So now, are we done yet? Hmm, not quite.</p> <p>Earlier, we made some position updates to our circles and&nbsp;<em>then</em> we check for collisions. Because of that, there is a chance that the two overlap and the velocity is not enough to seperate the two. A solution to that is to do some more math.</p> <p>Find the midpoint of the 2 circles (or the collision point, if both circles have the same radius). Now set the centers of the two circles to be radius R away from the midpoint, but along the "line of collision". The code will look like this:</p> <pre class="brush: lua"> midpointX = (circleA.x + circleB.x)/2 midpointY = (circleA.y + circleA.y)/2 dist = math.sqrt((circleA.x - circleB.x)^2 + (circleA.y - circleB.y)^2) circleA.x = midpointX + circleA.radius * (circleA.x - circleB.x)/dist circleA.y = midpointY + circleA.radius * (circleA.y - circleB.y)/dist circleB.x = midpointX + circleB.radius * (circleB.x - circleA.x)/dist circleB.y = midpointY + circleB.radius * (circleB.y - circleA.y)/dist</pre> <p>That (circleA.x - circleB.x)/dist there is a "normal" vector, that is, a vector with a direction, but with a magnitude of 1, and that is used here to&nbsp;move the circles along the line of collision.</p> <p>Now, our complete code for the collision resolution function is this:</p> <pre class="brush: lua"> function circleResolution(circleA, circleB) if checkCircleColl(circleA, circleB) then -- Find the new velocities local vxTotal = circleA.vx - circleB.vx local vyTotal = circleA.vy - circleB.vy local newVelX1 = (circleA.vx * (circleA.mass - circleB.mass) + (2 * circleB.mass * circleB.vx)) / (circleA.mass + circleB.mass) local newVelY1 = (circleA.vy * (circleA.mass - circleB.mass) + (2 * circleB.mass * circleB.vy)) / (circleA.mass + circleB.mass) local newVelX2 = vxTotal + newVelX1 local newVelY2 = vyTotal + newVelY1 -- Move the circles so that they don't overlap local midpointX = (circleA.x + circleB.x)/2 local midpointY = (circleA.y + circleA.y)/2 local dist = math.sqrt((circleA.x - circleB.x)^2 + (circleA.y - circleB.y)^2) circleA.x = midpointX + circleA.radius * (circleA.x - circleB.x)/dist circleA.y = midpointY + circleA.radius * (circleA.y - circleB.y)/dist circleB.x = midpointX + circleB.radius * (circleB.x - circleA.x)/dist circleB.y = midpointY + circleB.radius * (circleB.y - circleA.y)/dist -- Update the velocities circleA.vx = newVelX1 circleA.vy = newVelY1 circleB.vx = newVelX2 circleB.vy = newVelY2 end end</pre> <h1>More than Two</h1> <p>That's good enough for two circles, but what about 3 or more? You need to use a double for-loop for that. The unoptimized way would be this:</p> <pre class="brush: lua"> for i=1, #objects do local partA = objects[i] for j=1, #objects do local partB = objects[j] if i ~= j then -- check collision between partA and partB end end end</pre> <p>I said that's unoptimized because, it checks for collisions that are already checked. Here's what it will look like for 4 objects.</p> <pre class="brush: lua"> object1 to object2, object3, object4 object2 to object1, object3, object4 object3 to object1, object2, object4 object4 to object1, object2, object3</pre> <p>If you look carefully, the first statement checks for collisions for object1 and object2. But in the next statement, you are checking for object2 and object1! Certainly, if object1 doesn't collide with the object2, then object2 is also not colliding to object1. A better, more optimized loop, will look like this:</p> <pre class="brush: lua"> for i=1, #objects-1 do local partA = objects[i] for j=i+1, #objects do local partB = objects[j] -- check collision between partA and partB end end</pre> <p>Now what the collision checking for 4 objects will look like this:</p> <pre class="brush: lua"> object1 to object2, object3, object4 object2 to object3, object4 object3 to object4 object4 to none</pre> <p>Object4 (or the last object in an object array)&nbsp;checks to none, because all of the others are checking for it. So you see that if you use the unoptimized way, it turns out&nbsp;that you checking the collisions 2 times as much.</p> <p>Download the .love file (typos fixed by the way): <a href="https://dl.dropbox.com/u/105405645/Blog/LOVE2D%20Files/circle-collision.love">circle-collision.love</a>. As always, you can view the source code by either changing the extension to .zip and opening it, or opening it in an archive program like 7-zip.</p> <p><span style="color: rgb(0, 0, 0); font-size: 1.357em; line-height: 1.5;">And we are done!</span></p> <p>Alright, now we are done with the collision resolution. I hope you learned something here, and if you have any questions or suggestions, please comment below!</p> <p>Also, a credit goes to vrld for posting some suggestions too :).</p> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/circle-collisions"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Mon, 11 Mar 2013 06:11:13 +0000 substitute541 16 at http://blogs.love2d.org Hello World http://blogs.love2d.org/content/hello-world <div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/welcome">Welcome</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>Welcome to the official community blogs!</p> <p>Firstly, I'd like to say, welcome!</p> <p>About a month ago, there was a lot of chatter about blogging in the love community, not only on IRC but also the <a href="https://love2d.org/forums/viewtopic.php?f=3&amp;t=12957">forums</a>. At this point, with the blessings of bartbes, I took it upon myself, not only as a challenge, but a way to contribute to the LÖVE community, a multi-user community based blogging platform. After a lot of hard work, I am happy to present the community blogs!</p> <p>You'll notice that there is an application process, and this provides two benefits to the community;</p> <ul> <li>It will ensure that content posted to the blog will be of high quality</li> <li>The posts will have relatable community members that will be dedicated.</li> <li>The sub-community will be able to manage and monitor itself.</li> </ul> <p>Please see the about page for more information!</p> <p>Due to this application process, there may not be much content as first, as the first applications that will be processed are the Board Members.</p> <p>If you have comments or suggestions, or just want to chill, feel free to join our IRC channel, <a href="http://en.irc2go.com/webchat/?net=OFTC&amp;room=love-blogs">#love-blogs@OFTC</a>!</p> <p><img alt="" src="/sites/default/files/1359442384035.gif" style="width: 400px; height: 345px;" />​</p> </div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/hello-world"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a> <a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a> </div> </div></div></div> Thu, 31 Jan 2013 10:46:19 +0000 josefnpat 2 at http://blogs.love2d.org