⭐ If you would like to buy me a coffee, well thank you very much that is mega kind! : https://www.buymeacoffee.com/honeyvig Hire a web Developer and Designer to upgrade and boost your online presence with cutting edge Technologies

Friday, November 7, 2025

Practise JavaScript by Building Zelda! (Super simple)

 

0:00

Hey everyone. Today we're going to be building a game of Zelda in pure JavaScript, HTML, and CSS. And no, we're

0:07

not going to be using any fancy frameworks. No, we're not even going to be using Canva. This is pure JavaScript.

0:13

Okay, and this is to practice your fundamentals. Okay, so this is the final product. We're going to be building this

0:19

game. You can see Link here. He can move around. He can, of course, kill the enemies and then move to other levels

0:26

once he has killed them, too. Now, these levels will loop because honestly, this

0:32

is all about learning the fundamentals. I want to give you all the tools to essentially build this game, but then

0:37

take it, make it your own, style up, add more levels. All of this will be possible by the end because this, once

0:44

again, just to repeat, is a way for you to practice your JavaScript. Now, once you finish building this project, you'll

0:50

probably want to show off to the world. And to do that, you're going to need to deploy it onto the internet. I'm going

0:56

to drop a link for Savala, which is a cloud platform that makes deployment super super straightforward. All you

1:02

need to do is connect your GitHub, GitLab, or Gitbucket account, and you're basically done. Push your code to the

1:08

repository like this, and Savala handles the rest. So, you simply select it from

1:13

here, and it deploys to the internet. Easy. And here's the cool part. If you're deploying a static site like this

1:19

one, it's completely free. So, follow deploys it onto the edge network so your site loads instantly. No matter where

1:25

your visitors are located, whether you're just experimenting with projects like we're doing here, or you're

1:31

planning something bigger down the line, maybe with a database, user authentication, the whole nine yards,

1:37

you'll be able to do it here, too. So, go ahead and click on the link in the video description to check out Savala

1:44

and bookmark it for when you're ready to deploy. Otherwise, let's get to actually

1:49

building this thing. Okay, so what are we waiting for? Let's do it. Let's build Zelda. Once you have finished your game,

1:55

please do share with me. I would love to see how you have taken this, taken your knowledge and basically improved what

2:02

you see here today. Okay, so here we go. Let's do it. I'm going to start off in my code editor, which in this case is

2:08

webtorm. Feel free to use whatever code editor you wish. I'm just going to go ahead and just start completely from

2:15

scratch. So, let's create a new project. And this is going to be an empty

2:21

project. So, let's just go on ahead and do that. I am in my WebStorm directory

2:27

that lives on my computer. And I'm just going to call this Zelda

2:32

JS and click create. So, that has just created an empty directory for me.

2:38

There's no files or anything like that. And I'm just going to create a new file.

2:43

This is going to be an HTML file. I'm going to call it index. You don't need to put the extension but you know just

2:49

in case you are in another code editor I've done that for you and some boilerplate code has been generated for

2:56

me thanks to webtorm. So along with that indexjs file I'm going to have a

3:01

JavaScript file. I'm just going to call this app.js and then one more file. It's

3:06

going to be a stylesheet. So once again I just put style or I could double click

3:13

here and it will just add the style.css CSS extension to let our code editor know to treat this as a CSS file. So, a

3:21

stylesheet. So, there we go. Those are going to be my three files. I now have to link them up. So, they all live in

3:27

the same directory on the same level. Like I said, it's going to be super simple. So, we're not going to make it

3:33

any more complicated than that. I'm going to call this zel davcript.

3:42

Just like that. Now, to link up our stylesheet, well, we use the link tag.

3:47

So, let's go ahead and do that. It is a self-closing tag that actually doesn't

3:52

need this. Okay, it's one of few that doesn't. And then what I'm going to do

3:58

is do real style sheet. And now I'm going to link it with

4:07

the href attribute. And it's just going to go to style CSS. Okay. So that one

4:14

file there. Great. And the script tag.

4:19

We're not going to actually link it up in here. I'm going to use the DOM content loaded method. I'm going to

4:25

explain that in a bit. So we are done with this setup. At the moment we will come back to it when the time comes to

4:32

execute the JavaScript. I'm just going to put some very basic things in the body. Okay. So not much. Like I said,

4:39

this is going to be super simplified. I'm going to create a div. And here is essentially, let's give this the class

4:46

name of UI. It's going to be stuff such as the player current score, the plane

4:51

current level, and the enemy counter. So, these are just going to be simple P tags because like I said, we're making

4:57

this super simple so that you can take it and essentially do with it what you want. Okay. So, I'm going to span. So,

5:04

the score we'll put here. And then I'm going to break up that P tag with the

5:10

span. I'm going to break it up because we want to pick out just this little bit here. Okay. So if I do ID

5:19

score, we can just pick out this span element and not affect this score word right here. So that is it for the score.

5:27

Then what did I say? I said we're going to have some levels. So level

5:32

uh which means this is the ID for picking out the level. Let's start with level one. I'm just hard coding that

5:39

enemies. Uh, let's have the enemy counter here. So, enemies,

5:45

let's start off with two. So, I've hardcoded that. We can change it with our JavaScript later on. Great. Uh, so

5:52

we have this div here and one more div here. It's going to just be for our

5:57

game. So, I'm going to give this the class of grid. Okay, because our game grid is

6:04

going to go here. And final one is just going to be a P element that says use

6:10

arrow keys to move space to attack. So that's our game instructions. And

6:17

honestly, that's really it. I feel like we've done everything. So now, if I want

6:23

to see this in the browser, I copy the path, copy the absolute path, and just

6:29

paste it in like so. So that is what my screen looks like at the moment. Okay,

6:38

if I inspect it, you will see that's literally what we have in the body. The div with the class UI, the div with the

6:44

class of grid. So we're going to be injecting a lot of elements into this div. Okay, at the moment it's just a div

6:50

that is empty. It's going to have so much stuff in there that we're going to inject into it with JavaScript. And of

6:55

course, this P element right here. Use arrow keys to move space to attack. Great. So, let's continue. I think next

7:05

we should maybe style this up a tiny bit. So, let's go to our stylesheet. So,

7:11

let's get up our styles. Okay. So, what I'm going to do is just grab the whole body like so. And again, it's going to

7:18

be super simplified. Let's do font family for any fonts that we use. I'm going to use courier

7:25

new and then monospace as a backup. So it's kind of retro fonts that I am using

7:31

the background color. Uh I'm going to go with hash

7:37

one. We're using hex values for this 1 a 1 a2 e. I have picked this out already.

7:43

It's a dark blue background. The color of the text is going to be white. So that is a short hand for writing six fs.

7:51

It's still white. And now I'm going to use display flex. So this is initializing flexbox. so that I can use

7:58

flex direction column to make sure everything in the

8:03

body stacks up on top of each other from top to bottom. And then I'm going to align items

8:11

center. This is going to center them horizontally. And I'm going to use just spy

8:17

content center two to center them vertically. But uh oh, this will not work unless we

8:24

have a height. So I'm going to put min height 100 viewport height. So the

8:31

height of the browser essentially. Okay. So at the moment it will just look like

8:38

this. Okay. So we've added a few things. Let's also

8:43

Here's the body. Here's the grid. Here's the UI. Uh I think for the UI

8:50

let's do the grid first actually. So, I'm just going to go back to here. Let's

8:56

pick out the grid just like so. And I'm going to say that the grid is going to

9:02

have a height of 432 pixels. Again, I've already picked this out, a width of 480

9:09

pixels. We're going to have each of the grid, because it's a grid based game, right? Made of lots of little squares.

9:15

And every single square is going to be 48 by 48 cm. So this means that the

9:20

width is actually 10 squares and same for here that's going to be nine

9:26

squares. So that is the height and width. Uh for now maybe let's just give

9:32

it a box shadow so you can see what's going to look like. So zero and the x-axis 2 pixels on the y axis four

9:39

pixels spread. And then the color I'm going to use rgb8 because I want to make it transparent. So 0 0.5

9:48

opacity and then inset. And then I'm going to have another one on top. 0 x

9:54

axis 1 pixels y axis zero blur and make it solid white in color. So now if you

10:01

have a look there's the grid. I'm just going to zoom back out.

10:08

Okay. That's what we've created. So it kind of has this 3D effect. So again, UI

10:15

