19. January 2019

How to find unread email in Gmail Inbox

Sometimes it’s hard to find unread emails in Gmail Primary Inbox. Browsing manually through the whole inbox is not very effective.

The solution is quite simple. Type following expression into the search field of Gmail:

category:primary is:unread

10. January 2019

IntelliJ Idea vertical text block selection

It’s easy to create vertical text block selection in IntelliJ Idea.

  • macOS: Option + Command + Left click and drag mouse
  • Windows 10 – Creators update: Click Mouse wheel and drag
  • Older Windows: Alt + Left click and drag mouse
  • Linux: Click Mouse wheel and drag
  • Without mouse: Open Edit menu and select Column Selection Mode (Alt+Shift+Insert), then use Shift + Arrows to select a block

You’ll select vertical text block:

9. January 2019

IntelliJ Idea zoom text by mouse wheel

Common feature in many application is possibility to zoom text content by Ctrl + Mouse Wheel.

IntelliJ Idea has this feature, but it’s disabled by default.

You can enable zoom in few steps. Open Settings (Ctrl+Alt+S), search for “zoom“, select Editor.

Check the option “Change font size (Zoom) with Ctrl+Mouse Wheel“. Click OK and enjoy the zoom feature :-)

6. January 2019

How to write game with Vue.js – Sokoban – Part 4 – Move avatar by mouse click

In previous article we displayed also game objects. Now it’s time to add some movement.

We will use mouse click to navigate an avatar around the stage. It seems pretty straightforward, but there are several gotchas. Let’s explore them.

First of all we need to revisit the topic of Vuex store which we mentioned in the first article. It’s a very simple yet powerful design. All information about the state of the game is stored in the store. When you’d like to change something you dispatch a commit from your code and store methods will create a new state. In Vuex store these methods are known as mutations.

Let’s design simple mutation moveObject where we will send game object and two vectors in file js/game.js.

const store = new Vuex.Store({
...
    mutations: {
        moveObject(state, { gameObject, vectorX, vectorY }) {
            gameObject.x += vectorX;
            gameObject.y += vectorY;
        },
    }
});

You may wonder about interesting syntax of moveObject. The second attribute is an object which contains three attributes. If you write code this way it will allow you to pass more than one attribute to mutation function.

Values of vectorX and vectorY will be -1, 0, 1. We can send this values from method in component playground.

Vue.component('playground', {
    ...
    methods: {
        moveGameObject: function(gameObject, vectorX, vectorY) {
            store.commit("moveObject", { gameObject, vectorX, vectorY });
        },

This code here is pretty straightforward. It’s just transporting information about a move from component to the store. Now we need to tell HTML component to listen on click and send it to component. We will use v-on:click to send the event to JavaScript method mouseClicked. Note: @click is shorthand for v-on:click.

<script type="text/x-template" id="playground-template">
  <div @click="mouseClicked">

Now we’re missing just the last piece of the puzzle to make this thing work. It’s the method mouseClicked. This one will be a little bit tricky. Let’s split the method into several parts. In the first part, we will need to determine coordinates where a user clicked relative to the component. This requires some computation because the object of event does not contain the information about relative coordinates.

methods: {
        ...
        mouseClicked: function(event) {
            let rect = event.currentTarget.getBoundingClientRect();
            let scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
            let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
            let top = rect.top + scrollTop;
            let left = rect.left + scrollLeft;

So we have the coordinates of click relative to the component. We would like to know whether a user clicked left, right, below or above the avatar. We need this information to determine in which direction avatar should move. We will retrieve coordinates of the first object (avatar) from the store. Then we will compute delta so we can decide the direction.

            let avatar = this.$store.state.gameObjects[0];
            let deltaX = (event.clientX - left - 32)/64 - avatar.x;
            let deltaY = (event.clientY - top - 32)/64 - avatar.y;

You may wonder why we’re dividing coordinates by 64. It’s size of tile from previous articles.

Based on delta we can decide what to do. First of all, it’s good to eliminate case when we should not do anything.

            // Ignore clicks within avatar box
            if (Math.abs(deltaX) < 0.5) {
                deltaX = 0;
            }

            if (Math.abs(deltaY) < 0.5) {
                deltaY = 0;
            }

           // Do not move in case of click inside the icon of avatar
            if ((deltaX === 0) && (deltaY === 0)) {
                return;
            }

Let’s add code for deciding in which direction should the main character move.

          if (Math.abs(deltaX) > Math.abs(deltaY)) {
                if (deltaX > 0) {
                    this.moveGameObject(avatar, 1, 0);
                } else {
                    this.moveGameObject(avatar, -1, 0);
                }
            } else {
                if (deltaY > 0) {
                    this.moveGameObject(avatar, 0, 1);
                } else {
                    this.moveGameObject(avatar, 0, -1);
                }
            }
        }

The result should look like this and it should react on mouse click:

The source code of this article is stored at Github branch article-04.

In the next article, we will add checks so the avatar does not move through other objects or walls.

You can find more HTML5 games at https://georgik.rocks/tag/games

Back to tutorial Sokoban in Vue.js

5. January 2019

How to write game with Vue.js – Sokoban – Part 3 – Display game objects

In previous article we were talking about graphics tiles. Now we would like to display game objects. Sokoban contains just two types of objects: avatar and boxes.

We will store these game objects in a list and we will use the same CSS trick to display graphic for each object like in the previous article. We will load just one PNG and define class for each tile that should be displayed.

Let’s define one avatar and one box in js/game.js:

const store = new Vuex.Store({
    state: {
        ...,
        gameObjects: [
            {
                name: 'avatar',
                x: 1,
                y: 1
            },
            {
                name: 'box',
                x: 2,
                y: 2
            }
        ]
    }
});

The template for HTML in index.html will iterate over the list. It will set coordinates using top and left CSS attributes. Graphics will be mapped by class name.

<script type="text/x-template" id="playground-template">
    <div>
    ...
    <div v-for="(gameObject, index) in gameObjects"
            :class="['game-object game-object-' + gameObject.name]"
            :style="{ top: gameObject.y*64 + 'px', left: gameObject.x*64 + 'px'}">
    </div>
    </div>
</script>

The last remaining thing is to define picture mapping in css/game.css from tiles.png.

.game-object {
    width: 64px;
    height: 64px;
    position: absolute;
    background: url("../data/images/gfx64/tiles.png") -192px -192px;
}

.game-object-avatar {
    background: url("../data/images/gfx64/tiles.png") -192px 0;
}

.game-object-box {
    background: url("../data/images/gfx64/tiles.png") -128px 0;
}

The result should look like this:

The source code of this article is stored at Github branch article-03.

In the next article, we will add controls to player’s avatar so it could move around the scene.

You can find more HTML5 games at https://georgik.rocks/tag/games

Back to tutorial Sokoban in Vue.js