click fraud detection
click fraud detection
Blog Case

Создание карточной игры Blackjack

BLOG
CASE
144
0
5/ 5stars
5/5
Время чтения: 25 минут

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

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

sudo npm install -g @angular/cli

Итак, создаем приложение следующим образом:

ng new client

При установке соглашаемся на использование роутинга, он нам пригодится. После чего получим каталог client с необходимой структурой папок. Нас больше всего будет интересовать каталог src/app, в котором и будет код нашего приложения. Игра будет содержать три роутинга и соответственно – три страницы и привязанных к ним компонента.

  1. Страница с формой авторизации.
  2. Страница со списком пользователей онлайн.
  3. Станица комнаты с игрой между двумя пользователями.

Поэтому создадим эти три компонента следующими командами:

ng g c login;
ng g c online;
ng g c 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 в корневом модуле, иначе вы увидите следующую ошибку в консоле браузера:

Can't bind to 'ngModel' since it isn't a known property of 'input'.

Поэтому импортируем этот модуль и включим в секцию imports корневого модуля app.module.ts.

import {FormsModule} 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 ${login} to server`);
    this.socket.emit('LoginEvent', {data: login});
  }
}

Декоратором @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/5
Проголосовало людей: 1
ПОЛУЧАТЬ ИНТЕРЕСНЫЕ СТАТЬИ
Уже подписались 244 человек
Автор
144
0
Дмитрий Жариков
Дмитрий
Жариков
most
Popular
Возможно
Как продвигать сайт самостоятельно этот вопрос интересует многих. Мы описали все способы и методы продвижения…
Александр Осиевский
Александр Осиевский
Поэтапное руководство по продвижению сайта. Созданный ресурс может быть идеальным по структуре, дизайну, юзабилити и…
Александр Вострецов
Александр Вострецов
WordPress используют различные компании для рекламирования услуг и простого освещения событий. Давайте пошагово разбираться, как…
Андрей Зубатюк
Андрей Зубатюк
Давайте начнем
беседу!
КОММЕНТАРИИ0
ОСТАВИТЬ КОММЕНТАРИЙ К СТАТЬЕ
ПОДПИСЫВАЙТЕСЬ НА РАССЫЛКУ АЙТЫЖБЛОГ
ХОТИТЕ ПОЛУЧАТЬ 
ИНТЕРЕСНЫЕ СТАТЬИ?
Уже подписались 244 человек
313
ПОПИСЧИКОВ
ЧИТАТЬ
4295
ПОПИСЧИКОВ
СЛЕДИТЬ
9307
ПОПИСЧИКОВ
СЛЕДИТЬ