grid P element. I think the UI I don't want this to be stacked on top of each other. I want it to be the full length.

10:22

So what I'm going to do is go back here and let's grab the UI just like that.

10:29

And I'm going to use flexbox to do this again. So display flex. So this essentially initializes flexbox. And I'm

10:36

going to use justify content

10:41

space between. I'm going to show you what this looks like. Uh we also

10:46

actually need to say that the width of the whole UI is the same as the grid. So I'm just going to copy that there.

10:53

Great. So now you will see that the UI, there we go, is 480 pixels in width.

10:59

Same as this, but the space in between is equal. Okay, that's equal and that's

11:06

equal and that's thanks to space between. So display flex made them made

11:12

each of the text. So this text this this text appear

11:17

on a straight line essentially and then space between spaced that out. If you don't believe me, check it out. So that

11:23

was what it looked like without the justify content and without display flex that wouldn't even work. Okay, cool.

11:30

Let's move on. So great. Do you know what why I am here? Okay, that is our grid of course.

11:38

However, we're going to also say because we already know that every div that we

11:43

put inside that grid, we're going to put in divs with JavaScript. I already told you it's going to have a height of 48

11:49

pixels and a width of 48 pixels. Okay.

11:54

So, we don't have any in there at the moment, but I'm just going to leave it like that

12:00

for now. Wonderful. So, now let's get to creating our board. I think that's the

12:09

first function that we'll do. So, like I said, I'm going to use document and add

12:14

event listener. So, hopefully you've used this method from JavaScript before. Listener.

12:20

And then we're going to listen out for DOM content loaded. Okay, so this is

12:26

going to wait for the HTML document to be fully loaded before executing the game code. And once it is fully loaded,

12:34

okay, meaning that all of this has been loaded. So you can put a script tag here

12:40

that's it's kind of the same, but this is a little bit more foolproof because we're saying, oh, wait till everything is loaded.

12:46

And then it's going to call this function which is essentially the game code. Okay.

12:53

So now what we're going to do like I said I want to inject elements into the grid. So con grid. What we're going to

13:00

do is use document again and we're going to use query selector

13:06

to look for any element with a class. Is it class name? Class name of grid. You

13:13

could use class. We should probably use ID. So, let's look for anything with the

13:18

ID of grid because we know that the hash means, but we're looking for an ID.

13:24

Great. Okay. So, that also means that we need

13:29

to change that here. So, there we go. We're looking for an

13:36

element with the ID of grid, an element for an ID of grid, and any div that lives inside of it. Wonderful. Okay.

13:43

Okay, so you can use query selector or you can just use get element by ID. It's

13:49

up to you. But then we don't need to specify it's an ID because you know that kind of is already doing it for us in

13:55

there. So we're grabbing the grid that is cool. Uh while we are here, I'm also

14:00

going to grab the spans. So this whole element I can grab by this ID. So let's

14:09

go ahead and do that. I'm going to do score display.

14:15

Look for element with the ID of score. Let's do the same for the others. So, we

14:20

also have the level display and the enemy display. So, look

14:28

for level look for enemies. Great.

14:34

Okay. So, we've already discussed this. The width of my game grid is 10 squares

14:43

which are all 48 pixels wide. Uh in fact I'm just going to define the tile size

14:49

here as well. 48. So this is each tile size in pixels which is 48x 48 pixels.

14:57

And now what I'm going to do is actually uh well we are going to create the

15:06

board. So let's write the function create board just like that. And what

15:14

we're going to do is loop essentially. So let's write a for loop for let i

15:20

equals zero. And as long as

15:26

i is smaller than 9, we're going to increment i

15:32

by one. Okay? So, we're actually going to loop through each row first. So, imagine the grid based game is a row. In

15:41

fact, maybe it's best to kind of get the layout first of these games so you can

15:46

fiction them better. So, let's define maps. So, let's have two, right? Because

15:52

we have two levels. It's going to be an array. And my first map is going to be an array that lives inside of an array.

15:59

This is essentially our first map. If you want, we can even annotate it. level

16:04

one layout and I'm going to do it for you in a way

16:11

because usually you just write a string. I'm going to do it visually for you. Uh so let's write the string of the top

16:19

row. So essentially what I'm going to do is say the certain things are describe

16:25

corner walls and so on. So I've already written this out for us. So, these are

16:32

going to be corner walls, meaning that the visuals that you see or saw on the

16:39

Zelda have already been planned out. I did this in advance to save you time. A

16:45

and B are going to be side walls. C and D are going to be top and bottom walls.

16:51

This shape right here, so this is going to be lanterns.

16:58

This is going to be fire pot. So this shape right here. This

17:04

is going to be a left door. This is going to be a top door. This is going to be stairs.

17:11

This is going to be the slicer enemy. This is going to be a skeletal. And then a space is just going to be an empty

17:16

walkable area. So using this I'm going to create my map. So let's go with Y. So

17:22

this is a side corner wall. Then CC, as we know, this is a top and bottom wall. Then I'm going to put a lantern. So I'm

17:30

going to go like that. CC again for a wall. And there's going to be a door. So

17:36

that is a top door. CC for walls. And W for a corner wall. Okay. So that is my

17:44

first top row with a top door in the center. Now I'm going to do the second

17:52

one. So, second row and that's going to be a because that's a side wall. I'm

17:57

just going to have a bunch of spaces here. Okay. And a b. So, that's the other side wall. So, great. That's side

18:04

walls with an open space. And we said that this was going to be nine squares

18:11

high. So, we need nine of this. So, we've already have one row, two rows,

18:16

three rows. But, ah, let's have a slicer here, I think. So, let's just put the slicer there. Let's put a comma there,

18:24

too. Then we have another one. And this time, we're going to put a lantern here.

18:29

So, let's put the lantern there, maybe. Really is up to you where you want to

18:36

put this stuff. Let's have another one. But instead of a wall here, I'm going to put a left door.

18:45

I'm going to grab this once more. Let's put another lantern. And then

18:51

let's put another slicer, but this time I want the slicer

18:57

to be here. Okay. And then finally the bottom

19:03

row, which is going to be again corner wall, bottom wall, bottom wall, lantern,

19:09

bottom wall, bottom wall, lantern, bottom wall, bottom one, corner wall. Okay, so imagine this is my layout.

19:17

Okay. If you put it all on one line, it wouldn't look so nice and might be quite visually difficult to really see what's

19:25

going on. You'll be like, "What is this?" At least this kind of resembles the map we are doing. So, this is just

19:30

for us. Like, the computer won't know any different. This is just for me and you. So, we can kind of see what our map

19:35

looks like. Okay. So, now what I'm going to do is actually I'm just going to put

19:42

in a second layout, which I've already done as well.

19:48

So let's make another array. This is going to be level two layout.

19:54

So level two layout. And using the same key, I've just

20:01

created a second layout. So now you can actually add as many layouts as you want using the key here. Okay. You can keep

20:10

that if you wish. Uh it's up to you. So once again, these are our two levels.

20:17

Let's continue. So now I'm going to use those two arrays essentially. And I'm going to loop through each row, right?

20:24

Because like I said, this is a row and there's nine rows. Hence, we are looping

20:30

nine times. So that's going to loop through each row. Then I'm going to loop through. So this is inside that for let

20:39

J equals zero. As long as J is smaller than 10 this

20:44

time because there's 10 columns, J increments by one. And for each time

20:51

it does this, it's going to create a square. So const square. And we're going

20:57

to use square equals document create element. So we're going to create a div.

21:05

But uh oh, this is kind of currently just a div, right? It's not even in our grid. We just assign it to the con

21:11

square. that square. We're then going to grab and use set attribute. So another

21:17

JavaScript method to assign an ID to it. And that ID is just going to be the loop

21:24

that we are doing. Uh this unique ID is actually going to be based on the position. So I'm going to get I multiply

21:31

it by the width which we know is 10 plus the value of J. So before we start

21:39

adding the characters to these squares, I just want to show you what that looks like. I'm going to grab the grid which

21:45

we already picked out in the first few rows. I'm going to use another JavaScript method called append child to

21:52

put in the square we just created. Okay. So now if I call this function, I'm just

21:59

going to do so down here. And now we need to add the script tag to our HTML

22:04

document. So instead of putting the script tag here, we're actually going to put it in the head. So I'm going to put

22:10

script up here. Just like that.

22:16

Source app.js. So now our DOM content event listener

