For foreigners/English

Tetris game development #1-JavaScript, HTML, CSS, responsive web

아미넴 2020. 11. 15.
반응형

Select the language you need from the flag button at the top of the blog.

All content on this blog can be translated using the translation function.

 

The original of this article is here.

sangminem.tistory.com/37


The first thing that comes to mind when developing games is board games,

Among them, I think it is Tetris.

 

Besides, the recent web language is highly utilized and the interest is growing.

From now on , I am going to make a Tetris game using only pure HTML, JavaScript, and CSS .  


Demo page

sangminem-game.web.app/tetris/play.html

 

When completed, it works like the site above.

Are you not looking forward to it? hehe


GitHub source sharing

github.com/sangminem/tetris

 

We share the finished source on GitHub

I hope you use it for learning purposes only :)


 

In this post, I will simply configure the screen.

 

1. Space for real blocks

2. Space to display the next block

3. Space to express levels, remaining lines, and scores

 

We will make the above three points into a responsive web in order to consider mobile support in the future .

<!DOCTYPE html>
<html>
    <head>
        <title>Tetris</title>
        <link href="common.css" rel="stylesheet"/>
    </head>
    <body>
        <div class="wrap">
            <div class="main-contents">
                <canvas id="main-board" class="main-board"></canvas>
            </div>
            <div id="side-contents" class="side-contents">
                <canvas id="next-board" class="next-board"></canvas>
                <p>Level: <span id="level">1</span></p>
                <p>lines: <span id="lines">0</span></p>
                <p>scores: <span id="score">0</span></p>
            </div>
        </div>
        <script src='main.js'></script>
    </body>
</html>

First, I have composed the body part.

Wrap the whole thing once using the wrap class

In it, it is divided into main-contents and side-contents.

 

In main-contents, to implement the board on which the actual game will be played

I used the canvas tag (element) .

 

In the side-contents, the next-board part to show the next block  was written as a canvas tag.

The level, line, and score parts are also placed in text simply using p tags.

 

And I simply included one css file and one js file.

I am going to write the overall style and logic here.

 

Now, I'll write css, but I'll briefly introduce the font to use before that.

github.com/Dalgona/neodgm/releases/tag/v1.50

 

It seems that a person named Dalgona is modifying the round cap font to be more complete.

It is also free to use and the font is pretty. :)

You can download neodgm.woff from the site above.

 

@font-face {
    font-family: 'NeoDungGeunMo';
    src: url('neodgm.woff') format('woff');
    font-weight: normal;
    font-style: normal;
}

If you write the following in common.css, you are ready to use fonts on the web.

 

 

 

 

 

 

 

 

Next, let’s write:

* {
    font-family: 'NeoDungGeunMo';
    background-color: darkblue;
    color: white;
}

html {
    font-size: 10px;
}

First, the font to be used for all tags, and the default background and text color were specified.

And in order to implement the font size as responsive

The top tag, the html tag, has a fixed size of 10px.

The unit of relative font size, rem, moves based on the html font size.

 

Now let's specify the style for each class.

.wrap {
    display: grid;
    grid-template-columns: 2fr 1fr;
    width: fit-content;
}

.main-contents {
    padding: 1vw;
}

.side-contents {
    padding: 1vw;
    font-size: 1.6rem;
}

.main-board {
    border: 2px solid white;
}

.next-board {
    border: 2px solid white;
}

First, to use the grid layout

In the outermost tag class wrap,

Set the display property to grid.

Then, using the grid-template-columns property

I divided the ratio between main-contents and side-contents by 2:1.

And if the browser width is larger than a certain size,

I used fit-content as the width property.

If you would like to know more about fit-content, please refer to the site below.

https://o7planning.org/en/12557/the-keywords-min-content-max-content-fit-content-stretch-in-css

 

The main-contents class gave you 1vw of the inner margin.

1vw means 1% of the total width of the window.

 

The side-contents class also gives 1vw padding.

I set the font size to 1.6rem, which means 1.6 times the 10px specified in html.

 

The main-board and next-board gave a 2px thick white border.

 

 

 

 

 

 

 

 

How about writing and running this far?

Something is incomplete.

