diff options
| author | Amir Rajan <[email protected]> | 2020-10-13 00:45:16 -0500 |
|---|---|---|
| committer | Amir Rajan <[email protected]> | 2020-10-13 00:48:54 -0500 |
| commit | 05cbef7fb8224332795e5685be499d81d20e7d93 (patch) | |
| tree | 13ec5f1755c2f45618741f2f016ed8729dbedd41 /docs/docs.html | |
| parent | abad948c1154d88d79b9f891e3b7315540e0b0a3 (diff) | |
| download | dragonruby-game-toolkit-contrib-05cbef7fb8224332795e5685be499d81d20e7d93.tar.gz dragonruby-game-toolkit-contrib-05cbef7fb8224332795e5685be499d81d20e7d93.zip | |
Synced with 1.26.
Diffstat (limited to 'docs/docs.html')
| -rw-r--r-- | docs/docs.html | 605 |
1 files changed, 341 insertions, 264 deletions
diff --git a/docs/docs.html b/docs/docs.html index b21caff..0b76535 100644 --- a/docs/docs.html +++ b/docs/docs.html @@ -1,7 +1,7 @@ <html> <head> <title>DragonRuby Game Toolkit Documentation</title> - <link href="docs.css?ver=1600750589" rel="stylesheet" type="text/css" media="all"> + <link href="docs.css?ver=1602116477" rel="stylesheet" type="text/css" media="all"> </head> <body> <div id='toc'> @@ -14,20 +14,22 @@ <li><a href='#--getting-started-tutorial'>Getting Started Tutorial</a></li> <li><a href='#--important--go-through-all-of-the-sample-apps!-study-them-thoroughly!!-no-really,-you-should-definitely-do-this!'>IMPORTANT: Go through all of the sample apps! Study them thoroughly!! No really, you should definitely do this!</a></li> <li><a href='#--deploying-to-itch.io'>Deploying To Itch.io</a></li> +<li><a href='#--deploying-to-mobile-devices'>Deploying To Mobile Devices</a></li> <li><a href='#--dragonruby's-philosophy'>DragonRuby's Philosophy</a></li> -<li><a href='#--how-to-determine-what-frame-you-are-on'>How To Determine What Frame You Are On</a></li> -<li><a href='#--how-to-get-current-framerate'>How To Get Current Framerate</a></li> -<li><a href='#--how-to-render-a-sprite-using-an-array'>How To Render A Sprite Using An Array</a></li> -<li><a href='#--more-sprite-properties-as-an-array'>More Sprite Properties As An Array</a></li> -<li><a href='#--different-sprite-representations'>Different Sprite Representations</a></li> -<li><a href='#--how-to-render-a-label'>How To Render A Label</a></li> -<li><a href='#--a-colored-label'>A Colored Label</a></li> -<li><a href='#--extended-label-properties'>Extended Label Properties</a></li> -<li><a href='#--rendering-a-label-as-a--hash-'>Rendering A Label As A <code>Hash</code></a></li> -<li><a href='#--getting-the-size-of-a-piece-of-text'>Getting The Size Of A Piece Of Text</a></li> -<li><a href='#--how-to-play-a-sound'>How To Play A Sound</a></li> -<li><a href='#--using--args.state--to-store-your-game-state'>Using <code>args.state</code> To Store Your Game State</a></li> <li><a href='#--frequently-asked-questions,-comments,-and-concerns'>Frequently Asked Questions, Comments, and Concerns</a></li> +<li><a href='#--cheatsheet--how-to-determine-what-frame-you-are-on'>CHEATSHEET: How To Determine What Frame You Are On</a></li> +<li><a href='#--cheatsheet--how-to-get-current-framerate'>CHEATSHEET: How To Get Current Framerate</a></li> +<li><a href='#--cheatsheet--how-to-render-a-sprite-using-an-array'>CHEATSHEET: How To Render A Sprite Using An Array</a></li> +<li><a href='#--cheatsheet--more-sprite-properties-as-an-array'>CHEATSHEET: More Sprite Properties As An Array</a></li> +<li><a href='#--cheatsheet--different-sprite-representations'>CHEATSHEET: Different Sprite Representations</a></li> +<li><a href='#--cheatsheet--how-to-render-a-label'>CHEATSHEET: How To Render A Label</a></li> +<li><a href='#--cheatsheet--a-colored-label'>CHEATSHEET: A Colored Label</a></li> +<li><a href='#--cheatsheet--extended-label-properties'>CHEATSHEET: Extended Label Properties</a></li> +<li><a href='#--cheatsheet--rendering-a-label-as-a--hash-'>CHEATSHEET: Rendering A Label As A <code>Hash</code></a></li> +<li><a href='#--cheatsheet--getting-the-size-of-a-piece-of-text'>CHEATSHEET: Getting The Size Of A Piece Of Text</a></li> +<li><a href='#--cheatsheet--how-to-play-a-sound'>CHEATSHEET: How To Play A Sound</a></li> +<li><a href='#--cheatsheet--using--args.state--to-store-your-game-state'>CHEATSHEET: Using <code>args.state</code> To Store Your Game State</a></li> +<li><a href='#--cheatsheet--troubleshoot-performance'>CHEATSHEET: Troubleshoot Performance</a></li> <li><a href='#--docs---gtk--runtime-'>DOCS: <code>GTK::Runtime</code></a></li> <li><a href='#--docs---gtk--runtime#reset-'>DOCS: <code>GTK::Runtime#reset</code></a></li> <li><a href='#--docs---gtk--runtime#calcstringbox-'>DOCS: <code>GTK::Runtime#calcstringbox</code></a></li> @@ -94,7 +96,7 @@ <li><a href='#--mouse---coordinate-systems---main.rb'>Mouse - Coordinate Systems - main.rb</a></li> <li><a href='#--save-load---save-load-game---main.rb'>Save Load - Save Load Game - main.rb</a></li> <li><a href='#--advanced-rendering---simple-render-targets---main.rb'>Advanced Rendering - Simple Render Targets - main.rb</a></li> -<li><a href='#--advanced-rendering---render-targets-with-alphas---main.rb'>Advanced Rendering - Render Targets With Alphas - main.rb</a></li> +<li><a href='#--advanced-rendering---render-targets-with-tile-manipulation---main.rb'>Advanced Rendering - Render Targets With Tile Manipulation - main.rb</a></li> <li><a href='#--advanced-rendering---render-target-viewports---main.rb'>Advanced Rendering - Render Target Viewports - main.rb</a></li> <li><a href='#--advanced-rendering---render-primitive-hierarchies---main.rb'>Advanced Rendering - Render Primitive Hierarchies - main.rb</a></li> <li><a href='#--advanced-rendering---render-primitives-as-hash---main.rb'>Advanced Rendering - Render Primitives As Hash - main.rb</a></li> @@ -529,6 +531,21 @@ DragonRuby will package _and publish_ your game to itch.io! Tell your friends to <p> If you make changes to your game, just re-run dragonruby-publish and it'll update the downloads for you. </p> +<h1 id='--deploying-to-mobile-devices'>Deploying To Mobile Devices</h1> +<p> +If you have a Pro subscription, you also have the capability to deploy to mobile devices. +</p> +<p> +To deploy to iOS, you need to have a Mac running MacOS Catalina, an iOS device, and an active/paid Developer Account with Apple. From the Console type: <code>$wizards.ios.start</code> and you will be guided through the deployment process. +</p> +<p> +To deploy to Android, you need to have an Android emulator/device, and a environment that is able to run Android SDK. <code>dragonruby-publish</code> will create an APK for you. From there, you can sign the APK and install it to your device. The signing and installation procedure varies from OS to OS. Here's an example of what the command might look like: +</p> +<pre>> adb logcat -e mygame # you'll want to run this in a separate terminal +> keytool -genkey -v -keystore mygame.keystore -alias mygame -keyalg RSA -keysize 2048 -validity 10000 +> apksigner sign --ks mygame.keystore mygame-android.apk +> adb install mygame-android.apk +</pre> <h1 id='--dragonruby's-philosophy'>DragonRuby's Philosophy</h1> <p> The following tenants of DragonRuby are what set us apart from other game engines. Given that Game Toolkit is a relatively new engine, there are definitely features that are missing. So having a big check list of "all the cool things" is not this engine's forte. This is compensated with a strong commitment to the following principals. @@ -596,7 +613,236 @@ We are bombarded by marketing speak day in and day out. We don't do that here. T <p> We want DragonRuby to *actually* help you build the game you want to build (as opposed to sell you something piece of demoware that doesn't work). </p> -<h1 id='--how-to-determine-what-frame-you-are-on'>How To Determine What Frame You Are On</h1> +<h1 id='--frequently-asked-questions,-comments,-and-concerns'>Frequently Asked Questions, Comments, and Concerns</h1> +<p> +Here are questions, comments, and concerns that frequently come up. +</p> +<h2>Frequently Asked Questions</h2> +<h3>What is DragonRuby LLP?</h3> +<p> +DragonRuby LLP is a partnership of four devs who came together with the goal of bringing the aesthetics and joy of Ruby, everywhere possible. +</p> +<p> +Under DragonRuby LLP, we offer a number of products (with more on the way): +</p> +<ul> +<li>Game Toolkit (GTK): A 2D game engine that is compatible with modern + gaming platforms.</li> +<li>RubyMotion (RM): A compiler toolchain that allows you to build native, cross-platform mobile + apps. <a href='http://rubymotion.com'>http://rubymotion.com</a></li> +</ul> +<p> +All of the products above leverage a shared core called DragonRuby. +</p> +<p> +NOTE: From an official branding standpoint each one of the products is suffixed with "A DragonRuby LLP Product" tagline. Also, DragonRuby is _one word, title cased_. +</p> +<p> +NOTE: We leave the "A DragonRuby LLP Product" off of this one because that just sounds really weird. +</p> +<p> +NOTE: Devs who use DragonRuby are "Dragon Riders/Riders of Dragons". That's a bad ass identifier huh? +</p> +<h3>What is DragonRuby?</h3> +<p> +The response to this question requires a few subparts. First we need to clarify some terms. Specifically _language specification_ vs _runtime_. +</p> +<h4>Okay... so what is the difference between a language specification and a runtime?</h4> +<p> +A runtime is an _implementation_ of a language specification. When people say "Ruby," they are usually referring to "the Ruby 3.0+ language specification implemented via the CRuby/MRI Runtime." +</p> +<p> +But, there are many Ruby Runtimes: CRuby/MRI, JRuby, Truffle, Rubinius, Artichoke, and (last but certainly not least) DragonRuby. +</p> +<h4>Okay... what language specification does DragonRuby use then?</h4> +<p> +DragonRuby's goal is to be compliant with the ISO/IEC 30170:2012 standard. It's syntax is Ruby 2.x compatible, but also contains semantic changes that help it natively interface with platform specific libraries. +</p> +<h4>So... why another runtime?</h4> +<p> +The elevator pitch is: +</p> +<p> +DragonRuby is a Multilevel Cross-platform Runtime. The "multiple levels" within the runtime allows us to target platforms no other Ruby can target: PC, Mac, Linux, Raspberry Pi, WASM, iOS, Android, Nintendo Switch, PS4, Xbox, and Scadia. +</p> +<h4>What does Multilevel Cross-platform mean?</h4> +<p> +There are complexities associated with targeting all the platforms we support. Because of this, the runtime had to be architected in such a way that new platforms could be easily added (which lead to us partitioning the runtime internally): +</p> +<ul> +<li>Level 1 we leverage a good portion of mRuby.</li> +<li>Level 2 consists of optimizations to mRuby we've made given that our + target platforms are well known.</li> +<li>Level 3 consists of portable C libraries and their Ruby + C-Extensions.</li> +</ul> +<p> +Levels 1 through 3 are fairly commonplace in many runtime implementations (with level 1 being the most portable, and level 3 being the fastest). But the DragonRuby Runtime has taken things a bit further: +</p> +<ul> +<li>Level 4 consists of shared abstractions around hardware I/O and operating + system resources. This level leverages open source and proprietary components within Simple DirectMedia Layer (a low level multimedia component library that has been in active development for 22 years and counting).</li> +<li>Level 5 is a code generation layer which creates metadata that allows + for native interoperability with host runtime libraries. It also includes OS specific message pump orchestrations.</li> +<li>Level 6 is a Ahead of Time/Just in Time Ruby compiler built with LLVM. This + compiler outputs _very_ fast platform specific bitcode, but only supports a subset of the Ruby language specification.</li> +</ul> +<p> +These levels allow us to stay up to date with open source implementations of Ruby; provide fast, native code execution on proprietary platforms; ensure good separation between these two worlds; and provides a means to add new platforms without going insane. +</p> +<h4>Cool cool. So given that I understand everything to this point, can we answer the original question? What is DragonRuby?</h4> +<p> +DragonRuby is a Ruby runtime implementation that takes all the lessons we've learned from MRI/CRuby, and merges it with the latest and greatest compiler and OSS technologies. +</p> +<h3>How is DragonRuby different than MRI?</h3> +<p> +DragonRuby supports a subset of MRI apis. Our target is to support all of mRuby's standard lib. There are challenges to this given the number of platforms we are trying to support (specifically console). +</p> +<h4>Does DragonRuby support Gems?</h4> +<p> +DragonRuby does not support gems because that requires the installation of MRI Ruby on the developer's machine (which is a non-starter given that we want DragonRuby to be a zero dependency runtime). While this seems easy for Mac and Linux, it is much harder on Windows and Raspberry Pi. mRuby has taken the approach of having a git repository for compatible gems and we will most likely follow suite: <a href='https://github.com/mruby/mgem-list'>https://github.com/mruby/mgem-list</a>. +</p> +<h4>Does DragonRuby have a REPL/IRB?</h4> +<p> +You can use DragonRuby's Console within the game to inspect object and execute small pieces of code. For more complex pieces of code create a file called <code>repl.rb</code> and put it in <code>mygame/app/repl.rb</code>: +</p> +<ul> +<li>Any code you write in there will be executed when you change the file. You can organize different pieces of code using the <code>repl</code> method:</li> +</ul> +<pre>repl do + puts "hello world" + puts 1 + 1 +end +</pre> +<ul> +<li>If you use the `repl` method, the code will be executed and the DragonRuby Console will automatically open so you can see the results (on Mac and Linux, the results will also be printed to the terminal).</li> +<li>All <code>puts</code> statements will also be saved to <code>logs/log.txt</code>. So if you want to stay in your editor and not look at the terminal, or the DragonRuby Console, you can <code>tail</code> this file.</li> +</ul> +<p> +4. To ignore code in <code>repl.rb</code>, instead of commenting it out, prefix <code>repl</code> with the letter <code>x</code> and it'll be ignored. +</p> +<pre>xrepl do # <------- line is prefixed with an "x" + puts "hello world" + puts 1 + 1 +end + +# This code will be executed when you save the file. +repl do + puts "Hello" +end + +repl do + puts "This code will also be executed." +end + +# use xrepl to "comment out" code +xrepl do + puts "This code will not be executed because of the x infront of repl". +end +</pre> +<h4>Does DragonRuby support <code>pry</code> or have any other debugging facilities?</h4> +<p> +<code>pry</code> is a gem that assumes you are using the MRI Runtime (which is incompatible with DragonRuby). Eventually DragonRuby will have a pry based experience that is compatible with a debugging infrastructure called LLDB. Take the time to read about LLDB as it shows the challenges in creating something that is compatible. +</p> +<p> +You can use DragonRuby's replay capabilities to troubleshoot: +</p> +<ol> +<li> DragonRuby is hot loaded which gives you a very fast feedback loop (if the game throws an exception, it's because of the code you just added).</li> +<li> Use <code>./dragonruby mygame --record</code> to create a game play recording that you can use to find the exception (you can replay a recoding by executing <code>./dragonruby mygame --replay last_replay.txt</code> or through the DragonRuby Console using <code>$gtk.recording.start_replay "last_replay.txt"</code>.</li> +<li> DragonRuby also ships with a unit testing facility. You can invoke the following command to run a test: <code>./dragonruby . --eval some_ruby_file.rb --no-tick</code>.</li> +<li> Get into the habit of adding debugging facilities within the game itself. You can add drawing primitives to <code>args.outputs.debug</code> that will render on top of your game but will be ignored in a production release.</li> +<li> Debugging something that runs at 60fps is (imo) not that helpful. The exception you are seeing could have been because of a change that occurred many frames ago.</li> +</ol> +<h2>Frequent Comments About Ruby as a Language Choice</h2> +<h3>But Ruby is dead.</h3> +<p> +Let's check the official source for the answer to this question: isrubydead.com: <a href='https://isrubydead.com/'>https://isrubydead.com/</a>. +</p> +<p> +On a more serious note, Ruby's _quantity_ levels aren't what they used to be. And that's totally fine. Every one chases the new and shiny. +</p> +<p> +What really matters is _quality/maturity_. Here is the latest (StackOverflow Survey sorted by highest paid developers)[https://insights.stackoverflow.com/survey/2019#top-paying-technologies]. +</p> +<p> +Let's stop making this comment shall we? +</p> +<h3>But Ruby is slow.</h3> +<p> +That doesn't make any sense. A language specification can't be slow... it's a language spec. Sure, an _implementation/runtime_ can be slow though, but then we'd have to talk about which runtime. +</p> +<h3>Dynamic languages are slow.</h3> +<p> +They are certainly slower than statically compiled languages. With the processing power and compiler optimizations we have today, dynamic languages like Ruby are _fast enough_. +</p> +<p> +Unless you are writing in some form of intermediate representation by hand, your language of choice also suffers this same fallacy of slow. Like, nothing is faster than a low level assembly-like language. So unless you're writing in that, let's stop making this comment. +</p> +<p> +NOTE: If you _are_ hand writing LLVM IR, we are always open to bringing on new partners with such a skill set. Email us ^_^. +</p> +<h2>Frequent Concerns</h2> +<h3>DragonRuby is not open source. That's not right.</h3> +<p> +The current state of open source is unsustainable. Contributors work for free, most all open source repositories are severely under-staffed, and burnout from core members is rampant. +</p> +<p> +We believe in open source very strongly. Parts of DragonRuby are in fact, open source. Just not all of it (for legal reasons, and because the IP we've created has value). And we promise that we are looking for (or creating) ways to _sustainably_ open source everything we do. +</p> +<p> +If you have ideas on how we can do this, email us! +</p> +<p> +If the reason above isn't sufficient, then definitely use something else. +</p> +<p> +All this being said, we do have parts of the engine open sourced on GitHub: <a href='https://github.com/dragonruby/dragonruby-game-toolkit-contrib/'>https://github.com/dragonruby/dragonruby-game-toolkit-contrib/</a> +</p> +<h3>DragonRuby is for pay. You should offer a free version.</h3> +<p> +If you can afford to pay for DragonRuby, you should (and will). We don't go around telling writers that they should give us their books for free, and only require payment if we read the entire thing. It's time we stop asking that of software products. +</p> +<p> +That being said, we will _never_ put someone out financially. We have income assistance for anyone that can't afford a license to any one of our products. +</p> +<p> +You qualify for a free, unrestricted license to DragonRuby products if any of the following items pertain to you: +</p> +<ul> +<li>Your income is below $2,000.00 (USD) per month.</li> +<li>You are under 18 years of age.</li> +<li>You are a student of any type: traditional public school, home + schooling, college, bootcamp, or online.</li> +<li>You are a teacher, mentor, or parent who wants to teach a kid how to code.</li> +<li>You work/worked in public service or at a charitable organization: + for example public office, army, or any 501(c)(3) organization.</li> +</ul> +<p> +Just contact Amir at [email protected] with a short explanation of your current situation and he'll set you up. No questions asked. +</p> +<h3>But still, you should offer a free version. So I can try it out and see if I like it.</h3> +<p> +You can try our [web-based sandbox environment](). But it won't do the runtime justice. Or just come to our [Slack]() or [Discord]() channel and ask questions. We'd be happy to have a one on one video chat with you and show off all the cool stuff we're doing. +</p> +<p> +Seriously just buy it. Get a refund if you don't like it. We make it stupid easy to do so. +</p> +<h3>I still think you should do a free version. Think of all people who would give it a shot.</h3> +<p> +Free isn't a sustainable financial model. We don't want to spam your email. We don't want to collect usage data off of you either. We just want to provide quality toolchains to quality developers (as opposed to a large quantity of developers). +</p> +<p> +The people that pay for DragonRuby and make an effort to understand it are the ones we want to build a community around, partner with, and collaborate with. So having that small monetary wall deters entitled individuals that don't value the same things we do. +</p> +<h3>What if I build something with DragonRuby, but DragonRuby LLP becomes insolvent.</h3> +<p> +That won't happen if the development world stop asking for free stuff and non-trivially compensate open source developers. Look, we want to be able to work on the stuff we love, every day of our lives. And we'll go to great lengths to make that happen. +</p> +<p> +But, in the event that sad day comes, our partnership bylaws state that _all_ DragonRuby IP that can be legally open sourced, will be released under a permissive license. +</p> +<h1 id='--cheatsheet--how-to-determine-what-frame-you-are-on'>CHEATSHEET: How To Determine What Frame You Are On</h1> <p> There is a property on <code>state</code> called <code>tick_count</code> that is incremented by DragonRuby every time the <code>tick</code> method is called. The following code renders a label that displays the current <code>tick_count</code>. </p> @@ -604,7 +850,7 @@ There is a property on <code>state</code> called <code>tick_count</code> that is args.outputs.labels << [10, 670, "#{args.state.tick_count}"] end </pre> -<h1 id='--how-to-get-current-framerate'>How To Get Current Framerate</h1> +<h1 id='--cheatsheet--how-to-get-current-framerate'>CHEATSHEET: How To Get Current Framerate</h1> <p> Current framerate is a top level property on the Game Toolkit Runtime and is accessible via <code>args.gtk.current_framerate</code>. </p> @@ -612,7 +858,7 @@ Current framerate is a top level property on the Game Toolkit Runtime and is acc args.outputs.labels << [10, 710, "framerate: #{args.gtk.current_framerate.round}"] end </pre> -<h1 id='--how-to-render-a-sprite-using-an-array'>How To Render A Sprite Using An Array</h1> +<h1 id='--cheatsheet--how-to-render-a-sprite-using-an-array'>CHEATSHEET: How To Render A Sprite Using An Array</h1> <p> All file paths should use the forward slash <code>/</code> *not* backslash <code></code>. Game Toolkit includes a number of sprites in the <code>sprites</code> folder (everything about your game is located in the <code>mygame</code> directory). </p> @@ -632,7 +878,7 @@ The following code renders a sprite with a <code>width</code> and <code>height</ ] end </pre> -<h1 id='--more-sprite-properties-as-an-array'>More Sprite Properties As An Array</h1> +<h1 id='--cheatsheet--more-sprite-properties-as-an-array'>CHEATSHEET: More Sprite Properties As An Array</h1> <p> Here are all the properties you can set on a sprite. </p> @@ -651,7 +897,7 @@ Here are all the properties you can set on a sprite. ] end </pre> -<h1 id='--different-sprite-representations'>Different Sprite Representations</h1> +<h1 id='--cheatsheet--different-sprite-representations'>CHEATSHEET: Different Sprite Representations</h1> <p> Using ordinal positioning can get a little unruly given so many properties you have control over. </p> @@ -714,7 +960,7 @@ def tick args h: 50) end </pre> -<h1 id='--how-to-render-a-label'>How To Render A Label</h1> +<h1 id='--cheatsheet--how-to-render-a-label'>CHEATSHEET: How To Render A Label</h1> <p> <code>args.outputs.labels</code> is used to render labels. </p> @@ -729,14 +975,14 @@ Here is the minimum code: args.outputs.labels << [640, 360, "I am a black label."] end </pre> -<h1 id='--a-colored-label'>A Colored Label</h1> +<h1 id='--cheatsheet--a-colored-label'>CHEATSHEET: A Colored Label</h1> <pre>def tick args # A colored label # X Y TEXT, RED GREEN BLUE ALPHA args.outputs.labels << [640, 360, "I am a redish label.", 255, 128, 128, 255] end </pre> -<h1 id='--extended-label-properties'>Extended Label Properties</h1> +<h1 id='--cheatsheet--extended-label-properties'>CHEATSHEET: Extended Label Properties</h1> <pre>def tick args # A colored label # X Y TEXT SIZE ALIGNMENT RED GREEN BLUE ALPHA FONT FILE @@ -760,7 +1006,7 @@ A <code>SIZE_ENUM</code> of <code>0</code> represents "default size". A <code>ne <p> An <code>ALIGNMENT_ENUM</code> of <code>0</code> represents "left aligned". <code>1</code> represents "center aligned". <code>2</code> represents "right aligned". </p> -<h1 id='--rendering-a-label-as-a--hash-'>Rendering A Label As A <code>Hash</code></h1> +<h1 id='--cheatsheet--rendering-a-label-as-a--hash-'>CHEATSHEET: Rendering A Label As A <code>Hash</code></h1> <p> You can add additional metadata about your game within a label, which requires you to use a `Hash` instead. </p> @@ -786,7 +1032,7 @@ You can add additional metadata about your game within a label, which requires y } end </pre> -<h1 id='--getting-the-size-of-a-piece-of-text'>Getting The Size Of A Piece Of Text</h1> +<h1 id='--cheatsheet--getting-the-size-of-a-piece-of-text'>CHEATSHEET: Getting The Size Of A Piece Of Text</h1> <p> You can get the render size of any string using <code>args.gtk.calcstringbox</code>. </p> @@ -805,7 +1051,7 @@ You can get the render size of any string using <code>args.gtk.calcstringbox</co ] end </pre> -<h1 id='--how-to-play-a-sound'>How To Play A Sound</h1> +<h1 id='--cheatsheet--how-to-play-a-sound'>CHEATSHEET: How To Play A Sound</h1> <p> Sounds that end <code>.wav</code> will play once: </p> @@ -836,7 +1082,7 @@ If you want to play a <code>.ogg</code> once as if it were a sound effect, you c end end </pre> -<h1 id='--using--args.state--to-store-your-game-state'>Using <code>args.state</code> To Store Your Game State</h1> +<h1 id='--cheatsheet--using--args.state--to-store-your-game-state'>CHEATSHEET: Using <code>args.state</code> To Store Your Game State</h1> <p> <code>args.state</code> is a open data structure that allows you to define properties that are arbitrarily nested. You don't need to define any kind of <code>class</code>. </p> @@ -870,234 +1116,29 @@ To assign a value every frame, just use the <code>=</code> operator, but _make s ] end </pre> -<h1 id='--frequently-asked-questions,-comments,-and-concerns'>Frequently Asked Questions, Comments, and Concerns</h1> -<p> -Here are questions, comments, and concerns that frequently come up. -</p> -<h2>Frequently Asked Questions</h2> -<h3>What is DragonRuby LLP?</h3> -<p> -DragonRuby LLP is a partnership of four devs who came together with the goal of bringing the aesthetics and joy of Ruby, everywhere possible. -</p> -<p> -Under DragonRuby LLP, we offer a number of products (with more on the way): -</p> -<ul> -<li>Game Toolkit (GTK): A 2D game engine that is compatible with modern - gaming platforms.</li> -<li>RubyMotion (RM): A compiler toolchain that allows you to build native, cross-platform mobile - apps. <a href='http://rubymotion.com'>http://rubymotion.com</a></li> -</ul> -<p> -All of the products above leverage a shared core called DragonRuby. -</p> -<p> -NOTE: From an official branding standpoint each one of the products is suffixed with "A DragonRuby LLP Product" tagline. Also, DragonRuby is _one word, title cased_. -</p> -<p> -NOTE: We leave the "A DragonRuby LLP Product" off of this one because that just sounds really weird. -</p> -<p> -NOTE: Devs who use DragonRuby are "Dragon Riders/Riders of Dragons". That's a bad ass identifier huh? -</p> -<h3>What is DragonRuby?</h3> -<p> -The response to this question requires a few subparts. First we need to clarify some terms. Specifically _language specification_ vs _runtime_. -</p> -<h4>Okay... so what is the difference between a language specification and a runtime?</h4> -<p> -A runtime is an _implementation_ of a language specification. When people say "Ruby," they are usually referring to "the Ruby 3.0+ language specification implemented via the CRuby/MRI Runtime." -</p> -<p> -But, there are many Ruby Runtimes: CRuby/MRI, JRuby, Truffle, Rubinius, Artichoke, and (last but certainly not least) DragonRuby. -</p> -<h4>Okay... what language specification does DragonRuby use then?</h4> -<p> -DragonRuby's goal is to be compliant with the ISO/IEC 30170:2012 standard. It's syntax is Ruby 2.x compatible, but also contains semantic changes that help it natively interface with platform specific libraries. -</p> -<h4>So... why another runtime?</h4> -<p> -The elevator pitch is: -</p> -<p> -DragonRuby is a Multilevel Cross-platform Runtime. The "multiple levels" within the runtime allows us to target platforms no other Ruby can target: PC, Mac, Linux, Raspberry Pi, WASM, iOS, Android, Nintendo Switch, PS4, Xbox, and Scadia. -</p> -<h4>What does Multilevel Cross-platform mean?</h4> -<p> -There are complexities associated with targeting all the platforms we support. Because of this, the runtime had to be architected in such a way that new platforms could be easily added (which lead to us partitioning the runtime internally): -</p> -<ul> -<li>Level 1 we leverage a good portion of mRuby.</li> -<li>Level 2 consists of optimizations to mRuby we've made given that our - target platforms are well known.</li> -<li>Level 3 consists of portable C libraries and their Ruby - C-Extensions.</li> -</ul> -<p> -Levels 1 through 3 are fairly commonplace in many runtime implementations (with level 1 being the most portable, and level 3 being the fastest). But the DragonRuby Runtime has taken things a bit further: -</p> -<ul> -<li>Level 4 consists of shared abstractions around hardware I/O and operating - system resources. This level leverages open source and proprietary components within Simple DirectMedia Layer (a low level multimedia component library that has been in active development for 22 years and counting).</li> -<li>Level 5 is a code generation layer which creates metadata that allows - for native interoperability with host runtime libraries. It also includes OS specific message pump orchestrations.</li> -<li>Level 6 is a Ahead of Time/Just in Time Ruby compiler built with LLVM. This - compiler outputs _very_ fast platform specific bitcode, but only supports a subset of the Ruby language specification.</li> -</ul> -<p> -These levels allow us to stay up to date with open source implementations of Ruby; provide fast, native code execution on proprietary platforms; ensure good separation between these two worlds; and provides a means to add new platforms without going insane. -</p> -<h4>Cool cool. So given that I understand everything to this point, can we answer the original question? What is DragonRuby?</h4> -<p> -DragonRuby is a Ruby runtime implementation that takes all the lessons we've learned from MRI/CRuby, and merges it with the latest and greatest compiler and OSS technologies. -</p> -<h3>How is DragonRuby different than MRI?</h3> -<p> -DragonRuby supports a subset of MRI apis. Our target is to support all of mRuby's standard lib. There are challenges to this given the number of platforms we are trying to support (specifically console). -</p> -<h4>Does DragonRuby support Gems?</h4> -<p> -DragonRuby does not support gems because that requires the installation of MRI Ruby on the developer's machine (which is a non-starter given that we want DragonRuby to be a zero dependency runtime). While this seems easy for Mac and Linux, it is much harder on Windows and Raspberry Pi. mRuby has taken the approach of having a git repository for compatible gems and we will most likely follow suite: <a href='https://github.com/mruby/mgem-list'>https://github.com/mruby/mgem-list</a>. -</p> -<h4>Does DragonRuby have a REPL/IRB?</h4> -<p> -You can use DragonRuby's Console within the game to inspect object and execute small pieces of code. For more complex pieces of code create a file called <code>repl.rb</code> and put it in <code>mygame/app/repl.rb</code>: -</p> -<ul> -<li>Any code you write in there will be executed when you change the file. You can organize different pieces of code using the <code>repl</code> method:</li> -</ul> -<pre>repl do - puts "hello world" - puts 1 + 1 +<h1 id='--cheatsheet--troubleshoot-performance'>CHEATSHEET: Troubleshoot Performance</h1> +<ol> +<li> If you're using <code>Array</code>s for your primitives (<code>args.outputs.sprites << []</code>), use <code>Hash</code> instead (<code>args.outputs.sprites << { x: ... }</code>).</li> +<li> If you're using <code>Entity</code> for your primitives (<code>args.outputs.sprites << args.state.new_entity</code>), use <code>StrictEntity</code> instead (<code>args.outputs.sprites << args.state.new_entity_strict</code>).</li> +<li> Use <code>.each</code> instead of <code>.map</code> if you don't care about the return value.</li> +<li> When concatenating primitives to outputs, do them in bulk. Instead of:</li> +</ol> +<pre>args.state.bullets.each do |bullet| + args.outputs.sprites << bullet.sprite end </pre> -<ul> -<li>If you use the `repl` method, the code will be executed and the DragonRuby Console will automatically open so you can see the results (on Mac and Linux, the results will also be printed to the terminal).</li> -<li>All <code>puts</code> statements will also be saved to <code>logs/log.txt</code>. So if you want to stay in your editor and not look at the terminal, or the DragonRuby Console, you can <code>tail</code> this file.</li> -</ul> <p> -4. To ignore code in <code>repl.rb</code>, instead of commenting it out, prefix <code>repl</code> with the letter <code>x</code> and it'll be ignored. +do </p> -<pre>xrepl do # <------- line is prefixed with an "x" - puts "hello world" - puts 1 + 1 -end - -# This code will be executed when you save the file. -repl do - puts "Hello" -end - -repl do - puts "This code will also be executed." -end - -# use xrepl to "comment out" code -xrepl do - puts "This code will not be executed because of the x infront of repl". +<pre>args.outputs.sprites << args.state.bullets.map do |b| + b.sprite end </pre> -<h4>Does DragonRuby support <code>pry</code> or have any other debugging facilities?</h4> -<p> -<code>pry</code> is a gem that assumes you are using the MRI Runtime (which is incompatible with DragonRuby). Eventually DragonRuby will have a pry based experience that is compatible with a debugging infrastructure called LLDB. Take the time to read about LLDB as it shows the challenges in creating something that is compatible. -</p> -<p> -You can use DragonRuby's replay capabilities to troubleshoot: -</p> -<ol> -<li> DragonRuby is hot loaded which gives you a very fast feedback loop (if the game throws an exception, it's because of the code you just added).</li> -<li> Use <code>./dragonruby mygame --record</code> to create a game play recording that you can use to find the exception (you can replay a recoding by executing <code>./dragonruby mygame --replay last_replay.txt</code> or through the DragonRuby Console using <code>$gtk.recording.start_replay "last_replay.txt"</code>.</li> -<li> DragonRuby also ships with a unit testing facility. You can invoke the following command to run a test: <code>./dragonruby . --eval some_ruby_file.rb --no-tick</code>.</li> -<li> Get into the habit of adding debugging facilities within the game itself. You can add drawing primitives to <code>args.outputs.debug</code> that will render on top of your game but will be ignored in a production release.</li> -<li> Debugging something that runs at 60fps is (imo) not that helpful. The exception you are seeing could have been because of a change that occurred many frames ago.</li> -</ol> -<h2>Frequent Comments About Ruby as a Language Choice</h2> -<h3>But Ruby is dead.</h3> -<p> -Let's check the official source for the answer to this question: isrubydead.com: <a href='https://isrubydead.com/'>https://isrubydead.com/</a>. -</p> -<p> -On a more serious note, Ruby's _quantity_ levels aren't what they used to be. And that's totally fine. Every one chases the new and shiny. -</p> -<p> -What really matters is _quality/maturity_. Here is the latest (StackOverflow Survey sorted by highest paid developers)[https://insights.stackoverflow.com/survey/2019#top-paying-technologies]. -</p> -<p> -Let's stop making this comment shall we? -</p> -<h3>But Ruby is slow.</h3> -<p> -That doesn't make any sense. A language specification can't be slow... it's a language spec. Sure, an _implementation/runtime_ can be slow though, but then we'd have to talk about which runtime. -</p> -<h3>Dynamic languages are slow.</h3> -<p> -They are certainly slower than statically compiled languages. With the processing power and compiler optimizations we have today, dynamic languages like Ruby are _fast enough_. -</p> -<p> -Unless you are writing in some form of intermediate representation by hand, your language of choice also suffers this same fallacy of slow. Like, nothing is faster than a low level assembly-like language. So unless you're writing in that, let's stop making this comment. -</p> -<p> -NOTE: If you _are_ hand writing LLVM IR, we are always open to bringing on new partners with such a skill set. Email us ^_^. -</p> -<h2>Frequent Concerns</h2> -<h3>DragonRuby is not open source. That's not right.</h3> -<p> -The current state of open source is unsustainable. Contributors work for free, most all open source repositories are severely under-staffed, and burnout from core members is rampant. -</p> -<p> -We believe in open source very strongly. Parts of DragonRuby are in fact, open source. Just not all of it (for legal reasons, and because the IP we've created has value). And we promise that we are looking for (or creating) ways to _sustainably_ open source everything we do. -</p> -<p> -If you have ideas on how we can do this, email us! -</p> -<p> -If the reason above isn't sufficient, then definitely use something else. -</p> -<p> -All this being said, we do have parts of the engine open sourced on GitHub: <a href='https://github.com/dragonruby/dragonruby-game-toolkit-contrib/'>https://github.com/dragonruby/dragonruby-game-toolkit-contrib/</a> -</p> -<h3>DragonRuby is for pay. You should offer a free version.</h3> -<p> -If you can afford to pay for DragonRuby, you should (and will). We don't go around telling writers that they should give us their books for free, and only require payment if we read the entire thing. It's time we stop asking that of software products. -</p> -<p> -That being said, we will _never_ put someone out financially. We have income assistance for anyone that can't afford a license to any one of our products. -</p> -<p> -You qualify for a free, unrestricted license to DragonRuby products if any of the following items pertain to you: -</p> -<ul> -<li>Your income is below $2,000.00 (USD) per month.</li> -<li>You are under 18 years of age.</li> -<li>You are a student of any type: traditional public school, home - schooling, college, bootcamp, or online.</li> -<li>You are a teacher, mentor, or parent who wants to teach a kid how to code.</li> -<li>You work/worked in public service or at a charitable organization: - for example public office, army, or any 501(c)(3) organization.</li> -</ul> <p> -Just contact Amir at [email protected] with a short explanation of your current situation and he'll set you up. No questions asked. +5. Use <code>args.outputs.static_</code> variant for things that don't change often (take a look at the Basic Gorillas sample app and Dueling Starships sample app to see how <code>static_</code> is leveraged. </p> -<h3>But still, you should offer a free version. So I can try it out and see if I like it.</h3> <p> -You can try our [web-based sandbox environment](). But it won't do the runtime justice. Or just come to our [Slack]() or [Discord]() channel and ask questions. We'd be happy to have a one on one video chat with you and show off all the cool stuff we're doing. -</p> -<p> -Seriously just buy it. Get a refund if you don't like it. We make it stupid easy to do so. -</p> -<h3>I still think you should do a free version. Think of all people who would give it a shot.</h3> -<p> -Free isn't a sustainable financial model. We don't want to spam your email. We don't want to collect usage data off of you either. We just want to provide quality toolchains to quality developers (as opposed to a large quantity of developers). -</p> -<p> -The people that pay for DragonRuby and make an effort to understand it are the ones we want to build a community around, partner with, and collaborate with. So having that small monetary wall deters entitled individuals that don't value the same things we do. -</p> -<h3>What if I build something with DragonRuby, but DragonRuby LLP becomes insolvent.</h3> -<p> -That won't happen if the development world stop asking for free stuff and non-trivially compensate open source developers. Look, we want to be able to work on the stuff we love, every day of our lives. And we'll go to great lengths to make that happen. -</p> -<p> -But, in the event that sad day comes, our partnership bylaws state that _all_ DragonRuby IP that can be legally open sourced, will be released under a permissive license. +6. Consider using a <code>render_target</code> if you're doing some form of a camera that moves a lot of primitives (take a look at the Render Target sample apps for more info). </p> <h1 id='--docs---gtk--runtime-'>DOCS: <code>GTK::Runtime</code></h1> <p> @@ -7412,8 +7453,8 @@ end $gtk.reset </pre> -<h1 id='--advanced-rendering---render-targets-with-alphas---main.rb'>Advanced Rendering - Render Targets With Alphas - main.rb</h1> -<pre># ./samples/07_advanced_rendering/02_render_targets_with_alphas/app/main.rb +<h1 id='--advanced-rendering---render-targets-with-tile-manipulation---main.rb'>Advanced Rendering - Render Targets With Tile Manipulation - main.rb</h1> +<pre># ./samples/07_advanced_rendering/02_render_targets_with_tile_manipulation/app/main.rb # This sample is meant to show you how to do that dripping transition thing # at the start of the original Doom. Most of this file is here to animate # a scene to wipe away; the actual wipe effect is in the last 20 lines or @@ -8796,6 +8837,7 @@ end </pre> <h1 id='--performance---sprites-as-hash---main.rb'>Performance - Sprites As Hash - main.rb</h1> <pre># ./samples/09_performance/01_sprites_as_hash/app/main.rb + # Sprites represented as Hashes using the queue ~args.outputs.sprites~ # code up, but are the "slowest" to render. # The reason for this is the access of the key in the Hash and also @@ -9821,11 +9863,14 @@ end </pre> <h1 id='--12-c-extensions---basics---main.rb'>12 C Extensions - Basics - main.rb</h1> <pre># ./samples/12_c_extensions/01_basics/app/main.rb -$gtk.ffi_misc.gtk_dlopen("./samples/12_c_extensions/01_basics/build.dir/ext.lib") +$gtk.ffi_misc.gtk_dlopen("ext") include FFI::CExt def tick args - args.outputs.labels << [460, 600, "square(42) = #{square(42)}"] + args.outputs.labels << [640, 500, "mouse.x = #{args.mouse.x.to_i}", 5, 1] + args.outputs.labels << [640, 460, "square(mouse.x) = #{square(args.mouse.x.to_i)}", 5, 1] + args.outputs.labels << [640, 420, "mouse.y = #{args.mouse.y.to_i}", 5, 1] + args.outputs.labels << [640, 380, "square(mouse.y) = #{square(args.mouse.y.to_i)}", 5, 1] end @@ -22111,12 +22156,12 @@ module GTK end def save_history - $gtk.ffi_file.storefile(@history_fname, @command_history.reverse.join("\n")) + $gtk.ffi_file.write_root @history_fname, (@command_history.reverse.join "\n") end def load_history @command_history.clear - str = $gtk.ffi_file.loadfile(@history_fname) + str = $gtk.ffi_file.read @history_fname return if str.nil? # no history to load. str.chomp!("\n") # Don't let endlines at the end cause extra blank line. @@ -22329,6 +22374,36 @@ S args.inputs.keyboard.key_down.any? console_toggle_keys end + def try_search_docs exception + string_e = "#{exception}" + @last_command_errored = true + + if (string_e.include? "wrong number of arguments") + method_name = ((string_e.split ":")[0].gsub "'", "") + if !(method_name.include? " ") + results = (Kernel.__docs_search_results__ method_name) + if !results.include? "* DOCS: No results found." + puts (results.join "\n") + puts <<-S +* INFO: #{results.length} matches(s) found in DOCS for ~#{method_name}~ (see above). +You can search the documentation yourself using the following command in the Console: +#+begin_src ruby + docs_search \"#{method_name}\" +#+end_src +S + log_once_info :exported_search_results, "The search results above has been seen in logs/puts.txt and docs/search_results.txt." + end + end + end + rescue Exception => se + puts <<-S +* FATAL: ~GTK::Console#try_search_docs~ +There was an exception searching for docs (~GTK::Console#try_search_docs~). You might want to let DragonRuby know about this. +** INNER EXCEPTION +#{se} +S + end + def eval_the_set_command cmd = current_input_str.strip if cmd.length != 0 @@ -22355,18 +22430,8 @@ S end @last_command_errored = false rescue Exception => e - string_e = "#{e}" - puts "* EXCEPTION: #{e}" - log "* EXCEPTION: #{e}" - @last_command_errored = true - if (string_e.include? "wrong number of arguments") - method_name = (string_e.split ":")[0].gsub "'", "" - results = (Kernel.docs_search method_name).strip - if !results.include? "* DOCS: No results found." - puts results - log results - end - end + try_search_docs e + puts "* EXCEPTION: #{e}" end end end @@ -22980,6 +23045,7 @@ module GTK if args.inputs.mouse.click clicked = @buttons.find { |b| args.inputs.mouse.inside_rect? b[:rect] } if clicked + args.inputs.mouse.click = nil send clicked[:method] end end @@ -25043,6 +25109,10 @@ module GTK point.inside_rect? rect end + def inside_circle? center, radius + point.point_inside_circle? center, radius + end + alias_method :position, :point def clear @@ -25626,6 +25696,8 @@ S if definitions.include?(:ratio) result = rand * result + elsif definitions.include?(:int) + result = (rand result) end result @@ -26138,7 +26210,12 @@ module GTK You can display these diagnostics using: #+begin_src - args.outputs.debug << args.gtk.framerate_diagnostics_primitives + def tick args + # .... + + # IMPORTANT: Put this at the END of the ~tick~ method. + args.outputs.debug << args.gtk.framerate_diagnostics_primitives + end #+end_src ** Draw Calls: ~<<~ Invocation Perf Counter |