22:22

will listen out to when all the HTML elements have loaded and then execute

22:28

the JavaScript in a foolproof way. Let's check it out. Tada. So now, like I said,

22:34

we've injected all these divs, okay? We've given them ID, id 0, one, two,

22:39

three. They're going all the way down, however. So, we don't want that. See? D.

22:44

We actually want them to wrap from left to right and then make another one. And another one, another one. So, we do that

22:51

with CSS. So, back on the G grid, I'm going to use display flex once more.

22:58

Flex wrap. Okay. So there we go. So now it

23:03

goes diagally like I wanted on the next row and so on.

23:09

And you will see these ids have been assigned to the divs like I did here

23:15

using JavaScript using the set attribute. Okay. So if this was zero 0

23:21

multiply by width is still zero plus J which at the moment is zero that's zero.

23:28

Then of course we're still in the columns, right? And we have to complete all the columns until we move on to I.

23:33

So it would be 0 * width is 0 + 1, which

23:38

would be 1. 0 * 0 is still 0 + 2 and so

23:43

on until we get all the way up to 9. And then this turns to a one. So 1

23:49

multiplied by width is 10 plus J, which is zero, which gives us a 10. And so on

23:56

and so on and so on. So hopefully that explains it. Let's move on. Okay, so

24:02

we've done that. The next thing we're going to do is get the character at this position in the map. And for that,

24:10

well, we're going to have to essentially get the levels.

24:16

So get the maps here. And inside this function, I'm going to get the current

24:22

map. And the current map is simply the maps. And I'm going to open my array.

24:28

And we just want the first one, right? So let's also maybe assign some

24:35

variables here. So I think what we should do is let's

24:41

also collect the squares all in one array as well. So we know what we're working with uh in the JavaScript file,

24:47

not just when we look at the game grid. Let score start with zero. Let level,

24:55

we do want to start at level one. Yes, but in computing we start counting from zero. So it's going to be index based.

25:02

Let player position. Well, now that we have assigned ids to all our divs, I

25:07

know that I want it to go in the div with id or index 40. So I'm going to put

25:14

it there. Let enemies, we're going to collect our enemies in an array again, just we can keep track of them. And

25:20

we'll start off with the player direction being right. Okay. And of course, let

25:27

game running. We'll start off with it being true. So when you kind of, you know, just go open

25:34

the browser, it's already running. Cool. So now let's use this level variable and

25:42

put it through into maps because this will get us back the first map. Zero is

25:47

essentially one. it will get us back the first map in our array. So that is the current map that we are working with. So

25:54

now if I get the current map and I go into it

25:59

right because this is the current map and I go into here that is the first

26:05

item and I want to go further into it I do so again just with another array. So

26:11

that is how I get the exact character that we want to get at this position in

26:16

the map. Okay. So maybe let's just save this as char. So character and we're

26:22

going to write another function for this add map element. This is going to process this character to add

26:28

appropriate styling to it and so on. So that is something that we are yet to write. So we'll pass through the square

26:34

that we are working with. We'll pass through the character and of course we'll pass I and J as the positioning

26:42

references. So I'll comma that out for now. So at the moment, yes, we are putting the square in the grid, but like

26:47

I said, we also want to save it to this file, which is why I made a squares array. So I'm going to do squares push,

26:54

and I'm just going to put in push in that square. Okay, so amazing. If I

27:00

console log squares after this whole function has

27:06

run, just comment this out like so.

27:11

Tada. We get all our divs. This is great. Okay. So, I'm just going to maybe do

27:19

that and let's work on our add map element function next.

27:25

So, I'm just going to do so

27:31

here. So function add map element. Like I

27:38

said, we pass through the square, the character, then x and y. We did pass

27:44

through an i and a j, but essentially it's the same thing. And this is just going to be one long switch statement.

27:51

So we'll pass through the character like so. And if the character is an a, well,

27:56

we know this is a left wall, right? because we have our key to refer back to

28:02

and in that case we use square class list

28:08

and we add a class we are yet to write called left wall. Okay. And then we simply break out

28:16

of this. So that's all we're going to do. We're going to do this a lot. So left wall essentially. Let's just go

28:23

down here. Just going to zoom out a little bit for you.

28:29

and left wall. So, dotle left wall. Well, it's just going to be an image.

28:35

So, background image. Now, I've done two things in my

28:41

code that I've attached. I've actually added all the images. However, if you don't want to get all the images, that's

28:47

fine. I've also stored them on imager. So, here you go. This is essentially a

28:53

picture of a left wolf. So, you're more than welcome to take this link. So, you

29:00

could do that or what we can do, and I'm just going to do that here in case whatever imager goes down or something.

29:05

I'm not sure. I'm just going to make an images folder. And I've already got all

29:11

the images. I've downloaded them already because, you know, they are mine. This took me a long time to do. And I'm just

29:17

going to whack them in like so. So, here they all are. Okay. So, now you can see

29:23

them. There's link. There's some walls. It's really all of them. There's so many. Um, please feel to check out my

29:31

code. Okay. So, let's go back. So, like I said, you could do this or you could

29:37

just go to images just like that.

29:43

Okay. So, left wall we have done. So now

29:48

well actually we can go ahead and just comment these out and

29:54

ta you will see those left walls are being applied. Great.

30:00

Let's move on. Okay. So perhaps I'll just make this a little bit smaller for

30:05

you and let's carry on. So this will take a

30:11

while. We also have case B. So I don't know how you want to

30:18

do it, but we could just copy that. And this is going to be right wall and then break. And then we

30:24

have case C, which is going to be a top wall. Then we have case D, which is

30:33

going to be a bottom wall. Let's move on. Now we're

30:39

going to do W, which is going to be a top right wall. Top right wall. Then we

30:47

have X, which is going to be a bottom left wall.

30:53

Then we have Y, which is going to be a top left wall.

31:01

And then just the bottom right wall, which is going to be a Z. So bottom

31:08

right wall. Okay, cool. Now let's do the

31:13

left door. So left door. This is going to be this if you

31:19

remember from our key. And then the top door was

31:25

this little hat. So that is top

31:31

door. What else do we have? So maybe it's

31:38

better just to do that for copying.

31:43

So then we have stairs which was a dollar sign and this

31:49

was stairs. Then we have this which was lanterns.

31:56

lanterns. Then we have the other side and this was fire pot.

32:06

Fire pot. Then we have this which is slicers. So for this I'm

32:14

not going to do that. I'm going to actually call a function called called slicer which we

32:19

yet to write and pass through the column and row positions.

32:27

And then the same for this one. This is going to be for Skeletor. So let's write

32:33

a function called create Skeletor. And once again pass through X and Y.

32:41

Great. Okay. So now we need to add that here.

32:48

So we have the left wall. Let's do top wall. And once again, it's

32:54

going to be background image URL.

33:00

Just going to do this a few times. So once again, I think it's best to copy

33:06

this. We have top wall, we have bottom wall,

33:13

we have right wall, we have

33:20

bottom left wall.

33:30

We have bottom. Right wall.

33:38

We have top, left wall.

33:43

We have top right wall.

33:50

Then let's move up to the doors. So top

33:56

door, left door,

34:01

stairs, fire, pot,

34:08

lanterns. We go. Slicer is going to be coming up.

34:15

So once again, that's an image and skeletor.

34:20

Uh we're going to have another one which we haven't seen and it's kaboom for the little explosion as well. So now I'm

34:26

just going to go ahead and add those images. So once again, they live in images and this is going to be just

34:34

maybe just put that in all of these. It's a shame we didn't include that in our copy paste. Images

34:41

images. They all live in the images directory.

34:48

Okay. So like one big happy family for now. Okay. So left wall we did. Let's do top

34:56

wall, bottom wall. So apologies. This is a bit

35:03

repetitive, but it's necessary. It's a necessary evil. uh we'll know very

35:09

quickly if we got anything wrong as soon as I refresh the page because we've already done all the mapping of the

35:14

characters onto the map. So at least that's a positive, right? We're not going to carry on coding and then be

35:20

like, "Oh no, we've used the wrong image." It'll be super obvious to us as soon as we finish adding all of these.

35:27

So top right wall and then we have the top door. So let's paste that in like

35:34

so. Then we have the left door.

35:44

Then we have the stairs. Then we have the firepot.

35:52

Then we have the lanterns. Then we have the slicer.

36:02

