文字起こし 🔗
WEBVTT
00:00:01.320 --> 00:00:04.389
Hello everyone and welcome to another episode of Code and the Code Encoders.
00:00:04.389 --> 00:00:04.871
Who Code it?
00:00:04.871 --> 00:00:12.644
I'm your host, drew Bragg, and I'm thrilled today to be joined by Amir Rajan from DragonRuby Ruby community as a whole.
00:00:12.644 --> 00:00:17.353
Anyone who's not familiar with you, could you do a brief introduction about what you do?
00:00:18.059 --> 00:00:21.742
I'm Amir Rajan and the short version is I'm a code hobo and I just kind of work on random things and sometimes interesting things happen.
00:00:21.742 --> 00:00:25.022
I'm a code hobo and I just kind of work on random things and sometimes interesting things happen.
00:00:25.022 --> 00:00:53.838
And one of those interesting things happens to be DragonRuby Game Toolkit, which is a game engine built on Ruby, and I've been doing indie game development like commercial, full-time indie game development with Ruby for the past 10 years now, and so I've got six commercial titles, my claim to fame being a port of a dark room, which hit the number one spot in the iOS app store, number two on Android has a console release and I just last year released to Steam, and so I'm a game dev using Ruby.
00:00:55.619 --> 00:00:56.959
That's super awesome and not something you hear every day.
00:00:56.959 --> 00:01:06.641
I also love code hobo as like a word for describing like I don't work on one particular thing, I just move from code base to code base.
00:01:06.641 --> 00:01:11.251
That's awesome I am so interested in.
00:01:11.251 --> 00:01:12.796
I'm not a game developer.
00:01:12.796 --> 00:01:21.927
If I ever had anything resembling free time, I would love to give it a try, but that's a lot of math and that was how I got into programming was cheating on math tests, so maybe not.
00:01:21.927 --> 00:01:28.403
But also the idea of being able to use Ruby for game development is so awesome.
00:01:28.403 --> 00:01:29.727
So was it?
00:01:29.727 --> 00:01:35.590
You were a game developer and wanted to use Ruby, or you were Ruby-ous and wanted to build games, and that's how everything was born.
00:01:36.433 --> 00:01:39.403
Ruby, especially dynamic languages, specifically Ruby.
00:01:39.403 --> 00:01:53.456
People talk about Ruby and they say it's a beautiful language or it's an expressive language and there's like an artistic flair to the language that when I started doing game dev with Ruby like versus app development it's like working with oil paints, I think of.
00:01:53.456 --> 00:02:02.250
Like statically type languages are like C sharp, you're working with marble and a chisel, you make a mistake and the correction is so difficult and the exploration's much harder.
00:02:02.250 --> 00:02:04.442
But with Ruby it's just working with oil paints.
00:02:04.442 --> 00:02:07.890
You just kind of work with the canvas and nudge things around.
00:02:07.890 --> 00:02:20.581
And the dynamic capabilities of the language, the DSL, the expressivity of the language it really works really well for game dev and a lot of those nuances is what I discovered when starting to build games with the language itself.
00:02:21.743 --> 00:02:23.426
So how did that come to be?
00:02:23.426 --> 00:02:26.433
As far as I'm a Rubyist, I want to build games.
00:02:26.433 --> 00:02:28.022
Okay, now what?
00:02:28.103 --> 00:02:48.326
What was the spark that was like I can do it this way, or like was it just nonstop investigation until I was doing corporate development right out of college and I got really burned out and I was like I'm just going to take a sabbatical and just kind of do my own thing for a little bit, live off the savings, and then, once I'm refreshed, then go back into a cubicle writing tax software.
00:02:48.326 --> 00:02:49.829
And so I'm going to build a game.
00:02:49.829 --> 00:02:55.373
And there's a product called Ruby Motion which allows you to use Ruby for building iOS apps.
00:02:55.373 --> 00:02:58.016
And I was like, okay, I can do iOS development.
00:02:58.016 --> 00:03:11.026
And I found a game on web-based game called A Dark Room it's like an incremental kind of ASCII-based roguelike built by Michael Townsend and I emailed him and said, hey, let me port this over to iOS and see if we can do something.
00:03:11.026 --> 00:03:15.587
So then I used RubyMotion Ruby and started porting this game over.
00:03:15.587 --> 00:03:18.006
And then that's kind of how it started.
00:03:18.006 --> 00:03:20.782
And then I was like, wow, game dev is actually kind of fun.
00:03:20.782 --> 00:03:22.485
It's interesting, surprise, surprise.
00:03:22.905 --> 00:03:27.772
And so after that I started building additional commercial titles, especially with the success of the first game.
00:03:28.473 --> 00:03:47.246
And then it came into like, okay, well, with respect to Ruby motion and just building games with Ruby, you're right, it was kind of like that exploratory process where you make a lot of mistakes, trying to discover like patterns, and I had a mental like do, a huge mental shift from like app development to game development and there were a lot of challenges there.
00:03:47.246 --> 00:04:05.578
But then I think it was like, yeah, from 2013 to 2017 was when I built a lot of commercial titles and then I was like, okay, I'm seeing these patterns emerge and I'm seeing the things that I like about Ruby and I don't like about existing game engines and those eventually codified into Dragon Ruby.
00:04:05.578 --> 00:04:18.790
So like from 2013 to 2017 was just building commercial games and the onus of being cross-platform and then releasing to the Nintendo Switch was that final straw that broke the camel's back.
00:04:18.790 --> 00:04:22.927
I was like, okay, I need to really think about what this environment will look like.
00:04:22.927 --> 00:04:29.372
And then all those lessons I learned just got extracted or codified into the engine that you see today.
00:04:29.372 -->
Load full transcript
00:04:30.341
That's so cool.
00:04:30.482 --> 00:04:35.680
That's such a neat starting with this app-based game and then moving into.
00:04:35.680 --> 00:04:41.593
Okay, we're going to go full steam ahead, building a game engine that becomes DragonRuby.
00:04:42.221 --> 00:04:57.249
The really interesting part, especially in this domain, is like Ruby's a very mature language, especially for app development, and so there's a lot of established patterns and a lot of ways you do things, like of course, you're going to build your controller or your MVC application in this specific way.
00:04:57.249 --> 00:05:11.839
And with respect to game dev, there's established patterns, but they're always in the context of I'm using a statically typed, rigid language that can't do what ruby can do, and so trying to just take those same patterns and apply to the language ended.
00:05:11.839 --> 00:05:19.327
I was like wait, this feels excessive, like there's no reason to have, uh, all these like different aspects of boilerplate and they establish patterns.
00:05:19.348 --> 00:05:46.307
And then that discovery process was it has that same feel of upheaval, from like using spring to rails right, look at all the stuff I'm not doing kind of vibe to it so the way that the episodes normally work because that ended up being like a really long intro because I was just so excited to start picking your brain about dragon ruby but normally the way that the show works is I will ask you three questions in addition to like the nine I just asked you what are you working on?
00:05:46.528 --> 00:05:47.771
Yeah, what are you working on?
00:05:47.771 --> 00:05:49.713
What kind of blockers do you have?
00:05:49.713 --> 00:05:52.290
It could be a current blocker.
00:05:52.290 --> 00:05:55.425
Or if you don't have one, like what's a recent blocker, how'd you go around solving it?
00:05:55.425 --> 00:06:00.863
And then the last one is what's something cool, new or interesting that you've recently learned or discovered or built?
00:06:00.863 --> 00:06:15.492
It doesn't have to be coding related I have a feeling it might be in this case but it doesn't have to be so, just to make sure we don't get lost, because I will go down so many rabbit holes if we don't stick to the program.
00:06:15.492 --> 00:06:15.935
Amir, what are you?
00:06:15.975 --> 00:06:16.637
working on?
00:06:16.637 --> 00:06:17.519
What am I working on?
00:06:17.519 --> 00:06:24.172
So I have a game in pre-production and it's called the Little Probe and have you read we Are Legion, we Are Bob.
00:06:24.172 --> 00:06:25.793
No, it's a great book.
00:06:25.793 --> 00:06:30.209
So think, hitchhiker's Guide to the Galaxy meets Von Neumann Probes.
00:06:30.209 --> 00:06:36.271
So Von Neumann Probes is this idea of your own consciousness is put into a machine and then that machine can replicate.
00:06:36.271 --> 00:06:40.379
So then you start replicating your consciousness across time and then can search the universe.
00:06:40.379 --> 00:06:56.560
So the Little Probe is a metroidvania where you're a Von Neumann probe exploring a dead civilization and a dead planet and you get power-ups and all the different facets of platforming and kind of think Metroid, right, it's a Metroidvania, and that's what I'm working on.
00:06:56.620 --> 00:07:02.983
As far as, like, the hurdles, the biggest hurdle it's math, it's always math, it's always math, it's always math.
00:07:02.983 --> 00:07:06.653
That's one of the reasons why I do 2D games is because the math is way simpler.
00:07:06.653 --> 00:07:08.927
I was afraid of math, but it really isn't that bad.
00:07:08.927 --> 00:07:10.824
You need to have a good trick foundation.
00:07:10.824 --> 00:07:19.742
So if you know trigonometry, trigonometry, geometry and algebra, those things together gives you pretty much 80% of what you need for building 2D games.
00:07:19.742 --> 00:07:30.548
So the most recent hurdle I had was ramps Ramp collision like how do you move up a ramp but keep the player pinned to the ground while gravity is being applied and stuff.
00:07:30.548 --> 00:07:33.028
But I figured it out, I figured it out.
00:07:33.028 --> 00:07:39.790
There are quite a few blog posts out there that kind of show different approaches to using ramp collision and the math around that.
00:07:39.790 --> 00:07:41.666
But that was my most recent hurdle.
00:07:42.680 --> 00:07:49.689
Yeah, that's a blocker that not a lot of people have said on this show, because most of my guests do app development.
00:07:49.689 --> 00:07:59.651
What do you think the biggest difference between the mental model you use for doing app development and the mental model you use for game development is?
00:08:00.560 --> 00:08:09.466
I think the biggest difference is you have long running state when it comes to a game and that state is updated at 60 times a second.
00:08:09.466 --> 00:08:14.468
So if you think like a controller action, it feels kind of transaction.
00:08:14.468 --> 00:08:23.033
You got the HTTP request coming in, you rehydrate, you have some short running state for the life of that function, maybe you have some session stuff, but outside of that you're in and out and that's it.
00:08:23.033 --> 00:08:28.858
But for game dev, this game object, this singleton, stays around for hours.
00:08:28.858 --> 00:08:40.874
It could pretend you know someone having a long play session that ends up staying around for hours and then the facet of it being at 60 frames per second or running this function at so many times.
00:08:41.400 --> 00:08:46.032
When it comes to debugging, the common debugging approaches are like the testing approaches that we use for app dev.
00:08:46.032 --> 00:08:56.106
It's much harder for game dev because you make an action and it's 80 frames later that the bug or like some compounding stuff ends up surfacing to your app.
00:08:56.106 --> 00:08:59.708
And where the bug appears is not necessarily the frame where the cause exists.
00:08:59.708 --> 00:09:05.649
So you're not dealing with only backtraces but time traces to try to figure out where something breaks.
00:09:05.649 --> 00:09:08.326
So yeah, your approaches to testing and regression.
00:09:08.326 --> 00:09:09.210
It's different.
00:09:10.259 --> 00:09:12.488
What do you do for testing in game dev?
00:09:12.488 --> 00:09:14.567
Can you unit test a game?
00:09:14.567 --> 00:09:16.279
Can you do a system test?
00:09:16.279 --> 00:09:26.811
Because I can think of how I test a web-based application, but, like you just said, when you're testing a web-based application, you're testing essentially a part of a transaction, right?
00:09:26.811 --> 00:09:32.013
That sounds like it would be a lot more difficult to test bits of the game in isolation.
00:09:32.013 --> 00:09:34.024
But maybe that is how you do it.
00:09:34.024 --> 00:09:34.827
How does that work?
00:09:35.600 --> 00:09:50.301
So I think for turn-based games where it's kind of like a tactical if you get like a tactical top-down RPG or something like that a lot of the testing practices that you would use for app dev mostly apply right, and the reason for that is that you can codify that slice of time.
00:09:50.322 --> 00:09:54.582
You can say okay, here's my setup, here's where the player is, are they close to the enemy?
00:09:54.582 --> 00:09:57.547
Then the attack option should show up there.
00:09:57.547 --> 00:10:02.383
What gets really tricky and what gets much harder to test is real time games.
00:10:02.383 --> 00:10:05.600
So anything with physics in there becomes a little bit trickier.
00:10:05.600 --> 00:10:08.433
Because I've had situations with that ramp collision.
00:10:08.433 --> 00:10:12.986
I'm going to have nightmares about ramp collision for a very long time, but it feels great.
00:10:12.986 --> 00:10:17.706
Right, the player jumps, he runs up the map, he runs down dashes, all that stuff.
00:10:17.706 --> 00:10:28.424
But there's a situation where if I do a frame perfect input of pressing forward and then at the same time press jump, he would tunnel through the ramp and fall out the other end.
00:10:28.424 --> 00:10:38.562
And it's like, okay, I have to replicate a frame perfect input of hitting left, then right and jump at the exact same time on the same frame and then he drops down through the ramp.
00:10:38.562 --> 00:10:39.745
This is ridiculous.
00:10:39.745 --> 00:10:41.691
So as far as applying that.
00:10:41.691 --> 00:10:56.649
The cool thing is that and it goes to this idea of the status quo of game engines today they just accept that this is something that you have to deal with, though they know I'm putting a replay system into DragonRuby so you can actually say all right, I'm going to start a replay.
00:10:56.649 --> 00:11:02.423
It resets your game and then you fiddle around with it until you get the bug and it captures that input history.
00:11:02.423 --> 00:11:05.431
You can have the replay run every time you save code.
00:11:05.431
--> 00:11:09.748
So DragonRuby is all hot loaded, because Ruby is amazing like that.
00:11:09.748 --> 00:11:18.349
And so what I would do is I would say, okay, well, what if I set the gravity to zero before I execute the jump function?
00:11:18.349 --> 00:11:25.966
So I'll set the gravity to zero and it would automatically run the replay and then go through those steps and then see if the player drops down through the stage or not.
00:11:25.966 --> 00:11:28.642
That's kind of how you have to do some of these regression facets.
00:11:28.642 --> 00:11:34.322
It's almost like systems testing or end-to-end testing, but it's just a different mindset with respect to that.
00:11:34.865 --> 00:11:36.629
And backfilling with a unit test.
00:11:36.629 --> 00:11:50.736
There's so much context that has to be communicated within that unit test that it's just hard to say let me do a frame, perfect jump and then the value of gravity should be zero at the next frame and you get a failure.
00:11:50.736 --> 00:11:55.980
And then you're like, okay, it's a failure, but I wrote this test three months ago and I have no idea why this is a failure or not.
00:11:55.980 --> 00:11:57.582
So that's one facet of it.
00:11:57.643 --> 00:12:14.543
Another tricky facet of it is that, like I was building a racing game, and a racing game is called a car that turns my game names are ridiculous, so it's a car that turns and I'm playing around and you take that first corner, how can you like deterministically quantify or describe it?
00:12:14.543 --> 00:12:21.500
Doesn't feel right, right, right, it's a little stiff, or it doesn't float as nicely as I wanted to.
00:12:21.500 --> 00:12:27.049
And then you tweak some numbers and, okay, it feels good now, but what's the regression test for that?
00:12:27.049 --> 00:12:31.808
And then you're like, okay, well, it feels right for this turn, but the next turn doesn't feel right.
00:12:31.808 --> 00:12:33.379
And then you tweak the values again.
00:12:33.379 --> 00:12:39.059
You're like, okay, both turns feel good, but now your unit test fails because the values that you originally set up are not the same.
00:12:39.059 --> 00:12:42.902
And then you're like, well, test it assert that game is fun.
00:12:43.221 --> 00:12:44.503
So those kinds of facets of it.
00:12:44.503 --> 00:12:56.568
And then one challenge I had with a car that turned the game was that I had a really good initial release and I was like, okay, this feels good and I made the controls a little bit more floaty and it felt really nice.
00:12:56.568 --> 00:13:00.750
But because I did that, there was a part of a track that is impossible to get around because the corner is too tight.
00:13:00.750 --> 00:13:03.231
That is impossible to get around because the corner is too tight.
00:13:03.231 --> 00:13:12.495
So now you've got this overarching issue of okay, with the values and how I've changed them, is it still possible to complete the 15 tracks that I have in this game?
00:13:12.495 --> 00:13:14.057
I don't know the answer to that.
00:13:14.596 --> 00:13:16.357
That's why I came in and was like, please help me, please.
00:13:16.357 --> 00:13:20.785
Well, actually, speaking of help, there's actually a pretty cool.
00:13:20.785 --> 00:13:24.774
I got to shout out my podcast host, buzzsprout, which is a Rails app.
00:13:24.774 --> 00:13:27.384
So yay for using Ruby products in the wild.
00:13:27.384 --> 00:13:31.373
There is actually a link in the show notes.
00:13:31.373 --> 00:13:33.985
When you're viewing that, buzzsprout automatically adds it.
00:13:33.985 --> 00:13:35.729
You can text the show.
00:13:35.729 --> 00:13:50.008
So if you're hearing what's going on with Mir and like, oh, I know how to solve that, I don't know if anybody does Text when you're listening to this episode and I will relay it to him and we will use this super cool new feature from Buzzsprout.
00:13:50.008 --> 00:13:53.144
Maybe we can get you unblocked with a text message.
00:15:15.089 --> 00:15:17.372
I love the idea of live streams, it's lots of fun.
00:15:17.372 --> 00:15:23.298
And so another facet of the testing thing is like, of course we're both apparently Zelda linked to the past or Zelda fans.
00:15:23.298 --> 00:15:34.362
And so the other facet of it is that when it comes to games, humans find games interesting for a specific problem domain.
00:15:34.362 --> 00:15:45.759
If it's a puzzle game where it just takes mental compute to try to figure out like move covers to try to figure out the answer, then it's apparently those games are more boring to play than games like Zelda, and there's like a really old write-up of Zelda.
00:15:45.759 --> 00:15:53.254
And the problem then it's apparently those games are more boring to play than games like Zelda and there's like a really old write-up of Zelda and the problem domain that it exists in and apparently it's an NP-hard problem.
00:15:53.453 --> 00:16:02.521
Zelda, a Link to the Past, is NP-hard and that algorithmic problem space is something that computers just have a very difficult time solving.
00:16:02.521 --> 00:16:09.933
So how do you write a test to solve Legend of Zelda when it can't be solved?
00:16:09.933 --> 00:16:17.938
There's this facet of you can't even write an end-to-end or system level test that says beat Zelda for me and make sure that it can be done.
00:16:17.938 --> 00:16:23.781
And there's, of course, advancements that are happening there, but these are the kind of the challenges that games have.
00:16:23.781 --> 00:16:29.738
It's just that what we find interesting ends up being really difficult problems that computers have a hard time solving.
00:16:29.738 --> 00:16:46.850
So that's another challenge with this idea of like testing and regression parallel to app dev too.
00:16:46.870 --> 00:16:48.235
But like, how do you come up with an idea for a game?
00:16:48.235 --> 00:16:57.430
I know you said you originally did a port and a car racing game is at least a
solid enough concept that when you're like it's a car racing game, it's like okay, there might be a unique thing there, but it's probably a car racing game.
00:16:57.430 --> 00:17:04.462
Yeah, a metroid like platformer I can sort of visualize playing it in my head.
00:17:04.462 --> 00:17:10.097
But like, how do you come up with the idea for everything else other than it's a platformer?
00:17:10.097 --> 00:17:14.958
We're going to go from one end of the screen to the other and fight bad guys, everything else that goes into a game.
00:17:14.958 --> 00:17:19.097
Before you can even come up with writing the code, you have to have some idea of what's going on.
00:17:19.097 --> 00:17:20.985
How does that work?
00:17:21.547 --> 00:17:26.651
And you're right, it's got a lot of correlations to app dev and the overarching theme is to fail fast.
00:17:26.651 --> 00:17:31.011
So fail fast and control scope is kind of my overarching tips.
00:17:31.011 --> 00:17:34.113
But what I end up doing is I think of games that I like.
00:17:34.113 --> 00:17:43.654
So an example would be, let's say, legend of Zelda, and I think about that game and I think about all the things that I appreciate about it and I take something away from Legend of Zelda.
00:17:43.654 --> 00:17:46.616
Maybe I take away a bunch of the items.
00:17:46.616 --> 00:17:49.140
Is it still a game that I would play?
00:17:49.640 --> 00:18:07.682
And so you're trying to distill an experience down to the parts that you find that you connect most strongly with, and so that's kind of how I decided on an idea or a concept pull out from the feature set and think about the feel of the game.
00:18:07.682 --> 00:18:11.008
So what I tell people to do is think about your perfect five-star review.
00:18:11.008 --> 00:18:11.729
What does it say?
00:18:11.729 --> 00:18:20.320
It's not going to say I like this game because it had procedurally generated maps, and it's not going to say that right, it's going to have more facets of like.
00:18:20.320 --> 00:18:34.283
When I first picked up that sword and left and was able to charge it and throw out a fire beam, I felt like a powerful, godlike hero, and thinking of the five-star review is what helps you figure out that forest for the trees kind of idea.
00:18:34.283 --> 00:18:42.201
So you have your distillation to control scope, you've got the feel of the game to help guide your approach to the actual mechanics and stuff.
00:18:42.201 --> 00:18:48.922
And then the final thing is a 20-second demo where you communicate that hook within that 20-second period.
00:18:50.235 --> 00:18:51.623
So the challenges though, especially within the game development.
00:18:51.623 --> 00:18:59.936
I'm not nintendo, so the player is not going to give me the benefit of the doubt and wait two to three hours before that big, nice facet of game mechanics comes in.
00:18:59.936 --> 00:19:15.075
And so, with respect to like live ops and what people and the industry and how they measure metrics,
so from the point that they open the application, menu, screens, controls, splash screens, all that you have 20 seconds before the falloff rate ends up being more than 90%.
00:19:15.075 --> 00:19:21.682
So you have to say get them into the action, communicate why they should continue playing your game within that first 20 second period.
00:19:21.682 --> 00:19:26.701
So that's how my initial prototyping ends up happening, and then from there I expand on this.
00:19:26.855 --> 00:19:28.743
Oh yeah, I've hooked them for the first 20 seconds.
00:19:28.743 --> 00:19:33.538
How can I keep them playing?
00:19:33.538 --> 00:19:36.348
I've communicated why they should or shouldn't play the game, and then it's about expanding on that longer game loop.
00:19:36.348 --> 00:19:38.556
But that's kind of how I approach ideas.
00:19:38.556 --> 00:19:39.659
I think about game.
00:19:39.659 --> 00:19:54.316
You know, draw inspiration from literature, like we Are Legion, we Are Bob games that I enjoyed playing, and then distill it down and focus in on those things that I found valuable and then the final thing is finding those niche audience that value the same things you do.
00:19:54.937 --> 00:19:58.163
You were pretty successful with at least one of your games.
00:19:58.163 --> 00:20:02.761
A Dark Room was up there, but is there.
00:20:02.761 --> 00:20:08.237
I know why that got super successful it was because I have no idea why you have no idea.
00:20:08.237 --> 00:20:14.183
Okay, it was one of those viral phenomenons or just the right person tweeted about it, okay.
00:20:15.098 --> 00:20:21.245
The interesting thing, though, is that, with respect to my subsequent games, the success is primarily long tail and hyper niche.
00:20:21.245 --> 00:20:26.083
So the idea there is that I'm not trying to compete with the big AAA companies there.
00:20:26.083 --> 00:20:37.543
What I'm trying to focus in on is there's an underserved niche community that loves XYZ and cannot provide a digital interactive experience for them that they end up appreciating.
00:20:37.543 --> 00:20:53.407
So the definition of success ends up being about not trying to put all your eggs in one basket and hope for that lottery ticket, but to focus in on those hyper niche experiences, create your wheelhouse, your identity from that perspective, and then service those air quotes smaller communities.
00:20:53.407 --> 00:20:56.324
So our dark room was out there, like whatever.
00:20:56.324 --> 00:20:59.565
So then the question was can I capture lightning in a bottle twice?
00:20:59.565 --> 00:21:06.160
And so I ended up making a pre-sequel, and that ended up in the top five of the app store, so it did really well.
00:21:06.160 --> 00:21:09.278
And then I was like okay, can I capture lightning a third time of the app store?
00:21:09.278 --> 00:21:11.142
So it did really well, and then I was like okay, can I capture lightning a third time?
00:21:11.201 --> 00:21:28.694
And so what I ended up doing was I
created a narrative, satirical, rhythm-based game based off of a book that was written in the 1800s called Flatland Romance of Many Dimensions and it's about this 2D world and it basically was a satire on Versailles and how royalty and the life of Versailles was like.
00:21:28.694 --> 00:21:40.067
You know what I'm going to take this idea of a 2D world and the concepts in there and then do a satirical commentary of the 20th century in the context of a game, and it ended up doing well too.
00:21:40.067 --> 00:21:45.248
So it made it into, I think it was like number nine overall and it's been in the top 100.
00:21:45.248 --> 00:21:54.066
So I would like to say that maybe this model can work, this idea of digitalization find your unique audience, find your voice and cater to those people.
00:21:55.197 --> 00:22:06.848
But I have no idea what I'm doing basically, it sounds like a lot like app dev from the startup perspective of like keep your mvp very small and very tight and like focused.
00:22:06.848 --> 00:22:10.377
You're not going after google or you're not going after Amazon.
00:22:10.377 --> 00:22:12.886
The StoryGraph did not go after Amazon.
00:22:12.886 --> 00:22:25.442
It went after Goodreads, which is a lot smaller of a thing but it was a lot slimmer and it was a lot tighter and it kept its focus on its audience and that's why Naughty's been so successful with it.
00:22:25.442 --> 00:22:27.807
It solved a problem that people had.
00:22:27.807 --> 00:22:31.523
Yeah, goodreads is an amazon product, but she wasn't going after amazon.
00:22:31.543 --> 00:22:40.519
You're not going to make the next witcher game the other challenge that you have is like, with an app idea, if you pitch it to someone say, hey, wouldn't it be cool if you had xyz?
00:22:40.519 --> 00:22:42.764
That made this part of your life easier.
00:22:42.764 --> 00:22:45.576
And you're like yes, please make this and take my money.
00:22:45.576 --> 00:22:58.065
And when it comes to games like what do you think about a satirical commentary of the 20th century as a top-down 2D rhythm-based game, they're like I guess I don't know, I guess it's sort of like pitching books to a degree.
00:22:58.154 --> 00:23:04.361
Like I have this idea for the story, you don't write the whole novel before validating the idea, but you have to convey it.
00:23:10.355 --> 00:23:13.470
There's a really good book called the Mom Test and it's this idea of idea generation and then vetting your ideas and taking it to market.
00:23:13.470 --> 00:23:14.715
I was like, okay, this is definitely going to help me.
00:23:14.715 --> 00:23:18.737
And then halfway through the book it says this is great and all, but it's not going to really work for games.
00:23:18.737 --> 00:23:21.002
I'm like, ah, shakes face.
00:23:21.002 --> 00:23:38.576
But yeah, that's one weird facet of it and that's why I say you build a 20-second experience and hook them and make sure that you have the idea of your perfect five-star review in your head, so you know what kind of emotions and feelings you're trying to convey, and then you need to communicate that very quickly and I think that helps mitigate the risk, but it's just difficult.
00:23:38.998 --> 00:23:40.742
So the power of Dragon Ruby.
00:23:40.742 --> 00:23:43.188
Like we're talking 2D games, not 3D.
00:23:43.188 --> 00:23:59.992
So for anyone who's not like a super big gamer and doesn't quite understand what we're talking about is not like a super big gamer and doesn't quite understand what we're talking about, If you think of, like the new Final Fantasy 7 games that just were rebuilt, like that's very 3D animations versus a game like Stardew Valley is a 2D game.
00:23:59.992 --> 00:24:08.552
The big difference there, aside from like the computational stuff of like 3D math, Math Right Is the assets.
00:24:08.552 --> 00:24:09.367
The sprite is, I believe, what they're called in 2D math, Math Right Is the assets.
00:24:09.367 --> 00:24:13.841
The sprite is, I believe, what they're called in 2D games.
00:24:13.841 --> 00:24:24.802
Yes, or I might be aging myself back when, like we used to play games in the browser but sprites those little 2D guys versus that full-blown like Blender 3D animation model Yep.
00:24:27.154 --> 00:24:30.382
How does that work inside of Dragon Ruby?
00:24:30.382 --> 00:24:38.632
Is it just like, hey, I've got these pictures, these PNGs or SVGs or whatever file format, and you upload them?
00:24:38.632 --> 00:24:47.464
And then you're like, okay, and you're going to move like this, and when you're doing this, it's this sprite, and if it's standing still it's this sprite and it's just to get it look the way that you want.
00:24:47.464 --> 00:24:54.826
You're just uploading assets, or does DragonRuby have something in it where it's like here's how we build a Sprite pixel by pixel.
00:24:55.215 --> 00:25:01.029
So the tech behind it is really cool and so we have a core dependency on LiveSDL.
00:25:01.029 --> 00:25:08.042
So SDL stands for Simple Direct Media Layer and it's a C library that it's been around for 20, 25 years, like Valve.
00:25:08.042 --> 00:25:10.245
Steam Client is built with LoveSDL.
00:25:10.245 --> 00:25:15.211
So when it comes to like battle-hardened kind of thing, that's where the magic happens.
00:25:15.211 --> 00:25:25.105
So what SDL does is that it's a abstraction over all the operating systems out there mobile, android, web PC, mac, linux, console, et cetera.
00:25:25.595 --> 00:25:32.400
And so you tell SDL render this air quotes sprite and it figures out how to render it on that specific operating system.
00:25:32.400 --> 00:25:38.022
And so the air quotes official term is that it's a texture and for 3D I think it's called material.
00:25:38.022 --> 00:25:42.622
But you're basically saying okay, when you say, render this PNG on the screen.
00:25:42.622 --> 00:25:59.127
Behind the scenes, what we're saying okay, get the PNG, load all the bytes from it, create a texture
out of that PNG, cache it and then tell SDL to render this texture at this specific location with these specific dimensions.
00:25:59.127 --> 00:26:20.606
And so what SDL does behind the scenes is it takes that RGBA I forgot the explicit format but that byte array and that specific byte array and that texture it's a common construct for across gpus, so gpus understand this data structure of an array of bytes that represents rgb values, rgba values, on a screen.
00:26:20.606 --> 00:26:36.817
So what stl does behind the scenes is it says, okay, you have this texture and I'm going to give you another program which is called a shader, and I want, hey, gpu, I want you to take the shader program and this texture and do the work to present it onto the screen.
00:26:37.259 --> 00:26:38.463
So what a shader is?
00:26:38.463 --> 00:26:41.955
It's kind of a C-based program, it's a C-based dialect.
00:26:41.955 --> 00:26:44.960
That is, I guess, highly parallel.
00:26:44.960 --> 00:26:54.986
So the value of a GPU and its power and what it brings to the table is that it can run a very small function extremely fast across all pixels on the screen.
00:26:54.986 --> 00:27:05.006
So what happens is that texture that has 8K worth of values gets sent to the GPU and the program gets run for each pixel on the screen.
00:27:05.006 --> 00:27:07.721
So, yeah, you think about that 8K texture.
00:27:07.721 --> 00:27:12.003
Yeah, yeah, yeah, it's saying for each pixel, give me the RGB, run this thing.
00:27:12.003 --> 00:27:15.923
And so for Windows, the shader language is Vulkan or Direct3D.
00:27:15.923 --> 00:27:17.761
For Linux it's OpenGL.
00:27:17.761 --> 00:27:19.922
For iOS and Mac it's Metal.
00:27:19.922 --> 00:27:22.343
And then your consoles have various ones.
00:27:22.343 --> 00:27:24.683
They're all kind of consolidating on Vulkan.
00:27:24.683 --> 00:28:12.145
But that's the GPU tech that happens behind the scenes.
00:28:12.145 --> 00:28:22.520
So the great thing in Dragon Ruby, is you just shuffle a hash into an array, that's my next question how much does Dragon Ruby help me with this Cause?
00:28:22.761 --> 00:28:24.066
I'm lost already.
00:28:24.427 --> 00:28:30.063
Yeah, you give it an X, so we have a logical canvas of 1280 by 720 and it's geometric.
00:28:30.083 --> 00:28:31.948
So zero, zeros in the bottom left-hand corner.
00:28:32.355 --> 00:28:49.639
So if I want to render a sprite in the bottom left-hand corner, we've got a argument called outputs and it's an array and you just do outputs and then you shovel a hash or an object that responds to X, y, width, height and path, which is your PNG path, and it'll render it to the screen and that's all you have to do.
00:28:50.100 --> 00:28:58.031
So when it comes to animations and we talk about sprite sheets, it's frame by frame, so you can take the option of like okay, attack animation is across three PNGs.
00:28:58.031 --> 00:29:08.784
So then you've got your frame that the action happened, and you can say okay, I want to hold each one of these PNGs for four frames, and the duration of the entire thing is eight frames.
00:29:08.784 --> 00:29:16.262
And so you can tell DragonRuby eight frames, and so you can tell DragonRuby do the rendering across this collection of sprites on the screen.
00:29:16.262 --> 00:29:18.567
So when you do an attack, it cycles through those, do those specific animations?
00:29:18.567 --> 00:29:24.517
And it's a matter of providing objects that respond to that specific contract, which is the beauty of Ruby, right?
00:29:24.517 --> 00:29:27.189
It doesn't have to be a sprite class or whatever.
00:29:27.189 --> 00:29:30.779
It's just hey, if it responds to these functions, these properties, we're good.
00:29:31.641 --> 00:29:44.463
That's so interesting, the thought of just like, yeah, I've got a bunch of static pictures and then I load them into this program and then you press a button on your keyboard or controller and then it moves and it's so cool.
00:29:44.463 --> 00:29:46.129
Yeah, it's such a cool concept.
00:29:46.661 --> 00:29:54.028
What's really interesting is that and a difference that I saw with AppDev and GameDev is, with GameDev, a lot of it is kind of data-oriented.
00:29:54.028 --> 00:30:06.329
Like this it's like your game state is a function, what's rendered to the screen is a pure function that's derived based off of your game state, and so it feels data oriented and functional.
00:30:06.329 --> 00:30:10.768
It's an interesting paradigm shift that also existed when going from like app dev to game dev.
00:30:10.768 --> 00:30:21.449
So, yeah, a lot of the DragonRuby APIs are around this data oriented approach where you have referential transparency on what is actually going to be sent to the renderer and whatnot, and it's cool.
00:30:21.449 --> 00:30:24.009
It's really cool to kind of see all that in action.
00:30:24.009 --> 00:30:36.124
And then the simplicity of it of saying I can just have a value type that represents what's rendered to the screen and not have to think about immutability and a lot of the other complexities that exist out there.
00:30:36.964 --> 00:30:50.416
So Ruby, if you ask a non-Rubyist, is notorious for being slow, so how is it that we can run a game at 60 frames per second in a slow language?
00:30:50.416 --> 00:30:51.637
Air quotes slow language.
00:30:53.160 --> 00:30:53.640
Yeah, I've given up.
00:30:53.640 --> 00:30:58.044
So I was to a point where I was going to do like a white paper and we'll talk to that first and then I'll give you what I show them now.
00:30:58.044 --> 00:31:19.630
So the idea is that the initial response I run as fast as the NET Core CLR runtime that does a bitcode compilation in JIT.
00:31:19.630 --> 00:31:24.270
It's just not going to run that fast and so this idea of a language can't be fast or slow.
00:31:24.270 --> 00:31:29.388
It's a runtime implementation that makes it fast or slow With Ruby and this whole oh Ruby is slow.
00:31:29.388 -->
00:31:31.907
We're talking about MRI Ruby from.
00:31:32.460 --> 00:31:37.693
Like the 1.8, 1.9 days 1.8, 1.9 days, which is like ancient Ruby at this point.
00:31:37.693 --> 00:31:41.827
And so the runtime implementation with like Ruby 3.3 is a different runtime.
00:31:41.827 --> 00:31:43.713
It's got a different execution profile.
00:31:43.713 --> 00:31:47.468
For DragonRuby we use mruby as our primary dependency.
00:31:47.468 --> 00:31:56.651
So we took mruby and then gutted the core lib and polyfilled it with a lot of the libSDL stuff so that it could do cross-platform stuff.
00:31:56.651 --> 00:32:00.410
So you've got your file class and you do filereadfile.
00:32:01.260 --> 00:32:13.296
The mRuby, cruby, all those assume that you're working with an operating system that's PC, mac, linux that has a regular file system that isn't locked down the way that consoles or isolated storage or those other environments are.
00:32:13.296 --> 00:32:15.327
So we had to gut a lot of those things.
00:32:15.327 --> 00:32:20.412
And then those core libs are replaced with these across platform dependencies yeah, language can't be slow.
00:32:20.412 --> 00:32:28.932
And then with this, I guess, extraction and replacement process that's another facet of what makes the language fast is what is the implementation of your core lib?
00:32:28.932 --> 00:32:34.346
What is the speed of the C function that is being invoked through that foreign function interface?
00:32:34.346 --> 00:32:40.427
I went through all these details and it showed the employees like yeah, but Ruby's slow, and I'm like okay.
00:32:40.748 --> 00:32:41.390
Okay, yeah.
00:32:42.143 --> 00:32:50.189
So what I ended up doing was I was like, okay, I'm going to create a YouTube video and I'm going to have a scene where it renders as many sprites on the screen as I possibly can.
00:32:50.189 --> 00:32:57.394
And so the YouTube video yeah, if you do DragonRuby performance, it'll come up and what I show is rendering, I think, like 10 to 20,000.
00:32:57.394 --> 00:32:59.312
I give a profile, I say, okay, what's the speed of rendering?
00:32:59.312 --> 00:33:04.525
5,000 sprites on the screen that are moving across and have some concept of collision, and they'll wrap around.
00:33:04.525 --> 00:33:06.702
And so I do 5,000 sprites.
00:33:06.702 --> 00:33:13.731
And then, okay, I'm going to bump it to 10,000 sprites, 20, 80, 40, like 80,000 sprites.
00:33:14.231 --> 00:33:21.888
Dragon Ruby got around 20 to 30 frames per second, and I did the exact same thing with Unity and it got four frames per second.
00:33:21.888 --> 00:33:26.989
And so the conversation ended, All the white people, all the explanations, the details.
00:33:26.989 --> 00:33:28.666
I'm like watch this YouTube video.
00:33:28.666 --> 00:33:32.367
And they're like okay, there's still people like I don't believe that.
00:33:32.367 --> 00:33:34.909
So I did another one for many to many collisions.
00:33:34.909 --> 00:33:37.728
So it's like you
don't believe that.
00:33:37.728 --> 00:33:38.270
So I did another one for many to many collisions.
00:33:38.270 --> 00:33:47.772
So it's like you've got collisions on your page and how do you construct something that visually shows that this object collided with these other objects and 1500 sprites with many, many collisions at 60 FPS.
00:33:47.772 --> 00:33:49.667
You need to get one frame a second.
00:33:49.667 --> 00:33:52.787
It's completely broken from that perspective.
00:33:53.121 --> 00:34:11.969
It just goes back to that idea of like runtime implementation and your core lib implementation and the runtimes I'm picking on Unity because that's usually what people think of, yeah, sure, what people think of and the runtime implementation is, at this point, a 15-year-old fork of mono, of C-sharp mono, the C-sharp mono runtime.
00:34:12.539 --> 00:34:22.733
And then the way they dealt with cross-platform compatibility was through a transpiler that takes the intermediate representation of C-sharp and emits C code.
00:34:22.733 --> 00:34:28.313
So you're taking C-sharp code which gets converted into this intermediate representation.
00:34:28.313 --> 00:34:39.041
It's kind of like your virtual machine, and that virtual machine those specific opcodes are then code-gen as C code and then that C code then gets compiled.
00:34:39.041 --> 00:34:49.251
So you've got the C sharp to IL transition, the IL to C transition, the C to intermediate representation transition, and then that gets translated into the compiler.
00:34:49.251 --> 00:34:54.541
And once you've done all those transpilations, you've lost any semblance of optimization at that point.
00:34:54.541 --> 00:34:56.483
And so their runtime implementation.
00:34:56.483 --> 00:35:06.766
It's a good and bad thing, right, you have BitRot and it's a longer running project, but they can't take advantage of all the advancements and compilers that we have today, and so that's why it's faster.
00:35:06.766 --> 00:35:09.108
It's just, our runtime is just that way.
00:35:09.840 --> 00:35:21.688
Speaking of taking advantage of newer things, are you able to take advantage of the new stuff in Ruby 3.3 and what's coming out in 3.4, like the new parser, the new YJIT and things like that?
00:35:21.688 --> 00:35:27.067
Or is that not quite in your purview, because you're using mRuby and then sort of gutting it?
00:35:27.561 --> 00:35:32.747
We're able to take advantage of those things as those changes make it over to the mRuby.
00:35:32.747 --> 00:35:35.628
Now, the biggest benefit of mRuby is that it's embedded.
00:35:35.628 --> 00:35:40.806
It's fairly trivial to put that into a C program and have it run everywhere.
00:35:40.806 --> 00:35:47.625
So there's no OS level dependencies from that perspective or assumptions that are made that you're running on like a server class machine.
00:35:47.625 --> 00:36:00.648
And so when you think about like YJIT and the native or the assembly code that it emits, yes, that will work on Windows and they've got it working on Emscripten, but the backend compilers that are used for consoles, it's not going to work there.
00:36:00.950 --> 00:36:01.892
Or at least not yet.
00:36:02.780 --> 00:36:03.201
Not yet.
00:36:03.601 --> 00:36:07.409
And now we're getting into NDAs and all that crazy stuff.
00:36:08.110 --> 00:36:09.713
So there's a facet of that.
00:36:09.713 --> 00:36:13.264
So those changes, if they make it into MRuby, then we can look at co-opting them.
00:36:13.264 --> 00:36:23.884
And for us we're kind of like in this parallel stream where there are some things that we can send back to upstream saying that, hey, this change makes XYZ better or faster.
00:36:23.884 --> 00:36:28.721
But it's difficult to say, oh yeah, your file IOs is actually not cross-platform.
00:36:28.721 --> 00:36:34.211
Take this dependency on 250,000 lines of C code which is libSDL.
00:36:34.211 --> 00:36:37.668
So that maintenance burden is why the product exists.
00:36:37.668 --> 00:36:41.070
Right, it's what makes this process sustainable on our end.
00:36:41.070 --> 00:36:42.425
That's why you pay for the engine.
00:36:42.425 --> 00:36:44.144
We can take advantage of some things.
00:36:44.385 --> 00:36:45.027
I love Prism.
00:36:45.027 --> 00:36:50.273
I love the traversal of the specific recursive descent parser that's used in Prism.
00:36:50.273 --> 00:36:51.201
It's good.
00:36:51.201 --> 00:36:59.349
But mRuby was built later, which means that it has a nicer parser than what Ruby originally had, so it doesn't have as much as the other cruft that was there.
00:36:59.349 --> 00:37:06.672
So there's benefits that exist and it's just that balancing act of okay, how much are we going to invest in that parser facet?
00:37:06.672 --> 00:37:10.050
Can we collaborate with upstream to help that process?
00:37:10.050 --> 00:37:12.085
And someone's got to take the lead.
00:37:12.085 --> 00:37:16.449
If they're going to start with the prison port, I'm there, right, I want to make sure that that happens.
00:37:16.449 --> 00:37:18.753
But doing that work and then pushing it upstream.
00:37:18.753 --> 00:37:22.996
It's that question of whether MRuby is positioned to accept those kinds of changes.
00:37:22.996 --> 00:37:26.867
But it's really cool and our parity is with MRuby.
00:37:26.867 --> 00:37:32.201
So once the feature, that syntax, comes into MRuby, then we can leverage it.
00:37:32.481 --> 00:37:40.333
One interesting thing and I'd love to hear your thoughts on this is that with DragonRuby and the ideas that I have around it, we can break Ruby from that perspective.
00:37:40.333 --> 00:37:50.054
Dragonruby is a Ruby, but it doesn't have the same onus of backwards compatibility or mission critical applications.
00:37:50.054 --> 00:37:52.081
So what are some experimental things that could be added to like DragonRuby?
00:37:52.081 --> 00:38:04.385
Maybe we do create a pipe forward operator or maybe we actually do introduce some
experimental syntax that doesn't have the onus and the air quotes red tape that exists with CRuby or MRuby.
00:38:04.385 --> 00:38:11.208
So it's an environment for experimentation and it's a safe environment because you're not building medical software with it, right?
00:38:11.920 --> 00:38:12.844
That's interesting.
00:38:12.844 --> 00:38:19.623
I didn't think about the fact that you're sort of isolated from what goes on in Ruby because you have your own.
00:38:19.623 --> 00:38:29.612
Would that be considered like having your own dialect in a way of like you know, sort of in the way that Americans speak English and the English speak.
00:38:29.612 --> 00:38:33.034
English and they are not the same language.
00:38:33.034 --> 00:38:35.836
There are similarities, but they're not the same.
00:38:35.836 --> 00:38:37.018
That's interesting.
00:38:37.820 --> 00:38:48.525
It's a world for experimentation and potential innovation, and I think that's a big challenge for Ruby today is that we have the maturity and the ideas that have been set in place, but there's a trade-off, right.
00:38:48.525 --> 00:38:51.945
That maturity I won't say stifles, but it stifles innovation.
00:38:51.945 --> 00:38:52.099
Right, you're slower to innovate, no-transcript.
00:38:52.099 --> 00:38:54.327
You're slower to innovate because you don't want to break things.
00:38:54.327 --> 00:39:01.268
But DragonRuby has this unique environment where it's like okay, it's games, we don't have 25 years of code to think about.
00:39:01.599 --> 00:39:07.889
We're building a new experience and the opportunities to innovate on what exists out there are, there, they're closer.
00:39:08.599 --> 00:39:18.846
Have you done any experimenting yet, or is there a bit of it where you're like we actually added this syntax that if you're writing Dragon Ruby code, you can do this, but you can't do that in regular Ruby.
00:39:19.340 --> 00:39:23.306
We've done an experimentation and it's actually went really well around the core lib.
00:39:23.666 --> 00:39:27.681
So in Dragon Ruby, hash is quack-like attribute accessors.
00:39:28.123 --> 00:39:45.628
So you can use the bracket symbol, whatever to access a key in a dictionary, or you can just do x and what it will do is it does the method missing the pre-cache and all those facets to where you'll actually get the x key value from, and it forwards to get key.
00:39:45.628 --> 00:39:46.028
Basically.
00:39:46.028 --> 00:39:55.028
And the interesting thing there is that with this approach you don't have to air quotes, pay the tax of creating a class to represent one of your game entities.
00:39:55.028 --> 00:40:06.934
You can say I'm just going to create a hash with XY armor that has this name and stuff and just create that dictionary structure, invoke it as if there were attributes and then later evolve to using a class.
00:40:06.934 --> 00:40:10.666
And the nice thing there is that because we've done those polyfills, you're not changing the call sites.
00:40:10.666 --> 00:40:17.702
You can continue to keep those specific properties that you decided these objects would have and just transition to a class.
00:40:17.702 --> 00:40:20.509
So those kind of things, same thing right.
00:40:20.509 --> 00:40:27.842
Like if I sent the pr that said hey, hashes, quack like classes with respect to attribute accessors, decline, right, they'll immediately.
00:40:28.342 --> 00:40:31.007
Nope nope, you've got data classes.
00:40:31.007 --> 00:40:34.266
You've got structs, like there are ways to do it, but not hashes.
00:40:34.266 --> 00:40:35.273
Sorry, no dice, but dice.
00:40:35.614 --> 00:40:39.387
But from our perspective we're like, yeah, we can do this, we can try this approach and see how it feels.
00:40:39.387 --> 00:40:48.088
And it's fun because we'll have Ruby devs that come in there and say, man, this is really nice, though I can just treat a hash like a full-blown class and you end up missing it.
00:40:48.088 --> 00:40:53.114
And I was like, yeah, I probably feel I opened up the hash and did the same thing and like more crime.
00:40:53.114 --> 00:40:58.596
Yeah, those are primarily the experimentations that we've taken is expanding the core lib from that perspective.
00:40:59.456 --> 00:41:08.478
It's sort of like when someone goes from doing primarily Rails dev work to just raw Ruby and they're like I can't do any.
00:41:08.478 --> 00:41:09.902
It's like, yep, that's active support.
00:41:09.902 --> 00:41:11.505
Sorry, that's exactly Yep.
00:41:11.505 --> 00:41:15.063
I don't want to not do my favorite question, so we're going to do it now.
00:41:15.063 --> 00:41:16.688
Let's do it Before any more rabbit holes.
00:41:16.688 --> 00:41:23.865
What is something cool, new or interesting that you've recently learned or discovered or built Doesn't have to be coding related.
00:41:23.865 --> 00:41:24.949
What do you got?
00:41:25.800 --> 00:41:29.268
It's really the shader tech, so how the GPUs work and everything.
00:41:29.268 --> 00:41:36.253
So there's shader language for OpenGL is different than the shader language for Direct3D, which is different than Metal.
00:41:36.253 --> 00:41:44.230
And then you're like okay, well, if I want to do this cool ripple effect or visual effect, I have to write five different versions of this program.
00:41:44.230 --> 00:41:45.112
That's not fun.
00:41:45.112 --> 00:42:01.913
But there's something called the Spear V toolchain, which is a cross compiler where you write I think it's Vulkan, you write your shader in Vulkankan and it will create the OpenGL, Metal, Direct3D variants of that specific shader language.
00:42:01.913 --> 00:42:12.646
So we're getting into a world where we've got fragmentation at the language to hardware level and each one of these companies is saying, no, our language is the best and we're not going to consolidate onto one.
00:42:12.646 --> 00:42:16.188
So of course someone said, no, we're going to do that and then provide that transpilation.
00:42:16.188 --> 00:42:21.211
But that's been some of the really interesting stuff that I've been exploring.
00:42:21.211 --> 00:42:32.882
We think about CPU and just languages that target CPU, but now we're getting into GPU languages and then their idioms and their highly parallel approach and paradigms are just, they're fascinating and they're different.
00:42:33.183 --> 00:42:36.590
There's a website like, if you want some idea of like what that looks like.
00:42:36.590 --> 00:42:49.284
There's a website called Shader Toy and there's a scene of a tree with like leaves waving in the wind and like a grassy landscape and there's like a day-night cycle and clouds and everything Like how the hell did they do this?
00:42:49.284 --> 00:42:51.628
And you look at the program and you're like what is this?
00:42:51.628 --> 00:42:52.804
It's just all math.
00:42:52.804 --> 00:43:00.182
But all the way down, all the way down.
00:43:00.182 --> 00:43:08.648
But the fact that someone can take this highly parallel concept of every pixel is run in parallel with every other pixel, and how you form a program that can make a tree, it's just mind-blowing.
00:43:08.648 --> 00:43:14.288
But yeah, shader toy, you can lose hours just looking at all the cool little tech demos that exist out there.
00:43:14.288 --> 00:43:15.802
It changes your brain right.
00:43:15.802 --> 00:43:21.427
It exposes you to a domain that you haven't been exposed to and it'll make you a better developer across the board.
00:43:22.059 --> 00:43:27.567
Yeah, I will include that in the show notes and then I will go waste hours staring at it here in a little bit.
00:43:27.567 --> 00:43:39.192
So if someone wanted to get started doing game dev, they have a little idea or they just want to tinker and they want to use everyone's favorite language, Ruby and Dragon Ruby.
00:43:39.192 --> 00:43:41.826
Like, how do you recommend getting started aside from?
00:43:41.826 --> 00:43:46.110
Like go buy Dragon Ruby so you have the Dragon Ruby engine and get started.
00:43:46.110 --> 00:43:52.471
But like how do you recommend going from I have nothing on the screen to hello world with Dragon Ruby?
00:43:52.759 --> 00:43:57.132
So, just an aside, anyone that listens to the podcast, you send me an email saying that you heard about it.
00:43:57.132 --> 00:43:59.489
I'll hook you up with a free license, no big deal there.
00:43:59.489 --> 00:44:08.949
We also have income assistance if you're unemployed or in school under 18 or a parent that wants to teach a kid Any one of those like heartwarming, good feeling stuff.
00:44:08.949 --> 00:44:11.804
Just send me an email and I'll get you set up.
00:44:11.804 --> 00:44:13.686
So I'm not trying to put anyone out financially.
00:44:13.686 --> 00:44:18.170
But yeah, you download it, you double click to unzip and that's it.
00:44:18.170 --> 00:44:20.913
There's no dependency installation, it's all self-contained.
00:44:20.913 --> 00:44:26.121
And there's a book that one of
our community members wrote that I recommend and it's in our docs.
00:44:26.121 --> 00:44:34.905
But you end up building like a side-scrolling shooter and like a Flappy Bird clone is also a facet of it and kind of work through that book.
00:44:34.905 --> 00:44:39.768
And if you're familiar with coding I think you'll get up to speed pretty quickly by working through that.
00:44:40.500 --> 00:44:46.268
Aside from that, we've got I think like 150 plus sample applications that go in increasing difficulty.
00:44:46.268 --> 00:44:47.878
So it kind of teaches the basic.
00:44:47.878 --> 00:44:53.128
Then we dig into some of the advanced rendering concepts and then we have genre-specific reference implementations.
00:44:53.128 --> 00:45:09.108
If you want to do a platformer, here are some reference implementations of how to do a platformer, like a Mario Star or platformer, or if you're doing like a tactical RPG, we actually have a sample app where it's like a green sprite walking around the screen and it's the first area of Legend of Zelda from the NES.
00:45:09.108 --> 00:45:13.346
And then you enter a cave and it's like here, take the sword, take this.
00:45:13.346 --> 00:45:19.661
So we actually have that as like as a sample app and that's kind of like your springboard with respect to starting on a game.
00:45:20.163 --> 00:45:25.704
I think that's like a big observation that I found is that with Rails applications, the scaffolding is extremely productive.
00:45:25.704 --> 00:45:29.802
I mean, we're building CRUD apps, we're taking data, sticking it into a database.
00:45:29.802 --> 00:45:32.563
It's formulaic, at least at that level.
00:45:32.563 --> 00:45:36.632
But when it comes to games, it's difficult to create that kind of scaffolding.
00:45:36.632 --> 00:45:52.349
So how we compensate for that is saying, okay, here's springboards to creating a top-down game or a platformer or a turn-based or ascii-based roguelike or a bullet hell shooter or twin stick shooter and all those variations and that ends up working pretty well.
00:45:52.349 --> 00:45:55.603
And our discord community is absolutely phenomenal.
00:45:55.603 --> 00:46:02.346
The idea of Minus is there and it's so great because there's so many people that it's Ruby is their first language, right?
00:46:02.346 --> 00:46:04.246
They're like I've never used Ruby before.
00:46:04.246 --> 00:46:05.664
That clicking happens.
00:46:05.664 --> 00:46:08.248
You see that magic that we felt and they're like this is so awesome.
00:46:08.248 --> 00:46:11.139
And so if you're ever stuck, you come to the Discord community.
00:46:11.139 --> 00:46:17.052
You're going to find a lot of help there, and I think a combination of those three things is the best way to get going Super cool.
00:46:17.320 --> 00:46:18.371
This has been great.
00:46:18.371 --> 00:46:28.007
Thank you so much for coming on and reaching out and asking to come on, because this was so much fun getting to pick your brain on it and learn more about it and it's such a cool project and I love that.
00:46:28.007 --> 00:46:30.492
We can do literally anything with Ruby.
00:46:30.492 --> 00:46:34.148
It's not just web stuff, it's full blown applications and games.
00:46:34.148 --> 00:46:35.259
Just web stuff, it's full blown applications and games.
00:46:36.442 --> 00:46:37.266
And commercial games.
00:46:37.266 --> 00:46:39.907
This is putting food on my table, right, right, right, yeah.
00:46:39.907 --> 00:46:49.601
So it's wonderful and the innovations I think that the language will bring to game dev is sorely needed and it's good and it's an investment in that future.
00:46:49.601 --> 00:46:58.750
I think the future like kids and students and things like that, and education, and I think that's where I feel the renaissance and that resurgence and what we discovered again.
00:46:59.559 --> 00:47:02.904
Bringing developer happiness to game devs sounds pretty important.
00:47:02.904 --> 00:47:07.025
Cool, is there anything else you wanted to talk about before we do the wrap up?
00:47:07.025 --> 00:47:07.780
Take?
00:47:07.800 --> 00:47:08.806
the time, feed your soul.
00:47:08.806 --> 00:47:12.387
I know people say like, oh, I got to learn the next new hot tech.
00:47:12.387 --> 00:47:16.811
And just step back and just remember that, why you decided to become a developer.
00:47:16.811 --> 00:47:21.822
Right, the love of the craft and the encoding, and I think game dev is a wonderful way to do that well.
00:47:21.842 --> 00:47:22.907
Thank you so much for coming on.
00:47:22.907 --> 00:47:26.259
Where can people find you and dragon ruby on the internet?
00:47:27.021 --> 00:47:30.273
yeah, we have our discord server, so dragonrubyorg has a link to that.
00:47:30.273 --> 00:47:34.768
I'm on the artist formerly known as twitter at amirazan.
00:47:34.768 --> 00:47:38.282
I on Mastodon, on rubysocial, on Mastodon.
00:47:38.282 --> 00:47:41.034
Shoot me an email, also DMs welcome.
00:47:41.034 --> 00:47:43.125
All those great things Excellent.
00:47:43.146 --> 00:47:47.025
Yeah, I'll put all that stuff in the show notes so that people have access to it.
00:47:47.025 --> 00:47:48.543
And again, thanks for coming on.
00:47:48.543 --> 00:47:58.771
It was a blast having you on and hopefully I'll get an opportunity to do some tinkering of my own and then maybe even have you on again to pick apart how bad my game code is.
00:47:58.771 --> 00:48:00.594
Oh, my game code is terrible, don't worry.
00:48:00.594 --> 00:48:11.570
Great Well, audience members, don't forget to text in if you liked the show, if you have comments, questions, concerns, or if you'd like to be on the show, shoot me a text.
00:48:11.570 --> 00:48:13.427
I'd love to talk more to you.
00:48:13.427 --> 00:48:17.521
Otherwise, see you in the next episode.
00:48:17.521 --> 00:48:24.027
Bye, everyone.