Дмитро
Дмитро
Developer Python, PHP, Javascript
23.08.2019

Створення карткової гри Blackjack

Дмитро
Дмитро
Developer Python, PHP, Javascript
23.08.2019
23.08.2019
5.0
6867
25 минут
0

Завдання полягає у створенні розрахованої на багато користувачів карткової онлайн-ігри в «очко», де гравцям по черзі пропонується брати карти. Виграє той, хто набрав більше очок але не більше 21. При виграші, сума ставки додається до рахунку гравця, який переміг і віднімається у того, хто програв.

Наш додаток складатиметься з 2-х частин: серверної та клієнтської. Створимо каркас програми ангуляр для клієнтської частини. Для цього скористаємось бібліотекою командного рядка angular-cli, яку бажано встановити глобально до системи.

sudo npm install -g @angular/cli

Отже, створюємо додаток так:

ng new client

При установці погоджуємось на використання роутингу, він стане нам у нагоді. Після цього отримаємо каталог client з необхідною структурою папок. Нас найбільше цікавитиме каталог src/app, в якому і буде код нашої програми. Гра міститиме три роутингу і відповідно – три сторінки та прив'язані до них компоненти.

  1. Сторінка із формою авторизації.
  2. Сторінка зі списком користувачів онлайн.
  3. Станиця кімнати із грою між двома користувачами.

Тому створимо ці три компоненти наступними командами:

ng gc login;
ng gc online;
ng gc room.

Ось так має виглядати результат, при якому створилися 3 однойменні каталоги з компонентами, які також були включені в кореневий модуль app.module.ts, про що свідчить рядок:

UPDATE src/app/app.module.ts

Якщо ми відкриємо цей файл, то зауважимо, що до нього додався імпорт кожного компонента і включений до секції декларації.

import { LoginComponent } from './login/login.component';
import { OnlineComponent } from './online/online.component';
import { RoomComponent } from './room/room.component';