And then we have the skeletal. And then we have the kaboom explosion.

36:08

So now, tada. This is looking good. And of course, we see we something went wrong

36:15

here. So, let's figure it out. But like I told you, super simple to find out. We found that out pretty easily. I do also

36:22

have a background. And we do also need to add our little link character. So, let's look at the top right wall first.

36:31

So, top right wall. What is up with that? Aha, it's cuz we put a dot. Okay,

36:38

so maybe the eagleeyed of you would have noticed that. But there we go. So, that is looking good. Okay, let's also add

36:45

our link positions. Even though we haven't actually added link, he will be there. So, we'll do link going left. And

36:53

this time I will copy paste everything like so. So link going left

37:03

then link going right.

37:09

Then we also have link going

37:14

down and link

37:20

going up. Okay. And once again, I already have

37:26

these in my images folder. So there's one, there's two,

37:33

there's three, and there's four. And finally, on the

37:40

grid itself, I'm going to do background URL

37:47

images. And once again, I have an image in here for the background. So, I'm just

37:53

going to do that. And I want to make it cover. So, background. I want to make it

37:59

cover the whole thing. Background size cover.

38:05

Okay. So, now it looks like this. How cool is that? So, great. I think we also

38:14

need to give the grid a position of relative as we're going to be putting stuff in there. So, let's add position

38:22

relative because we're going to position everything that goes inside the grid and we need to do it based on the grid, not

38:28

the actual browser itself. Okay. So, I'm happy with this.

38:37

I'm just also going to get rid of any padding. So, padding zero.

38:43

Let's make sure that on the divs themselves we also make the images cover them completely. So using backward size

38:50

cover and a repeat center just in case.

38:56

And we see that we missed a row. So 1 2 3 4 5 6 7 8. Let's go ahead and add

39:03

another row. So again, it's so easy to see if you've made a mistake.

39:09

Let's go back all the way to the levels here. and level one here. I'm just going to

39:16

make sure that this is indeed nine. And once again here, 1 2 3 4 5 6 7 8 9.

39:22

Okay, let's change the level to see what the second one looks like. So, I've

39:29

just changed that to a one. And this is what our second level looks like. Okay, that is good. Let's go back.

39:38

Great. I'm happy with this. So now let's move on. I'm just going to go back to

39:44

our create board function for now. And after we've essentially mapped

39:52

through all of this, but still inside the function, I want to

39:58

create player. Okay. So let's write our create player function.

40:05

So all the way down here, I'm going to write a function. I'm just

40:11

going to move this up. Function create layer

40:18

just like so. Now the main character link, we're going to essentially put him

40:24

somewhere on the grid. So let's go ahead and do that. Document

40:31

create element just like so. and create a div

40:37

const player element. And now I'm going to grab that player

40:44

element and use class name to give it the class

40:49

name of link going right which we already wrote before. I'm also going to give it a ID

40:58

so we can pick it out on the board. element id equals

41:04

player. So now once again the grid which we

41:09

picked out at the very beginning if we use append child and append the actual player to the grid or player element

41:16

that is tada link at the moment is here.

41:24

So if we look in the grid, there he is. We also need to position

41:31

him. So before we put him in, we need to position him. And what I'm going to do

41:37

is essentially calculate and set the horizontal position. So we're going to

41:42

get the player element style left.

41:48

And using back ticks, I'm going to get the player position, which we know is 40. We set it above modulus width

41:57

multiplied by tile size which is 48. Okay. So the player position modulus

42:03

width converts linear position to column number. So imagine position is 47 and 47

42:12

modulus 10 leaves a remainder of seven right because modulus finds the

42:18

remainder. So the remainder would be seven which means the player is in column seven of the grid. Now seven by

42:23

itself means nothing. We want to actually not move him to the left seven.

42:28

Move him to the left seven multiply by 48 because that is the tile size. So that would appear that he is he is let

42:36

me show you first off. However, we do have to set a position of absolute to

42:42

link. So maybe let's do it here. I'm going to do it for link going left,

42:49

link going right, link going down,

42:54

and link going up. So, position absolute is needed so in the grid. Uh,

43:02

let's also set the width and height of link. Like I said, everything is 48

43:08

pixels. So, 48 pixels. 48 pixels. And then just to make sure he's always in

43:14

the front, I'm going to set a Z index of 10. And once again, just in case, don't

43:21

think it should make a difference, but you know, just in case your images are different size, we just want to make

43:26

sure that it fits in that 48x 48 square. So now link is there.

43:35

Okay. and style left is zero pixels at the moment

43:41

because console log just get all of this

43:47

zero is being passed through into here. Okay, because 40 is our player position

43:54

modulus width leaves zero remainder and zero multiply the tile size is still zero. for this is zero pixels left which

44:02

is exactly what is being passed through. Great. So now let's do the same for the

44:08

top. So player style top and this time again in back ticks.

44:17

What we're going to do is calculate and set vertical position. So we're going to

44:22

do row multiplied by tile size. However, we're using math floor to essentially

44:28

round down. So let's say the player's position is 47 this time. 47 / 10 with

44:34

math floor is four, meaning the player is in the fourth row of the grid. But

44:41

again, we have to multiply by tile size, so he's in the right place. Great. Tada.

44:47

He ends up here. So this is looking really good. We've created our player.

44:53

I'm happy with this. Now let's do the same for enemies, right? So, let's do

44:59

it. I'm just going to clean this up like this for now. Uh, you can just do player

45:05

class name or you can do class list add

45:12

and do that if you want. Both are going to give you the same results. Okay? So,

45:19

it's up to you. I'm going to do that just because I was doing it all above here. So, let's create the slicer next.

45:26

So function create slicer. So once again

45:32

we're going to do const element this time document create element and then

45:40

we're going to create a div once more. But this div is nowhere at the moment. Okay. Let's also go element or maybe

45:47

let's be more precise and call this slicer element just cuz we did so above.

45:52

So let's get the slicer element. and do class list add and we're going to

46:00

add slicer. So an image of a slicer will be applied and a slicer element once

46:05

again style left equals and then let's

46:10

do top as well. Okay, so just like that. And for the

46:18

left, well, we're just going to use the X that we passed through multiplied by

46:23

the tile size. And for the Y or the top, we're just going to use the column that

46:29

we are looping over multiplied by the tile size. To position it vertically based on the Y coordinate.

46:36

Okay, we are not yet done. However, first of all, we of course need to grab the grid and append

46:44

child slicer element just so we can actually

46:50

see the slicer. So, let's uncomment that out for now.

46:57

So, tada, there they are. However, this has messed everything up for us. Okay,

47:03

it's kind of pushed everything out. No, this is because we also just like we did

47:09

with link. I'm just going to go to the slicer.

47:16

So, here is our slicer. I'm going to grab the slicer and grab skeletor.

47:25

And once again, we need position absolute.

47:32

Let's assign the width 48 pixels.

47:40

height 48 pixels, Z index, I'm going to go with five this

47:48

time. And once more, just in case you're using different images or they look funky, I just want to make sure they

47:54

cover the whole square. So now that looks much better. Okay, cool. So our

48:03

slices are there. The next thing to do is actually make them move. So let's do that now.

48:09

So before we put the slicer in the grid, I'm going to actually

48:15

create a slicer object with properties. So this is going to be X Y and then direction. So let's start off

48:23

with minus one. Type I'm going to go with

48:29

slicer. So this is just an enemy identifier really. and then the

48:35

reference to the DOM element. Okay, which is going to be the slicer element.

48:41

Make sure to spell direction correctly. So direction. Okay, so this is the current position.

48:49

In fact, let's just put these on that line. That's the current positions. Uh the X and Y, that's the movement

48:55

direction. This will be a minus one or a1. The identifier and the DOM element itself or the reference to the DOM

49:01

element. Okay, so we are collecting enemies. So I'm going to just push that

49:06

through. Push the

49:12

slicer in so we can keep track of them. And we know that's a slicer because in it it will say type slicer. And you can

49:18

probably even see the slicer element. Okay, so we're collecting all those enemies. That's good because we're going

49:24

to want to know how many enemies we have killed. And now using the same approach

49:29

pretty much, we're going to create skeletal. So let's do it. I'm just going

49:35

to move this all up here. Function create

49:41

skeletor.

49:47

You of course pass through X and Y. So you know the drill. Document

49:55

Create element div. Let's save this as

50:04

