loading...

Angular idle game tutorial: basic setup.

akkonrad profile image akkonrad Updated on ・4 min read

Intro

Hi. This will be a very short intro for the very basic tutorial in angular. We will develop a very simple idle game, that shows how we can use Angular with NGRX and RXJS, but it will touch a few different aspects of the app as well.

Plan

The goal is to create a game with basic idle/click game functionality: gain by click, gain by time, gain by idle, bonuses, perks, improvements, etc. Only necessary text and a lot of code, with repo as a source. Everything based in angular 10 and bootstrap 4 CSS to not reinvent the wheel for basic components.
Because of recent presidential elections in Poland, I'm a bit disappointed, this game will be about a politician that wants to be a president. We will incrementally improve the complexity of the game, but we will start very simple.

Preparation

Initialize the app

First, install Angular CLI if you don't have it yet

npm i -g @angular/cli

Then just start the project and follow instructions

ng new idle


a value and then it

Then, add bootstrap to our project.

npm i bootstrap

...and include it in angular.json so the CSS classes will be accessible inside your IDE. We need new entry in projects\[project-name]\architect\build\options\scripts so the angular.json will look like this:

{
  ...
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/idle",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "aot": true,
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "./node_modules/bootstrap/scss/bootstrap.scss",
              "src/styles.scss"
            ],
            "scripts": []
          },
  ...
}

Finally, let's add bootstrap CDN to the <head> element in the index.html file

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

Icons

For icons, we will use font-awesome@4 since it's free. However, you can use whatever you want.

npm i font-awesome@4

Then we need to add it to angular.json in the same way as bootstrap.scss

Basic template

We will use mainly app.component.html and child components for now. So let's create it quickly:

<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
  <div class="container">
  <a class="navbar-brand" href="#"><i class="fa fa-gamepad" aria-hidden="true"></i> Idle</a>
  </div>
</nav>

<div class="container">
  container
</div>

Let's go!

Finally, the meat.

Value display component

We will need a simple component that will display the value of some resources (cash, influence, popularity etc). We assume that there will be a few of them to illustrate the data, so we want to specify a color and icon for each. So let's create it first with the CLI command:

ng generate component components/value-display --skip-tests

We won't write tests for that app, although it could be interesting, I want to focus on a different aspect of the angular app.

And let's fill it out:

// value-display.component.html
import { Component, OnInit, Input } from '@angular/core';
import { Color as COLOR } from '../../types';

@Component({
  selector: 'app-value-display',
  templateUrl: './value-display.component.html',
  styleUrls: ['./value-display.component.scss']
})
export class ValueDisplayComponent implements OnInit {

  @Input() title: string;
  @Input() color: COLOR = COLOR.primary;
  @Input() icon: string;
  @Input() value: number;

  constructor() { }

  ngOnInit(): void {
  }

  getTitle() {
    return this.icon ? `<i class="fa fa-${this.icon}></i> ${this.title}` : this.title;
  }

  getText() {
    return this.value;
  }
}
<!-- value-display.component.html -->
<div class="card my-3" [ngClass]="'bg-' + color" >
  <div class="card-header">
        <i *ngIf="icon" class="fa" [ngClass]="'fa-' + icon"></i> {{ title }}
  </div>
  <div class="card-body">
      <p class="card-title" [innerHTML]="getText()"></p>
      <p class="card-text small"><ng-content></ng-content></p>
  </div>
</div>

Engine

We will need to control the time for a few purposes. So for now, we will create an engine.service.ts that will take care of that.

ng g s engine --no-spec
import { Injectable } from '@angular/core';
import { interval, Subscription, Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class EngineService {
  time$: Observable<number> = interval(1000);

  constructor() { }
}

We also need to add it to app.module into providers array.

Then we can update our app.component

export class AppComponent implements OnDestroy {
time = 0;

  subscriptions: Subscription[] = [];

  constructor(private engine: EngineService) {
    this.subscriptions.push(this.engine.time$.subscribe(time => {
      this.time = time;
    }));
  }

  ngOnDestroy(): void {
    this.subscriptions.map(subscription => subscription.unsubscribe());
  }
}

And then update the app.component markup:

...
<app-value-display class="col-4" [icon]="'clock-o'" [title]="'time'" [value]="time" [color]="'warning'">
      time goes by
    </app-value-display>
...

And voila!

game day #1

Summary

You can get the codebase from github. If you have any ideas on how the game could look like, or any other question, please let me know in the comments!

Discussion

pic
Editor guide