 Hello everyone, my name is Chung. I'm a front-end engineer in Singapore and today I'll talk about a small tech street game that I built with Angular like maybe six months ago during the circuit breaker. I am not a circuit breaker, it's just a time I spent. I stayed at home and I think it was a cool thing to do. So before we just say can I hide this one? Hi. Floating? Okay. Okay, thanks. So just a bit about me before we continue. So I'm currently a front-end engineer at KDeFi platform that let you earn cash flow through your cryptocurrency and we also like looking for JavaScript engineer at the moment. So you are interested in and I just take a look at our Twitter. Also I'm an organizer of Angular Vietnam and we have the Twitter also at the moment, ngvnofficial. You can follow us to get less Disney mobile Angular and our upcoming event. One of the focusing we are doing is like the 100-day of Angular that we wrote in Vietnamese to try to advocate the Angular community in Vietnam. And so for today's agenda, I will go through tech streets and why I built the tech streets game with Angular. What is the tech stack behind? And there's some development challenge that I faced when I was working with the game itself. So yeah, like I started. So the tech streets game, like I hope that all of us are familiar with it. It's like a game that invented by Alexei Russian in 1984. So the rule is very simple. You just rotating and move the pieces so that you try to fill out the horizontal row of the bluffing without any empty cell. You can fill in a solid row, which means that you can clear that and you got the score. And basically that tech streets and the version that I built with Angular is look like that. You can go to tech streets.chungk18.com and let me slide. So that is the game. Basically, it follows the same rule of tech streets. You can take the pieces, it generates the pieces for you. You can move it down and try to fill in the block, maybe something like that. So when this one row is filled with all of the block, it will just clear it. So yeah, basically that is the game. It has some option. You can turn off and turn on the cell and you can put the pieces like faster by pressing the space like that. And that is the Angular tech streets that I built. So why I decided to build Angular tech streets is like, I think tech streets was one of the first game consoles that I ever have in my life, like when I was five years old. At that time, the money, the tech streets game cost about $2,000 a week. We can fit the family for about one or two weeks. So I think when my dad gave me the tech streets, he really hoped that I utilized the game and really enjoyed it. Actually, I really enjoyed it. The one that I have is the yellow thing here. I think it's still there. Now they're still selling it, but the quality is not like the one that I have before. Maybe, I don't know, just the feeling is different. And the Angular tech streets were not like originally or originated coming from my mind. It's like I saw the similar version, which is written in Vue.js. And also my wife saw it. And I thought that why not I do the same with Angular. And also my wife encouraged me to do the same thing. So, you know, that is a thing in life. You have to accept it. And I think that was the time when I received the tech streets. So it's like 1996 or 97. I was born in the rural area. It's like the mountain side of Vietnam. So at the background, you can see there's just a mountain and the house was like really 20 years ago, I guess. Yeah, so because there's a viewer tech streets already, so the approach was, I think it's much simple for me. I don't have to decide the game. I don't have to write all of this. So the thing I did first is like I look at the Vue.js source code and I view a small to do it because I work by my own, but I still need something to like keep track of the task. So it is just the simple to do it. Yeah, okay, I have it here. Yeah, so basically it is going to look like that. Very simple. It just has some checklists. And I'll just keep track of what I'm going to do. Sure. We cannot see. I think we can only see your slides at the moment. If you switch to another app, we cannot see. If you really want to do that, then you might have to unshare and reshare. I see. Just like maybe I just do it in the same screen. Yeah. Yeah. Okay, sure. Just give me a sec. I will bring back the thing. Yeah. Oh, no. Okay, have a try. But I think we're still looking at your browser. I think when you shared your screen, you only shared your browser. Oh, yeah, yeah, yeah, yeah. I think I get what you mean. So just now there's a few things that you I didn't see. Yeah, I think you were playing the game, maybe. Yeah, yeah, but it's fine, I think. Can you see it now? Sorry. She want to check. Can you still see the slide? No, I can only see you now. Okay. If you go share screen and then that's all, I think. Let's stop. But it's just that's all one. Maybe I tried. Can you see it now? I can see your browser still. Yeah, you can see the slide. Yeah, correct. Sure. Yeah, okay, so the game is basically looked like that. Just now I show it. But I think you added and see it. So yeah, just hide this one. So this is a game. Basically, you can go into the address here, that's restart from creating. You can play it around. And basically, it's just very simple. You can use keyboard to navigate the thing around. And yeah, basically, it's just trying to clear, like fill in the business. And it's going to be clear for you. And you can enable sound. I think it's going to be loud. Not sure you can hear it, but you play it on your own browser. It's going to be a bit louder. So yeah, so I just talking about this simple checklist for myself to keep track of all the tasks that I'm working on. It is not to like a proper Kanban board or something. It's just something for me to know where I am and when it's going to be ready for publishing. And I just started with the HTML that you are seeing here. So the HTML is like just the skeleton with the with the game boys and stuff. And the core thing is just the one in the central of the screen, where everything is moving. And you can use a keyboard or small to control it. And I'll end up using another library for for the call of the game because writing the whole thing like from scratch is not something that I like to do. And it's going to take a lot of time. And I also replace the set timeout and set interval uses with the IHS, which is the reactive way of doing program. And it's just like well known in the Angular community. And after that, I just handling the keyboard and something. So when I look at the view with JS code, it was, I think it was well written. It is just like, because it was written in JavaScript, so there's a few parts that it could be like easy error prone, because when you you view it, it doesn't tell you like weak part might go wrong. It is like it's a natural of JavaScript, which is a dynamic language. So we cannot blame it. But when I start to migrate the code over to TypeScript, I start to realize there's a few bugs that we can catch earlier. And the the viewer version was using set timeout and set interval like a lot of time. And there's there were a few parts that were difficult to understand. And I will show you right now. I think. So this is the, like I said, is the most important part of the game. And because the screen is a bit smaller. So the left side is basically what I was like, rewrote with TypeScript. It is just a service. And the right side was the viewer JS. So I try to break it into a smaller function and give it a like, like meaningful name so that when you read a code after six months, you can understand it a bit. The viewer, I think there's there's a few bits that I don't understand, like all of these four things. And just their own of the manipulation plus thing here, like x y at the zero one. And I don't really understand it. So that's why I decided to use another library. And also really rewrite the brain of the game. I don't reuse the viewer JS logic for that. So I use this NGA Tetris game. So it is just a call. Like, basically, there's an array which fill in like 200 objects. And when you wanted to render it on the UI, you need to do your own part. It just provided you the call, which is the data structure. And I added a bit more functionality like navigating between the pieces like left, right and clearing and stuff. But the call thing was like still inside the library and Tetris. Give the guy the shower is very good job here. So the game look when you think about it is very simple. You see it like when you start the game, always there's every time like after a fix like time, there will be the pieces going down. And when it's rigged to the bottom, another pieces will be like, like, like will be rendered on the screen. And it's keep going down. And it's just keep going down. And for every movement, you will try to check when the thing is like colliding with other pieces. You wanted to know, is it like filling one solid row so that you can clear it? Or it is the game over state. That's it. Very simple. So the it is just inside in one simple function called auto. And it takes a delay, which is the number in millisecond. And I'll just run the time of every this delay, like could be 300 milliseconds. The speed is going to be faster along the way when you like, like getting high score. So the level here now is one, but it could go up to six when the level is going up. It means the time for you to the time when the piece is falling is faster, like I can start the level five. And you see the the the pieces is moving very fast. That is the delay that I put in. And if you look at the code, the auto function is calling just one function, which is the update function. And just set. Can you still see a code now? Joe? Yes, can see. Sure. Thanks. So the function to to the function inside the the game loop was pretty simple. That is the update function. And the update function is just do a few things like can mention above. So even Oh, that there's a few but I will not explain because it's just the way I do it. So basically, you wanted to try to move the current pieces now, like just plus one on the screen. And then it is colliding with a bottom you, you mark the current pieces as solid, which means that there's even it had been filled on the screen. It's not going anywhere. It's fixed the position. And then you try to check if the thing is like making a full line or making the full two line or making a full three or four line. And then after that, just trying to set the next pieces available. And then if it is like get out of this function, it will draw the next pieces. And then the update will call again. And you will get the thing. So yeah, basically, that's the roughly the idea. And you can always take a look at my code. So go back to the slide. So now get back to the data structure that I store the pieces. So basically, the pieces that render on the screen is just the geometric shape that composing a four square. You can see that all of that is four square. And it's just in a different arrangement, like the F and the G here is like the reflection of each other or the L and the J here is just the reflection of each other. And to store it, I have the base class, which I call pieces. And then at a certain point of time, there's always x and y to know that widely on the screen. And I have the shape thing, the shape property to store the current shape at the moment, because the pieces could like rotate, like something like that. Yeah. So you need to know exactly the current shape of the pieces like if I change to this one, it's like it has four direction movement. So the shape is just like to store the the current shape of pieces at a certain point of time. And let me open the code for you so that you can see it easier. So that is the base class, just x and y and the current rotation, always even start with the degree zero. And if you take a look in the rotation, you can see that there's just zero 90 degree 180 and 270. So always like maximum four direction. And the shape if you look into there's a array of shape, which is just an array of something else. If I look into the Z, maybe the T thing. So I just set the the shape of the T by default, which is an empty array. And then I put in the corresponding of the degree to the shape. So if you look into the array here, so one is meaning even gonna be rendered on the screen. And zero is nothing. I put it like four, four times four, because the I think is going to take the whole row and the whole thing. So I need to put it at least four by four. That's the reason if I will have a question. And if you define all of the movement like degree, you can see that there's also the property called next, which to display it on the on the right side. Basically, that's the one, the next shape. So I'm not using the same because the next thing is like, going to be the smaller, like two times eight, two times four. Yeah, it's just the array is smaller. So I don't use the the same data structure that I put for the shape. But basically, that's the idea. And because I put the shape in this like very like verbose way, so that if you want to do a customised pieces, it's going to be simple. I will say so. Because I tried it before with simple pieces, which is not existing on the dashes game ever, like this is the F thing. So you can put in the F. And if you look at the code, it's going to be quite interesting to see because it's going to be very simple. You just define the pieces F, which extend from the piece class. And then in the shape array, you put in what you want is going to look so you will put the degree like 90, you can just copy and paste it and you change the thing here. So it will be like update corresponding on the UI for you. I think it's quite easy to extend. And the piece is going to be generated through one factory. Actually, I forgot what it's called. Is it a piece factory? Oh, yeah, it's a piece factory. So when I tried to get a piece to display on the screen, it tried to generate a new bag, which always has a maximum of I think seven dashes pieces. And it is to evenly distribute the piece like you will see at least the Z or at least the T. If you just do it like a random movement without putting it into the bag, which means you could see the T like five times and then you see the T. Then it's not going to make sense. So I put it into the current bag. And if the bag is empty, I will generate the new bag, which has all of the pieces that I put in so that I make sure that the pieces will be like evenly distributed. You might see this one, but you see the other thing twice. For example, it's the maximum. You will not see something 10 times and you see another piece for just one time. That is the idea behind this bag. Yeah, and I think it's just basically about the data structure of the piece. And each shot is quite verbal, but it's easier to extend. So I think I will still stick with that approach in the future. You might need to do something. I would rather do it verbal and easier to understand and maintain rather than to do it a bit short and then later on we'll be struggling. Animation why is I didn't like I'm not an expert of keyframe and stuff. So I using IHS also to reload the animation. And on the viewer chess version, they was using set timeout and set interval a lot. We're creating this code back that we own new about. So I don't want to repeat that decision. So I just try to do it with IHS. So the animation wise, I was utilizing one of the CLS transform thing to just flip the image over so that I don't have to stop to image. And what does it mean is that when you put the scale with negative one, it will just flip the thing over like you put things into the mirror. And that is how I do to get the reflection of the dinosaur when you see it when you first open the app, this one, this dinosaur. So by default, I only has the photo to store it facing to the right side. But when I do the transform with scale negative one, I have exactly the same person. But the dinosaur now is looking to the left side. And why do I need this because it's just to make some animation. Yeah, basically. So the first animation we need to look at is the eye. The eye is very simple. It just like changing between the first two photos, the one and the two, you look at this is the first one and the second one. So it just I close and eyes open. And here is like I close as I open. I also do a very simple IHS. The timer here is working exactly like set interval. So it will go into this, this tab, like every 500 millisecond. And I will take why the thing is less than six. And if it's even, I will just set it to one, if not is set it to two. So basically, it just to talk all between the two step every 500 milliseconds so that you have this animation, which is the dragon is opening the eye. The next thing is like the running animation, which is you still do the same. But because the running is requiring faster movement, that's why I put the timer, it just 100 milliseconds. And every like after the lag is moving for eight or 10 times, it will change the direction. So inside the tab function, I also check wherever is is moved like enough for every light is divided by 10, which is is moved for 10 movement on one side. Then I just flip the side by doing this left and right. So the left and right here is using the the transform negative one that you saw before. That's why I can flip between the two sides. And then the same thing, it will just toggle between the three and the four spray, which you see the just the three and the four. So just the lag is moving up and down. And if you just toggle it fast, it will look like it is moving. That's it. I think it's going to be simple. And at the end, I need to combine the thing together. And by combining, I mean, the dragon will open the line and then it will start to run. Run, run, run, please run. Yeah, and start to run. And then after a while, it will open the guy and just keep repeating this thing. So I was combining the two things together using this cold cat operator, which means that you just finish the first one and then you run the second one. I put the delay for five seconds because when I first load the test sheets, usually you're going to take five seconds for the first animation, which is this one, the one go down and go up. And then I start to load the dinosaur. And after it's finished one time, you're gonna stop for another five seconds. And it will restart it again. So could you wrap up in about five minutes? Is that okay? Sure. Yeah, I think it should be okay. Okay. Yeah, probably fine. And yeah, it is at the end is the animation on the left is that what I did. And the right is the original version. Basically, it's not very identical. But yeah, for me, it's good enough. So the keyboard handling was simple, because in Angular, they have this hot listener. So you just define a function, you put the hot listener, and you put you put a key with the light, you separate it with the dot, and then like you do key down and the arrow left. So when you press left on the keyboard, it will go inside it function, like automatically. And what you need to do is just to handling it. And for the web audio is a bit tricky because different browser get different implementation for the web audio, so that I receive a lot of feedback after I published it on on GitHub. And the guy was saying that sound was not like working properly. That's why I using this audio context monkey patch, you might want to consider to use it. So basically just like streamline some of the API between Chrome Opera, Firefox and stuff. And you don't have to worry about the rest. Yeah, and I think somewhere here should be I forgot. And with that, you know, the town spending was like I was spent about 30 hours. I think it was still a bit long because I don't have to write all of the HTML and CSS and also the core of the game. But still it took 30 hours, which is like a week of work. But yeah, pretty enjoying it. Like, it's a cool game. Anyways, and I can play it later on. Got some community support and people were sharing it over and over. And I was really like exciting to see it. It's growing. Yeah, it's worth even get to the top training on GitHub for that one day for TypeScript. And with that, thank you. And I hope you enjoy playing the game. Yeah, I think that's it from my top. And you have any questions, just just just put it on the chat or you can unmute and we can have some discussion now. Thank you. And I forgot. Happy New Year, everyone. I'm finished. Thank you very much, Trun. Nice. And I just take a three shot. I did have a couple of questions, but well, you answered both of them. Oh, yeah. Oh, nice. Is anyone else have a question? Yeah, I know, because I always talk about Angular, but I think because