skeletor class name. Add skeletor

50:15

schedule element style left equals

50:23

this. and SC [Music] to element

50:31

style top is that this should actually say classless add.

50:38

Sorry. And now we can essentially uncomment out

50:43

the create skeletal function. Okay.

50:49

So now let's also get the grid. Use append

50:57

child to push in the skeletor element. We'll also get the enemies

51:08

and push in the skeletor

51:14

object that we have to make. So, const scal

51:19

equals and then let's pass through the current positions direction. Let's also

51:25

start off with minus one timer. Okay, because we're going to have a random timer for direction change on this one.

51:32

So, let's do math random. Let's call it and multiply it by five. Okay, so this

51:39

will change every 0 to 5 seconds, right? Randomly, it will produce a number from 0 to 5. The type is going to be scallet.

51:48

And I'm going to pause through the reference to the DOM object. Cool.

51:55

So amazing. I think that looks good. Once again, if I just go all the way to

52:02

the top and change the level. Tada. There's our skeletal. Amazing. So

52:09

now, let's actually make everything move. Let's just change that back to zero. and let's continue.

52:15

Okay, so that is my fold create skeletal function. Let's work on the move player

52:20

function next. And this is going to be quite a long one, so I hope you're ready.

52:26

Okay, so after the create skeletal function, I'm just going to move all this down. It's time to write our

52:32

function called move player. And the move player, this is going to handle the player movement. So we're going to

52:39

handle it by putting it through a direction. And once again, we're going

52:44

to get reference to the player doll element. So we're going to go document getelement

52:51

by ID. And luckily, we gave link an ID of player. So we can now pick him out

52:57

wherever he is on the game board. So let's also assign this to player element

53:04

just like so. And

53:09

we're going to get a new position as the current position. So let new position

53:14

and we're just going to get the player position which we set to 40 at the top of the screen. So now we're going to

53:21

handle the movement based on direction input. So whatever direction we put in, so whether it's left, right, you name

53:31

it, we have a case for it. So if he's going left,

53:36

we're going to use modulus again. So we're going to check if the player is not at left edge of grid and we're going

53:42

to do player position modulus width to give us the column number. So either it's 0 1 2 0 to 9 will come back. And if

53:50

the result is zero, it means the player is in the leftmost column and can't move left anymore. So we know where he is.

53:57

He's in the leftmost column. So that's how we're going to use modulus to figure out where he is in which column. So if

54:04

player position modulus width does not equal zero. So if

54:12

he's going left, right, he can continue going left because as long as he's not in the leftmost column, he can go left,

54:19

which means we can change the new position and it's simply going to be the player position

54:25

minus one. So it appears to be going left. Okay, so great. That's only if it

54:31

is not zero, meaning he's not in the already most left hand column. And let's

54:36

now get the player element class list add

54:46

link going left. Okay. And then we'll change the

54:53

player direction to also be left continuously

54:59

and break out of this. Now let's do the same for right. So in fact I'm just

55:04

going to copy all of this and if right. So this time I'm going to

55:10

check if player position modulus width does not equal width minus

55:18

one. So width is 10 - 1 is 9. So we know

55:23

essentially just like with the left that if the column if link is in a column

55:30

that is divisible by nine and leaves no rema remainer he's in the rightmost column but if it's not then he can

55:38

continue moving right. So we change the position we change the new position simply by adding one. Okay. And then we

55:45

change it to ring link going right. and we change the player direction to right.

55:52

So a good example of this is imagine if the player position is 29. 29 modulus

55:59

width does leave a remainder. It leaves a remainder of 9. So we know we're at

56:04

the right edge. So this does not apply. We don't do anything. However, if position is 25, 25 modulus width. So

56:12

modulus 10 leaves a remainder of five. That does not equal 9. So yes, we can continue to move right. Please take this

56:19

really slow uh if you don't understand and console log so much of this so you

56:25

can see the numbers changing and hopefully you will get it. Okay.

56:31

So once again, this time case

56:36

up and for this this time we're going to get the player position once again. This

56:46

time we're going to minus the width and we're going to check it's higher than or equal to zero. So we're just checking if

56:54

the player is not at the top edge. Um, and if the player position is for

57:00

example, so what's the top edge? It will be anything. Zero, one, two, three, four, five, six, seven, eight, nine. So

57:06

like say it's a nine. 9 minus width is minus one. That's not higher than zero.

57:12

So we would just get out of this. However, if player position is 15, 15

57:17

minus 10 is higher than zero. So then we can go up one more, which means we change position.

57:24

New position. player position

57:29

and we minus a whole width from it. Okay, we minus a whole width. We minus a whole 10 squares. Okay, a whole 10

57:36

squares. So if we're here, for example, minus 10 squares. So

57:42

will take us to here. Okay, so whole width would just mean that we're here. Another whole width would mean we're

57:48

here and so on. That's why we're minusing the width. Okay. And once again, we update the

57:56

player visually. So, let's do

58:02

link going up and player direction

58:12

equals up. And you break out of this. The last one

58:19

is down. So, I'm just going to copy all of this down. And if player position

58:26

this time plus width is smaller than

58:33

width multiply by 9, we change the position

58:39

again and this time we add a whole width. So, we can go down. So, we're just checking if he's not at the bottom

58:45

edge first. Okay. So the position has to be essentially smaller than 80.

58:51

And if he's not, well then we change the position to make him move down a whole level. So this time player going down

58:58

and then player direction is down. Okay. So I think we should check this

59:06

out. So in order to do this, we actually need to hook this up to listening out for

59:15

keyboard inputs. So key down is what we're going to listen out for. So document

59:22

add event listener

59:28

just like so. And we're going to listen out anytime we press a key down on our

59:34

keyboard. And then E for event because we're going to know which key we pressed.

59:41

And then what do we do? Well, first, if the game is not running,

59:49

we don't do anything, right? Because if the game is not running, if it's a game over, we don't want to be able to move

59:56

uh link on the board. So, do that. And

60:01

then let's use switch again. We're going to pass through the E key code that we

60:06

pass that we pressed. So, we're doing a lot of switches in here. case arrow

60:13

left. So if you press the left arrow, we move player and we pass through the

60:19

direction of left and we break out of this. So now I think you know what to

60:26

do. Let's copy this.

60:32

Let's have four arrow right. Move player right arrow.

60:41

Was it up? Just trying to do it in the same order that we did it before. And down.

60:49

We play it down. There is going to be one more case and that is if we press the space bar and then we're going to

60:56

spawn a kaboom. So we are yet to write this function. It's just going to go kaboom. Uh essentially when we attack an

61:03

enemy. Okay. So let's check it out. Okay. So now if you move and you're not

61:08

on here, there's actually a bunch of scrolling that happens here. We don't want that. So I'm also going to add the

61:14

prevent default to all of these

61:21

because we don't want any scrolling happening. Okay.

61:28

So now that shouldn't happen. Okay, cool. This is looking good. So he's

61:34

moving up. But that seems to be the only one that is happening.

61:41

We just need to actually visually make a move as well. Not just change the new

61:46

position. This actually needs to be shown on the board. So I'm also going to

61:51

get the player position now and change that to be the new

61:57

position. And I'm going to get the player element style

62:03

left back ticks. And just like we did before,

62:10

position them on the board. Player style top back ticks.

62:15

So now he should move. This is looking great. Of course, there are still fewer

62:21

things we need to figure out. For example, uh so it all the classes are adding.

62:27

This is not what we want to do. We want to completely replace the class. So that is good to know. Instead of classless

62:34

add on these, I'm just going to do class name equals to completely override it

62:42

and get rid of the other ones. So class name equals class name equals is

62:47

necessary for these. Okay, great.

62:54

Okay? Because you want to just replace it completely, not add it to a list. So

63:00

there we go. So now he will appear to me moving in all these directions. This is

63:05

looking great. I'm happy with that. Let's move on. Let's do collisions next.

63:11

So I'm just going to go ahead and still in the move player function. So after we

63:18

change the direction but before we assign the new position

63:24

we're going to check if can move to. So this is going to be

63:31

another function that we write and we're going to pass through the new position.

63:39

So let's write our can move to function. So just going to comment that out for now.

63:45

So let's do so down here.

63:53

Function can move to or pass through a position to check that

64:00

position if the player can move to it.

64:08

Okay. So if position is smaller than zero or we're checking

64:15

if the position is outside the grid boundaries right or position is suddenly larger than or equal to

