pixi-rainman-game-engine 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,6 +10,7 @@ export const defaultAppConfig = {
10
10
  idleTimeout: 10000,
11
11
  fontSize: 35,
12
12
  mobileFontSize: 45,
13
+ shouldSpeedUpMobileReels: false,
13
14
  updatableSpineContainerFontSize: 50,
14
15
  updatableTextValueColor: new Color(0xffffff).toHex(),
15
16
  autoplayGlowColor: new Color(0xff3000).toNumber(),
@@ -14,6 +14,7 @@ export type OptionalAppConfig = {
14
14
  gameHeight: number;
15
15
  idleTimeout: number;
16
16
  fontSize: number;
17
+ shouldSpeedUpMobileReels: boolean;
17
18
  updatableSpineContainerFontSize: number;
18
19
  mobileFontSize: number;
19
20
  mobileFontColor?: string;
@@ -239,7 +239,7 @@ export class ButtonsEventManager {
239
239
  * @param {boolean} disabled - flag for enabling/disabling button
240
240
  */
241
241
  initGambleButton(onClick, disabled) {
242
- if (!RainMan.componentRegistry.has(BUTTONS.gamble))
242
+ if (!RainMan.componentRegistry.has(BUTTONS.gamble) && RainMan.settingsStore.gambleGameUsed)
243
243
  return;
244
244
  RainMan.componentRegistry.get(BUTTONS.gamble).setOnClick(onClick);
245
245
  RainMan.componentRegistry.get(BUTTONS.gamble).flipDisabledFlag(disabled);
@@ -330,6 +330,7 @@ export class AbstractMainContainer extends Container {
330
330
  });
331
331
  if (this.gambleGame) {
332
332
  this.removeChild(this.gambleGame);
333
+ this._controller.updateGambleValues(RainMan.settingsStore.gambleGameWin);
333
334
  this.gambleGame = null;
334
335
  }
335
336
  this._controller.balance = newBalance;
@@ -9,7 +9,7 @@ import { Container } from "pixi.js";
9
9
  */
10
10
  export declare class GambleGame extends Container {
11
11
  private resolver;
12
- private bet;
12
+ private lastWinAmount;
13
13
  private balanceValue;
14
14
  static gambleCurrentWinRegistryName: string;
15
15
  static gambleWinRegistryName: string;
@@ -25,9 +25,11 @@ export declare class GambleGame extends Container {
25
25
  private readonly previousGamblesText;
26
26
  private readonly previousGamblesContainer;
27
27
  private previousGambles;
28
- constructor(cardSpineName: string, resolver: (newBalance: number) => void, bet: number, balanceValue: number);
28
+ constructor(cardSpineName: string, resolver: (newBalance: number) => void, lastWinAmount: number, balanceValue: number);
29
29
  private showPreviousGambles;
30
+ private closeGame;
30
31
  private updateDoubleAndWinFields;
32
+ private loseDoubleAndWinFields;
31
33
  private handleGamblePlay;
32
34
  resize(): void;
33
35
  private initChildPositions;
@@ -4,7 +4,7 @@ import { Spine } from "pixi-spine";
4
4
  import { COLOR_BUTTONS_CENTER_OFFSET, COLOR_BUTTONS_SCALE_X, gamblesTextStyle } from "../../constants";
5
5
  import { RainMan } from "../../Rainman";
6
6
  import { getSpineData, globalMinRatio } from "../../utils";
7
- import { BlackButton, CollectButton, RedButton } from "../buttons";
7
+ import { BlackButton, BUTTONS, CollectButton, RedButton } from "../buttons";
8
8
  import { GambleUpdatableText } from "../updatable";
9
9
  /**
10
10
  * Class for representing mechanic of gamble
@@ -16,7 +16,7 @@ import { GambleUpdatableText } from "../updatable";
16
16
  */
17
17
  export class GambleGame extends Container {
18
18
  resolver;
19
- bet;
19
+ lastWinAmount;
20
20
  balanceValue;
21
21
  static gambleCurrentWinRegistryName = "gambleCurrentWin";
22
22
  static gambleWinRegistryName = "gambleWin";
@@ -32,10 +32,10 @@ export class GambleGame extends Container {
32
32
  previousGamblesText;
33
33
  previousGamblesContainer;
34
34
  previousGambles = [];
35
- constructor(cardSpineName, resolver, bet, balanceValue) {
35
+ constructor(cardSpineName, resolver, lastWinAmount, balanceValue) {
36
36
  super();
37
37
  this.resolver = resolver;
38
- this.bet = bet;
38
+ this.lastWinAmount = lastWinAmount;
39
39
  this.balanceValue = balanceValue;
40
40
  this.eventMode = "static";
41
41
  this.background = new Sprite(Texture.from("black-bg.png"));
@@ -50,12 +50,16 @@ export class GambleGame extends Container {
50
50
  this.collectText.pivot.x = this.collectText.width / 2;
51
51
  this.collectText.pivot.y = this.collectText.height / 2;
52
52
  this.card = new Spine(getSpineData(cardSpineName));
53
- this.card.state.addAnimation(0, "idle", true, 0);
54
- this.currentWin = new GambleUpdatableText(GambleGame.gambleCurrentWinRegistryName, i18next.t("currentWinGamble"), this.bet, 1);
55
- this.gambleWin = new GambleUpdatableText(GambleGame.gambleWinRegistryName, i18next.t("gambleToWin"), this.bet * 2, 2);
53
+ this.card.state.addAnimation(0, "wait2", true, 0);
54
+ this.currentWin = new GambleUpdatableText(GambleGame.gambleCurrentWinRegistryName, i18next.t("currentWinGamble"), this.lastWinAmount, 1);
55
+ this.gambleWin = new GambleUpdatableText(GambleGame.gambleWinRegistryName, i18next.t("gambleToWin"), this.lastWinAmount * 2, 2);
56
56
  this.redButton.setOnClick(() => this.handleGamblePlay("red"));
57
57
  this.blackButton.setOnClick(() => this.handleGamblePlay("black"));
58
- this.collectButton.setOnClick(() => this.resolver(this.balanceValue));
58
+ this.collectButton.setOnClick(() => {
59
+ RainMan.settingsStore.gambleGameWin = this.lastWinAmount;
60
+ RainMan.componentRegistry.get(BUTTONS.gamble).flipDisabledFlag(true);
61
+ this.resolver(this.balanceValue);
62
+ });
59
63
  this.resize();
60
64
  }
61
65
  showPreviousGambles(previousGambles) {
@@ -73,16 +77,23 @@ export class GambleGame extends Container {
73
77
  this.previousGamblesContainer.y =
74
78
  this.previousGamblesText.y + this.previousGamblesText.height + this.previousGamblesContainer.height / 2;
75
79
  }
80
+ closeGame() {
81
+ RainMan.componentRegistry.get(BUTTONS.gamble).flipDisabledFlag(true);
82
+ this.resolver(this.balanceValue);
83
+ }
76
84
  async updateDoubleAndWinFields(value) {
77
- return Promise.all([this.gambleWin.update(value * 2), this.currentWin.update(value)]);
85
+ return Promise.all([this.gambleWin.update(value), this.currentWin.update(value / 2)]);
86
+ }
87
+ async loseDoubleAndWinFields() {
88
+ return Promise.all([this.gambleWin.loseUpdate(), this.currentWin.loseUpdate()]);
78
89
  }
79
90
  async handleGamblePlay(choice) {
80
- if (this.bet === 0)
91
+ if (this.lastWinAmount === 0)
81
92
  return;
82
93
  this.redButton.flipDisabledFlag(true);
83
94
  this.blackButton.flipDisabledFlag(true);
84
95
  this.card.state.addAnimation(0, "wait", true, 0);
85
- const gambleData = await window.connectionWrapper.fetchGambleData(RainMan.settingsStore.roundNumber, this.bet, choice);
96
+ const gambleData = await window.connectionWrapper.fetchGambleData(RainMan.settingsStore.roundNumber, this.lastWinAmount, choice);
86
97
  this.balanceValue = gambleData.balance + gambleData.win_amount;
87
98
  await new Promise((resolve) => {
88
99
  this.card.state.clearTracks();
@@ -90,14 +101,25 @@ export class GambleGame extends Container {
90
101
  this.card.state.addAnimation(0, gambleData.winning_card, false, 0);
91
102
  this.card.state.addListener({ complete: () => resolve() });
92
103
  });
93
- await this.updateDoubleAndWinFields(Math.max(gambleData.win_amount, 0));
94
104
  if (gambleData.win_amount > 0) {
105
+ await this.updateDoubleAndWinFields(Math.max(gambleData.win_amount, 0));
95
106
  this.redButton.flipDisabledFlag(false);
96
107
  this.blackButton.flipDisabledFlag(false);
97
108
  }
98
- this.card.state.addAnimation(0, "idle", true, 0);
99
- this.bet = gambleData.win_amount;
109
+ this.card.state.addAnimation(0, "wait2", true, 0);
110
+ this.lastWinAmount = gambleData.win_amount;
100
111
  this.showPreviousGambles(gambleData.previous_gambles);
112
+ if (gambleData.win_amount === 0) {
113
+ this.redButton.flipDisabledFlag(true);
114
+ this.blackButton.flipDisabledFlag(true);
115
+ this.card.state.addAnimation(0, "idle", true, 0);
116
+ Promise.all([
117
+ this.loseDoubleAndWinFields(),
118
+ setTimeout(() => {
119
+ this.closeGame();
120
+ }, 2000),
121
+ ]);
122
+ }
101
123
  }
102
124
  resize() {
103
125
  const { width, height } = RainMan.app.screen;
@@ -4,7 +4,7 @@ import { Container } from "pixi.js";
4
4
  import { animationsSpeedLevels, defaultSpeedConfig, SoundManager, SoundTracks, SPEED_LEVELS, } from "../../application";
5
5
  import { FrameLayer } from "../../layers";
6
6
  import { RainMan } from "../../Rainman";
7
- import { logInfo } from "../../utils";
7
+ import { getDeviceOrientation, logInfo } from "../../utils";
8
8
  import { droppableSymbolsFactory } from "./DroppableSymbolsColumn";
9
9
  import { Phase, Speed } from "./types";
10
10
  /**
@@ -138,7 +138,8 @@ export class AbstractSymbolsColumn extends Container {
138
138
  if (!this.topMostSymbol) {
139
139
  return;
140
140
  }
141
- const distance = Math.round(this.velocity * this.velocityMultiplier * delta);
141
+ const mobileSpeedUp = getDeviceOrientation() === "mobile-portrait" && RainMan.config.shouldSpeedUpMobileReels ? 1.3 : 1;
142
+ const distance = Math.round(this.velocity * this.velocityMultiplier * delta * mobileSpeedUp);
142
143
  for (const symbol of this.symbols) {
143
144
  symbol.y += distance;
144
145
  }
@@ -31,5 +31,6 @@ export class GambleUpdatableText extends UpdatableValueComponent {
31
31
  this.pivot.x = this.frame.width / 2;
32
32
  this.pivot.y = this.height / 2;
33
33
  this.countingDivider = this.speedLevelMapper[DEFAULT_SPEED];
34
+ this.set(initialValue);
34
35
  }
35
36
  }
@@ -29,6 +29,7 @@ export declare abstract class UpdatableValueComponent extends Container implemen
29
29
  adaptToSpeed(speedLevel: SpeedLevel): void;
30
30
  get value(): string;
31
31
  update(newValue: number, time?: number): Promise<void>;
32
+ loseUpdate(time?: number): Promise<void>;
32
33
  stopUpdate(): void;
33
34
  set(newValue: number): void;
34
35
  setStringValue(value: string): void;
@@ -60,6 +60,10 @@ export class UpdatableValueComponent extends Container {
60
60
  Ticker.shared.add(() => this.animate());
61
61
  await this.initAnimation(newValue, time / this.countingDivider);
62
62
  }
63
+ async loseUpdate(time = RainMan.config.durationOfActions.updatableTextCountingDuration) {
64
+ Ticker.shared.add(() => this.animate());
65
+ await this.initAnimation(0, time / this.countingDivider, true);
66
+ }
63
67
  stopUpdate() {
64
68
  this.shouldBeUpdated = false;
65
69
  this.set(this.finalValue);
@@ -88,9 +92,9 @@ export class UpdatableValueComponent extends Container {
88
92
  return this.limitValue;
89
93
  return finalValue;
90
94
  }
91
- initAnimation(newValue, countingDuration) {
95
+ initAnimation(newValue, countingDuration, shouldDescendToZero = false) {
92
96
  this.shouldBeUpdated = true;
93
- const finalValue = this.getFinalValue(newValue);
97
+ const finalValue = shouldDescendToZero ? 0 : this.getFinalValue(newValue);
94
98
  return new Promise((resolve) => {
95
99
  this.tween = new TWEEN.Tween({ value: this.updatableValue })
96
100
  .onUpdate(({ value }) => {
@@ -47,6 +47,7 @@ export declare abstract class AbstractController<T> {
47
47
  private componentRegistry;
48
48
  protected skipFreeSpinSummary: boolean;
49
49
  protected scatterCountForFx: number;
50
+ protected summaryStop: boolean;
50
51
  protected _lastWinAmount: number;
51
52
  protected constructor(buttonsEventManager: ButtonsEventManager, mainContainer: AbstractMainContainer, connection: SubscribableConnectionWrapper);
52
53
  init(): void;
@@ -154,6 +155,7 @@ export declare abstract class AbstractController<T> {
154
155
  protected onSpinningStart(): Promise<void>;
155
156
  protected onSpinningEnd(_spinLogic: SpinLogic): Promise<void>;
156
157
  protected performActionsAfterSpin(): void;
158
+ protected gambleGameEnabler(winAmount: number): void;
157
159
  /**
158
160
  * Function for spin logic of the game
159
161
  * This function is responsible for:
@@ -224,7 +226,8 @@ export declare abstract class AbstractController<T> {
224
226
  * @returns {SymbolId[]} - symbols from streak
225
227
  */
226
228
  protected getSymbolIdsForStreak(streak: StreakReelsIndexes): SymbolId[];
227
- protected updateUiValues(value: number): void;
229
+ updateUiValues(value: number): void;
230
+ updateGambleValues(value: number): void;
228
231
  /**
229
232
  * Function for composing win actions queue based on wins and transformations from {@link transformationTypes} and {@link PossibleWins}
230
233
  * @param spinLogic
@@ -46,6 +46,7 @@ export class AbstractController {
46
46
  componentRegistry;
47
47
  skipFreeSpinSummary = false;
48
48
  scatterCountForFx = 2;
49
+ summaryStop = false;
49
50
  _lastWinAmount = 0;
50
51
  constructor(buttonsEventManager, mainContainer, connection) {
51
52
  this.buttonsEventManager = buttonsEventManager;
@@ -153,7 +154,10 @@ export class AbstractController {
153
154
  this.buttonsEventManager.initInfoButtonEvent();
154
155
  this.buttonsEventManager.initMoreButtonEvent();
155
156
  this.buttonsEventManager.initAutoplayButtonEvent();
156
- this.buttonsEventManager.initGambleButton(() => this.mainContainer.invokeGambleGame(), this.lastWinAmount === 0);
157
+ this.buttonsEventManager.initGambleButton(() => {
158
+ RainMan.settingsStore.gambleGameUsed = true;
159
+ this.mainContainer.invokeGambleGame();
160
+ }, this.lastWinAmount === 0);
157
161
  RainMan.componentRegistry.get(SpeedControlButton.registryName).setOnClick(() => {
158
162
  this.quickStopController.speedPopupDisabled = true;
159
163
  RainMan.componentRegistry.nextSpeedLevel();
@@ -194,8 +198,9 @@ export class AbstractController {
194
198
  refreshButton.on("touchstart", () => {
195
199
  this.mobileSpinTimeout = setInterval(() => {
196
200
  this.handleDisablingButtons(true);
201
+ this.summaryStop = this.skipFreeSpinSummary ? false : this.invokeFreeSpinSummaryPlateAfterWin;
197
202
  if (this.invokeFreeSpinPlateAfterWin ||
198
- this.invokeFreeSpinSummaryPlateAfterWin ||
203
+ this.summaryStop ||
199
204
  this.resolveBigWin !== undefined ||
200
205
  this.resolveSuperBonusWin !== undefined ||
201
206
  this.resolveMysteryWin !== undefined) {
@@ -541,6 +546,13 @@ export class AbstractController {
541
546
  async onSpinningStart() { }
542
547
  async onSpinningEnd(_spinLogic) { }
543
548
  performActionsAfterSpin() { }
549
+ gambleGameEnabler(winAmount) {
550
+ if (RainMan.componentRegistry.has(BUTTONS.gamble) && !RainMan.settingsStore.gambleGameUsed) {
551
+ RainMan.componentRegistry
552
+ .get(BUTTONS.gamble)
553
+ .flipDisabledFlag(RainMan.settingsStore.isFreeSpinsPlayEnabled || winAmount === 0);
554
+ }
555
+ }
544
556
  /**
545
557
  * Function for spin logic of the game
546
558
  * This function is responsible for:
@@ -612,10 +624,6 @@ export class AbstractController {
612
624
  this.invokeFreeSpinSummaryPlateAfterWin = true;
613
625
  RainMan.componentRegistry.getIfExists(FreeSpinButton.registryName)?.setInteractivity(true);
614
626
  }
615
- if (RainMan.componentRegistry.has(BUTTONS.gamble))
616
- RainMan.componentRegistry
617
- .get(BUTTONS.gamble)
618
- .flipDisabledFlag(RainMan.settingsStore.isFreeSpinsPlayEnabled || spinLogic.winTotalAmount === 0);
619
627
  RainMan.settingsStore.setTotalNumberOfFreeSpins(availableFreeSpins);
620
628
  RainMan.settingsStore.setNumberOfFreeSpin(availableFreeSpins);
621
629
  await new Promise((resolveAfterSpins) => {
@@ -913,6 +921,9 @@ export class AbstractController {
913
921
  this.uiController.updateShownBalance();
914
922
  }
915
923
  }
924
+ updateGambleValues(value) {
925
+ this.uiController.setDisplayedCurrentWinGamble(value);
926
+ }
916
927
  /**
917
928
  * Function will turn off loop while `RainMan.settingsStore.isAutoplayEnabled` is `true`
918
929
  */
@@ -56,4 +56,5 @@ export declare class UiController {
56
56
  triggerUiElementsUpdate(): void;
57
57
  private setDisplayedBalance;
58
58
  private setDisplayedCurrentWin;
59
+ setDisplayedCurrentWinGamble(value: number): void;
59
60
  }
@@ -166,4 +166,11 @@ export class UiController {
166
166
  }
167
167
  RainMan.componentRegistry.get(MessageBox.currentWinTextRegistryName).set(this._recentWin);
168
168
  }
169
+ setDisplayedCurrentWinGamble(value) {
170
+ if (RainMan.settingsStore.isFreeSpinsPlayEnabled) {
171
+ RainMan.componentRegistry.get(MessageBox.currentWinTextRegistryName).set(this.totalFreeSpinWinAmount);
172
+ return;
173
+ }
174
+ RainMan.componentRegistry.get(MessageBox.currentWinTextRegistryName).set(value);
175
+ }
169
176
  }
@@ -26,6 +26,8 @@ export declare class SettingsStore {
26
26
  roundNumber: number;
27
27
  HiResolutionFlag: boolean;
28
28
  batterySaverFlag: boolean;
29
+ gambleGameUsed: boolean;
30
+ gambleGameWin: number;
29
31
  containersWithSpines: (ResumableContainer | SpineWithResumableContainer | SpriteWithResumableContainer)[];
30
32
  cumulativeWinAmount: number;
31
33
  progress: number;
@@ -32,6 +32,8 @@ export class SettingsStore {
32
32
  roundNumber = 0;
33
33
  HiResolutionFlag = getFromLocalStorage(LOCAL_STORAGE.hiResolution, true);
34
34
  batterySaverFlag = getFromLocalStorage(LOCAL_STORAGE.batterySaver, false);
35
+ gambleGameUsed = false;
36
+ gambleGameWin = 0;
35
37
  containersWithSpines = [];
36
38
  cumulativeWinAmount = 0;
37
39
  progress = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixi-rainman-game-engine",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "This repository contains all of the mechanics that used in rainman games.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -13,7 +13,8 @@
13
13
  "lint": "eslint src/** --fix",
14
14
  "prepublishOnly": "husky && yarn build",
15
15
  "prepare": "husky",
16
- "docs": "typedoc --options typedoc.json "
16
+ "docs": "typedoc --options typedoc.json",
17
+ "deploy:upload": "rsync -avr docker-compose.yml game-server:ops-casino/"
17
18
  },
18
19
  "type": "module",
19
20
  "author": "@niceguys",