diff --git a/pokeR/ClientApp/angular.json b/pokeR/ClientApp/angular.json index f28b19b..c10f48c 100644 --- a/pokeR/ClientApp/angular.json +++ b/pokeR/ClientApp/angular.json @@ -29,7 +29,9 @@ "styles": [ "src/styles.scss" ], - "scripts": [] + "scripts": [ + "node_modules/canvas-confetti/dist/confetti.browser.js" + ] }, "configurations": { "production": { diff --git a/pokeR/ClientApp/package-lock.json b/pokeR/ClientApp/package-lock.json index ad67169..472cda6 100644 --- a/pokeR/ClientApp/package-lock.json +++ b/pokeR/ClientApp/package-lock.json @@ -456,7 +456,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -869,7 +870,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -925,6 +927,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -968,12 +971,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -2733,6 +2738,11 @@ "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==", "dev": true }, + "canvas-confetti": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-0.2.0.tgz", + "integrity": "sha512-Rt7LnO9SdVnfGLWdU2yG5LdqAMW26qg6vujYO5+49+uZboEI7BfTJCMQt04QrYX/CTxEWRveoKuzykA2oirgFA==" + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", diff --git a/pokeR/ClientApp/package.json b/pokeR/ClientApp/package.json index 81de464..0fbad50 100644 --- a/pokeR/ClientApp/package.json +++ b/pokeR/ClientApp/package.json @@ -22,6 +22,7 @@ "@angular/router": "~7.2.11", "@aspnet/signalr": "^1.1.0", "@ng-bootstrap/ng-bootstrap": "^4.0.1", + "canvas-confetti": "^0.2.0", "core-js": "^2.5.4", "rxjs": "~6.4.0", "tslib": "^1.9.0", diff --git a/pokeR/ClientApp/src/app/pages/ingame/ingame.component.html b/pokeR/ClientApp/src/app/pages/ingame/ingame.component.html index 3acccde..9c80653 100644 --- a/pokeR/ClientApp/src/app/pages/ingame/ingame.component.html +++ b/pokeR/ClientApp/src/app/pages/ingame/ingame.component.html @@ -1,9 +1,9 @@
- - -
+ + +
@@ -16,4 +16,5 @@

Room not found 😢

-
\ No newline at end of file + + \ No newline at end of file diff --git a/pokeR/ClientApp/src/app/shared-components/confetti/confetti.component.html b/pokeR/ClientApp/src/app/shared-components/confetti/confetti.component.html new file mode 100644 index 0000000..fcfc6f4 --- /dev/null +++ b/pokeR/ClientApp/src/app/shared-components/confetti/confetti.component.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/pokeR/ClientApp/src/app/shared-components/confetti/confetti.component.scss b/pokeR/ClientApp/src/app/shared-components/confetti/confetti.component.scss new file mode 100644 index 0000000..c85fe0d --- /dev/null +++ b/pokeR/ClientApp/src/app/shared-components/confetti/confetti.component.scss @@ -0,0 +1,7 @@ +.confettiHolder { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; +} diff --git a/pokeR/ClientApp/src/app/shared-components/confetti/confetti.component.spec.ts b/pokeR/ClientApp/src/app/shared-components/confetti/confetti.component.spec.ts new file mode 100644 index 0000000..3987005 --- /dev/null +++ b/pokeR/ClientApp/src/app/shared-components/confetti/confetti.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConfettiComponent } from './confetti.component'; + +describe('ConfettiComponent', () => { + let component: ConfettiComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ConfettiComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ConfettiComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/pokeR/ClientApp/src/app/shared-components/confetti/confetti.component.ts b/pokeR/ClientApp/src/app/shared-components/confetti/confetti.component.ts new file mode 100644 index 0000000..dd2072a --- /dev/null +++ b/pokeR/ClientApp/src/app/shared-components/confetti/confetti.component.ts @@ -0,0 +1,54 @@ +import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; +import { ConfettiService } from './confetti.service'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +declare const confetti; + +@Component({ + selector: 'app-confetti', + templateUrl: './confetti.component.html', + styleUrls: ['./confetti.component.scss'] +}) +export class ConfettiComponent implements AfterViewInit { + @ViewChild('canvas') canvas: ElementRef; + private confettiLauncher: any; + + constructor(private service: ConfettiService) { } + + ngAfterViewInit(): void { + this.setupConfetti(); + this.watchRequests().subscribe(); + } + + setupConfetti = (): void => { + this.confettiLauncher = confetti.create(this.canvas.nativeElement, { resize: true }); + this.confettiLauncher({ + particleCount: 100, + spread: 160 + }); + } + + watchRequests = (): Observable => this.service.confettiPlz.pipe(map(this.launch)) + + launch = (duration: number): void => { + var end = Date.now() + (duration); + + var interval = setInterval(() => { + if (Date.now() > end) { + return clearInterval(interval); + } + + confetti({ + startVelocity: 30, + spread: 360, + ticks: 60, + origin: { + x: Math.random(), + // since they fall down, start a bit higher than random + y: Math.random() - 0.2 + } + }); + }, 200); + } + +} diff --git a/pokeR/ClientApp/src/app/shared-components/confetti/confetti.service.spec.ts b/pokeR/ClientApp/src/app/shared-components/confetti/confetti.service.spec.ts new file mode 100644 index 0000000..db75cc7 --- /dev/null +++ b/pokeR/ClientApp/src/app/shared-components/confetti/confetti.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { ConfettiService } from './confetti.service'; + +describe('ConfettiService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: ConfettiService = TestBed.get(ConfettiService); + expect(service).toBeTruthy(); + }); +}); diff --git a/pokeR/ClientApp/src/app/shared-components/confetti/confetti.service.ts b/pokeR/ClientApp/src/app/shared-components/confetti/confetti.service.ts new file mode 100644 index 0000000..ffbf8fc --- /dev/null +++ b/pokeR/ClientApp/src/app/shared-components/confetti/confetti.service.ts @@ -0,0 +1,13 @@ +import { Injectable, EventEmitter } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class ConfettiService { + + constructor() { } + + public confettiPlz: EventEmitter = new EventEmitter(); + + public pop = (): void => this.confettiPlz.emit(5000); +} diff --git a/pokeR/ClientApp/src/app/shared-components/playfield/playfield.component.ts b/pokeR/ClientApp/src/app/shared-components/playfield/playfield.component.ts index eb44eb1..36a7322 100644 --- a/pokeR/ClientApp/src/app/shared-components/playfield/playfield.component.ts +++ b/pokeR/ClientApp/src/app/shared-components/playfield/playfield.component.ts @@ -4,6 +4,7 @@ import { User } from 'src/app/models/entities/user'; import { Observable, forkJoin } from 'rxjs'; import { map } from 'rxjs/operators'; import { Card } from 'src/app/models/entities/card'; +import { ConfettiService } from '../confetti/confetti.service'; @Component({ selector: 'app-playfield', @@ -14,7 +15,7 @@ export class PlayfieldComponent implements OnInit { lastState: Array = new Array(); isRevealed = false; - constructor(private service: PokerService) { } + constructor(private service: PokerService, private confetti: ConfettiService) { } ngOnInit() { this.watchState().subscribe(); @@ -57,7 +58,13 @@ export class PlayfieldComponent implements OnInit { revealCards = (): void => { this.isRevealed = true; console.log('YOU ACTIVATED MY TRAP CARD!'); + if (this.lastState.map(s => s.currentCardId).every(i => this.lastState.find(() => true).currentCardId === i)) { + console.log('party time!'); + this.showConfetti(); + } } getEmblemUrl = (id: number): string => this.service.getEmblemUrl(id); + + private showConfetti = (): void => this.confetti.pop(); } diff --git a/pokeR/ClientApp/src/app/shared-components/shared-components.module.ts b/pokeR/ClientApp/src/app/shared-components/shared-components.module.ts index 2396e79..eb1bdea 100644 --- a/pokeR/ClientApp/src/app/shared-components/shared-components.module.ts +++ b/pokeR/ClientApp/src/app/shared-components/shared-components.module.ts @@ -11,6 +11,7 @@ import { PlayfieldComponent } from './playfield/playfield.component'; import { RoundStatusComponent } from './round-status/round-status.component'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { AppRoutingModule } from '../app-routing.module'; +import { ConfettiComponent } from './confetti/confetti.component'; @NgModule({ declarations: [ @@ -21,7 +22,8 @@ import { AppRoutingModule } from '../app-routing.module'; JoinRoomComponent, CardListComponent, PlayfieldComponent, - RoundStatusComponent + RoundStatusComponent, + ConfettiComponent ], imports: [ CommonModule, FormsModule, @@ -35,7 +37,8 @@ import { AppRoutingModule } from '../app-routing.module'; JoinRoomComponent, CardListComponent, PlayfieldComponent, - RoundStatusComponent + RoundStatusComponent, + ConfettiComponent ] }) export class SharedComponentsModule { }