From 9502c3a37f04711a377d95b6a6a3b5c526d6b88b Mon Sep 17 00:00:00 2001 From: Brett Chalupa Date: Tue, 13 Dec 2022 12:20:34 -0500 Subject: [PATCH 01/22] fix(intro): weird clarity with sentence h/t Vlevo --- src/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/introduction.md b/src/introduction.md index 3b9f2cb..037a6ae 100644 --- a/src/introduction.md +++ b/src/introduction.md @@ -70,7 +70,7 @@ Start by making small games that you can finish in a couple of days. Make a lot What's shipping? Isn't that when you want Mulder and Scully to kiss? No! Get your head out of the gutter you alien-loving freak. (I want to believe! 🛸) Shipping is when you 1. finish your game and 2. release it for people to play it. -So here's your mindset, boiled down: make a small game and ship it for free, then make another small game and ship it for free. Before long, you'll be building a visual novel where Mulder and Scully kiss and be swimming in a pool of cryptocoins! But seriously, what that mindset will do is help you grow as a developer, build a fanbase, and get your shipping muscle primed and ready for making a better game each time. +So here's your mindset, boiled down: make a small game and ship it for free, then make another small game and ship it for free. Before long, you'll be building a visual novel where Mulder and Scully kiss. Imagine yourself swimming in a pool of cryptocoins! But seriously, what that mindset will do is help you grow as a developer, build a fanbase, and get your shipping muscle primed and ready for making a better game each time. ## What We'll Be Making From 3f2529187d5f9e9af03bf5b64c2930c48b6f3ea2 Mon Sep 17 00:00:00 2001 From: Brett Chalupa Date: Tue, 13 Dec 2022 12:33:01 -0500 Subject: [PATCH 02/22] chore: remove readme disclaimer --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index c05af9d..fcc7ff8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # Building Games with DragonRuby -🚧 A work in progress! Expect typos, issues, and incompleteness. 🚧 - An open source book that walks you through how to build games with [DragonRuby Game Toolkit](https://dragonruby.org/toolkit/game). [Play the game you'll be building, right in the browser.](https://dragonridersunite.itch.io/dragonruby-book) @@ -19,7 +17,7 @@ When the code is pushed to the `main` branch on GitHub, an action runs that depl ## Key Versions - DragonRuby Game Toolkit: v3.24 -- mdbook: v0.4.21 +- mdbook: v0.4.22 ## Running Samples From 429c6002618a79ea12f61ca038a5319dde20fabc Mon Sep 17 00:00:00 2001 From: Vlevo Date: Tue, 13 Dec 2022 16:23:16 -0500 Subject: [PATCH 03/22] Small grammar-esc change --- src/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/introduction.md b/src/introduction.md index 037a6ae..68f050a 100644 --- a/src/introduction.md +++ b/src/introduction.md @@ -70,7 +70,7 @@ Start by making small games that you can finish in a couple of days. Make a lot What's shipping? Isn't that when you want Mulder and Scully to kiss? No! Get your head out of the gutter you alien-loving freak. (I want to believe! 🛸) Shipping is when you 1. finish your game and 2. release it for people to play it. -So here's your mindset, boiled down: make a small game and ship it for free, then make another small game and ship it for free. Before long, you'll be building a visual novel where Mulder and Scully kiss. Imagine yourself swimming in a pool of cryptocoins! But seriously, what that mindset will do is help you grow as a developer, build a fanbase, and get your shipping muscle primed and ready for making a better game each time. +So here's your mindset, boiled down: make a small game and ship it for free, then make another small game and ship it for free. Before long, you'll be building a visual novel where Mulder and Scully kiss. Now, imagine yourself swimming in a pool of cryptocoins! But seriously, what that iterative mindset will do is help you grow as a developer, build a fanbase, and get your shipping muscle primed and ready for making a better game each time. ## What We'll Be Making From 504cd3d9e9a2662fffe7c66589c9dba7fb6ed171 Mon Sep 17 00:00:00 2001 From: Vlevo Date: Tue, 13 Dec 2022 17:24:36 -0500 Subject: [PATCH 04/22] typo "shoots" instead of "shots" --- src/introduction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/introduction.md b/src/introduction.md index 68f050a..eb9bf8c 100644 --- a/src/introduction.md +++ b/src/introduction.md @@ -106,7 +106,7 @@ When I was 16, I took a computer science class in high school. It was my first e That class was foundational in the course my life would take in the 14 years since. At age 16 I was an emo kid who loved video games and anime. Imagine a swoopy haired teen in their bedroom listening to Bright Eyes while playing _Final Fantasy XII_. That was me. -So naturally, for my final project in that high school computer science class I made a game. You pilot a Moltres from Pokemon who shots fire balls at Zaku mechs from Gundam that fly across the screen. If you get hit by an enemy, it's game over. If you defeat all of the enemies, you win. This game was lovingly titled _Zaku Space Battle_. +So naturally, for my final project in that high school computer science class I made a game. You pilot a Moltres from Pokemon who shoots fireballs at Zaku mechs from Gundam that fly across the screen. If you get hit by an enemy, it's game over. If you defeat all of the enemies, you win. This game was lovingly titled _Zaku Space Battle_. ![screenshot of Zaku Space Battle showing the Moltres sprite, Zaku sprites, fire ball, and space background](./img/zaku-space-battle.jpg) @@ -120,7 +120,7 @@ If you want to, you can [buy me a coffee](https://buymeacoffee.com/brettchalupa) ## Contribute -This book is open source. That means anyone can view the code that builds it and contribute toward making better. Did you find something that doesn't work, contains a typo, or lacks clarity? [Submit an issue or contribute on GitHub.](https://github.com/DragonRidersUnite/book) It's easy, and you can do it right from your browser. Thanks in advance! +This book is open source. That means anyone can view the code that builds it and contribute toward making it better. Did you find something that doesn't work, contains a typo, or lacks clarity? [Submit an issue or contribute on GitHub.](https://github.com/DragonRidersUnite/book) It's easy, and you can do it right from your browser. Thanks in advance! If you're stuck and would like some extra assistance, reach out in [the DragonRuby Discord](https://discord.dragonruby.org). We'll get you unstuck! From 7453e233cd2d817883a9f7924ac716dbcdbf21ba Mon Sep 17 00:00:00 2001 From: Kayla Kantola Date: Tue, 13 Dec 2022 19:18:58 -0500 Subject: [PATCH 05/22] hello dragon typo fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thank you for writing this book ❤️ Really enjoying it so far. Caught a few typos! --- src/01-hello-dragon.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/01-hello-dragon.md b/src/01-hello-dragon.md index 269ffd7..6abad33 100644 --- a/src/01-hello-dragon.md +++ b/src/01-hello-dragon.md @@ -18,7 +18,7 @@ When you download DragonRuby Game Toolkit, it contains everything you need to bu Let's go over the key files in the archive you just extracted: -- `dragonruby` — the executable you'll run to launch your game in development mode, you're primary entry into the development flow +- `dragonruby` — the executable you'll run to launch your game in development mode, your primary entry into the development flow - `dragonruby-publish` — a command-line tool to help you easily build and publish your game online, don't worry about this yet! - `samples/` — a folder of example code that you can explore and run if you'd like, or just ignore it for now - `docs/` — the DragonRuby Game Toolkit docs for the version you've downloaded, extremely handy if you want to dive deeper than this book @@ -51,7 +51,7 @@ This isn't a game... yet! But it is doing three key things: And you haven't even written any code yet. Not a bad starting place. -DRGTK handles the boring stuff when it comes to making games—dealing with low-level APIs like graphics, window, and sounds. We can instead focus on creating our game instead of, for example, figuring out how to save data in a way that's compartible with Linux, Mac, Windows, Android, iOS, and web. +DRGTK handles the boring stuff when it comes to making games — dealing with low-level APIs like graphics, window, and sounds. We can instead focus on creating our game instead of, for example, figuring out how to save data in a way that's compatible with Linux, Mac, Windows, Android, iOS, and web. ## An Overview of the Main Game File @@ -71,7 +71,7 @@ Here's what that code does, line by line: {{#include code/chapter_01/01_default/app/main.rb:1}} ``` -This `def`ines a method called `tick` and passes in an parameter called `args`. `args` is short for arguments and is provided to us by DragonRuby GTK. +This `def`ines a method called `tick` and passes in a parameter called `args`. `args` is short for arguments and is provided to us by DragonRuby GTK. Methods are reusable pieces of code that you can call to do something over and over again. Think of methods like verbs; they're actions. Methods are a foundational building block that allow for code reuse. @@ -90,7 +90,7 @@ francis = Friend.new give_cookie(francis) ``` -Note: methods in Ruby have optional parenthesis. You can use them or leave them out when defining and calling your methods. These are the same: +Note: methods in Ruby have optional parentheses. You can use them or leave them out when defining and calling your methods. These are the same: ``` ruby def give_cookie(friend) @@ -124,7 +124,7 @@ And then finally the code within the brackets `[]` is an array of data that repr I think of arrays like a stack of CDs. The CDs are in a specific order, but you don't know what a given CD is unless you pull one out of the stack and look at it. You have to do the same thing with an array. In programming, you put data into an array to collect that data and keep track of it. If you want to know what's at a specific place in a array, you have to check. -You can see some code in quotes, those are strings. And they're what's being displayed by the game. In order to show the text, though, we need to tell the engine where to place it on the screen. That's what the first two elements of the array do: they specify the x and y position in of the text in the game. Then there's the text we want to render. That's followed by the text size. Then finally the alignment (centered in this case). +You can see some code in quotes, those are strings. And they're what's being displayed by the game. In order to show the text, though, we need to tell the engine where to place it on the screen. That's what the first two elements of the array do: they specify the x and y position of the text in the game. Then there's the text we want to render. That's followed by the text size. Then finally the alignment (centered in this case). Here's it broken down: @@ -133,7 +133,7 @@ Here's it broken down: [640, 500, 'Hello World!', 5, 1] ``` -Don't worry about memorizing what the positional elements of the array mean. This is just a quick way to render text. We'll start using a more friendly approach soon enough. The sample game does this three times, thus rendering three difference pieces of text. The `y` coordinate is different for each, stacking them on top of each other vertically instead of overlapping one another. +Don't worry about memorizing what the positional elements of the array mean. This is just a quick way to render text. We'll start using a more friendly approach soon enough. The sample game does this three times, thus rendering three different pieces of text. The `y` coordinate is different for each, stacking them on top of each other vertically instead of overlapping one another. Gosh enough of this rambling, let's adjust some code. Change the text from `"Hello World!"` to be `"Hello Dragon!"` and save the file. From a7774a4da131e369955b89f2d1f7022276e18d13 Mon Sep 17 00:00:00 2001 From: Vlevo Date: Tue, 13 Dec 2022 21:21:56 -0500 Subject: [PATCH 06/22] various grammatical tweaks to 01-hello-dragon.md explanation worthy mentions: Itch.io always calls itself 'itch.io' and so, at least in print, should we. Apple spells it macOS, even at the beginning of sentences. --- src/01-hello-dragon.md | 60 +++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/01-hello-dragon.md b/src/01-hello-dragon.md index 269ffd7..4dea7df 100644 --- a/src/01-hello-dragon.md +++ b/src/01-hello-dragon.md @@ -1,26 +1,26 @@ # Hello Dragon! -We'll start by rendering an image and some simple text on the screen. But first, we need to get our computer and DragonRuby Game Toolkit ready for developing. +We'll start by rendering an image and some simple text on the screen. But first, we need to get our computer and DragonRuby Game Toolkit ready for developing games. ## First Steps 1. **Download a code editor:** Since you'll be coding your game, you need a special text editor to write the code without any extra formatting that text editors like Microsoft Word add. [Visual Studio Code](https://code.visualstudio.com/) is a great free editor. Download and install it. (Or use your own favorite editor.) -2. **Get DragonRuby GTK:** You need to get a copy of DragonRuby GTK so you can use the engine. [Buy it on Itch and download the zip file for your operating system.](https://dragonruby.itch.io/dragonruby-gtk/purchase) +2. **Get DragonRuby GTK:** You need to get a copy of DragonRuby GTK so you can use the engine. [Buy it on itch.io and download the zip file for your operating system.](https://dragonruby.itch.io/dragonruby-gtk/purchase) 3. **Extract the DRGTK engine zip**: In your computer's file explorer, extract the engine zip file. You're ready to work on your game. Let's get to it! -**ProTip:** don't delete the zip file! You can unzip it again for when you start working on your next game. It's helpful to keep it around. +**ProTip:** don't delete the zip file! You can unzip it again when you start working on your next game. It's helpful to keep it around. ## What's in the Engine Zip -When you download DragonRuby Game Toolkit, it contains everything you need to build your game. There's no external dependencies to install or monkey with. You just use the provided files and start making your game. +When you download the DragonRuby Game Toolkit, it contains everything you need to build your game. There are no external dependencies to install or monkey with. You just use the provided files and start making your game. Let's go over the key files in the archive you just extracted: - `dragonruby` — the executable you'll run to launch your game in development mode, you're primary entry into the development flow - `dragonruby-publish` — a command-line tool to help you easily build and publish your game online, don't worry about this yet! -- `samples/` — a folder of example code that you can explore and run if you'd like, or just ignore it for now +- `samples/` — a folder of example code that you can explore and run if you'd like, or just ignore for now - `docs/` — the DragonRuby Game Toolkit docs for the version you've downloaded, extremely handy if you want to dive deeper than this book - `mygame/` 🌟 — as the name implies, this is where the code, graphics, sound, and other assets live for your game; this is the primary folder you'll be working in - `app/` — this is where your Ruby code goes @@ -37,7 +37,7 @@ Don't worry about the other files yet. Focus on the `mygame/` directory, and, sp Launch the `dragonruby` file. -If you're on MacOS, right-click the file and select "Open". You'll need to ensure software from unverified sources can be run. +If you're on macOS, right-click the file and select "Open". You'll need to ensure software from unverified sources can be run. Here's what gets displayed: @@ -51,7 +51,7 @@ This isn't a game... yet! But it is doing three key things: And you haven't even written any code yet. Not a bad starting place. -DRGTK handles the boring stuff when it comes to making games—dealing with low-level APIs like graphics, window, and sounds. We can instead focus on creating our game instead of, for example, figuring out how to save data in a way that's compartible with Linux, Mac, Windows, Android, iOS, and web. +DRGTK handles the boring stuff when it comes to making games—dealing with low-level APIs like graphics, sounds and the game window. We can instead focus on creating our game instead of, for example, figuring out how to save data in a way that's compartible with Linux, Mac, Windows, Android, iOS, and web. ## An Overview of the Main Game File @@ -63,7 +63,7 @@ Let's take a look at what's in `mygame/app/main.rb`: Open this file yourself in Visual Studio Code. Go ahead and do that: New Window > Open > [select the folder on your computer with the engine in it] -Six lines of codes to render text and an image? Not bad! (Trust me, if you did this all from scratch without an engine, it'd take hundreds of lines of code.) +Six lines of code to render text and an image? Not bad! (Trust me, if you did this all from scratch without an engine, it'd take hundreds of lines of code.) Here's what that code does, line by line: @@ -71,9 +71,9 @@ Here's what that code does, line by line: {{#include code/chapter_01/01_default/app/main.rb:1}} ``` -This `def`ines a method called `tick` and passes in an parameter called `args`. `args` is short for arguments and is provided to us by DragonRuby GTK. +This `def`ines a method called `tick` and passes in a parameter called `args`. `args` is short for arguments and is provided to us by DragonRuby GTK. -Methods are reusable pieces of code that you can call to do something over and over again. Think of methods like verbs; they're actions. Methods are a foundational building block that allow for code reuse. +Methods are reusable pieces of code that you can call to do something over and over again. Think of methods like verbs; they're actions. Methods are a foundational building block that allows for code reuse. Let's say you wanted to give a friend a cookie 🍪, you'd define a method called `give_cookie` and pass in the `friend` as a parameter. The friend then has a method called `eat` that we call, passing in a parameter of cookie. @@ -112,19 +112,19 @@ The next three lines handle outputting text to the screen: {{#include code/chapter_01/01_default/app/main.rb:2:4}} ``` -Your eyes might be melting a little bit. But don't worry, wipe that melted bit of eye away and focus! It's actually pretty intuitive once you get the hang of it. +Your eyes might be melting a little bit. But don't worry, wipe that melted bit of eye away and focus! It's pretty intuitive once you get the hang of it. -Remember `args` from above? That parameter that's passed into `tick`? Well, you can call methods on it! This allows you to interact with the game engine. +Remember `args` from above? The parameter that's passed into `tick`? Well, you can call methods on it! This allows you to interact with the game engine. -`args` has a method called `outputs` that represents the data that gets rendered in the screen. You access it with `args.outputs`. Neato! `labels` is a method on `outputs`, see how the `.` chains things together? +`args` has a method called `outputs` that represents the data that gets rendered on the screen. You access it with `args.outputs`. Neato! `labels` is a method of `outputs`, see how the `.` chains things together? The `<<` is called the shovel operator. It lets you push data into a collection. `labels` is the collection we're shoveling data into because we want to render some text. And then finally the code within the brackets `[]` is an array of data that represents what we want to display on the screen. It may not be clear exactly what it's doing yet, but it'll become more clear over time. -I think of arrays like a stack of CDs. The CDs are in a specific order, but you don't know what a given CD is unless you pull one out of the stack and look at it. You have to do the same thing with an array. In programming, you put data into an array to collect that data and keep track of it. If you want to know what's at a specific place in a array, you have to check. +I think of arrays like a stack of CDs. The CDs are in a specific order, but you don't know what a given CD is unless you pull one out of the stack and look at it. You have to do the same thing with an array. In programming, you put data into an array to collect that data and keep track of it. If you want to know what's at a specific place in an array, you have to check. -You can see some code in quotes, those are strings. And they're what's being displayed by the game. In order to show the text, though, we need to tell the engine where to place it on the screen. That's what the first two elements of the array do: they specify the x and y position in of the text in the game. Then there's the text we want to render. That's followed by the text size. Then finally the alignment (centered in this case). +You can see some code in quotes, those are strings. And they're what's being displayed by the game. In order to show the text, though, we need to tell the engine where to place it on the screen. That's what the first two elements of the array do: they specify the x and y position of the text. Then there's the text we want to render. That's followed by the text size. Then finally the alignment (centered in this case). Here's it broken down: @@ -133,27 +133,27 @@ Here's it broken down: [640, 500, 'Hello World!', 5, 1] ``` -Don't worry about memorizing what the positional elements of the array mean. This is just a quick way to render text. We'll start using a more friendly approach soon enough. The sample game does this three times, thus rendering three difference pieces of text. The `y` coordinate is different for each, stacking them on top of each other vertically instead of overlapping one another. +Don't worry about memorizing what the positional elements of the array mean. This is just a quick way to render text. We'll start using a more friendly approach soon enough. The sample game does this three times, thus rendering three different pieces of text. The `y` coordinate is different for each, stacking them on top of each other vertically instead of overlapping one another. -Gosh enough of this rambling, let's adjust some code. Change the text from `"Hello World!"` to be `"Hello Dragon!"` and save the file. +Gosh enough of this rambling, let's adjust some code. Change the text from `"Hello World!"` to `"Hello Dragon!"` and save the file. ![screenshot of the Hello Dragon! for DragonRuby GTK](./img/hello-dragon.jpg) -Did you see that? The game reloaded your code and changed the text to be "Hello Dragon!" That was quick, wasn't it? That's one of the best parts of DRGTK—live reloading of your game code in the engine. This allows you to make changes to your game quickly, reducing the time between the cycles of writing your code and testing it. +Did you see that? The game reloaded your code and changed the text to "Hello Dragon!" That was quick, wasn't it? That's one of the best parts of DRGTK—live reloading of your game code in the engine. This allows you to make changes to your game quickly, reducing the time between the cycles of writing your code and testing it. ``` ruby {{#include code/chapter_01/01_default/app/main.rb:5}} ``` -`args.outputs.sprites` is like labels, but it's instead a collection for sprites. It renders the `"dragonruby.png"` image at x: 576, y: 280, just like label text, but it also sets the size of the image to display. That's what the `128` and `101` represent in the array. Here's a break down of those elements: +`args.outputs.sprites` is like `args.outputs.labels`, but instead of holding labels it's a collection of sprites. It renders the `"dragonruby.png"` image at x: 576, y: 280, just like label text, and it also sets the size of the image to display. That's what the `128` and `101` represent in the array. Here's a breakdown of those elements: ``` ruby # x, y, w, h, image [576, 280, 128, 101, 'dragonruby.png'] ``` -Just like with labels, don't worry about memorizing the order here. There are friendlier ways to display them that we'll get to shortly. But it's an easy enough bit of code for putting an image on the screen. +Just like with labels, don't worry about memorizing the order here. There are friendlier ways to use them that we'll get to shortly. But it's an easy enough bit of code for putting an image on the screen. Finally, the last line: @@ -165,21 +165,21 @@ signifies that the definition of the `tick` method is over. Any code after that ## Screen Coordinates Explained -Let's take a detour down Screen Coordinates Road. The `x` and `y` position are coordinates on the two-dimensional plane of the game window. Remember geometry? I barely do. But this is important, so don't doze off on me yet. We're only still in the first chapter! +Let's take a detour down Screen Coordinates Road. The `x` and `y` positions are coordinates on the two-dimensional plane of the game window. Remember geometry? I barely do. But this is important, so don't doze off on me yet. We're only still in the first chapter! ![diagram showing x, y axis with 0, 0 being in the bottom left and 1280, 720 being in the upper right](./img/c01-coords.png) -DRGTK games are made up of a window that's 1280x720 pixels large. That's 1280 pixels wide and 720 pixels tall. The rectangle of the game screen contains 921600 pixels, that's those two numbers multiplied. Each of those pixels has a coordinate on the plane. It makes it easy to refer to a specific pixel by using its `x` and `y` position. +DRGTK games are made up of a window that's 1280x720 pixels in size. That's 1280 pixels wide and 720 pixels tall. The rectangle of the game screen contains 921600 pixels, that's those two numbers multiplied. Each of those pixels has a coordinate on the plane. It makes it easy to refer to a specific pixel by using its `x` and `y` position. -DRGTK starts 0, 0 in the lower left. So 1280, 720 would be the upper right. **Note:** this varies from most game engines and libraries and tools, but it's intentional to make it easier to think about gravity and follows the geometric 2D plane that is taught in mathematics. +DRGTK starts 0, 0 in the lower left. So 1280, 720 would be the upper right. **Note:** this varies from most game engines, libraries, and tools, but it's intentional to make it easier to think about gravity and follows the geometric 2D plane that is taught in mathematics. -It's important to keep coordinates in mind, as we'll be using them a lot when making our game. A major aspect of games is moving things on the screen, which we do by changing their coordinates on the screen. +It's important to keep coordinates in mind, as we'll be using them a lot when making our game. A major aspect of games is moving things around on the screen, which we do by changing their coordinates. ## Our Own Hello Back to making the game. Okay, yeah, you changed a string and it changed what was displayed. That's neat. But let's hit reset and do it ourselves. -I want you to delete the code in `mygame/app/main.rb`. Select it all and delete it. Yup, I know, the blank canvas is a challenge. But you need to start writing the code yourself in order to learn and build the muscle memory. So go ahead and type out each line below into your `main.rb`. +I want you to delete the code in `mygame/app/main.rb`. Select it all and delete it. Yup, I know, the blank canvas is a challenge. But you need to start writing the code yourself in order to learn and build your mental muscle memory. So go ahead and type out each line below into your `main.rb`. ``` ruby def tick args @@ -187,7 +187,7 @@ def tick args end ``` -You know what that does, right? Well you saw it automatically reload in your game, so of course you do! +You know what that does, right? Well, you saw it automatically reload in your game, so of course, you do! Let's greet our friend Oboe too. @@ -211,11 +211,11 @@ def tick args end ``` -The new code refactors (changes the implementation of the code without changing the behavior) the original so that we can easily change the greeting in one place instead of many. This is a bit of a trivial example, but it shows how we can write our own methods in DRGTK to make our code better. Reusing code is foundational for the rest of this book. +The new code refactors (changes the implementation of the code without changing the behavior) the original so that we can easily change the greeting in one place instead of many. This is a bit of a trivial example, but it shows how we can write our own methods in DRGTK to make our code better. Reusing code is fundamental for the rest of this book. The `"Hello #{friend}!"` code does what's called string interpolation. It takes whatever `friend` is, hopefully a name as a string, and inserts it. It's pretty similar to this code: `"Hello " + friend + "!"`, but quite a bit friendlier to use. The `#{}` tells Ruby to run any Ruby code within those curly braces. -Methods in Ruby return a value. Return values can then be used by the caller for whatever purposes are needed. In the example above, the return value is the string we build. Ruby returns the last line of the method definition automatically. But you can explicitly return early with `return`, which can be useful if you want to end the execution of a method early. +Methods in Ruby return a value. Return values can then be used by the caller for whatever purposes are needed. In the example above, the return value is the string we built. Ruby returns the vaue of the last line of the method definition automatically. But you can explicitly return early with `return`, which can be useful if you want to end the execution of a method early. Go ahead and change the `#greet` method to: @@ -240,9 +240,9 @@ That's some pretty fine code for the first chapter. We've got text and an image ## Game Loop Explained -There's a lot of magic happening where we can just write `def tick` and magically have a game. What's happening here is that DragonRuby Game Toolkit takes the code in `mygame/app/main.rb`, finds the `tick` method, and then runs a loop that calls it 60 times every second until the program closes. This loop is referred to as the Game Loop. +There's a lot of magic happening if we can just write `def tick` and magically have a game. What's happening is that DragonRuby Game Toolkit takes the code in `mygame/app/main.rb`, finds the `tick` method, and then runs a loop that calls it 60 times every second until the program closes. This loop is referred to as the Game Loop. -When programming games, any number of things are happening at one time. Enemies are moving, images are being displayed, math is being calculated, input is being handled. The loop runs over and over again, accounting for any changes in the state of the game. This is similar to how screens on devices work—they refresh so many times a second, so fast that it's barely perceptible to the human eye. +When programming games, any number of things are happening at one time. Enemies are moving, images are being displayed, math is being calculated, input is being handled, etc. The loop runs over and over again, accounting for any changes in the state of the game. This is similar to how screens on devices work—they refresh so many times a second, so fast that it's barely perceptible to the human eye. Within the game loop, we'll keep track of everything that's happening, update state, and render text and images. It's important to begin to think about things in a loop, as it influences timing and code structure. From 716e2337b90170780719cdf4b31cc46cbf638dfe Mon Sep 17 00:00:00 2001 From: Brett Chalupa Date: Thu, 15 Dec 2022 16:27:09 -0500 Subject: [PATCH 07/22] fix(ch01): Velvo edits edits just making some changes based on what I'd prefer from those edits --- src/01-hello-dragon.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/01-hello-dragon.md b/src/01-hello-dragon.md index 4dea7df..f25e108 100644 --- a/src/01-hello-dragon.md +++ b/src/01-hello-dragon.md @@ -10,11 +10,11 @@ We'll start by rendering an image and some simple text on the screen. But first, You're ready to work on your game. Let's get to it! -**ProTip:** don't delete the zip file! You can unzip it again when you start working on your next game. It's helpful to keep it around. +**ProTip:** don't delete the zip file! You can unzip it again when the times comes to start working on your next game. It's helpful to keep it around. ## What's in the Engine Zip -When you download the DragonRuby Game Toolkit, it contains everything you need to build your game. There are no external dependencies to install or monkey with. You just use the provided files and start making your game. +When you download DragonRuby Game Toolkit, it contains everything you need to build your game. There are no external dependencies to install or monkey with. You just use the provided files and start making your game. Let's go over the key files in the archive you just extracted: @@ -51,7 +51,7 @@ This isn't a game... yet! But it is doing three key things: And you haven't even written any code yet. Not a bad starting place. -DRGTK handles the boring stuff when it comes to making games—dealing with low-level APIs like graphics, sounds and the game window. We can instead focus on creating our game instead of, for example, figuring out how to save data in a way that's compartible with Linux, Mac, Windows, Android, iOS, and web. +DRGTK handles the boring stuff when it comes to making games—dealing with low-level APIs like graphics, sound, and the game window. We can instead focus on creating our game instead of, for example, figuring out how to save data in a way that's compartible with Linux, Mac, Windows, Android, iOS, and web. ## An Overview of the Main Game File @@ -146,7 +146,7 @@ Did you see that? The game reloaded your code and changed the text to "Hello Dra {{#include code/chapter_01/01_default/app/main.rb:5}} ``` -`args.outputs.sprites` is like `args.outputs.labels`, but instead of holding labels it's a collection of sprites. It renders the `"dragonruby.png"` image at x: 576, y: 280, just like label text, and it also sets the size of the image to display. That's what the `128` and `101` represent in the array. Here's a breakdown of those elements: +`args.outputs.sprites` is like `args.outputs.labels`, but instead of holding labels, it's a collection of sprites. It renders the `"dragonruby.png"` image at x: 576, y: 280, just like label text, and it also sets the size of the image to display. That's what the `128` and `101` represent in the array. Here's a breakdown of those elements: ``` ruby # x, y, w, h, image @@ -165,7 +165,7 @@ signifies that the definition of the `tick` method is over. Any code after that ## Screen Coordinates Explained -Let's take a detour down Screen Coordinates Road. The `x` and `y` positions are coordinates on the two-dimensional plane of the game window. Remember geometry? I barely do. But this is important, so don't doze off on me yet. We're only still in the first chapter! +Let's take a detour down Screen Coordinates Road. The `x` and `y` values are coordinates on the two-dimensional plane of the game window. Remember geometry? I barely do. But this is important, so don't doze off on me yet. We're only still in the first chapter! ![diagram showing x, y axis with 0, 0 being in the bottom left and 1280, 720 being in the upper right](./img/c01-coords.png) @@ -179,7 +179,7 @@ It's important to keep coordinates in mind, as we'll be using them a lot when ma Back to making the game. Okay, yeah, you changed a string and it changed what was displayed. That's neat. But let's hit reset and do it ourselves. -I want you to delete the code in `mygame/app/main.rb`. Select it all and delete it. Yup, I know, the blank canvas is a challenge. But you need to start writing the code yourself in order to learn and build your mental muscle memory. So go ahead and type out each line below into your `main.rb`. +I want you to delete the code in `mygame/app/main.rb`. Select it all and delete it. Yup, I know, the blank canvas is a challenge. But you need to start writing the code yourself in order to learn. So go ahead and type out each line below into your `main.rb`. ``` ruby def tick args @@ -240,7 +240,7 @@ That's some pretty fine code for the first chapter. We've got text and an image ## Game Loop Explained -There's a lot of magic happening if we can just write `def tick` and magically have a game. What's happening is that DragonRuby Game Toolkit takes the code in `mygame/app/main.rb`, finds the `tick` method, and then runs a loop that calls it 60 times every second until the program closes. This loop is referred to as the Game Loop. +There's a lot of magic that comes from DragonRuby Game Toolkit, where we can just write `def tick` and magically have a game. What's happening is that DragonRuby Game Toolkit takes the code in `mygame/app/main.rb`, finds the `tick` method, and then runs a loop that calls it 60 times every second until the program closes. This loop is referred to as the Game Loop. When programming games, any number of things are happening at one time. Enemies are moving, images are being displayed, math is being calculated, input is being handled, etc. The loop runs over and over again, accounting for any changes in the state of the game. This is similar to how screens on devices work—they refresh so many times a second, so fast that it's barely perceptible to the human eye. From 949394bada1ae458d45b6fab8355c3114bb17cce Mon Sep 17 00:00:00 2001 From: Brett Chalupa Date: Thu, 15 Dec 2022 16:30:38 -0500 Subject: [PATCH 08/22] chore: thank vlevo --- src/outro.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/outro.md b/src/outro.md index 1094c60..49a2e59 100644 --- a/src/outro.md +++ b/src/outro.md @@ -47,3 +47,4 @@ In particular, in alphabetical order, thank you to: - [Nick Culbertson](https://twitter.com/MobyPixel) for the dragon sprite included with DRGTK - Owen for corrections - Pineapple for feedback +- Vlevo for thoughtful edits From dbecccfc8964560d32abfab3326a3abaf0ccfa27 Mon Sep 17 00:00:00 2001 From: Vlevo Date: Fri, 16 Dec 2022 14:40:10 -0500 Subject: [PATCH 09/22] typos 02-player-movement.md 15: 'tick' here is "a concept of time" and not a variable/method/filename/etc. --- src/02-player-movement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/02-player-movement.md b/src/02-player-movement.md index e46a875..e5c7f68 100644 --- a/src/02-player-movement.md +++ b/src/02-player-movement.md @@ -12,7 +12,7 @@ end That displays our player dragon and nothing else. Excellent. Let's get this dragon moving! -In order to handle moving the player, we need to keep track of the position across the game loops. This lets us know where the player was last `tick`, check if they should move, and then update their position accordingly. +In order to handle moving the player, we need to keep track of the position across the game loops. This lets us know where the player was last tick, check if they should move, and then update their position accordingly. Update your `mygame/app/main.rb` to be this: From 0cd258139681bd8630bbcbdd529ade5fae14e661 Mon Sep 17 00:00:00 2001 From: Vlevo Date: Fri, 16 Dec 2022 14:59:30 -0500 Subject: [PATCH 10/22] `consistancy` 01-hello-dragon.md 127 make x & y coords/position consistent with the other "array" uses of `x` & `y` (or remove? from 136, 168, and 172) --- src/01-hello-dragon.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/01-hello-dragon.md b/src/01-hello-dragon.md index 418ae08..6c55d3e 100644 --- a/src/01-hello-dragon.md +++ b/src/01-hello-dragon.md @@ -124,7 +124,7 @@ And then finally the code within the brackets `[]` is an array of data that repr I think of arrays like a stack of CDs. The CDs are in a specific order, but you don't know what a given CD is unless you pull one out of the stack and look at it. You have to do the same thing with an array. In programming, you put data into an array to collect that data and keep track of it. If you want to know what's at a specific place in an array, you have to check. -You can see some code in quotes, those are strings. And they're what's being displayed by the game. In order to show the text, though, we need to tell the engine where to place it on the screen. That's what the first two elements of the array do: they specify the x and y position of the text in the game. Then there's the text we want to render. That's followed by the text size. Then finally the alignment (centered in this case). +You can see some code in quotes, those are strings. And they're what's being displayed by the game. In order to show the text, though, we need to tell the engine where to place it on the screen. That's what the first two elements of the array do: they specify the `x` and `y` position of the text in the game. Then there's the text we want to render. That's followed by the text size. Then finally the alignment (centered in this case). Here's it broken down: From 7b6a10f96190c73a62248d78aa2195835e3000d5 Mon Sep 17 00:00:00 2001 From: Vlevo Date: Fri, 16 Dec 2022 18:44:18 -0500 Subject: [PATCH 11/22] typo/grammar stuff 03-spit-fire.md 41 "can you begin to imagine ..." is a question. 88 The list contains no 'and', but feels more like it should "remain open-ended" (", etc.") than to acquire the written-in-stone feeling that ", and player inventory." would give it. ("Games are composed of huge collections of" only these four things!) 90 This list is a finite one, as it is an example list of "some ways" to do something and so wants for lack of an ", and ". 120 "(oftentimes hashes)" or "(often hashes)" --- src/03-spit-fire.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/03-spit-fire.md b/src/03-spit-fire.md index 03deab8..b0c0af7 100644 --- a/src/03-spit-fire.md +++ b/src/03-spit-fire.md @@ -38,7 +38,7 @@ The code above says: if the Z key is down OR the J key is You can combine `||` on one line (`if monday || tuesday || wednesday`), but it can be helpful to break long lines to make our code easier to read. -Outputting info to the console isn't that helpful for the player, but can you begin to imagine how we'll use that check to instead spit a fireball. +Outputting info to the console isn't that helpful for the player, but can you begin to imagine how we'll use that check to instead spit a fireball? ## Displaying Fireballs @@ -85,13 +85,13 @@ Move your dragon around, spit some fire, and bask in the glory of a word moving Try changing around `speed + 2` to make the fireballs move faster or slower and see how that feels. Adjusting speed values can really change the vibe of your game and is important in tuning it to feel just right. -There are a lot of important concepts in those three newly added lines of code. In Ruby, when there's an array of data, we can loop through **each** item and modify their properties. Games are composed of huge collections of things: enemies, fireballs, menu options, player inventory. Arrays (and just collections in general) aren't anything to be afraid of, and soon enough, you'll be naturally thinking of your game data in terms of arrays. +There are a lot of important concepts in those three newly added lines of code. In Ruby, when there's an array of data, we can loop through **each** item and modify their properties. Games are composed of huge collections of things: enemies, fireballs, menu options, player inventory, etc. Arrays (and just collections in general) aren't anything to be afraid of, and soon enough, you'll be naturally thinking of your game data in terms of arrays. -Looping through an array of data in each `#tick` and then doing _something_ is the stuff games are made of! Here are some ways this can be applied in all sorts of games: enemy behavior, checking for collision, animating. As our game (and any game you make) gets more complex, looping through collections of data becomes more and more common. +Looping through an array of data in each `#tick` and then doing _something_ is the stuff games are made of! Here are some ways this can be applied in all sorts of games: enemy behavior, checking for collision, and animating. As our game (and any game you make) gets more complex, looping through collections of data becomes more and more common. ## Switching to Hashes -So far throughout the book we've been using arrays to represent the entities in our game, whether it be the player's dragon sprite or our fireball text that gets displayed. Remember `[args.state.player_x, args.state.player_y, 'fireball']`? Arrays are wonderful and important, but they aren't so great for representing structured data because it's difficult to remember what each piece of data in the array's positions represents. Remembering that `fireball[2]` is the text value and not the y value is tricky. Luckily, DragonRuby has a more verbose and clear data structure we can use for managing our data. It's called a hash! Much like arrays, hashes are extremely useful. +So far throughout the book, we've been using arrays to represent the entities in our game, whether it be the player's dragon sprite or our fireball text that gets displayed. Remember `[args.state.player_x, args.state.player_y, 'fireball']`? Arrays are wonderful and important, but they aren't so great for representing structured data because it's difficult to remember what each piece of data in the array's positions represents. Remembering that `fireball[2]` is the text value and not the y value is tricky. Luckily, DragonRuby has a more verbose and clear data structure we can use for managing our data. It's called a hash! Much like arrays, hashes are extremely useful. Let's look at what the text example above would be like as a hash: @@ -113,11 +113,11 @@ dragon = { } ``` -Values of a hash are then accessed by their keys, so `dragon.name` returns the string `"Francis"`, `dragon.size` returns the string `"medium"`, and `dragon.age` returns the number `541`. This is much more clear than having to remember the position of these values within an array. +Values of a hash are then accessed by their keys, so `dragon.name` returns the string `"Francis"`, `dragon.size` returns the string `"medium"`, and `dragon.age` returns the number `541`. This is much clearer than having to remember the position of these values within an array. -Quick note: if you see a hash with key-value pairs that look like this: `{ :name => "Francis" }`, don't fret! That's just an another style in Ruby known as the hash rocket. +Quick note: if you see a hash with key-value pairs that look like this: `{ :name => "Francis" }`, don't fret! That's just another style in Ruby known as the hash rocket. -In general, differentiate between arrays and hashes like this: **hashes are used represent one piece of data with multiple properties** and **arrays are used to collect data (often times hashes) to keep track of and manipulate them**. +In general, differentiate between arrays and hashes like this: **hashes are used to represent one piece of data with multiple properties** and **arrays are used to collect data (oftentimes hashes) to keep track of and manipulate them**. Below is our entire game translated to use hashes instead of arrays for our rendering: @@ -125,7 +125,7 @@ Below is our entire game translated to use hashes instead of arrays for our rend {{#include code/chapter_03/05_switching_to_hashes/app/main.rb}} ``` -It may not seem like much has changed, but there are two key changes that make this worthwhile: +It may not seem like much has changed, but two key changes make this worthwhile: 1. `fireball.x += args.state.player.speed + 2` — it is much clearer when we move the fireball that we're adding to its `x` position AND using the player's speed 2. `args.outputs.sprites << args.state.player` — because we're keeping track of our player in `args.state.player` and it has the data DragonRuby needs to render it, we can just push it into `args.outputs.sprites` and not construct the array that we used to use From 3d596b1005e21ad0cd6141d088dee4db37d53b26 Mon Sep 17 00:00:00 2001 From: Vlevo Date: Sun, 18 Dec 2022 23:21:19 -0500 Subject: [PATCH 12/22] Update 05-fireball-clean-up.md --- src/05-fireball-clean-up.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/05-fireball-clean-up.md b/src/05-fireball-clean-up.md index 09fe850..eedc878 100644 --- a/src/05-fireball-clean-up.md +++ b/src/05-fireball-clean-up.md @@ -50,7 +50,7 @@ Feel free to remove the `args.outputs.debug` lines if you don't want to see them There will be many opportunities when working on your games to optimize your code so that it performs better. This was just a taste of what that process can be like. As you get better at making games, you'll improve at making them more performant. -Don't obsesses over performance too much yet though. Focus on making your game fun to play. +Don't obsess over performance too much yet though. Focus on making your game fun to play. ## What's Next From f4ab1b79cb9c9e7b54db4d544343a0ffa55401ce Mon Sep 17 00:00:00 2001 From: Vlevo Date: Sun, 18 Dec 2022 23:31:14 -0500 Subject: [PATCH 13/22] grammar tweaks 04-target-practice.md 23 list part "agreement": a's for b, c's for d, e "for" f. 59 "at the same point" or "in the same space" 114 originally I made this "what used to be exciting seems" and then realized that I was miss-chunking/interpreting it, because "games" -> "it" made the "it" seem so wrong. 137 "between 0 and 100", "from 0 up to 100". 'between' sounds more like "0 < number < 100". and you want "0 <= number < 100". --- src/04-target-practice.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/04-target-practice.md b/src/04-target-practice.md index 580ac08..76c443b 100644 --- a/src/04-target-practice.md +++ b/src/04-target-practice.md @@ -20,7 +20,7 @@ We need to render our target sprites too, so include those in the array we push {{#include code/chapter_04/01_display_targets/app/main.rb:79}} ``` -Similar to how we represent the player and fireball sprites, the targets have an x and y coordinate for position, a width and height, and an image file to represent the sprite. We create three items in our `args.state.targets` array, which then displays three different targets. +Similar to how we represent the player and fireball sprites, the targets have x and y coordinates for position, width and height for size, and an image file to represent the sprite. We create three items in our `args.state.targets` array, which then displays three different targets. ![dragon sprite with three targets rendered to the right](./img/c04-display-targets.jpg) @@ -54,9 +54,9 @@ Then when we lazily assign `args.state.targets ||=`, we call the method three ti ## Collision Detection -The fireballs our dragon spits just fly behind our targets and off the screen into infinity. Let's make it so that if a fireball hits a target, _something_ happens. Eventually we'll want to play a sound, remove the target, and even play an animation. But humble beginnings, humble beginnings. +The fireballs our dragon spits just fly behind our targets and off the screen into infinity. Let's make it so that if a fireball hits a target, _something_ happens. Eventually, we'll want to play a sound, remove the target, and even play an animation. But humble beginnings, humble beginnings. -Collision detection is when one object overlaps with another object in our game. Because we're manufacturing the space the game exists in, there's no physics like we have in real life. We need to simulate that by checking to see if two objects are attempting to exist in the same point and react accordingly. +Collision detection is when one object overlaps with another object in our game. Because we're manufacturing the space the game exists in, there's no physics like we have in real life. We need to simulate that by checking to see if two objects are attempting to exist at the same point and react accordingly. Our fireball sprite is a 32x32 square, so we want to check in every single game loop whether or not the points of the fireball's square overlapping with any of the points of the target sprites. If they are overlapping, then we do that _something_. @@ -76,9 +76,9 @@ Here's the written out logic behind the collision detection we'll implement: {{#include code/chapter_04/03_collision_detection/app/main.rb:67:75}} ``` -Play the game and hit the some targets. Nothing visually happens (yet), but if you check the console (~), you'll see that `"fireball hit target"` was output multiple times. +Play the game and hit some targets. Nothing visually happens (yet), but if you check the console (~), you'll see that `"fireball hit target"` was output multiple times. -With a loop and a method we've implemented collision detection. That wasn't too bad, was it? +With a loop and a method, we've implemented collision detection. That wasn't too bad, was it? ## Remove Targets On Collision @@ -105,13 +105,13 @@ So in our collision detection code where we call `puts`, we'll instead mark the {{#include code/chapter_04/04_remove_targets/app/main.rb:67:79}} ``` -Since the target and fireball that collided are no longer being tracked in `args.state`, they don't get rendered on the screen and are, for all intents and purposes, gone! We then `#reject!` each fireball and target that are `dead`. +Since the target and fireball that collided are no longer being tracked in `args.state`, they don't get rendered on the screen and are, for all intents and purposes, gone! We then `#reject!` each fireball and target that is `dead`. This almost feels like a game. That's a great feeling. We're getting close to _fun_. ## Spawn New Targets -Shooting three targets and having them disappear doesn't make for much fun though. After the three targets are hit, it's just your dragon floating in the sky with not much else to do. We're back to chapter 3! Ugh, chapter 3 was so boring! I can't believe we ever even made anything that boring before. (But remember how cool it was when we got the fireballs working? That was cool! It's funny how games evolve and what it used to be seems so basic compared to where we're at now.) +Shooting three targets and having them disappear doesn't make for much fun though. After the three targets are hit, it's just your dragon floating in the sky with not much else to do. We're back to chapter 3! Ugh, chapter 3 was so boring! I can't believe we ever even made anything that boring before. (But remember how cool it was when we got the fireballs working? That was cool! It's funny how a game evolves and what it used to be, seems so basic compared to where we're at now.) Remember back in the day, way back when, like a few sections ago, when we introduced `#spawn_target`? It was helpful then, but now it's going to be even more helpful. We'll call it every time we destroy a target so that a new one spawns. We'll be able to play _Target Practice_ forever! @@ -134,13 +134,13 @@ We create a `size` variable to store the width and height of the sprite to use i Then we apply some math. Don't let math scare you away from programming! We'll keep it simple and the toolbox you need is relatively small. Plus, the math will help make our game even better. Games make math fun. -`rand` is a method that we get from DragonRuby that's available everywhere. `rand` without any parameter generates a random real number between 0 and 1. That's not really useful for us right now, so we can instead pass in a parameter that sets the upper boundary of the random number. `rand(100)` generates a random integer between 0 up to 100 (not including 100). +`rand` is a method that we get from DragonRuby that's available everywhere. `rand` without any parameter generates a random real number between 0 and 1. That's not really useful for us right now, so we can instead pass in a parameter that sets the upper boundary of the random number. `rand(100)` generates a random integer from 0 up to 100 (not including 100). So for the x position of the target, we generate a random number that's up to two-fifths the width of the game screen and then we add three-fifths of the width to that number so that the targets spawn on the far right side of the screen. We don't want to spawn targets too close to the player, otherwise our game will be too easy. For the y position, we generate a random y position based on the height of the game, but we subtract twice the size of the target sprite and then add one of its sizes back to the random number to give the spawn area a gutter. This prevents the target from spawning partially off the screen, which would make it impossible to hit. -### Change initial three targets +### Change the initial three targets ``` ruby {{#include code/chapter_04/05_spawn_new_targets/app/main.rb:22:24}} From 10d10842df9cc3e592d4645abb153e326d96895d Mon Sep 17 00:00:00 2001 From: Vlevo Date: Mon, 19 Dec 2022 00:25:09 -0500 Subject: [PATCH 14/22] Update 06-time-attack.md 43 we have the time remaining, but to get the time remaining, we divide it (the time remaining) by 60... 45 let's us --> let us us --- src/06-time-attack.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/06-time-attack.md b/src/06-time-attack.md index 69f9479..5c1d774 100644 --- a/src/06-time-attack.md +++ b/src/06-time-attack.md @@ -19,7 +19,7 @@ We'll start by introducing `args.state.timer` that will be used to keep track of {{#include code/chapter_06/01_time_attack/app/main.rb:25:28}} ``` -We lazily set it to `30 * 60`. We want the game to last thirty seconds and our `#tick` method runs sixty times every second, so we multiple them together to get the total number of ticks our timer will run for. We'll then subtract one from `args.state.timer` every `#tick` so that it decreases as we play our game. +We lazily set it to `30 * 60`. We want the game to last thirty seconds and our `#tick` method runs sixty times every second, so we multiply them together to get the total number of ticks our timer will run for. We'll then subtract one from `args.state.timer` every `#tick` so that it decreases as we play our game. Right below decreasing our `args.state.timer` by one, we check to see if the timer is less than zero. If it is, that means game over. @@ -28,7 +28,7 @@ Right below decreasing our `args.state.timer` by one, we check to see if the tim ``` If it is game over, then we let the player know, display their final score, and tell them how to play again (by pressing the fire button). We make an array of labels which we then push into `args.outputs.labels` to efficiently render them all. -If any of our fire keys are pressed, the game is reset with `$gtk.reset` and the player can play again. +If any of our fire keys are pressed, the game is reset with `$gtk.reset`, and the player can play again. The `return` line is _really_ important. It says, return out of the `#tick` method so that none of the code below runs. We don't want to have the dragon be movable or for targets to spawn when it's game over. So we eject early and only display the game over screen details. @@ -40,9 +40,9 @@ Way at the bottom of `#tick`, let's display a label with the time remaining: {{#include code/chapter_06/01_time_attack/app/main.rb:124:138}} ``` -We use the same pattern of creating a `labels` array, pushing in the player's score and the time remaining. In order to get the time remaining, we divide it by 60 and round. We do the opposite of what we did when we set the total time in ticks. +We use the same pattern of creating a `labels` array, pushing in the player's score and the time, in ticks, remaining. In order to display the time remaining as seconds, we divide it by 60 and round. We do the opposite of what we did when we set the total time in ticks. -The `alignment_enum` let's us specify that we want the text to be right aligned instead of the default left alignment. This let's us nicely position our timer in the upper right corner of the game. +The `alignment_enum` lets us specify that we want the text to be right-aligned instead of the default left alignment. This let's us nicely position our timer in the upper right corner of the game. ![gameplay with Time Left reading 10 seconds](./img/c06-timer.jpg) @@ -58,7 +58,7 @@ If you happen to press the fire button right when the timer runs out, you may re Because we keep subtracting from `args.state.timer`, we can check to see if the current value is less than -30. If it is, then we'll accept input to restart the game. -`&&` (double ampersand, often read as "and-and") means that both sides of the expression must be true for the code within the conditional to happen. In our new restart check, we combine AND and OR by saying: if the game timer is less than -30 AND any of our fire keys are down, then we reset the game. When you group together expressions in parentheses, `(monday? || tuesday?)`, it evaluates them as one express against the other checks. We care about the timer being below a certain amount AND any of the inputs being pressed. +`&&` (double ampersand, often read as "and-and") means that both sides of the expression must be true for the code within the conditional to happen. In our new restart check, we combine AND and OR by saying: if the game timer is less than -30 AND any of our fire keys are down, then we reset the game. When you group together expressions in parentheses, `(monday? || tuesday?)`, it evaluates them as one expression against the other checks. We care about the timer being below a certain amount AND any of the inputs being pressed. Combining logic in this way for flow control is very common when making games. `&&` and `||` are pretty common operators in most programming languages. @@ -66,7 +66,7 @@ Combining logic in this way for flow control is very common when making games. ` Our main `#tick` method is getting a bit long in the tooth, being over 100 lines long. We've also duplicated two things: frames per second with the `60` value and checking for fire input. This is a good opportunity to refactor our code once again to make it easier to work with. Let's break up `#tick` into a series of smaller methods that we call from within it. Encapsulating our logic into smaller pieces makes it easier to work on those smaller pieces without concerning ourselves with the rest of the code. -How small should you make your methods? That's up to you. Use your best judgment and do what feels right. Code can change and grow quite organically. Once something feels too big or complex or is duplicated, improve it. Don't over-engineer your game right from the start, otherwise you'll be off in the weeds and not actually making your game fun. On the other hand, if you just neglect your code, you'll make it more difficult to change, thus slowing down the development process. There's a fine line between over-engineering and creating a mess. +How small should you make your methods? That's up to you. Use your best judgment and do what feels right. Code can change and grow quite organically. Once something feels too big or complex or is duplicated, improve it. Don't over-engineer your game right from the start, otherwise, you'll be off in the weeds and not actually making your game fun. On the other hand, if you just neglect your code, you'll make it more difficult to change, thus slowing down the development process. There's a fine line between over-engineering and creating a mess. Here's the entire game broken down into some smaller methods to make it easier to work with moving forward: From f36c13b1fe2a8274ce138caf81eff0fae0ec7883 Mon Sep 17 00:00:00 2001 From: Brett Chalupa Date: Thu, 22 Dec 2022 05:22:24 -0500 Subject: [PATCH 15/22] chore: add newsletter links --- src/introduction.md | 2 +- src/outro.md | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/introduction.md b/src/introduction.md index eb9bf8c..3dd3939 100644 --- a/src/introduction.md +++ b/src/introduction.md @@ -116,7 +116,7 @@ This book is freely accessible so that someone who loves games and wants to try You'll learn the foundations of game programming and making games, as well as some more advanced topics. If this book can help even just one person start and finish a game, it's worth every minute I've spent on it. We'll make a game not too dissimilar from _Zaku Space Battle_. Once you finish it, take what you've learned and make it your own! -If you want to, you can [buy me a coffee](https://buymeacoffee.com/brettchalupa) as a way of saying thank you. It's much appreciated. +If you want to, you can [buy me a coffee](https://buymeacoffee.com/brettchalupa) or [subscribe to my newsletter](https://buttondown.email/brettchalupa) as a way of saying thank you. It's much appreciated. ## Contribute diff --git a/src/outro.md b/src/outro.md index 49a2e59..6f63acc 100644 --- a/src/outro.md +++ b/src/outro.md @@ -20,7 +20,9 @@ Here are some ideas for what you could do to put your personal stamp on it: Say thanks in [the DragonRuby Discord](https://discord.dragonruby.org) or on [Mastodon](https://mastodon.gamedev.place/@brettmakesgames). It would mean so much to me know that you've read the book. The website version of this book has no analytics tracking. My success metric isn't the number of views this book goods. I'll only be able to measure the success of this book through community and connecting. Share what you've made! -If you really want to say thanks, [buy me a coffee](https://www.buymeacoffee.com/brettchalupa) by sending me a small tip. Financial support means the world and helps me continue to make free resources like _Building Games with DragonRuby_. +If you really want to show your appreciation, [buy me a coffee](https://www.buymeacoffee.com/brettchalupa) by sending me a small tip. Financial support means the world and helps me continue to make free resources like _Building Games with DragonRuby_. + +Want to know when I finish a new book, game, or creative project? [Subscribe to my mailing list.](https://buttondown.email/brettchalupa) I only send out updates when I finish a proiject or have something significant to share. ## Want More? From ba7b77ca9fb8797ce5a87ac4c6507f8993f5d62f Mon Sep 17 00:00:00 2001 From: Brett Chalupa Date: Sun, 8 Jan 2023 11:19:40 -0500 Subject: [PATCH 16/22] fix: alpha max val --- src/09-background.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/09-background.md b/src/09-background.md index 76d7983..1d00c0b 100644 --- a/src/09-background.md +++ b/src/09-background.md @@ -14,7 +14,7 @@ At the top of `#tick`, below where we start the music, create a solid rectangle {{#include code/chapter_09/01_blue_sky/app/main.rb:102:115}} ``` -We're familiar with a lot of the shape hash keys for the position and size, but `r`, `g`, and `b` are new. They specify the values for the (r)ed, (g)reen, and (b)lue color values for the rectangle we're drawing. Their values can be set to anything between 0 and 255, inclusive. Adjust the values to see a different color displayed. The higher the value for a given color, the more it'll be part of the mix. So our color has a blue of 230, meaning blue comes through more than the others. You can also specify `a`, the alpha value, between 0 and 100, inclusive, to get transparency in our color. +We're familiar with a lot of the shape hash keys for the position and size, but `r`, `g`, and `b` are new. They specify the values for the (r)ed, (g)reen, and (b)lue color values for the rectangle we're drawing. Their values can be set to anything between 0 and 255, inclusive. Adjust the values to see a different color displayed. The higher the value for a given color, the more it'll be part of the mix. So our color has a blue of 230, meaning blue comes through more than the others. You can also specify `a`, the alpha value, between 0 and 255, inclusive, to get transparency in our color. Now we've got our dragon flying over a blue sky. That looks quite a bit better. From d4f01c67d231386ca71aa4a0304987eaa0375905 Mon Sep 17 00:00:00 2001 From: Brett Chalupa Date: Sun, 8 Jan 2023 11:23:51 -0500 Subject: [PATCH 17/22] fix(ch03): awkward array phrasing fixes https://github.com/DragonRidersUnite/book/issues/10 thanks to @Vlevo for the feedback and suggestions --- src/03-spit-fire.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/03-spit-fire.md b/src/03-spit-fire.md index 03deab8..d5f020f 100644 --- a/src/03-spit-fire.md +++ b/src/03-spit-fire.md @@ -58,7 +58,7 @@ Then where we check for the action input, push a fireball into the `arg.state.fi All we have to do is render our fireballs by pushing them into the `args.outputs.labels` collection. DragonRuby is smart enough to know that if we push an array into any `args.outputs` collection it'll flatten it and display them correctly. Thanks, DragonRuby! -We use arrays to represent various data in our game like labels and sprites, but we can create our own arrays to keep track of the data in our game. Arrays are a great way to collect data that we then use throughout our game. In this case, we're maintaining a collection of fireballs. +We've been using arrays to represent the fields for different data in our game like labels and sprites, but arrays have other uses too. Arrays are a great way to keep track of information we need in a list. The array we've created in the code above tracks our fireballs. Play your game and see what happens! Fireballs everywhere. Wait! You're not impressed by those fireballs? I'd be pretty frightened if the word "fireball" was flying at me. From 8eb80e939801be6441cb1c9a62e6da4c34e8e9d1 Mon Sep 17 00:00:00 2001 From: Brett Chalupa Date: Sun, 8 Jan 2023 11:32:34 -0500 Subject: [PATCH 18/22] fix: introduction of #method shorthand Fixes https://github.com/DragonRidersUnite/book/issues/8 thanks to @Vlevo! --- src/01-hello-dragon.md | 2 +- src/02-player-movement.md | 2 +- src/03-spit-fire.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/01-hello-dragon.md b/src/01-hello-dragon.md index 6c55d3e..8a95f3b 100644 --- a/src/01-hello-dragon.md +++ b/src/01-hello-dragon.md @@ -217,7 +217,7 @@ The `"Hello #{friend}!"` code does what's called string interpolation. It takes Methods in Ruby return a value. Return values can then be used by the caller for whatever purposes are needed. In the example above, the return value is the string we built. Ruby returns the vaue of the last line of the method definition automatically. But you can explicitly return early with `return`, which can be useful if you want to end the execution of a method early. -Go ahead and change the `#greet` method to: +Go ahead and change the `greet` method to: ``` ruby def greet friend diff --git a/src/02-player-movement.md b/src/02-player-movement.md index e5c7f68..fd05976 100644 --- a/src/02-player-movement.md +++ b/src/02-player-movement.md @@ -59,7 +59,7 @@ Then, finally, we change the `x` and `y` value for the dragon sprite to be the v ## Checking for Input -In `#tick` we'll check to see if a given input is pressed. If it is, we'll change the sprite's x and y position accordingly. +In `#tick` (`#name` is Ruby shorthand for "the `name` method") we'll check to see if a given input is pressed. If it is, we'll change the sprite's x and y position accordingly. Our ole buddy `args` has a little something known as `args.inputs`. This lets us check... inputs! Isn't programming nice? Most of the time the words used in programming make sense. But some of the time, they really don't, and it's a gosh dang nightmare. Let's commit right here, right now to trying to name things in a way that's useful. Okay, you're committed. When you name a method `def thingy`, you'll remember this. And your ears will ring a little bit and your eyes will get just a little dry and you'll remember that you broke your commitment. diff --git a/src/03-spit-fire.md b/src/03-spit-fire.md index 604c3a5..78905db 100644 --- a/src/03-spit-fire.md +++ b/src/03-spit-fire.md @@ -6,7 +6,7 @@ Our next mission is to make our dragon spit fire because that's just what they d In the last chapter, we used `args.inputs` to check for player input from the four main directions. If those inputs are pressed, then we move the dragon. Now let's check to see if the Z key is pressed to know when to have our dragon spit a fireball. -To check if a key was pressed, we can use `args.inputs.keyboard.key_down` and then whatever key we want to check. So in our case, we'll check `args.inputs.keyboard.key_down.z`. In our `#tick` method, right above where we render the dragon sprite, let's check for that input: +To check if a key was pressed, we can use `args.inputs.keyboard.key_down` and then whatever key we want to check. So in our case, we'll check `args.inputs.keyboard.key_down.z`. In `#tick`, right above where we render the dragon sprite, let's check for that input: ``` ruby {{#include code/chapter_03/01_input/app/main.rb:36:40}} @@ -44,7 +44,7 @@ Outputting info to the console isn't that helpful for the player, but can you be We want to display a fireball on the screen when the action key is pressed. We've got most of the code, all we need to do is change `puts` to instead display the fireball. -At the top of `#tick` (`#name` is Ruby shorthand for "the `name` method"), assign an empty array to `args.state.fireballs` if nothing has been assigned yet. This will let us keep track of fireballs across the game loop to do all sorts of things with them (display them, move them, collide them with other objects): +At the top of `#tick`, assign an empty array to `args.state.fireballs` if nothing has been assigned yet. This will let us keep track of fireballs across the game loop to do all sorts of things with them (display them, move them, collide them with other objects): ``` ruby {{#include code/chapter_03/03_displaying_fireballs/app/main.rb:1:4}} From 2932bd8b99d72e512f43d949cfa43f57858a1bf6 Mon Sep 17 00:00:00 2001 From: Brett Chalupa Date: Sun, 8 Jan 2023 11:43:32 -0500 Subject: [PATCH 19/22] feat: expand Game Dev Resources --- src/game-dev-resources.md | 6 +++++- src/ruby-primer.md | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/game-dev-resources.md b/src/game-dev-resources.md index 1e49a22..cac2a8f 100644 --- a/src/game-dev-resources.md +++ b/src/game-dev-resources.md @@ -4,17 +4,20 @@ While this book covers the technical aspects of programming games with Ruby, the ## Tools -Tools for making games that I recommend. Centered around on 2D games, like the book is. +Recommended tools for making games. ### Audio - [jsfxr](https://sfxr.me/) — generate sound effects +- [ChipTone](https://sfbgames.itch.io/chiptone) — another sound effect tool - [Audacity](https://www.audacityteam.org/) — audio editor - [1BitDragon](https://1bitdragon.com/) — intuitive music creation software +- [LMMS](https://lmms.io/) — music creation tool ### Graphics - [Aseprite](https://www.aseprite.org/) — pixel art tool +- [Piskel](https://www.piskelapp.com/) — free browser pixel tool - [Krita](https://krita.org/en/) — digital painting tool ## Assets @@ -39,4 +42,5 @@ A selection of the best videos about making games: - ["Juice it or lose it" presentation](https://www.youtube.com/watch?v=Fy0aCDmgnxg) — how to polish games - ["The art of screenshake" presentation](https://www.youtube.com/watch?v=AJdEqssNZ-U) — step-by-step guide on making a game feel good to play +- ["Game a Week: Teaching Students to Prototype" presentation](https://www.youtube.com/watch?v=9O9Q8OVWrFA&list=PLT0BvNof1jZKXdGj7pT8pxakQVFUPO9GA&index=6&t=9s) — two college instructors talk about their courses where students make a game a week diff --git a/src/ruby-primer.md b/src/ruby-primer.md index 1424672..2b9bf52 100644 --- a/src/ruby-primer.md +++ b/src/ruby-primer.md @@ -1,6 +1,6 @@ # Ruby Primer -New to Ruby? Here's a brief walk through the common language features and syntax as a quick reference. +New to Ruby? No worries! Here's a brief walk through the common language features and syntax as a quick reference. ## Core Types From c3941fd795d7765529df8261f28613bf5f07249a Mon Sep 17 00:00:00 2001 From: Brett Chalupa Date: Sun, 8 Jan 2023 11:46:47 -0500 Subject: [PATCH 20/22] chore: add testimonials to intro --- src/introduction.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/introduction.md b/src/introduction.md index 3dd3939..c0afafd 100644 --- a/src/introduction.md +++ b/src/introduction.md @@ -6,6 +6,14 @@ This book is aimed at new game developers who are interested in learning to code You need no prior experience with programming or game making to follow this book. +Here are some kind things people have said about the book: + +> Reading _Building Games with DragonRuby_ book was a breath of fresh air to me. + +> This is nuts! Great work with the book. + +> Thanks for the book, I really enjoyed the writing style! + ## Why Learn How to Make Games Making games is a total blast. It's challenging but rewarding. They're the sum total of many creative mediums, _plus_ they're interactive. You'll learn so many different skills by making games: From 98cd6d738a07b58c40c9572036f5616408ba4b34 Mon Sep 17 00:00:00 2001 From: Brett Chalupa Date: Sun, 8 Jan 2023 11:48:50 -0500 Subject: [PATCH 21/22] chore: mention DragonRiders recipes in outro --- src/outro.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/outro.md b/src/outro.md index 6f63acc..c7463cf 100644 --- a/src/outro.md +++ b/src/outro.md @@ -32,6 +32,8 @@ A second edition of the book could deep dive into making a shmup with enemy wave But I _need_ to be sure people want a follow up book where we build a more complex game using DragonRuby Game Toolkit. Let me know if you'd like to see a sequel in [Discord](https://discord.dragonruby.org). +In the meantime, read through my [advanced tutorials](https://www.dragonriders.community/recipes) online. + ## Extra Credit You'll find bonus chapters after this Outro. They're one-off deep dives into specific topics, from the mindset that's required to make games to how to back up your game's source code. Check them out and see what you can learn! From 0fc27fd495f76746f3b7b7668a01caa8d77afe12 Mon Sep 17 00:00:00 2001 From: Brett Chalupa Date: Sun, 8 Jan 2023 12:38:39 -0500 Subject: [PATCH 22/22] chore: document that DRGTK 4.0 works --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fcc7ff8..a961488 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ When the code is pushed to the `main` branch on GitHub, an action runs that depl ## Key Versions -- DragonRuby Game Toolkit: v3.24 +- DragonRuby Game Toolkit: v3.24, v4.0 - mdbook: v0.4.22 ## Running Samples