 and welcome to another episode of the Scalable Multiplayer Game Design series with OpenShift TV. I think that's where we are today. I'm your fake sort of internet wannabe host, Eric Jacobs, joining me today. We've got Roddy Keely, who I probably always butcher your name, Kylie. Okay, close Kylie. Kylie, damn. I'm going to commit that to memory one of these days, I promise. Derek Rees and Mr. Michael Clayton, the head nod. So yeah, since we last played around, we've made a bunch of progress with the game server and a few changes to the game client. And Roddy Keely is going to show us some of what we've got going on. We've made some extensible configuration and some other cool changes. I'll turn it over to you, Roddy. If you'd like to share your screen, show some of what we've got going on. All right. So I'm going to share my code for the server and just run that up really quickly. Hopefully I'll be sharing the right one, because it's giving me an option of 12 and it has a scroll bar. So there's quite a few to choose from. Which screen is which? That's right. Let's try this one. Lucky number five. How does it look? I see command in and logging. Is that what we want? Configuration. Yes. Configuration class. Okay. Yes. That's a configuration. All right. So what we're going to do here, we're going to take a quick look. Hopefully people can see the microscopic size here of the command line arguments that we've added in over the past little while. So essentially we tell it where the broker lives, which for me is at 192.168.2.221, which for the moment is a Linux box. Port 5672 is our standard MQP 1.0. Are you showing us a file editor? So you don't actually see the window it pops up in the selected screen, of course. Let me dump it in chat for anybody who's actually on the screen. Maybe that's a better way to do it. Sure. So here's our very straightforward arguments. So the one thing that's been added here, if anybody's been following along, on the end, we have this new item, force multiplier. So one of the things that we know. Can you highlight that in the code itself? I can. So for those who might be watching this later who can't see the chat, basically these arguments can all be passed in via hyphenated command line arcs. Right. Exactly. Sorry. So go ahead with the force multiplier. Okay. So I'm just going to get to exactly where it is located with regards to parsing. So it looks like this on the command line. And so what we realized really early on is that we have a bit of a disconnect between what we had in the past, which was like a direct mapping between either sticks or keyboard being minus one to one in the X and Y directions. And the forces as being applied to the physics simulation and the masses and stuff that our ships are going to represent. So in testing, obviously, getting a nice update and test again, loop in development is obviously a good thing to do. So add it into the command line. So when you run the server, you don't actually have to recompile it for testing purposes. So we have this currently set to 300,000, which gives us a nice movement rate. I'm just going to. Yeah. And if I remember correctly, that was Newton's or something. Yeah. Pound kilogram meters per second or something like that. Correct. Yep. Yeah, I don't remember. Probably either Newton or something. I'm pulling up the notes that we had last time. Newton meters per second or something like that. Yeah. No, it's kilogram meters per second. There we go. So essentially. Oh, you have 300,000? I have written down 3 million, whatever. It's close enough. Yeah. So for the moment, that's what we have that actually gives you a sensible movement rate on the screen. So I'm pretty sure if I bring this into my screen, you're not going to see the update. Basically, I have a broker up and running on this 2.221 IP, which of course, nobody sees. I'll just see if I can do new or you can do new share. Let's see what happens. There you go. I still have. I think the numbers we had decided on last time, we had kind of started ballparking some things based around, you know, the quote unquote size of the ships, ships themselves are 300 meters and they move at about 300 meters a second, a full ship length in a second. Right. And I don't recall if the sizes and the mass of the ships has been updated. So what will happen with Box2D is if you put it in. I don't think any code got written to associate anything other than the default mass of the object. Yeah. And so essentially, by default mass, it goes by whatever size you put in, which didn't necessarily take our design choices into account at that point, right? But at least... Right. And design choices are all guidelines anyway. Like when you're building out a game, it's good to have enough feel for the numbers that you can talk about the designs without needing to go to the game. You can put it up on a whiteboard or on a piece of paper and talk to people. But once you get into the game, right, like no plan survives the real world, right? And that's kind of the same thing that's true with any video game. Are you trying to make a Mike Tyson quote? Drink my coffee. All right. So... Everyone's got a plan until they get punched in the face. What you may see here is the new AMQ broker that we're running was released in the fall, 7-8-1, which is based on the upstream active AMQ Artemis 216. One of the things that's nice about this one is that there's an updated GUI and a console. So this obviously is the text interface. And if we... What I'll do here really quickly, I will run the game server and I think you'll see... We're still just seeing the logs. Yeah. But I think you'll see it in the log in a second. So I'm running the game server now through the original GUI. The game server or the client? The game server. And you can see here that there wasn't an update. I thought there would be an update here on the log screen. Let me just quickly switch back and quickly show the log screen. So from the game server's point of view, it's now running through the C++ IDC line. Yes, we see that again. There's the log. And so one of the things in the... It is indeed very hard to read. And one of the things that we identified in the past was that I couldn't find the key combination to increase this very readily. Let's try that. Oh, yeah, baby. That's huge. So that works better for the code, right? Didn't make the log much bigger yet. Oh, look at that. There we go. Wow. All right. So put the spectacles away. All right. So this should be better for the logging, at least. Yeah, dude, that's great. And so the logging is set to one bump above the lowest, which basically means it kind of tells us the basic stuff like... The verbosity level. The verbosity level, correct. Right, okay. Because we're talking about size. Yes, right. To these basic AMQ people, primary key. Yes. So essentially in the last stream, we realized that by default on Mac in C-Lion, the scrolling capability to increase and decrease the font size is disabled. So I had to go through the configuration, find it and re-enable it. Okay. So people can see. So that's good. So all we're saying here is that, hey, there is a game server and it's connected to the broker as far as it's concerned. And things that are of concern for us are the command in, where commands come from, from the client in game event that where we spew our simulation updates essentially, right? So very quickly here. And from a lower level technical perspective, those are queues on the AMQP broker? Right. So the command dot in is a queue because it's between one producer and one client or one consumer. And in the case of game event out, it is a multicast address or what would be in the past called a topic, which is has a published subscribe mechanism. So you have one publisher, or maybe multiple publishers potentially publishing to one place. And then it goes outward to all the consumers. So like it's an end in kind of relationship. Got it. Yeah. And so conceivably in the future, if we had some intelligence where, or I should say, once we externalize game state into the data grid, any server could potentially process any incoming command and then send it to the appropriate client to let that client know what happened. Right. And in the multi service world, I mean, you could split that up, you could chart it. I mean, you have some flexibility then at that point, basically how you want to handle your load, right? Yeah. So in the new GUI for the broker, this is what it looks like. We can see that we have the address for command.in. It's a queue. That looks way better than the old one. Yeah, based on pattern fly. Yeah. Which some of us would know something about not me, of course. Yeah. Other than this guy. Yeah, that's right. So essentially here we have our command.in. We've done nothing with it at this point and we have our game event that outright. So the question is, what happens when we start a client, right? So give me one second and I'll spin up some clients and we can kind of show how that looks. Hey, Roddy, what happens when we spin up a client? We will be able to check the connected clients and producers. Let me get my key there. A little late, but we're talking. And see the traffic going back and forth, essentially, right? I'm just going to reload the client using npm and pop it up in browser now. Let me quickly turn off the music, which auto starts because I can't hear anything. I think that's the next configuration item we need to add. I'm always greatly distracted when the browser starts up and the music starts. Although it is a nice, spacey kind of ambient kind of tune. All right. So unlike my earlier attempt today, I'm going to use the arrow keys and not WASD. And we can see here now that I can move around the screen relatively well. It might take a second to reach you guys. But from my point of view, like it feels pretty good. If I hold down on the keys, I slow down kind of like in a physically simulated way. And I move around and I can basically use the keys and arrow keys to come to a stop. Right? Right now, we're not applying rotation force. We're just applying thrust in either the x or y. And so you saw that when Roddy hit the right arrow or whatever, the thing just moves to the right. It doesn't rotate or turn or do anything. And we're literally taking that force multiplier. We're multiplying it by the minus one plus one coming in either the x or the y direction and then moving either way, not no turn or rotation. Right? Not yet. Not yet. That's right. So let's just pop open a new client and see what happens. Okay, one more thing. I'm going to go back to the console first before I pop open the new client because there's some instructive stuff that happens there. We can see now, for example, that we have a command dot out with a very specific identifier tacked on the end. And so this is essentially how the server identifies a given client and send stuff back to it. Right? And we can see now that if we look at our game.event.out address, we have a multicast q, which really means it's a topic with a specific identifier, and we can check for connections. And we can see that at this point, we have three connections because I think there's one for the server and two for the client, maybe. And interestingly, you can drill down into the address. Let's go to game.event.out, for example, and go to attributes. And you can quickly scroll down and you can check whether or not this address is functioning properly. And you can see whether or not there's traffic flowing, whether those messages flowing through this address. And if we look here, we can see that there's been 8,366 messages and growing. And the number of messages acknowledged by the client is just a little tiny bit lower. And so I think the discrepancy here is because of the distance between when the server starts using the address and when the client starts consuming from it, right? But it gives you some very nice easy ways to grab statistics. Let's even get a chart here. I don't know if that works well here at the moment. We can see the timeline. Yeah, I don't know if that's working in my browser for the moment. So let me jump around one more second here. So that was the game.event.out. And what we'll do here now, we can see in my other browser window, I'm still floating around in space with my original spaceship still trying to use WASND to move. Everything is still okay here. I can move around. So let's start ourselves up a new client and join in and see what happens. It didn't work out very well. Try again. Get ready to mute. One more time. One more time. Okay, so now look at that. We have another player and I'll try with WASND again. So there's a good reason for that, though. I'm actually using, I switched my keyboard back and forth between using my mouse on my left hand side and my right hand side in order to reduce repetitive stress. So my Linux box has the mouse on the left hand side and my MacBook has the mouse on the right hand side. Oh gosh. And my left hand is resting on WASND. So sometimes I get a little confused. While I can get by pretty good for daily productive tasks, I don't know if I would want to take on anybody in a first person shooter using my left hand for the mouse. Traditionally, I've been right-handed. So I think I'd probably get beaten pretty handily. All right. So let's back in the day when we used to play Counter Strike at a near professional level. We had a couple of people, including myself, who would play left-handed to handicap ourselves just to give other people the fair shot. That would be a handicap if you're not used to it. Okay. So if we switch back and forth, I'm going to quickly speed up here and I can see that I'm pushing the other guy away and I switch back and I speed away and then I turn around and I go back the other way and we have a collision. So as far as we can tell, you can tell the bounding boxes are not quite right, but overall, the input is going where it's supposed to go in the server and the full loop is working with regards to the physics simulation. And getting back to the broker console part, we go back here now. We can see that there was a new command that out for the new consumer, which is a one-to-one relationship between the game server and the client. And we look at the multicast and we have another couple of addresses here. Another new couple of new identifiers for sending out the events to the given client. And of course, you can check your sizes and all that kind of stuff. So there's a lot of interesting stuff you can do here and there's a lot of ways you can drill down into this information to kind of ask the broker like, hey, what's going on? Like what's going on with the messages in a matter here? So by using the broker like right out of the gate. So like so far we've been pointing out like, hey, it's TCP right now. And so from a first person shooter perspective, that might be kind of sucky because of the headline blocking problem and the reliability it gives you. But by using the broker, for example, you get this nice GUI and you have all these statistics that you can drill into like kind of out of the box that like normally if you're writing your networking code, your net code from scratch, like you might have to write all this stuff from scratch too, right? So it's much better to focus on gameplay related stuff if we ignore that little, not so little headline blocking problem. Yeah. But at some point, I think, didn't you say that they're investigating making this work with UDP? Right, absolutely. So that brings me to my next point. If we look live on 2345. So the library that we've adopted here for AMQP 1.0 based on TCP called Cupid Proton in the upstream has developers as of right now working on raw UDP support for basically raw UDP in the library. Then the next step will be AMQP based on that raw UDP support. So that will be from the client's point of view. So when the client is UDP capable, you'd be able to do like peer to peer multiplayer UDP. And then you could do like a reliable UDP at the application level above that if you wanted, for example, or maybe you could integrate it with the lib quick to do like UDP into the browser, for example, because Chrome has really great quick support now. Because the way we work in getting our TCP traffic into a browser is that it goes through web sockets. And web sockets is like a, it's a web browser based implementation and standard for delivering TCP traffic into the more restrictive browser environment, right? So Chrome and Google in particular have been working on ways to speed up traffic for browsers. And they invented this new quick protocol, which basically uses UDP to deliver traffic into the browser. So HTTP three, for example, will be based on this new quick protocol, and it's going to be standardized by the IETF. So like, we're basing our assumptions here on the fact that we're open, we're using open standards, you know, it's not everything we want it to be from a gameplay perspective. But there's some legs here and some potential to grow. Roddy, can I ask a question about the quick support? Sure thing. Once the web socket connection is started up, once it's initialized, it's not HTTP anymore. So, right, is quick support going to have any impact on like web socket support for AMQ or I assume it will be an alternative. Like right now, like we have a WS colon slash slash to specifically say, hey, we're not just doing TCP, we're actually really doing web socket. And like, I think the next step we're going to get like, hey, we can do UDP. And then, okay, well, we want to do UDP into the browser. And the way to do that will be quick. So maybe we'll have quick colon slash slash browser IP colon port, for example, that's just the way I envision it going. Like right now, the discussions are still pretty early, like at least within my team in messaging engineering, of how this is all going to play out. But like one of the there's a couple of things that quick gives you that are really beneficial. So one of the design goals of quick as a protocol was to use UDP to get around the headline blocking problem. And to kind of like build upon all these years of experience we have in understanding what we can do from a protocol point of view at the application layer, because there's so much hardware out there that has TCP in it, like, you can't just say, well, let's just invent a new protocol. And we're going to deploy all new hardware all over the world. And we've seen how that went with the IPv4 IPv6 rollout, right? Like IPv6 has taken a huge, huge amount of time to become standard and commonplace. So they went back to the drawing board and they were like, how can we build upon our current infrastructure and still tackle the problems we want to tackle that we have today that we didn't have when, you know, TCP and UDP were invented, right? So two things they want to tackle was mobility challenges. So for example, one thing the TCP is bad at is because it's connection oriented is mobile, right? So you're on a phone, you're driving down the highway, you go and tower to tower. And TCP doesn't like that very much. Like if you look at how the broker would handle that, like it doesn't think connections are ever going to be dropped because TCP is reliable, right? So then how does that address translate as you move like tower to tower to tower? So that assumption's basically off the table. And then the other thing obviously is speed, right? Because TCP introduces a bunch of overhead. So like just to set up an encrypted connection, there's like three round trips. So your total round trip time before you can ever even do anything is all those three round trips for TCP, including the headline blocking problem. So like that's why when you bring up your browser sometime and you're like, Hey, I just want to write this page. And you look down the bottom left somewhere. And like it's trying to host. Yeah, getting image from XYZ, checking TLS connection to, you know, ABC, right? Like there's a bunch of stuff that happens. And if all that stuff has to be connected and there are multiple connections that are encrypted, there's like this three round trip thing that happens every single time, right? So you're really slow getting out of the gate. So one of the other things they did is make it zero round trip time. So as soon as it sends the first packet, it assumes it's going to get encrypted connection, right? And so it does some stuff in the background to assume to make that assumption work. And the clients have to do some extra legwork to make that assumption work. But if all goes well, you've skipped the line. You've skipped ahead three full back and forth communications, right? So that you can get connected quicker. And you can go, because it's not connection and address oriented, or it's not connection oriented, then you can do hops on mobile much more quickly and much more easily. So it helps to solve some of these problems that we currently don't have good solutions for. That really we're like, well, hey, you know, this is the way TCP was designed. We're just going to live with it because all the hardware out there, all that infrastructure can't replace it all. You know what I mean? We've built on it for like 40, 50, a lot more than that. It's late 60s ARPANET, right? So we've built on it. Yeah, as you're saying, this is all stuff that quick is bringing to the table. That's right. Exactly. So by going to UDP, so we get AMQP 1.0 is like an ISO standard, really great. Quick, also going to be an IETF standard. It's going to be the basis for HTTP3. Google already has a great implementation. There's a bunch of other companies with implementations. Like what will happen probably from a KUPA proton point of view is that will be like, hey, we've got KUPA proton. Does TCP with those UDP in the case of using proton with WebSocket, we use it together with Lib WebSocket to do QPT dispatch, which is an AMQP based router. But what will probably happen is that for quick, like there's going to be a lib quick, there's a couple of them now. I don't know which ones are necessarily the standard best ones to use. Which one will win? Which one will win? You know what I mean? It'll become ubiquitous open on the standard. We'll probably have like QPT proton configured for using UDP, use lib quick, put those together, and then build on top of that for QPT dispatch. And then in the case of the broker, this broker in particular is written in Java based on OpenJDK. So they'll have their own solution to doing UDP as well as quick and all that kind of stuff. But like the whole ecosystem has to evolve together basically to make it all happen. Do you, we've got Tony TV in the chat asking about like where the lib quick stuff is? Yeah, I can get those links out. I'll just, yep, just let me dig out the links. But I mean, if you've ever wondered how bleeding edge video game stuff is, we also had a question from Panic Maven. They were asking a question I think we had answered it in our first or second stream about, you know, why all of this and not like WebRTC or something like that. So certainly WebRTC is another standard for real-time communications hence WebRTC. And there are solutions out there to use WebRTC. But I guess you have to kind of consider the angle we're coming at the problem from, right? So we're on OpenShift TV and we're anticipating deployment to OpenShift. And OpenShift TV is Red Hat OpenShift TV. So part of our mission and our mandate here is to envision the Red Hat portfolio, how to use it in the best light for the game industry to solve some game development-related problems. And so like in my case, I take, you know, the Red Hat back there and I put it on like as a messaging engineer and I look at my background and I say, how can all this work I've done in messaging for the enterprise space? And as we can see it brings some nice tooling and nice technologies along with it. How can we apply that to the problems that game developers face, right? So it's not that WebRTC was necessarily a bad choice, it's probably a really good choice. It just so happens that it doesn't necessarily fit inside the, it's not in the toolbox of the things we're bringing to the table with our, with our Red Hat fedoras on our head and me as my messaging engineer hat on my head. So it's just this gives me a chance to be a little preachy too. When you're doing game development, I've known a ton of people to compare the process to, you know, you're driving a car down the road, but you're also building the car at the same time. And one of the things that tends to happen when you're building the cars, you don't need a dash, you can look out the window and see how fast you're going. And you can look down the road and see where the bumps are. And it's totally going to be fine, except you didn't build the steering wheel yet. And so a lot of times the things like the dashboard kind of come in last where you're like, oh yeah, this is our actual miles per hour. And wow, the miles per gallon we're getting is really terrible. And yes, like premature optimization is the root of all evil. That's a quote from Don Nuth. But honestly, like when you're building a game engine and you don't have those dashboards, you don't have those cool visualizations and that sort of interesting info, it's really easy to miss something like a pothole coming up where you just like slam full force into it. And you're like, oh God, we did not identify this problem. Whereas if you're using existing toolkits, like especially like a lot of this stuff, we get out of the box with red hat products and technologies. You already have all that stuff built in. And it's a lot easier to see those, you know, red flags coming up and go, okay, we should pay attention to this. We don't need to go optimize the code for it yet. We don't need to go spend a ton of time on it. But we're aware that this could be a potential issue. So when you start encountering some more warning signs, you know where to focus your development time and energy and effort, and you don't, you know, blow past your launch date by eight months or something like that. What when when you were just talking, Derek, I was thinking like, oh, I wonder if we can instrument the game server with Yeager to like traces through the game server. And so sure enough, there's like C++ Yeager libraries. Yeah. And actually, like the folks who work on the Kube proton have invested in doing some work on Yeager as well. Yeah. And I think it would be, it would be super neat to be able to see like the message come into the open shift environment, you know, and then into the game server and then like out to the data grid and then some other like server picks it up and then goes out like that'd be super neat to be able to see like that trace path. One of the things that I love to talk about, and I think we have a little bit of time today that I never get to is lossless versus lossy data streams. And it's something that's kind of not normally talked about in the, you know, era of web, because everything's TCP pretty much. And so that's lossless. And so if you ask for an image, eventually you get the whole image. But for a lot of the things in game development, you don't need lossless. Like if you get an image or a texture or something from a server, it doesn't necessarily have to be lossless. Like if you think about your eyes and the way they perceive things, your brain fills in a lot of gaps very quickly. So stuff in the real world doesn't have to actually match up to what's going on in your head at all for you to get the picture of what's happening. And so, you know, we run into this, this situation where we're kind of like real time streaming a lot of data in a lossless manner. But even then it gets displayed in a lossy manner because we're doing things like blurring it and post-processing and adding motion blur and all this stuff. And so we're wasting tons of bandwidth and, you know, even a lot of time and latency trying to deliver assets in a perfectly lossless manner because that's how humans like to do things. It's simple and easy when really like, it shouldn't matter, right? We should throw as much texture as you can potentially get. And whatever you get, you get, right? And you can run AI on the client side to regenerate those missing portions, or you can even use shader tricks to recreate some of that data. And that's something that's not really discussed right now because there's not a lot of research that's done into it. And there are definitely places on the web where it makes a lot of sense, right? Like if you're watching a movie on YouTube, you actually don't need that whole compressed data stream. You only need enough to like fill in enough of the blanks, right? And so Netflix actually has compression formats that they use that do that hack, right? They understand like how the human brain perceives an image and then discards a lot of that data. And some of it doesn't even need to get sent over the network for it to be a final result that you can enjoy. It's funny as you're talking about this, I'm thinking about two things. So one, I'm thinking about member dithering from back in the day where like images would like sort of come in and random, whatever's and eventually, we're smarter about it. Yeah. But the other thing that I was thinking about is like, we were talking earlier way early in one of the early streams about, you know, just sending updates and not necessarily the new like the whole state of the game again to the client. Yeah. And so as you're talking about video streaming, I'm like, yeah, like if you're watching like if you're watching this stream right now, we have four video streams, but 60 plus percent of each of our streams is pixels that are never changing. Like Roddy's door isn't going to move anytime soon. So why would I send the whole frame if the book is still in the same place? Like, so that's how video compression works, right? Yeah, totally. And so so it's just interesting. But like that's how video compression works. But even then it's like, well, is there something else we could have done other than just like wrote compression to reduce the amount of stuff that we want to send? I don't know. Well, yes. And then that's kind of the next step in that portion is like, you know, if you're sending a key frame, right? Like someone's head moves, you know, you're sending that whole key frame of like all of those data changes. You don't even need to send that. I mean, you could send like a partial key frame and just like a little annotation that says that's someone's head, right? And an AI program on the receiving end could go, okay, I know what human heads look like when they move and just redraw all of that space and fill it in kind of like what our brains do. And so video games actually use this quite a bit to save on data and help with latency for things like movement or, you know, ability usage, right? Like, and you'll notice like if you have a really bad network hiccup, you might see a player character, you know, they're running in one direction and then jump. Well, what happened there isn't that they were running and then, you know, jumped or something like that. It's that they started running in that direction that player changed what they were doing. And the server just dropped that data, right? Like the connection didn't show up or the packet got lost or, you know, whatever. Yeah, you have an AI program until it found out it was wrong. Yeah. And I mean, like, obviously I'm oversimplifying it's not AI, but that's just a generic term we can throw in anything with predictive logic these days. So I mean, that type of manipulation in data stream handling can happen on almost any avenue, it doesn't need to be limited to client side prediction and game development. You can do it with like I was saying, like textures with models with any bits of data where the human brain is allowed to do interpolation or you could have, you know, some sort of client side software doing interpolation, you don't have to send that over the network. And that's, you know, it might be in the area of over optimization, right? It's easier to just send a zip file to a client and be like, well, you have everything's fine, you know, but there's definitely a lot of opportunity to talk about some of the crazier things that we could do. I mean, could you stream a bunch of 4k videos inside a video game engine? Theoretically, yes. I mean, the bandwidth isn't possible right now. But if you employ some of these technologies and some of these tools that let us recreate data client side without needing the entire picture, all of a sudden, we could do crazy stuff like that. I'm not sure why we'd want to, but that's never stopped us before. Sorry, I totally do not mean to like derail the conversation, but it's one of those cool things where like there's there's a lot of limitless potential here for really crazy, weird stuff to play around with. And it's one of those things where, you know, technology inspires the art, art inspires technology. You get to this vicious cycle of development where you can have crazy things happen and make some really unique and interesting aspects of gameplay. Yeah. Let's see. So we talked about the new server stuff. So I guess where do we want to go now? Maybe do we want to try and hack some code in to actually be applying rotation or switch to using the mass bodies or like what, where we at at this point, I guess. Let's cover for a minute the client improvements that Jared made since the last stream. Yeah. I don't know, Roddy, if you're able to show and or talk to those or Michael, if you can show and or talk to those. I have not seen them. I've only heard of them. Well, I've seen them because they were they were demoed previously when Roddy, let me find the right window here. So I pop open the client code and I can only speak just barely to the client code because in this case, I didn't work on it other than today to try to figure out my misunderstanding between using WST and the arrow keys. It's always nice when you dig in and it's actually a simple problem and you don't need to go right new code to fix it. Yeah. Yeah. That's my problem for not writing documentation. Well, likewise. All right. So let me quickly see if I can share and find the right one. Number four. That's top four. One, two, three, four. All right. So Sea Lion create cursor keys. This one should be did I get Sea Lion or did I get SRT web client? I got Sea Lion main scene JS. Oh, okay. It is SRT web client. It's just that the the editor looks identical because it's WebStorm, right? So it's another one of the jet brains, IDEs. Yeah. Yeah. No. Okay. So we're looking at the JavaScript for main scene.js here. Yeah. So Michael may be actually able to talk to the JavaScript side better, but essentially Jared, who's not able to make it here today, he took a full pass on the client side and what we had before we had an index.html with a bunch of JavaScript thrown in more or less. Yeah. That's kind of where we were, right? So he took it and he broke it down into a sensible Java, like I guess would you call it a single page application? Michael, is that how you would describe what it is? You could get away with calling it that. Usually single page application is kind of indirectly referring to sub paths always routing back to the same applications. So if we went to the space ring things and let's say there was a configuration menu, we might want to expose that under the URL path slash config. So if you go to slash config, it automatically pops up the configuration menu, but it's still the same game underneath. It's the same index.html and the same JavaScript running. It's just sort of using the URL path instead of routing it to different files. It's just routing it to different states of the application. And we're not exactly doing that, but it's still a single page. So I'll allow it. Yeah. And so initially most of the work or a lot of the work that Jared was trying to do is as you described, like break it up into more modular components. And then we attempted to kind of go the typescript route, but ended up fighting with a bunch of stuff and Jared was trying to do it very quickly. So we abandoned it temporarily, but there's a goal maybe to try and go the typescript route with this thing. Yeah, it's like I'm looking through the diffs myself. It looks like he added an abstraction over the message. There's a send move function. Yes, right here. That gets throttled actually. Oh yeah, that's nice. So I assume if you're holding the key down, you don't wind up spamming the server with a trillion messages. Right, which is the nice comment that's right above there. Like why send move requests to the server faster than the server's going. Exactly. Although technically I think this is faster than the game client because how would how does the game client know that tick because we're using we're using a game engine to do the rendering here. And so Phaser has its own sort of tick rate loop rate. And so I'm not sure that that comment is accurate. Well, what's the tick rate on the server? It could be anything and it's not and the client doesn't know it. So maybe that's a case of where we need to enable the server to inform the client of the tick rate with the tick rate is. Yeah, right. And for those that aren't really familiar with tick rates and games, there's a pretty famous example of you've ever played the Elder Scroll Skyrim or any of the Bethesda creation engine games like Fallout, all of their game resource handling and all of their like world logic happens in the gameplay loop and it's based on your frame rate, which is tagged to 30 FPS on consoles and 60 FPS on computers, which means the fastest the game can do anything is that 60 Hertz, which includes physics and loading textures and models and doing gameplay simulation, everything. So if your frame rate, like if you go into the config and change that it changes the entire way the game works, which includes like breaking your physics, which there's plenty of hilarious videos on on YouTube. So when you're building game engines, right, that's kind of like a fundamental thing nowadays, when you're building like a modern game engine to separate out your tick rates, the Hertz at which you're processing things into different threads. So your frame rate, you know, the graphics updates are running at a different Hertz than what you're processing physics at, which you're loading models at that sort of thing. Yeah, and that that's that is that is nice. That's something that I've kind of struggled with writing games is trying to reconcile that trying to get the physics loop running fast enough so that you don't have, well, I've tried to write like collision detection that runs fast enough that if whatever the maximum speed of an object is, if it hits another object, there's no point where it can wind up overshooting and overlap the objects and kind of get stuck. But it's tough. It's it's a challenging thing. Yeah, it is really writing a good physics engine is hard. Oh, yeah, I've tried. One of the things that one of the things that I've done in the past, which you know, people look at you like you're crazy and they're like, wait a minute, this might actually work is instead of running one physics engine at an extremely fast Hertz, especially for where you have like objects or projectiles are traveling very quickly, you run two physics engines at the same time, one of them is a one step ahead. And then you know, I used to call this like quantum, even though it's nothing to do with it, it's just the fact that you're running two things at the same time, but quantum physics simulation. And what you do is you interpolate between the two states. And you say if at any point in here, it breaks like the physics engine, then we're going to resolve to the prior state and consider it a collision. And basically, it's like you're running like a simulation of what things will happen next and using that to inform how your simulation resolves currently. And that sounds crazy expensive. But when you're running like a physics engine, two of them only at like, you know, 15 Hertz or something like that, instead of one of them at like 90 or 120 Hertz, you actually have some performance gains on that. But it only really works in that scenario, where you have things that are moving like super fast and you're trying to resolve collisions where it's like super fast on this side of the map relative to the tick rate. Yeah. So, you know, things like spaceships flying throughout a solar system at near sub light speeds. Like that's a good use for that where you have a predictive physics engine informing what's actually happening and being like, hey, you know, some stuff broke. So you have to stop the simulation there, register a collision before it actually happens. Another thing on frame rates that I learned recently. So I got my first high frame rate monitor, maybe three months. And I was like, wow, the mouse is so smooth. Look at it move super smooth. And then I loaded up a game that Jared and I built Zorbio that we've talked about on stream, we've actually had the game on stream getting it running on OpenShift. So I load up that game to web based game. And I start playing it like, wow, this game, it's so smooth at 144 Hertz. This is incredible. And then like a month later, I find out that request animation frame, which is the function you call in a web browser to get a frame rate locked callback to basically to run something that's v-synced is one way to put it. It's how you animate things. I find out you can't go higher than 60. So I was looking at 60 Hertz and thinking this is so smooth. It's couldn't tell. So that's an interesting takeaway is that you at the moment in web browsers, you cannot go higher than 60 Hertz. Well, and there are ways around that actually. I think with canvas, right? There's a way to get around it. Well, you can draw faster. You've always been able to draw faster just with a set interval. You can go down to like every millisecond or something if you want. It's just a little inconsistent because that interval isn't... They're not evenly spaced. When your function gets called, it's not evenly spaced. Request animation frame is the only way to do smooth animations because it's locked to your monitor's frame rate, except in the case of having greater than 60. So yeah, you can draw things faster, but you're going to get tearing and you're going to get jitter. Yeah, that's definitely true. And there's... I swear there was a... I don't know. There was something that when I had originally messed with like HTML canvas, 3D sort of thing where you're not using a request animation frame, but you're essentially requiring a 3D hardware acceleration. There's a way to do that. And I think even like shader toy or something like that uses that hack to let you get above 60 frames per second. But yeah, I don't know if it's something that's shippable right now for a game on the screen, but to your point about feeling that it's smoother. So it actually... Even if the animation itself isn't updating more than 60 frames a second, that monitor... Anything that displays on that monitor will likely appear smoother just because it's less rough on your eyes. Like if you've ever gone into Home Depot, especially in like the 90s and like gotten a headache from the overhead lighting, you know, or any like home supply store that uses like mass manufactured CFLs, that's because that lighting is like running at like 40 hertz or something absurdly slow. And so it's flickering, you know, 40 times a second and your brain is like, oh, God, I have to make up so much information and you get a headache from it. It's not everybody that experiences this, but for some people, right? And the same thing can be said with computer monitors, you know, like I can very easily see the difference between a 240 hertz or a 600 hertz monitor versus a 60 hertz one. But I'm also someone... If I walk into like a looser Home Depot or even like a McDonald's that hasn't been updated in a while, I immediately get a headache. So it is pretty different for a person, but it is something that the human eye can notice. And I think it's somewhere up to 4,000 hertz, your brain can register a difference, but only with a certain amount of like lumens difference between the on and off states of the hertz. So lots of interesting things to like kind of be aware of and play around with how the human eye and human brain interprets light, essentially. Who knew? Who knew? This guy knew because he got really nerdy and did a lot of research. Zerati, you've been highlighting this code block of sending the move. Yeah, I was just giving a brief overview there of essentially what's going on. I mean, you can see if you take a quick look through, like the code is really nicely structured. There's constructors in place. It very much maps with like my game dev view of like an update loop and having this end move separate and all the stuff that you kind of expect to see. And then you look at the way the scenes are broke down, like coming from like a unity background, for example, that probably is like an easy thing to crack or even good though. So I think we don't have much right now in the way of scenes anyway. That's right. Exactly. But I think overall, like it's just it's just very it's very cleanly coded. It's nicely structured. It gives us a really great base to build upon versus like our original stuff, which was like, Hey, let's get this stuff working and let's throw all this code in here and like the crap out of it. And then it was like it got to the point where work. And then Jared was like, Hey, I see that that works. Let's take that and turn that into like make it clean. You know, so she had definitely a good job there. Roddy, I don't know if you've looked at this code much more than I have, but do you know where the client smoothing code is? Because I believe Jared added some some interpolation of of the server messages to smooth out the client motion. Simple linear interpolation to smooth that position updates. Yeah. So it says if the player has no group object create one physics groups. Well, the second thing looks like the interpolation. Yep. And so it just basically uses the linear interpolation from the phasor math library but looks at it. But what is it doing? So it calculates the new X and Y position and then interpolates. Basically using an argument and saying, Hey, here's the position that we have currently. Here's the position that the server is saying increment along that path. And in game development, essentially there's two ways that you want to do interpolation. There's linear interpolation and then there's spherical linear interpolation. And all that really means is a direct line to the point you're going to, or essentially you're going to have an arc between the two points. Spherical looks better, but it also requires a lot more finessing to make it look good. So linear is going to be our best option for now, for sure. Yeah. Like one of the things we could do here, like if we had the right information, you could like calculate your latency. And based on your latency, you could decide how much of an interpolation you're going to use, that kind of thing. Yeah. And so looking at that, I'm guessing that's 0.3 seconds, 300. I would have said T. So it's 0.3 from zero to 1.0. 30% of the way, essentially. So based on latency, the client will always be 60, 70% behind of whatever the latency number is. Yeah. Which for competitive FPS, that's terrible. And in fact, that's why you predict where the player will be. So the current position is always what the server says. And then you have predictions. And then you linear, spherical linear interpolate between the two for like an RTS or this type of strategy game. It's okay for things to be 30% of half a millisecond behind, right? Like it's, it's whatever. Got it. Very cool. So I would have made the text bigger, but of course, the default configuration in this IDE is also not to have the scroll wheel to do text size increasing. All right. So I'll just go ahead and stop sharing here. Well, no, I think we wanted to talk about. So last week, we had explored a little bit in box 3D about how to assign a mass to the objects and change the like the type of object that it was, because we were doing one type. And there's actually other types. And so maybe it's time to actually build some of that code. Yeah. So let me think about, you know, doing rotation-y stuff with Phaser instead, like instead of having left, right, you know, so there were, there were a couple of things. So one was, you know, center of mass and where we apply force and sort of today, we're only applying force in the, well, the left and the right arrow keys are not applying rotational force. They're simply applying left and right force to the center of mass. And so we probably want to figure out how we're going to do rotational force instead of left and right to center of mass and then also figure out, you know, once we start strapping things onto our ship, like how that's going to change the physics of the object and, you know, where we want to attach those things and so on and so forth. So it's a little bit of game design and a little bit of design element, if you will. Yeah. So like our limiting factor from like a server point of view at the moment is essentially we loop through the move queue and then literally we take them, like I said earlier, we take the x and the y and each x and y is between minus one and one. We take the configuration force multiplier and then we basically take that vector and we apply it to the center of the box 2D object, which is why we have like strictly this way, this way, and that's it, right. So one of the things I think Derek worked on was figuring out how our rotation is going to work with regards to gameplay. And so what we need to do there, I think, if my understanding is correct is determine the correct vector on the client side of where we are applying force to the body and send that vector to the server and apply it here, but it will no longer be applying it to the center, we will have to apply to a specific point. Is that right, Derek? Yeah. Sorry, go ahead, Derek. Well, so one of the things that a lot of space games do, especially modern ones, to help build out that like feel like when you're playing, you know, Elite Dangerous or Frontier or any of those or even, you know, wrote the new Star Wars Squadrons game, essentially they build out a realistic flight model and then they put an abstraction on top of that. So your controls are simplified and you can essentially, you know, put in your input the way you would expect any other video game to work. And then it translates that to a flight model. And so you get that like really nice feel to it. Now, I don't feel like we need to go something that complicated, you know, for essentially what is a mobile game. But I do like the idea of saying like, hey, you know, we have a force vector, it's the rear of the ship, it's where the engines are, you know, it's only going to cover that 180 degree angle of force. And so if you want to go, you know, backwards, essentially, you have to rotate the ship first. And that's a rule that the control logic, you know, come in is the only thing the ship should be concerned with. And the only thing the server should be concerned with is the thrust vector, you know, that's essentially being simulated against the engines for our spaceship. But on the player side, on the control side, we're going to be doing all that translation of, well, you want it to go left. So we're going to, you know, put in a thrust vector of this and send that to the server, or you want to rotate around like you're, you know, you're tapping behind the ship. So it needs to rotate. So we're going to send this thrust vector, whichever is, you know, the shortest distance to point. So and it sounds a little bit complicated. But honestly, like, that's the way that I've had personally the most success in building a simulation of like a vehicle that feels really nice, but is very simple and easy to control. And that's not having that direct one to one, like you tap left, it turns left, but rather, basically the player's communicating intent. And then we're translating that to what happens in the physics world. And from my point of view, that's a really great way to look at it, because the work on the server is less. We take the incoming vectors, we apply them as, as we're instructed. Hey, we've done our job. So yeah, and it's also a separation of concerns, right? Like most of your logic that has to deal with like what I like to call human BS, right, is on the client, because that's where the human is is on the client side. The server doesn't care about humans. It doesn't want to, you know, deal with people. That's, that's a client problem. And a lot of times when you're doing game development, you'd kind of run into this like scope problem where the human centric code is everywhere in the code base. And so when your players do stupid things, your code base does stupid things. But if you localize all of the logic that has to deal with, you know, your players into one place, it's a lot easier to handle. If you localize stupidity, I like that. It's going to be the name of my new podcast, localize stupidity. Or a band. Yeah, there you go. So it's a punk rock band, but we only play on keytar. It's only two words, so it can't be a ska band. Yeah, I can't. So I guess if I was to sort of unpack a little bit of what was said, so what we want to do is on the server side, simply accept a vector of force, and then on the client side, depending on the input device, calculate the vector of force to tell the server that we did. Is that a fair summary? Yeah, so one of the things that could happen that I could envision is, hey, we've blown up an enemy ship, we picked up a thruster, it happened to stick to whatever part of our ship. But from my point of view on the server, that's still simple because the vector will all be calculated before it's handed to the server, what the end effect of that is. Right, so there's two interesting things that you just said. So one is, we may be attaching a object to the body at an arbitrary location on the body, but all that does is impact center of gravity and physics calculations that are already hidden from us inside the physics engine of Box2D. The force vector that's applied, the client may need to do some math to figure out what that vector looks like, but because for example, if that was a thruster that we strapped on and now we have the standard thruster at the back and then this other one at a weird location on the ship, the client may need to say, okay, the resultant vector is blah. Or I need you, so we're actually also now changing the messaging structure. That's correct, yes. Because today the message for what's coming from the client doesn't do any of this. So we actually probably need to start at the message level with the ProtoBuff for sending, yeah, raw input, because what we're actually sending looks today like a PBVec. And there's only one, well there's two, there's one that's supposed to be moving, one that's supposed to be shoot, right? So that will change. Yeah, that's what I'm saying. So now the raw input coming from the client is potentially no longer a PBVec. Or if it is, then we have to do a lot more calculation on the client side to determine the vector that we then tell. And that's kind of what we're saying, right, is we're going to do that calculation on the client, right? Because the server lives in a very simple world of what is the control vector for the ship? And then it will translate that to the physics that's required to make that happen. Let's think about this, right? I'm not saying no, I'm just not understanding, so I'm trying to think through it like in real time. So if you have, and you know, it's hard without drawing something that everybody can see. But if you had a cylinder where there is thrust being applied from the back of the cylinder, and then some other weird thrust that's being applied to some arbitrary point, like between the two ends of the cylinder, from Box2D's perspective, you actually need to give it two vectors, not one, because there's a force that you're applying at zero comma 10, and then a force that you're applying at like one comma three. It's two distinct forces as opposed to one force vector being applied to the center of mass. Now, if we want to simplify everything, we could just always apply only one force to the center of mass, and then only one rotation to the end of the, regardless of where the thrusters are, and just sort of interpolate the thrusts at the client side always, as opposed to sending the individual forces. Does what I said make any sense? Yes, but I'm going to say let's do even less work, right? I think we should offload that work to the player, right? And that's a place where maybe there's artificial difficulty, maybe there's real difficulty, right? And that's a question to maybe solve later down the road. But it's something to be aware of is if you add a, you know, another thruster or weight or mass, or you change the way that the physics of the ship works as a player, how should that be affected with the game engine, right? And to me, like, the control structure shouldn't change, right? You keep it really simple. It's just a vector. No matter what, you're just saying the control vector, this is where I want the ship to go. Now, does that mean if you add a thruster that the we're not actually adding a physical additional point of thrust to the ship, what we're doing is incrementing, you know, the value of the base, you know, physics or something like that. So now the ship turns faster and goes faster. Is it an artificial, you know, addition? Or is it an actual physics addition? Regardless, I feel like the, like once we decide gameplay balance wise, which way to go, the problems should still have to be solved by the player. We shouldn't have the game engine adjust for that fact, you know, like having that difficulty of, oh, your ship's more unwieldy, right? Because when you tap here, instead of it turning how you expect, it turns faster. That should be, you know, an expected consequence. And in fact, that might be really good player feedback. When I add a thruster, my ship becomes harder to control, but it's faster. So it's interesting, you're sort of both agreeing with me and disagreeing with me. And so I'm going to try to paraphrase what you said a little bit. So if you think about a more classical flight sim, or like a racing game where you have a base level of control and let's assume the negative sort of situation, you have damaged your vehicle and now the handling is screwed up because the vehicle is damaged. So when you try to turn left, it turns left like way a lot. And when you try to turn right, it turns right like really badly, right? This is like classical race car, you know, kind of damage calculation stuff. So we're actually doing the opposite where we are adding handling performance to the vehicle, but we're not necessarily adding it equally in all directions. And so what you sort of we're describing is like, we could potentially make it more arcadey, where we don't care where this thing ends up attached to your vehicle, we're still going to apply the same forces in the same locations, we're just going to apply more of them. What I'm getting at is like, if you strap one thruster onto the left side of your spaceship, you're going to turn right really fast, but you're not going to turn left any faster. And the only way to make that work is either the client has to sort of do interpolated math to calculate the resultant single vector on the object, or we have to look at the fact that there's now two thrusters on this thing and apply the thruster, the one thrusters force and then apply the second thrusters force as two force vectors, every sort of game. Right. So we can do we can do one of two things, right? So we can do either, I don't care which it's just you know. So I guess the question is, are thrusters a special case of what we're going to do in general, right? Like in general, like if you look at the body as just a single unit, then calculating everything client side makes a lot of sense, right? But when you start picking up mass, do we still look at it as a single unit? Or do you want to physically simulate the breakdown? And each item then has its own properties, right? Because you can get into another level of detail where we say, like, well, there's a joint between this new thing that came along and it's stuck to the body. And we want to physically simulate that. And so just as you're saying, Eric, if it's a thruster, there's a point in a joint where that's connected. And because it's joined, it has a force. And through the joint, it applies the force to the original body. And that's all simulated all the way through, right? So like that's the my argument, my argument here is this should stay out of our proto buff. This is a gameplay feel and a gameplay balance question. And I think we should try both eventually, right to see which one feels better for the player, and which one kind of controls better and gives you more feedback. But in when we're talking about like the proto buff itself, we should just stick to that, you know, one vector of this is the control input from the spaceship. And then on the server, right, we should make sure we have a section of code that we can easily swap between the different models. So the I see where the where the disconnect is here. It's a it's a terminology disconnect, not actually a or like a perspective disconnect. So what you're saying is like, the client will only ever send the server. So if we think about an imaginary joystick inside the spaceship, ignore whatever the human interface is to the game. It could be a carrier pigeon, I don't care. But inside the spaceship, there is an imaginary joystick. And what Derek, it sounds like you're saying is the human interface device takes an input. And then figures out where the imaginary spaceship joystick is, and then sends that to the game server. And then the game server does whatever should happen based on the spaceship's imaginary joystick position. That's beautiful. I love that. Why didn't I think of that? Do we? Because you're because you're a perfect visualization, because I'm not in sales. That's why is that so I mean, is that a fair kind of assessment of what you were getting at? Yeah, absolutely. Okay, cool. Roddy, does that make sense too? Yes. Yeah. So now we're back to, yes, I agree with you, Derek. We do not have to change the protobuf. We don't have to change the messaging structure. We're going to take some scaled zero to one in both the X and the Y. That's the spaceship stick input position. And then, Roddy, to your point, however we implement the physics underneath, like, do we actually attach a new body with a joint? And, you know, then there's additional force applied scaled based on, you know, properties of that. So I think to your point also, Roddy, we may end up with keeping track of multiple things for the big body. So for example, like the main thruster, everybody starts with the same one. And then you fly around, you blow up some other bad people, you know, your opponents, whatever. And then suddenly you have an extra thruster that's attached to your thing. Now you have another thrust source that has to look at the input from the ship stick, if you will, and apply some proportional force based on its own properties. So you picked up the gold thruster as opposed to the platinum one. And the gold one only puts out, you know, 100,000 kilogram meter second force, whereas the platinum one is 200,000, you know, or something like that. And so we need to keep track of those things. I would say for the initial purposes of simplicity, like, we just need to change the numbers that the client's sending. We actually don't need to do anything different yet at the server side, slash physics level, right? Yeah. I mean, I'm just gonna go off on a tangent. So the next step after that, though, is like, once we implement the client side human input device to ship stick translation, then we get to the point of, okay, now what we want to do on the server side is change it so that left right on the ship stick is applying rotational force to the body, as opposed to currently where it only applies linear force in either the X or the Y. So the first simple change is just, you know, figure out the control scheme at the client level, and then send new numbers as opposed to negative one, the positive one, and then or a scaled number from zero to negative one to positive one on a linear scale as opposed to the on off where it is right now. And then the next step is to change it to add rotational force. That makes sense. So it's like kind of two, two pieces. Yeah, Roddy, I think so. So from a phaser perspective, now we're getting back to human interface. And since today, all we have is the web client, we probably need to figure out how in phaser to take the mouse click and calculate the ship stick from where you're clicking the mouse. Does that make sense? Exactly. Yeah. And this is the thing I had been talking about that I wanted to start working on and like I kind of wrote out the math, but I need to translate that to code. But yeah, just, you know, tapping mouse click or whatever, essentially you're just going to interpolate like that linear distance and say, you know, hey, this is how much force I'm going to request from the server in order to get the ship to move in this direction, right? Versus using like a controller, you might get more fine tune, you know, ability to control the ship. And should that be a problem? Probably not, right? Like if somebody really wants to go ham on how they're controlling your ship, I don't know that we should say no to that. As long as it checks out with the physics engine. Yeah. So I just had an idea for mouse control and you can tell me if you hated or not. So if you drew a ring around the, like a circle around the spaceship and you said any, if you click this, this also translates into cars because there's a thing called the physics circle where you only have a certain amount of traction in any direction, right? Forward, backwards, side to side. And so draw around the spaceship in your mind a circle and then take the mouse cursor. And if you click on the circle, that is the maximum that you, that's the farthest you could move the ship stick in that direction. So if the ship is pointed straight vertical and you click here, like at a perfect 45 degree angle from up and down, you are now maximum left thrust and maximum forward. And if you click right next to the ship, that's like almost zero. So as you, as you click in the circle, you're basically creating the vector of thrust application based on where you click. So it's super visual. You know exactly where the limit is and how far, so like if you click outside the circle, you're not going any faster. You're already past the maximum, you know, and then maybe there's even a trope of like, well, the more thrusters you have, like the bigger the circle gets, I don't know, right? But I think that's like a simple design element that gives direct feedback to the user on how the controls work. And so it's basically like you just move your finger around the ship inside that circle. And that's what's going to either turn you left or right or make you just go forward or backwards. I don't know, do you like that idea? Do you hate that idea? Absolutely. No, no, no. And in fact, so this, this gives me feet to like go on that tangent. I was talking about two minutes ago. But in a typical game developer studio, you will actually have dedicated engineers that are solving each one of these problems. So you will have a gameplay engineer who their only job is they're sitting there in Unity or Unreal or a version of the engine that you're working on. And all they're doing is iterating on the movement. They're trying to get the movement of the player character feeling right, feeling fun and engaging. So when the players interact with them, they're like, yeah, like I want to keep flying the ship because it's just fun to fly the ship. And you'll have somebody who's sitting there and they're just working with controllers and they're just working with, you know, keyboard and mouse and all the different inputs, prototyping out, you know, how that feels, how that interacts with the different movement system, things like that. So I mean, each one of these gameplay systems, right, like you'll have somebody like the most important thing is that player feedback, you know, the first step is you as a developer, right? Like, is this fun for me? And then you're going to go and play test that you're going to go grab your kids or, you know, family or coworkers and be like, hey, try this out. Does this feel really fun? So that's where like, you know, when you have an idea like that of like, hey, you know, if I tap and drag from the middle, right in this like this sphere, like we should be prototyping that we should be testing this out, you know, touching it and playing around with it and going, does this feel good? You know, and I can tell you from experience having played a lot of these games, that is a fantastic idea, right? And combining that with like tapping on the screen where you have like an automated, like it'll turn the ship for you automatically, you know, so you have that option of like tap and drag to manually kind of control the ship and like tweak everything, or just tapping on the screen, right? There's two different types of input mobile phones can detect that really easily. That's not something that's, you know, difficult to do would give players a lot of control and a decision between, do I have my finger on the ship and I'm like tweaking what's happening right now, because that's really important, or am I tapping somewhere because I need to move there and I need to bring up a menu and upgrade something real quick or whatnot, right? So what we're doing here by adding these types of controls that you're suggesting is giving player more agency and any chance to get the opportunity to do that without adding a complication is amazing. Like any additional free player agency is like kind of a holy grail of designing a control system. Yeah, I just wonder, so that from a movement perspective, that sounds easy, but now I'm thinking on a mobile device like, well then how would you target and fire? Huh? Well, you don't, right? This is a tap, tap to move, right? Click tap, but I'll say to certain degree. This is something, yeah, exactly. Well, within the circle, right? It would be kind of like a tap and drag, like you're, you know, essentially moving a joystick, right? But outside of that, if you're tapping like in the surrounding space, because your ship's going to, you know, only take up a small area on the screen, because you need to see other ships to know where they are and shoot them and that sort of thing, if you're tapping like behind that enemy ship, your ship should automatically rotate and try to move over in that direction versus you like manually controlling that to the movement, right? Yeah. And that makes a lot of sense, right? You know, do I want to manually control the ship? But it takes a lot of my attention and I'm not looking at what upgrades I have and where other players are, or do I want to just tap on the screen? But now my ship is going to, you know, move in a very predictable manner, which more important for me as a player. But to your question about targeting, so this is, this is something we'd kind of briefly discussed and then decided to like backlog and revisit, right? Was do we want to even allow players to target things? And my suggestion was like, no. Yeah, dumb. It's like, wherever the thing is, is strapped on, it's going to shoot however it shoots. And if you're not pointed in the right direction, when you fire too bad, right? So it's like, if you, that's your problem to solve is to get your ship oriented in a way that you can fire the weaponry so that the weapons actually hit something. Exactly. And it kind of brings into that like, I have limited space. I have a limited grid set on, you know, the spaceship frame that I have right now. If I go bigger, I'm easier to hit, but I can put more things on there like shield generators or whatever. But now my choice is, do I add missiles, which only fire to the side and then can arc away the farther away, you know, a target is, do I add only lasers, but lasers are short range, but they can hit any direction no matter what. Do I add a giant cannons, which only shoot forward, you know, and maybe instead I had a shield generator because I'm never going to attack somebody head on because I have a very flat and wide ship. These are the types of decisions that, you know, we can envision players making where, you know, hey, I literally have 30 seconds before I drop into the next arena. I just won the previous one. How do I upgrade and change my ship, you know, based on how other players are currently playing the game and how I'm kind of seeing the meta evolving where I can handle and win this next, you know, two minute round? Yeah. So to go back and paraphrase, it sounds like there is a desire among you all to have this, like, tap over here and the ship just tries to get there automatically. That almost seems like it makes the game. It certainly doesn't make the game too easy, but it seems like that's that seems like a weird design element for a very like seat of the pants strapped literally strapping things on to your ship. Kind of like it seems like too advanced of a control scheme. Well, they mean like oversimplified. Yeah, sort of like my vision is like you should have to control sort of thrust like you can you can go for you can apply forward and backward, you know, sort of around that circle. But if you what it sounded like you were saying is like, Oh, well, if I just click over here and hold outside the circle, the ship is just going to figure out how to get there. And it's like that that seems too simple. Well, actually, I really like that. And to me, we should prototype it right and see what feels better for a player. But I like that giving the player the choice of sure, like, especially if you have a smaller, maybe more agile ship with more thrusters, you know, and it's an advantageous to move very quickly to dodge missiles or something right versus a larger capital ship, where you're not going to be able to turn no matter what the important thing is you're blasting your way through all of the people who are stupidly flying headlong into you and not taking pot shots, you're going to spend your time upgrading, right? You're just going to like, there's a bunch of players over there, tap, bring up the menu and keep adding on that, you know, the additional whole items or whatever it is you're doing during combat. So you have that choice, like, do you want to be actively engaged in combat and dodging missiles? Or do you want to be focusing on, you know, like surviving whatever that battle is via your upgrades or power management or whatever, right? I like giving players choices that they feel are impactful to the way that they can win the game. We don't want to say, like, the only way to win the game is to be, you know, very agile with your thumb or something. Sure. I like your design tropes there. I think we do have to pick one to implement first. So if we're cool with the circle idea and like the mouse thing, I think, again, we're now back to like, maybe Michael, if you want to share your screen, since you're the phaser expert here today, and we can communally look through the phaser docs to figure out, like, how do we actually click on the screen with the mouse with phaser and have it do something? Yeah, I am. So we call it a virtual joystick. Does phaser have something in there for that? I think those are a virtual joystick. I can kind of fumble around and look for something. There's a game that Jared and I built called Pity About Earth that was... It does take joystick. Well, mouse cursor. Yeah. Game Jam game. And so it was like very short. It was just a weekend. Open jam. Later, we added virtual joystick. I believe that was phaser two, though, and there was a plug-in for phaser two that had a virtual joystick that was great for mobile. There is. They want five dollars for it. I'm sure there's another one that's probably free. Wait, fate. Can somebody share their screen and let's search altogether live on the stream instead of just talking about what we're doing in our browser? Can you guys hear me? Yes. Okay. Yep. Okay. All right. I will try to share. You are loud enough. Okay. Oh, wait. I think I put the wrong open jam in the chat. I totally did. Openjam.io. Yeah, definitely. Pity About Earth. Yes. Come on, zoom. There we go. See a terminal. Okay. And a really big screen. Great. So I'll see if I can bring up the one we were using just to, just as a really quick input. Let's see. Mouse. Oh, multi-touch. I guess multi-touch and mouse are similar. The other thing to note, accessibility-wise, as far as mobile games go, pretty much an accessibility requirement to have the joysticks, like invisible joysticks or whatever you call them, in the bottom right and bottom left of the screen, in addition to whatever on-screen controls you have, because there's plenty of people that have difficulty moving their fingers to the center of the screen. Well, that's the case where it's like... Yeah, but so then you get into this weird, like, okay, if this... I don't want to use the word term disabled, but like a person who's got a challenge with touching the center of the screen or whatever, like, well, if all they have is a joystick, then they don't get that sort of like, capital ship-esque touch over here and do other things kind of thing, because all they have is a joystick. So at that point, it's sort of there's a... I hate the word fair, because nothing in the world is fair. Like, there's this unfair input difference between the player who has an abilities challenge and the player who can tap anywhere on the screen. And so if we want to have the virtual joystick, then we should probably just have the virtual joystick and call it a day and make that be the only input. I think it would be weird that, like, hey, here's the virtual joystick for somebody who can't use this great touch on the screen, but like you're screwed compared to the people who can touch on the screen. So like you can play it, but you're at a huge disadvantage. I am not an accessibility expert, but I spend a lot of time talking with and working with accessibility experts. And you're kind of falling into some of the common tropes there. Accessibility is not about limiting everybody to the capabilities of a single type of input or person, right, or about fairness. What it is about is making affordances for people who do have disabilities, which is not a bad word, right? Disability is a word that describes exactly what it's about. And it's not something you should feel guilty or, you know, bad about saying, especially, you know, on a type of stream where accessibility is a topic we're going to cover. And it's something that's very important, I think, to all of us. But what it's more about is providing those options and opportunities for people who are differently able to be able to participate in the same environment. And they're not going to ask for it to be fair, and they're not going to ask for it to be, you know, specifically designed to accommodate, you know, the essentially minimum type of input, right? They're asking for is customization options and awareness, right? And as long as what you're doing is kind of covering your bases there and making sure that there's multiple different ways to approach the problem, because each person is different, right? No two people, even with a similar disability, are going to have the same exact experience. If you're building in those accommodations, right, then what you're doing is being responsible. So it's really, it's kind of a misnomer to say like being accessible is restricting gameplay to a, you know, very simple input, right? It is about that customization and that awareness. And that's what's really important. And the best thing that we can do about this is not make those decisions ourselves, but go to accessibility experts and go to people who have the disabilities that we're going to accommodate and get their input instead, right? Like we don't get to make that determination they do. Okay. I'm going to get off my high horse here now. So Michael, you are showing us. Yeah. So this is, I think this isn't something we could actually use, but maybe it'll be a good place to start the, or continue the conversation about virtual joysticks. So this is a game that Jared and I made written in phaser two. And this was a virtual joystick plugin. So I don't know if you can see my like touch cursor. It's right above the earth. It's very faint. It's very faint. Yeah, but I see it. So the way this virtual joystick works is it doesn't have a fixed origin anywhere on the page. It's as soon as you put your finger down, it appears. And as you drag, it goes out and it has this maximum, you see these three smaller circles that you can kind of see them pulling them in different directions. And as I pull them, you can see the barrier around the earth moves with them. So the idea here is that wherever you put your thumb down, which would probably, if you're holding the phone with one hand, it'll probably be around here. You can put it down and that's your origin point. And then you can drag to different sides to control the, the direction. And this game doesn't have a velocity or anything. So there's no magnitude considered here, but you can see the joystick has a magnitude as these smaller circles expand outward and then it has a maximum magnitude where I can't stretch them out any farther. So that sounds like something pretty close. Were you guys imagining that the, the control circle would be placed directly on top of the ship or? Yeah, I was. Yeah. And like your thumb is going to be blocking the view of the ship. Well, your index finger, right? Like, and your primary means of input with this game is going to be movement only, right? Like we don't have any sort of weapons, controls or anything like that. That's all automatic. So you're either moving the ship or upgrading the ship, right? Those are the two essential things that you're doing. To me, like I said, for, you know, accessibility purposes, as well as giving the player a lot of choice about the way they interact with the game, we should also support, you know, an option, like a check a box or something. And then the joystick is just permanently in the bottom left hand or bottom right hand corner or something, right? Like those are options. But for now, as far as like basic implementation, I think putting a virtual joystick smack on top of the, you know, the spaceship, right, is an easy way to get rolling with the control options. Yeah. Yeah. I like the idea of being able to move it so that it's, um, you can move it to a place that's more comfortable for any individual. And that was one of the things I liked about this dynamic one where there wasn't a fixed point is that you can, you can control the motion from whatever your comfortable hand position is. So one of the downsides though is you can't look at this screen and know what to do. You have to, you have to tap and start moving your finger around and kind of figure out what to do because there's no UI element showing you, here's where you control motion. Yeah. Right. Yeah. And there's different ways to solve that problem too, right? And not necessarily any of them are bad, right? A tutorial or some sort of graphic or letting the players figure it out, right? Like none of those are necessarily a bad option. Yeah. It's about figuring the one that fits things at them. Yeah. Yeah. But you can imagine in this game if the controls were fixed right on top of the earth, you would be dying a lot because you couldn't see what's coming at you under your hand. Right. Exactly. Yeah. And that doesn't mean we can't change things in the future, right? Like we're not locked in. And in fact, that's one of the most important things about game development is being able to iterate. You don't want to, you know, write yourself into a corner where, hey, we prototyped some random thing and oh my god, it's so much better than everything else we've done, right? You want to be able to pivot to that and immediately kind of build the game up around that. So if we, you know, accidentally put together some sort of, you know, weapon or, you know, tool or control interface, you know, just playing around, that's all of a sudden like, wow, this feels amazing. This is, this is addicting, right? That's where you know you have something good. And that's where you want to be able to put it into the game. So avoiding writing ourselves into corners is really important. Absolutely. So I don't know if, let's see, is this one that paid one now? This one's on GitHub. You're looking at Rex Rainbow. So yeah, do you have that one up, Eric? I have one up. I don't know if it's specifically the one that you're using. Let's still do the trick. The one, the one I was just demoing is from Phaser 2. So we cannot use that. This one has a nice little snap back to the center when you're close, kind of a dead zone there. That's good. Yeah. So there's a, there's a Rex Rainbow person and there appears to be a virtual joystick plug in. I don't know which one you're looking at. This is Rex. Oh, okay. This is, oh, there's a two. Dual stick. You can trigger both of them. Oh, that's funny. If you drag over, you then act, if you drag too far while you're holding it, it freaks them out. Yeah. Yeah. Kind of capture both of them. Well, that should do the trick. Let's see. Yeah, I don't think we need the dual one. I think the single one's probably the one. Yeah, for sure. Yeah. It's the same thing just twice. Yeah. Another thing that's super fun with mobile games in a place where mobile games are actually pretty further along than a lot of desktop games is consideration for all of the different aspect ratios on devices and placement on the screen. A lot of desktop games assume you're either, you're 16 by nine, no matter what, and you're 1920 by 1080 or 4K. And with mobile devices, you don't have that luxury. Your screen could be any size. It could be a bloody cube. There's some mobile phones out there that just do that. And so making those considerations of like when we're building the UI, when we're taking an input, when we're calculating the displays, it's always about making our best guess about, you know, what is the minimum width of the device and the absolute value, right? Exactly. Yeah, long gone are the days you can do just a couple of sets of like raster textures for mobile and consider it on, right? Well, I mean, you can, right? But you just can't place it pixel by pixel, or you have to have some sort of logic about where the display is being adjusted. There's an application I love to use called flawless widescreen. It's a DLL injector, a game file injector. But it goes to show like, too, how little effort it takes nine times out of 10, if you just think about these things, you know, before you write the code is what it does is it'll adjust. There's something like a library of nearly 1000 games in there that don't support arbitrary resolutions on desktop. But this little DLL injector, you know, just has somewhere around less than 150 lines of code for each one of the games that will adjust them to look good on, you know, any aspect ratio screen. That's neat. This is kind of nice. I think this will be a good base. It's simple enough. They're excellent configurable enough. Yeah. It looks like it has a base and a thumb configuration option, where the default is just to draw, draw this phaser circle for each. But this, this is kind of telling me and I'm sure I think the documentation would back this up that you can put any phaser game object here so we could replace this with a sprite or even a animated fancy thing if we wanted to spice up how this looks. Well, you got 24 minutes. Get to it. Well, I'll have to check out the repo first. And does the game run without a AMQ? So the game runs without the server. It just, you won't get a spaceship rendered. But if you start adding like a control element and drawing stuff to the scenes, like it'll appear. All right. Let's try it. All right. Live coding. Here we go. Woo. All right. All right. So we want srt web client, right? And what's the org? Open red hat dash game dev. Game dev. All right. Well, I guess I'll do the whole thing. All right. Red hat game dev. Do it. Client, right? I think so. So I have a hub command line from github that's supposed to let you clone like this. Oh, I did check out not clone. That's why it didn't work. Clone. There we go. Already exists. Oh, I do have it. Hey. Surprise. All right. So npm install. Do it live. Or I haven't been paying attention to the chat here. Starts with the music. Yeah. What do I want here? Red hat. Put that in the chat as well as the rex virtual joystick. Maybe we should get rex on our stream. That would be awesome. Yeah. So let's see where. Wow. He has a lot of plugins in here. So the joystick. His example just loaded it directly from github. I don't know if you want the dual stick one or the single stick one, but they both were just pulling it directly from. It's the same. The dual stick he just instantiated to joysticks. Got it. Yeah, you said that. That's right. Let's see. So let me, I want to check and see how close these pity about earth ones. Here we go. So how, how are the other packages getting included? Are we going from we're pulling in our like phaser dependencies? Okay. So there's a global phaser on this page. Right. What it looks like. Okay. Yeah. So script text in that case, this will work just fine. We got phaser. I'm getting some sort of like breathing or wind audio. Just definitely. I wonder if it's me. Did it stop? It did. Probably me. Did you stop breathing? I did. Don't stop breathing, Eric. Come back to us. The things we do for our streams. Well, you know, I just held my breath for a, yeah, two hours. It'll be fine. Champion swimmer over here. Let's see. So do we want this in? Well, it looked, let me, I'm going to look at that. Which scene do we want this in? Probably just the game scene, right? Yeah. Main scene. Yeah, we don't need it in the, in like the intro page or whatever. So we've got preload. I'm just pasting in what's from the, the demo. So it's got the URL in here. Since we're preloading the plugin this way, I'm going to remove the script tag I just added. Oh, it's just about to ask. Yeah. Like if we saw that. Rex virtual joystick plugin. All right. Let's, what can we, maybe there's something we can poke to make sure that it gets loaded. Well, if you try to create it and it blows up and it didn't get loaded. The test and try method. Yeah. TIAS. Try it and see. Create joysticks. So it looks like they're shooting. That applies to like baking and cooking too. Just try it and see. See what'll happen, except we're not baking cakes or baking video games. Well, you're kind of poking your way through this. Something I did want to talk about is like, yes, for a time's sake, we did move away from TypeScript, but it's never worth it. And especially if it's something as complex as building a game, you know, a runtime for a game. It's never worth it. No, no, no. I'm saying moving away from TypeScript is never worth it, especially in the long term where you're like dealing with a much larger code base with multiple people working on it. Like I've been down that road before of like spent multiple years working with TypeScript things. And then like the second I went into a project where they had like tried TypeScript and been like, oh, this is, you know, too much of a pain moved away from it. They ran into like all the problems that TypeScript solved with the code pace with like six people working on it. It was like, it was a really good case in point of like TypeScript is pretty fantastic. And while it is painful to get rolling with it sometimes, especially using third party libraries, it's almost always worth the effort just because of how much time it saves you down the road. So if you're planning on keeping the code around for, you know, longer than a week, definitely think about TypeScript. Yeah, one of these days, I'll actually understand what it is. I mean, do you want me to like launch into an extension? Just I'll do it. I mean, if you want to do that explanation while Michael's furiously coding away, sure. Yeah, two targets with one spaceship. Absolutely. I'm down for that. Launched some missiles while we're at it. TypeScript is really it solves the problem of the fact that in JavaScript, everything's an object. So what is it that you're dealing with in your code? Well, I don't know. You tell me. And that runs into all sorts of issues where you can be accidentally reassigning values to variables, you can be using variables and situations where does it make any sense? And doing static analysis on JavaScript code is kind of a nightmare for those reasons. We can't like, you know, run down every arbitrary runtime path just to see what'll happen with a bunch of random variables that you don't know what they're supposed to be. And so there's, you know, JS doc and other types of annotations that you can use to, you know, sort of make things a little bit easier for static analysis and for your programmers to take a look at the code and understand what it's supposed to be doing. But with TypeScript itself, you're actually, you know, you have a compiler, you're building the process itself together. Yeah, he froze. I'm assuming he'll be right back. But with the compiler, right, it's you're actually putting in types you're putting in definitions of how the different variables are defined in the system, you know, whether that's a string or an integer, if it's a constant, you know, or something that's static or not. And that compiler will perform that pre-analysis and that translation to JavaScript that will let you catch so many type issues that, you know, like that's kind of like a nightmare of like, you don't know what this type is at runtime. Well, I don't understand why this, you know, isn't populated. So then you put in a breakpoint and then you're like digging down to like, what happened? This is variable. And it's like, Oh, I redeclared it in another portion of the code. I used the same name. And if that's something that like, you shouldn't have to sit and spend 20 minutes debugging, the compiler should just tell you, Hey, you're, you're an idiot, you wrote the wrong code. Okay. Makes sense. It's one of those things where like modern PHP, you know, has like types now defined for input parameters for functions, return values, like all of this, you know, additional, you know, what you might call cruft, but really your IDE takes care of 90% of it these days. Like, that sort of stuff allows you that sort of cruft allows you to do static analysis. And like, in real time, look at your code. And as you're writing it, it's like, this isn't going to work. Like, I know what you're trying to do. Click this button and we'll get you there. But, you know, and that's, that's the sort of stuff that's going to make the difference, you know, between modern programming and what was happening, you know, even five years ago, we should be able to get to the point where we communicate an intent to the computer. This is what we want, not, you know, this is what we see happening. And the computer goes, Okay, here's the steps I can get you there. Right. This is makes sense. And we shouldn't be spending all this time just, you know, writing code, because it's time consuming, right. And it's painful, but instead we should be doing is spending all of our time deciding what will happen. Makes sense to me. I don't know that we're going to get we get like a crash or something. You might have a more serious problem. Well, when JavaScript can crash your computer, tell me about it. No, I mean, this is probably a good ending point then. We talked a lot and we showed what we had done. We talked a whole lot about kind of what we could do from a physics perspective. We have an idea for changing the control input to be some kind of virtual joystick. Yeah, sure. We talked a little bit about sort of physics and how we're going to sort of the virtual joystick is the virtual ship stick. And the server will figure out what to do with whatever that is telling us. Yeah. And so I made a bunch of bad jokes. We did. And so hopefully by next month, we'll be completely switched over to TypeScript. No. And we'll have the virtual joystick and maybe we'll have rotation of the spaceship or not. We'll see. Yeah, maybe for a super crazy, I'll go get a turret graphic that we can start sticking on there. Oh, yeah. And if we get that done, it sounds like the work on the server side should be relatively light with regards to enhancements. I know there's some bugs lurking there that need to be addressed. So yeah, the server just needs to take the force input or the ship stick position and do something with it. And so today that would be rotation. And then I guess we will need to change the client to actually rotate the ship because right now it only puts it in the same position at XY. That's right. So we'll need we'll need a heading of the object to come back in the message, which I think it does. And then we'll have to rotate the sprite accordingly according to what comes back. Cool beans. Well, thanks for joining us today. All of you out there and listener land and watcher land and thank you, Roddy, Kylie, and thank you, Derek, Rhys. And thank you, Michael and absentia. Invisible. You made it almost all the way, man. Good on you. I hope everything's okay for him. All right, we'll see you all next month, next time. Thanks again, and have a great time in that place. Say what? Same bad time. Same bad place. Yeah. All right. Thanks, everyone. Cheers.