@NgModule({
declarations: [
AppComponent,
LoginComponent,
OnlineComponent,
RoomComponent
],

Прив'яжемо ці компоненти до маршрутизатора, створивши 3 маршрути (насправді їх 4, але один використовується для редиректу).

import { LoginComponent } from './login/login.component';
import { OnlineComponent } from './online/online.component';
import { RoomComponent } from './room/room.component';

const routes: Routes = [
{
path: '',
redirectTo: 'login',
pathMatch: 'full'
},
{
path: 'login',
component: LoginComponent
},
{
path: 'online',
component: OnlineComponent
},
{
path: 'room/:uuid',
component: RoomComponent
}
];

У першому роутинг ми робимо редирект на форму авторизації (LoginComponent) на головній сторінці. Тобто. тепер, коли ми запустимо сервер розробки командою:

ng serve

Потім, коли перейдемо за адресою http://localhost:4200, нас автоматично перекине на адресу http://localhost:4200/login і ми побачимо таку картину:

В останньому роутинг ми визначили змінну :uuid при вказівці шаблону шляху, ця змінна буде змінюватися і містити унікальний ідентифікатор ігрової кімнати.

Тепер залишилося відкрити шаблон кореневого компонента app.component.html, прибрати все зайве від вітання та вставити посилання на кожен роут ось так:

Прийнято використовувати спеціальну директиву [routerLink] для вказівки роутингового шляху. Замість параметра :uuid у роутингу ігрової кімнати ми поки що вставимо тестове значення room_id. У тегу router-outlet буде виводитись вміст шаблонів компонентів, що відповідають шляху роуту.

Ось що має вийде:

Тепер пропоную оформити інтерфейс у кращих традиціях bootstrap та підключити бібліотеку ngx-bootstrap такою командою:

ng add ngx-bootstrap

Далі необхідно перезавантажити сервер розробки та застосувати у шаблоні розмітку bootstrap.

Ось що в нас вийшло:

Створимо форму для логіну у шаблоні login/login.component.html.

Тепер необхідно прив'язати сабміт форми до методу компонента. Для цього відкриємо код компонента login/login.component.ts і додамо змінну з логіном та методом.

export class LoginComponent implements OnInit {

login: string;
constructor() { }

ngOnInit() {
}

doLogin(){
console.log(this.login);
}

}

Для перевірки методу doLogin ми виводимо в консоль значення змінної login, оголошеної класі перед конструктором.

Ця змінна буде пов'язана зі значенням поля input у шаблоні таким чином:

Зверніть увагу на обов'язкову присутність атрибута name у тезі input. Однак, для зв'язування змінної login директивою [(ngModel)] необхідно підключити модуль FormsModule у кореневому модулі, інакше ви побачите наступну помилку в консолі браузера:

Може бути 'ngModel' since it isn't a known property of 'input'.

Тому імпортуємо цей модуль та включимо до секції imports кореневого модуля app.module.ts.

import from '@angular/forms';

@NgModule({

imports: [
...
FormsModule
],

Залишилося викликати метод doLogin при нашій формі.

Результат праці:

Тепер нам належить задіяти веб-сокети і по них передати логін користувача на сервер. Ми будемо використовувати бібліотеку socket.io, і для неї є обгортка під Ангуляром, встановлюємо.

npm i ngx-socket-io --save

Далі її необхідно імпортувати в кореневому модулі програми, налаштувати та додати до секції imports.

import { SocketIoModule, SocketIoConfig } from 'ngx-socket-io';
const config: SocketIoConfig = { url: 'http://localhost:3000', options: {} };

@NgModule({

imports: [
...
SocketIoModule.forRoot(config)
],

Як бачимо, ми плануємо запустити сокет-сервер на порту 3000 локальної машини.

Але з'єднання не буде ініційовано, поки ми не створимо сервіс, що його використовує, і не включимо його в конструктор компонента. Для таких цілей рекомендується використовувати саме сервіси, щоб не захаращувати компоненти. Сервіси є класами, екземпляри яких створюються в конструкторах компонентів шляхом механізму впровадження залежностей Ангуляра, але це окрема тема.

А поки що створимо такий сервіс у новому файлі socket.service.ts.

import { Injectable } from '@angular/core';
import { Socket } from 'ngx-socket-io';

@Injectable({
providedIn: 'root'
})
export class SocketService {

constructor(private socket: Socket) { }

sockLogin(login: string) {
console.log(`emmiting login $ to server`);
this.socket.emit('LoginEvent', );
}
}

Декоратором @Injectable ми робимо сервіс, здатний до застосування всередині компонентів. Функцією emit об'єкта socket ми надаємо інформацію на сервер.

Застосуємо цей сервіс у компоненті, поки просто імпортувавши його клас і додавши приватну змінну socket_service у конструктор класу компонента LoginComponent:

import { SocketService } from './../socket.service';
...
export class LoginComponent implements OnInit {

constructor(private socket_service: SocketService) { }
...
}

Після цього наш компонент спробує створити сокет-з'єднання з сервером, якого поки що немає. Про це свідчить повідомлення про помилку в консолі.

Причому спроби з'єднатися продовжуються не припиняючись, це дозволяє відновлювати сокет-з'єднання під час падіння сервера.

Але незважаючи на те, що робочого сервера поки немає, все ж таки реалізуємо відправку повідомлення, викликавши метод sockLogin нашого сервісу з компонента LoginComponent, і передамо в неї змінну login.

doLogin(){
this.socket_service.sockLogin(this.login);
}

Висновки

У цій статті розглянуто процес створення Angular з використанням системи маршрутизації. Також описано процес роботи з компонентами, їх шаблонами та сервісами на прикладі форми авторизації. Торкається використання сокет-з'єднання на базі бібліотеки ngx-socket-io.

У наступній статті буде розглянуто процес створення серверної частини та взаємодію його з клієнтською.

Як вам стаття?
5.0
Проголосувало: 3
Давайте обговоримо Ваш проєкт
Натискаючи кнопку “Відправити”, ви даєте згоду на обробку особистих даних. Детальніше
Коментарі
(0)
Будьте першими, хто залишить коментар
wezom logo
Залишились питання?
Залиште контактні дані. Наш менеджер зв'яжеться та проконсультує вас.
Підписуйтесь на розсилку Айтижблог
blog subscriber decor image
Бажаєте отримувати цікаві статті?
Натискаючи кнопку “Відправити”, ви даєте згоду на обробку особистих даних. Детальніше
Слідкуйте за нами у соціальних мережах
Цей сайт використовує cookie-файли для більш комфортної роботи користувача. Продовжуючи переглядати сайт, Ви погоджуєтеся на використання cookie.