64:22

squares length because obviously if it's below zero or longer than the amount of

64:28

squares we can we have then no you need to return out of this and we'll return

64:34

just a false value. Okay, so can move false

64:40

otherwise. So let's get all the squares and I'm going to pass through into that

64:45

squares array the position because we need to find out exactly what square we are dealing with. Okay, exactly which

64:52

one of these we are dealing with and pick one out to check. Just going to

64:58

save this to square as the square we are working with. And we're going to return

65:04

true if the square doesn't contain any blocking elements. Okay? So it doesn't contain a wall, doesn't contain a

65:09

lantern or anything like that. So we're going to return if the square

65:18

class list contains left wall. So we're going to return it

65:25

if it actually doesn't contain this. And if it doesn't contain I'm going to put

65:31

this on a new line a right wall. And

65:40

so once again it's going to be a lot here. Doesn't contain a

65:47

top wall and doesn't contain a bottom wall and doesn't contain a top

65:55

left wall and doesn't contain a top

66:01

right wall and doesn't contain a bottom left

66:10

wall and doesn't contain a bottom right wall and doesn't contain

66:18

lanterns and doesn't contain a fire

66:29

pot. Okay, so those are all the things

66:35

that we want to essentially

66:42

check for.

66:52

Okay. And that's it. That's really our can move to function. Um, there we go. So now we can uncomment

67:01

this out and work on it. Okay. So if we can move uh to the new position. So it's

67:08

not valid. It's not blocked by wall or an obstacle. So if that is true returns

67:15

a true, then we're going to get the square the plate is moving to. So once again, squares, we're going to look into

67:22

them. However, we're going to pass through the new position this time. So the new position that we got, and that

67:28

square is now what we're going to work with. So whatever the the future position is. And if that square

67:36

class list contains left door, then we know that it could be

67:43

open. So we're checking for interactive doors that could be opened first. So if that is true, we're just going to remove

67:49

it. Class list remove

67:55

left door. Okay, so that is one thing that we are checking.

68:02

We can also check for level progression triggers such as stairs or a top door. So if

68:08

square class list contains top door

68:16

or square class list contains

68:25

stairs and if enemies.

68:32

So all the enemies that exist, right? because we're collecting all the enemies of the level if they suddenly get down

68:38

to zero. So there's no enemies. So only if there's no enemies do we advance to the next level. So if we are about to

68:46

interact with the top door or about to interact with stairs and there's no enemies left on our game board, then we can progress to the next level. Else I'm

68:54

just going to show a message. So show enemies remaining

69:01

message and call it. So two functions that we need to write and then we

69:07

return. So we exit the function without move moving the player.

69:13

Okay, great. So I think this looks good. What do we want to work on next?

69:20

I think let's work on next level. So I'm just going to comment that out. So once

69:26

again, I think let's do this

69:32

here. So function

69:38

next level. This is actually going to be pretty easy. We'll just get the level and then

69:45

whatever the level is, we're going to add one. And then modulus

69:51

maps length. And this is actually going to allow us to cycle through levels infinitely. Of course, when you have

69:57

your own levels, you probably won't want to do this. You want to add your own, but for now, I'm just going to make them repeat over and over again. So, that is

70:03

a nice way to do this. Okay. And we're going to create board. So, create the

70:10

next board. So, great. I think that looks good. We will test that out soon.

70:17

We can't really test it out for now because we wrote a condition that we need to kill the enemies first. So,

70:22

let's maybe do that next. However, before we do that, I'm just

70:28

going to also do the show enemies remaining message. So, let's grab that.

70:34

And once again, it's going to delete a few of these

70:40

function show enemies remaining message. And what I'm going to do is just grab

70:46

the whole grid itself. I'm going to use style filter and I'm going to apply a

70:52

different hue essentially. So just a string and this is going to be applied

70:58

uh as the style filter. Okay. It's just going to create a dramatic effect of

71:03

kind of like a uh brightness. And then I'm going to do

71:08

grid style and add a box

71:18

shadow. It's going to be 20 pixels blur red. Uh zero on the X and

71:26

Y axis for the box shadow. and I'm going to remove it after a certain amount of time. So set time out is the method that

71:33

I'm going to use for this. And I'm simply just going to clear those again.

71:40

So after a certain amount of time, this is going to go back to just nothing essentially an empty

71:47

string. And that's going to happen after 300 milliseconds. Okay. So it's going to

71:52

flash red. And then I'm going to actually going to write another function. It's going to be show

71:57

temporary message and I'm going to pass through. I'm yet to write this. Defeat all

72:06

enemies first.

72:11

I want the color to be the text to be red. So I'm going to pass that through

72:16

as a string. And I want it last for 2,000 milliseconds. So now I'm going to write this function.

72:23

Okay, let's do so here. function

72:29

show temporary message. Uh and then of course we do pass through

72:34

a message. We do pass through a color and we pass

72:39

through a duration. So

72:46

I'm going to use document and I'm going to create an element. Once

72:51

again it's going to be a div. So, let's go ahead undo that. And I'm going to say

72:57

this is const message element just like so.

73:04

And I'm going to give it an ID just to make our lives easier so we can pick it out later. Temp message.

73:14

And I'm going to get the message element again and use text

73:19

content to assign the message that we passed through. and get it again and use

73:25

style color and make sure that the uh color of the text is whatever you pass

73:30

through. So in this case it's red and once again I'm going to use grid append child as a gentleman. Okay. So again I'm

73:39

going to use set timeout because I want to remove it after a certain amount of time. So set timeout

73:47

and this simply means that if there is a message element parent

73:56

node I want to get the message arament and remove it. Okay, so we it's just

74:02

safety check really to ensure elements still exist before their removal. Okay, great. One other thing I do and want to

74:09

do and this is just a safety thing is actually check if any message elements

74:16

exist. So document get

74:24

me by ID and we're going to search for anything

74:31

with temp message because we don't want to essentially you know show this if one exists already. So const existing

74:41

message we want to clear the existing message. So if there is an existing

74:46

message then we just want to get that existing

74:52

message and remove it before showing the new message. Okay. It's just kind of like a safety thing. So that duration

75:00

now I'm going to pass through here. Okay. And it's going to disappear after that duration. Great.

75:08

Let's make sure to spell message correctly here. and existing

75:16

existing existing message seems to have a lot of s's.

75:23

So let's fix that as well. Great. So that is my show

75:29

temporary message function all of that and we use it in the show enemies

75:36

remaining message. Okay, let's give this a go. So, for

75:43

example, if I try to open this door, it says, "Ah, no, defeat all enemies first." Let's style this message. This

75:50

should disappear after 2,00 milliseconds. But, ah, we're getting a

75:57

error on line 254. So, like 254 is here. Uh, this should be

76:07

removed. Sorry. Okay. So now let's style up this temp message. I'm just going to

76:12

grab it and all the way down here. So this time it's an ID and I'm going to

76:18

position it. So position absolute

76:24

top of the grid 50% because this will be in the grid. Remember we used a pen child grid to put it in the grid. Let's

76:32

give it a min width as well of 180 pixels. I'm going to also transform it.

76:39

Uh, translate minus 50% minus 50%.

76:46

Let's give it some padding. 15 pixels 25 pixels. Border radius just to soften

76:56

it by 8 pixels. Font weight bold make sure that it's in front of things. So Z

77:03

index 20 pointer

77:08

events none then back I'm just going to be RGBA. I want it to

77:15

be transparent black with 0.8 opacity.

77:21

Okay. So now the temp message. Let's go ahead. Defeat all enemies first. Okay. So

77:29

great. I love it. Okay, so this is looking good. Uh, we are able to move

77:36

through walls. So, let's carry on working on that and see if you go

77:41

through a left door and interact with it, it just disappears. So, it looks like you can go back through there. That

77:46

is a useful one for when you want to make more levels. Let's continue.

77:51

Okay, so back in the move player function. Ah, it would seem we could only move the player position. So, there

77:59

we go. if we can move to the player position. So still inside this if statement we will

78:06

put that code. Great. So now tada this

78:12

is looking good. We cannot interact with certain things. And if we try go through the door it says defeat all enemies

78:18

first and we get this nice glow around it. This is looking great. Now this means we can move on to making a kaboom

78:25

to kill enemies. So let's do it. So let's go down here. I'm going to

78:32

write it here. So function

78:41