That's because you haven't specified the canvas size yet.

After all, the font is pretty. Heh

 

Then I'll write main.js to specify the size.

const canvasMainBoard = document.querySelector('#main-board');
const ctxMainBoard = canvasMainBoard.getContext('2d');
const canvasNextBoard = document.querySelector('#next-board');
const ctxNextBoard = canvasNextBoard.getContext('2d');

const COLS_MAIN_BOARD = 10;
const ROWS_MAIN_BOARD = 20;
const COLS_NEXT_BOARD = 4;
const ROWS_NEXT_BOARD = 4;

First, take the two canvas elements written in html and put them in a global variable

Call the getContext method to indicate that you want to draw in 2d.

 

And to specify the horizontal and vertical dimensions for the main-board and next-board

You have declared the number of rows/columns you need.

 

Next, as I mentioned earlier, to make it a responsive web

We are going to write a function that recalculates the size whenever the browser size changes.

function resize() {
    const WINDOW_INNERWIDTH = (window.innerWidth > 660)?660:window.innerWidth;
    const MAIN_CONTENTS_WIDTH = Math.floor(WINDOW_INNERWIDTH*0.6);
    const BLOCK_SIZE = Math.floor(MAIN_CONTENTS_WIDTH/COLS_MAIN_BOARD);

    ctxMainBoard.canvas.width = BLOCK_SIZE*COLS_MAIN_BOARD;
    ctxMainBoard.canvas.height = BLOCK_SIZE*ROWS_MAIN_BOARD;
    ctxMainBoard.scale(BLOCK_SIZE, BLOCK_SIZE);

    ctxNextBoard.canvas.width = BLOCK_SIZE*COLS_NEXT_BOARD;
    ctxNextBoard.canvas.height = BLOCK_SIZE*ROWS_NEXT_BOARD;
    ctxNextBoard.scale(BLOCK_SIZE, BLOCK_SIZE);

    const FONT_RATIO = WINDOW_INNERWIDTH/350;
    document.querySelector('#side-contents').style.fontSize = FONT_RATIO+'rem';
}

 

First , I set the maximum width to prevent the board from getting  too big .

I set it to 660px, but you can set it appropriately according to the situation.

It can also be specified in css, but when used with the canvas element's scale method

As the ratio was not properly reflected, it was unavoidably implemented in JavaScript.

 

Next, out of the main-contents and side-contents areas divided by a 2:1 ratio

To calculate the main-board size in the main-contents area

We decided the main-contents area to be 60% of the window width

Accordingly, we found the size of one block.

If the calculated value is not an integer, the block cannot be expressed neatly, and less than the decimal point is discarded.

 

Based on the block size, the width and height of the main-board canvas were calculated again.

One pixel is enlarged by BLOCK_SIZE by using the scale method.

So, if you multiply the BLOCK_SIZE by the number of rows/columns, you get the canvas size.

 

The next-board canvas was also calculated.

Using the BLOCK_SIZE calculated based on the main-board

We found the size of the 4x4 canvas to display the next block.

 

The next is the font size, which can get tricky

I started with a fixed size of 10px in the html.

And if you use rem units, it's easy to calculate.

For example, a size like 10px is 1rem

If you want a size of 15px, you can declare it as 1.5rem.

 

Here, when the window width is 350, it seems to be suitable for 10px size.

I calculated the ratio based on that standard.

Whenever the screen size changes with that ratio, the font size is recalculated.

 

Once you have created the resize function, you should call it whenever the size changes.

(function (){
    main();
})();

function main() {
    resize();
    window.addEventListener('resize', resize);
}

I declared a main function and called the resize function once.

I wrote that using an event listener, the resize function is called whenever the resize event occurs.

And the main function is called when the page is loaded.

 

 

 

 

 

 

Then I'll try it again.

The shape is more beautiful than before, right?

The canvas size has also been initialized to the desired size.

 

Reducing the screen size does not change the shape, but only the proportions are smaller.

 

Now that the basic frame has been created

From the next post, we will create functions one by one.

Please look forward to. :)

 

#Next Lecture

sangminem.tistory.com/38

 

반응형

댓글

💲 추천 글