spawn kaboom. And this time we're going to

78:46

calculate player's current grid coordinates and extract the column and row from linear position for attack

78:52

placement. So this just means that we're going to give the player position

79:00

modulus width and that is going to be let kaboom

79:06

x because we want the kaboom to appear in front of the player. So we're going to have to do a few things. We're going to have to figure out where the player

79:12

is and figure out which square to put it in based on if he's facing left, right, up, or down. Uh let's also get let

79:21

kaboom y. And this time we're going to do math

79:28

floor and pass through the player position divide by width.

79:36

Okay. So now we're going to switch and pass through the player direction.

79:42

Uh, and like I said, if he's going left, well, then we're going to get kaboom

79:50

x and attack one square to the left. So, actually, we're going to minus

79:58

one from it. So, wherever the player is, we minus one because that's where we want kaboom x to appear.

80:07

And break. And let's do the same for case write kaboom x. This time is going to be

80:13

+ one. Let's do the same for case up. This time we're going to get kaboom

80:19

y and minus one and case direction down. This time we're going to

80:26

add one. And the y kaboom y. Okay. So spawn kaboom. That's it for

80:34

checking where the kaboom will show up. So still inside the function. Make sure

80:39

you're still inside the function. This I'm going to check if attack position is within the grid grid game boundaries. So

80:46

if kaboom x is larger than or equal to

80:52

zero and so we've used this logic before. Kaboom x

80:58

is smaller than the width plus kaboom y is larger than or equal to zero

81:06

plus kaboom y is smaller than nine. So if all

81:12

those are true then yes you are within the game grid boundaries and we're going to use document. We're going to create

81:18

an element. So you know the drill. Let's create a div. Let's assign this to a

81:25

constant kaboom element

81:30

just like so. Let's get the kaboom element. Just use

81:37

class name and just override it to be kaboom.

81:45

Okay. So now once again we're going to get the kaboom element style

81:51

left and just assign it the kaboom x multiplied by the tile size

82:02

pixels. Make sure that's all in that. And once again kaboom style top this

82:08

time. So let's use the y multiply by the time tile size. And now once again,

82:14

let's grab the grid append child kaboom element. Okay,

82:22

cool. And what I'm going to do is just

82:27

this time also I need to remove the

82:33

explosion. So set time out. And if

82:40

kaboom element parent node exists, then we get kaboom element parent node remove

82:48

child kaboom element. Great. And this will happen after 1,00 milliseconds. I

82:55

love it. Okay, so there we go. We can close that up now. Uh one other thing we

83:01

actually sorry I need to do is check kaboom

83:07

enemy collision we'll pass through kaboom x and kaboom

83:13

y. So we need to actually check if it worked really. So check kaboom enemy collision. Let's

83:21

just tidy this up a little bit. Okay, that looks good. So down here

83:27

function check kaboom collision

83:33

and we're going to loop through all the enemies that we have collected an array backwards to safely remove items during

83:38

iteration. So for let I equals

83:46

enemies means length

83:52

minus one. I is larger than or equal to zero. We're going to get I and just go

84:00

down. So let's get the enemies array and we're

84:06

going to pass through I to pick out the enemy that we are working with and I'm just going to save it as enemy.

84:13

Then let's get the round enemy positions to the nearest integer for accurate collision detection. So let's get enemy

84:22

X. I'm going to actually pass it through a math round

84:30

just like that and assign it just to enemy X. Okay, so there we go.

84:40

And we have enemy Y, enemy Y.

84:46

And if any of these positions, so if enemy x dp equals

84:54

kaboom x and

85:00

enemy y deeply equals kaboom y,

85:06

then we remove the enemy's visual element from the gra grid. enemy element

85:13

parent node. If that exists, we get the

85:18

enemy parent node and remove child

85:25

enemy element. So just like that.

85:30

Okay, great. So now let's pass through this in here

85:37

and kum Y. So after removing it visually we also need to remove it from the

85:43

enemies array. So enemies splice I one and then we increase

85:52

the player score. We update displays. So

85:57

we update the UI with the latest score and we break out of this.

86:04

Okay. So update displays. Now we are yet to write this function.

86:11

Okay. So maybe let's do that here. Function update displays.

86:18

We're just going to get the store display that we literally picked out at the very very beginning. You're going to use inner HTML to just display the score

86:25

and then the level display

86:31

inner HTML to display the level plus one. Right?

86:37

Because here we're counting at zero, but to the human eye we want it to appear as one. and the enemy display

86:46

inner HTML. We're going to get the enemies array and just get the length of

86:51

all the enemies that we've collected in there. Great. So, that's really it to update the score. That was an easy

86:58

function to write. Cool. Once again, this actually needs to

87:04

happen here. So, if both of these equal that. Wonderful. So that is my whole

87:12

check kaboom enemies collision method written already. Wonderful.

87:19

So great, we're doing that here. We've written the function spawn kaboom.

87:25

So now we can comment that out basically where we press the space bar. So let's

87:31

go all the way back here to the bottom and uncomment that out. So we should now

87:36

be able to spawn kabooms. So ah it spawns there. That's because we need to

87:44

do some styling. So here on the kaboom once again we need position absolute.

87:54

Let's add a width of 48 pixels

88:00

a height of 48 pixels. a Z index of

88:07

15. And then once again, let's just do background size cover, no repeat center.

88:15

One other thing I'm going to do is just write an animation. Uh, this is going to be explode. That's what I'm calling it.

88:21

One second. Ease out forwards is what I'm going to do. And now I'm going to

88:27

get key frames explode.

88:34

0% transform

88:40

scale 0.8

88:46

opacity one

88:51

and then at 100% of the animation I want to just

88:58

transform it to 1.2 two and opacity zero.

89:07

Great. So that is my whole kaboom and that is my frames, my key frames. And

89:13

this just means if I now press the space bar, tada. Kind of expands and goes

89:19

away. I love it. So this is looking good. Let's continue. Let's go back to

89:25

our app. Okay. So as we are at the bottom of the file here is the bottom of

89:32

our whole file. One things that I would like to do

89:37

is also write the game over function.

89:43

And we're actually just going to get game running

89:51

and assign false. And we're going to use the show temporary

89:57

message function that we wrote previously to just type game

90:04

over. So we're passing through the string of game over

90:11

final score and then we're going to pass through the actual score. Okay. We're

90:17

also going to say that we want the text to be white and we want this to last for 3,000 milliseconds. So that's the text

90:24

that we're going to show. So we'll leave that for now.

90:31

Okay. So we're showing temporary message. We're showing enemies remaining. We're updating displays. I

90:37

think what would be good if we start moving the slicer. So maybe let's do that here. Function

90:47

move slicer.

90:52

Let's pass through the slicer. Let's pass through delta time. So, this is going to handle slicer enemy movement

91:00

back and forth. Uh the speed. So, con speed

91:06

const speed. But what we're going to do is just going to be 2 multiplied by delta time. You can mess around with

91:13

this. Okay, I've already kind of done this. Uh this is essentially calculating speed movement by saying two units per

91:20

second scale by delta time for smooth animation. Next I'm going to calculate the new horizontal position based on

91:26

current direction. And for this I've already kind of done this. So there we

91:32

go. And then I'm going to get the current vertical position as well. Okay.

91:38

So this is rounded for wall checking. Now we're going to check for boundaries or wall collisions.

91:44

So again, we've kind of done this logic before just checking that we're not on zero or

91:51

new x is larger than the width

91:57

or then we're going to write a function is wall because we want to check if there is a wall and I'm going to pass

92:02

through bar math round. So rounded down new X

92:10

and Y. Okay. And then we're going to get the

92:15

slicer direction and just reverse it. So this is a nice

92:21

way to reverse whatever's there. If it's a minus one, it becomes a one. And if it's a one, it becomes a minus one.

92:28

Okay, great. Else we just want to update

92:33

position if movement is valid. So slicer x equals new x. Now what we're just

92:40

going to update visual position of the slicer element. So you know what to do.

92:45

We're going to get the elements star left and update the slicer x with it.

92:51

Great. So now let's write the is wall function. So function

92:57

is wall. I'm going to pass through the x and the y.

93:03

And this is just a function to check if a grid position contains a wall or a blocking element. So first we're going

93:09

to convert grid coordinates to array index. So that is how we can do it. And

93:16

next we're going to check if a position is outside the grid bound. So this going to return to true if position

93:23

is smaller than zero or position is larger than squares

93:31

length we return true.

93:37

Okay. And now let's get the square element at this position. So once again we go into the squares array to get the

93:46

current square. And let's just assign it to con square. And you've kind of already done this before. So this time

93:53

I'm going to check if swear contains any blocking elements. So I'm actually just going to copy this

94:01

from here.

94:07

Okay. So please go ahead and do the same. Just paste it like so. However,

94:13

this time we are returning if this is true. Okay.

94:19

So if it does contain a left wall

94:25

or so let's change all of these to or instead of ants.

94:33

Okay there

94:39

we go. So that is our iswool function.

94:46

And finally, just like we wrote move slicer, we're going to move skeletal. So

94:53

maybe let's do that here

94:58

function move skeletor

95:06

going to pass through skeletor pass through delta

95:12

time. We're going to calculate the movement speed. We're going to go with 1.5 units per second, which is slower

95:19

than the slicer. We're going to decrease the direction change timer. So, we're

95:26

going to randomly move skeletal. So if skeletal timer is suddenly smaller than

95:33

or equal to zero, I'm simply going to get the skeletal

95:39

direction and multiply by minus one. So you know

95:44

that that will change it to a one if it's a minus one and a minus one if it's a one. We're going to get the skeletal

95:50

timer and just reset it. So we're going to do math rand done

95:57

call it multiply by five. Okay. And now let's essentially calculate the new

96:05

vertical position based on current direction. So we're going to do that

96:11

by getting skeletal y plus the skeletal direction multiply the speed and that's the new direction that we are going in.

96:18

And we're going to get the current horizontal position too. So we're just going to get

96:24

skeletal x pass it through math round and assign it to the const x. Once again

96:31

just like we did with the slicer we need to check for boundary or wall collision.

96:37

So if new y is smaller than zero or

96:44

new y is larger than or equal to 9 or is

96:50

wall and we pass through x and this time math

96:57

round new y then we get skeletor

97:07

Just going to copy that to save myself writing skeletor direction

97:12

and change it

97:18

else skeletal y is just the new y. We update

97:25

the position if movement is valid and we have to visually

97:30

update skeletal on our game boards.

97:36

Great. Okay. So that is all looking good to me.

97:42

Correct this to be round. Okay. Correct that from here to be

97:48

round. Okay. So we are nearly done. And I'm just going to write one function to bring that all together. So above both

97:55

of these, this is the main function that will move the enemy position based on

98:01

elapse time. So move enemies delta time and for const enemy

98:11

of enemies if enemy

98:16

type equals slicer. Remember we added that to the

98:22

enemy object then we're going to get the move slicer function pass through the

98:28

enemy and a delta time

98:33

else if I guess enemy type equals scour

98:45

we move sk and pass through enemy

98:53

and delta time. Okay, so that is our move enemies

98:59

function. Great. So now we have to put this in a game loop.

99:05

So all the way down here all the way at the bottom. Let's do

99:11

above the game over function

99:18

game loop. Let's pass through the current

99:24

time. So this is going to be called every frame by the browser.

99:30

We're going to get delta time. And delta time is simply

99:36

the current time minus the last time divide by

99:44

1,000. So this is calculating the time elapsed since last frame in seconds. And then

99:51

we're going to update the last time to be from the current time. So current

99:57

time is now the last time. I'm going to set let

100:03

last time here to be zero. And I'm also going to save the animation ID here. So

100:10

that's going to be the ID of the current animation frame request. Okay. So now if the game is running

100:21

and delta time is smaller than 0.1,

100:27

I'm going to move enemies

100:32

and pass through delta time. I'm also going to check player

100:38

enemy collision. Uh we have not written this yet, but that is something I'm

100:44

going to do. So now that game loop is defined, I'm going to schedule the next

100:50

frame. So I'm going to grab the animation ID, request animation, and pause through the

100:58

game loop. Okay, animation frame. So

101:04

that is looking good. And we're also going to initialize

101:12

the game here. here. So I'm actually just going to copy this down here. So this is outside that function. This

101:18

should actually be inside this function still. So that is in the game loop function.

101:24

So let's write this function as well. So let's just go back up here. Function

101:35

check player enemy collision. So this is to check if the player collides with the

101:40

enemies. That is something that we are going to write. Great.

101:47

Now we are referring to the skeletal element and the slicer element here.

101:53

However, if you remember when we created the elements. So let's go all the way

101:59

back here. We pass it through as the skeletal element. I think it's easier for us to just pass it through perhaps

102:06

as the element Skeletor

102:14

element. So we can access it for both enemies. So that is for Skeletor. And

102:20

for the slicer again, let's just pass it through as an element just like so.

102:26

Okay. And great. So now I'm just going to comment out the check player enemy collision in our

102:33

game loop. And if I kill one. Amazing. So, we are

102:40

killing the enemies. As you can see, enemies went down to zero. Score went up to two. I've killed all the enemies. And

102:46

now I can progress at the next level. So, that is something that we're going to have to work on. But I love it. This

102:53

is looking good. Uh, when we go to the next level as well, we should do some

102:58

clearing of things. So, let's go back to the create board function all the way up

103:04

here. So here is create board and I'm just

103:09

going to reset. So reset game running to be

103:15

true. I'm going to get the grid inner HTML and just put an empty string.

103:24

I'm going to get squares length

103:29

and just do zero. and enemies. I will clear again because we're going to start

103:35

from scratch. So, this just means that if I now let's kill the enemies. Kill

103:40

the enemies. Can't die yet. So, that is good. Okay, that is looking so much

103:45

better. I love it. So, one last thing to do and that is check for a collision

103:51

with an enemy. Let's go. So, all the way back down here. Yes, I commented it out.

103:58

I'm going to uncomment that. Let's write this function which we kind of started doing already

104:07

here. So let's uncomment that out. And this time we're going to calculate the

104:13

players current grid coordinates. So let's get the player X's by getting

104:20

the player position modulus width. Let's also get the player Y by getting the

104:27

player position divided by the width pass through math floor. So for example,

104:34

if the player position is 84, 84 modulus width gives us a remainder of four,

104:40

meaning that player is in column 4. And for this if 84 / 10 rounded down gives

104:48

us 8 which means that player is in row 8 four const enemy

104:57

of enemies. We're going to do the same. We're going

105:03

to round enemy positions for accurate collision detection. So we get the enemy

105:08

X and Y. And if, so still in the loop, if

105:15

enemy X deeply equals player X and if enemy Y deeply equals Y, it means that

105:21

the enemy and the player are in the exact same position. And then we can trigger a game over. Okay. And then

105:27

let's return out of this. So that is the whole function really. It was quite a simple one in comparison to some of the

105:34

others. Just remove that and let's test it out.

105:40

So now I die. We get a game over. I can't move at all. Okay, we should

105:45

probably remove that scrolling as well. But this is looking good. Okay, I'm

105:52

happy with this. So, we've done it. I think we have finished the game. Really,

105:58

this is looking so so good. Let's kill this one, too. Bam. Bam. Bam.

106:05

I love it. And then we keep going and going. Okay, great. Let's do some

106:11

tidying up next. So, one thing that I do want to do is just get the create board

106:18

function. Just remove the console logs. Put the create board function all the

106:23

way at the bottom. This is kind of to initialize the game. Get rid of any

106:29

extra spacing that we did. So, just like that.

106:39

Okay. And I think I'm happy with this.

106:47

Okay. So, one thing I've noticed in the move player function, we should also probably call the check

106:57

player enemy collision here as well. So, I'm just going to add that there. Also

107:03

in my create board function, I'm just going to update displays there too. So when we create player, we update the

107:10

displays here as well. In my show enemies remaining function, I

107:16

wrote filter wrong for some reason. So let's

107:21

change that filter. Just going to change this here to be bigger than or equal to. So larger or

107:30

equal to. And that should be it. One last thing I'm going to do is just

107:36

do overflow hidden to stop any pesky scroll bars from showing up. Okay, so

107:42

that's it. I hope you've enjoyed code along with me. I thought this was super super fun. I love this game of Mario and

107:48

I really feel like it has the potential to be an incredible game. Please take it, make your own. I'd love to see what

107:54

you make with this. So please do share it with me at me, you know, on Twitter, Instagram. I would love to see. Okay.

108:01

So, I hope you enjoyed and I'll see you again soon.

No comments:

Post a Comment