├── .gitignore ├── README.md ├── assets ├── @pixi-BT9gqUNR.js ├── @socket.io-Dkula2eQ.js ├── audio │ ├── loadAudioData.json │ ├── music │ │ └── background.ogg │ ├── other │ │ ├── button_click.ogg │ │ ├── count_loop.ogg │ │ ├── credits_count.ogg │ │ ├── fire_frame.ogg │ │ └── line_match.ogg │ └── reel │ │ ├── reel_rotation.ogg │ │ └── reel_stop.ogg ├── call-bind-CkPzBTRv.js ├── clsx-l0sNRNKZ.js ├── define-data-property-CUxyvwXF.js ├── earcut-DOWYkTK5.js ├── engine.io-client-DBBxzneW.js ├── engine.io-parser-BiEtp6m2.js ├── es-define-property-28jGrh5V.js ├── es-errors-DzOT6E3C.js ├── eventemitter3-Bav5T-Ru.js ├── function-bind-B8G-TZ45.js ├── get-intrinsic-B1Ut8WxJ.js ├── gopd-O61WwtTx.js ├── gsap-ZORhgBxb.js ├── has-property-descriptors-Cvfij9iw.js ├── has-proto-JnoBQRdH.js ├── has-symbols-eVqrYdw7.js ├── hasown-B9bXSDSU.js ├── howler-BozPm2lL.js ├── images │ ├── UI │ │ ├── buttons │ │ │ ├── bet_down_button.svg │ │ │ ├── bet_down_button_hover.svg │ │ │ ├── bet_down_button_push.svg │ │ │ ├── bet_up_button.svg │ │ │ ├── bet_up_button_hover.svg │ │ │ ├── bet_up_button_push.svg │ │ │ ├── close_button.svg │ │ │ ├── close_button_push.svg │ │ │ ├── hamburger_button.svg │ │ │ ├── information_button.svg │ │ │ ├── sound_off_button.svg │ │ │ ├── sound_on_button.svg │ │ │ ├── spin_button.svg │ │ │ ├── spin_button_hover.svg │ │ │ └── spin_button_push.svg │ │ ├── buy_credits │ │ │ ├── buy_credits_icon.png │ │ │ └── buy_credits_icon.svg │ │ ├── spin_button │ │ │ ├── spin_button.svg │ │ │ ├── spin_button_hover.svg │ │ │ └── spin_button_push.svg │ │ └── symbols │ │ │ ├── banana.png │ │ │ ├── bar.png │ │ │ ├── bell.png │ │ │ ├── cherry.png │ │ │ ├── grapes.png │ │ │ ├── lemon.png │ │ │ ├── orange.png │ │ │ ├── plum.png │ │ │ ├── seven.png │ │ │ ├── strawberry.png │ │ │ └── watermelon.png │ ├── bet_label_background.svg │ ├── credits_counter_background.png │ ├── credits_counter_shine.png │ ├── dark_screen.png │ ├── eagle.atlas │ ├── eagle.json │ ├── eagle.png │ ├── feather.png │ ├── game │ │ ├── background │ │ │ ├── background.jpg │ │ │ ├── background.json │ │ │ ├── background_overlay.json │ │ │ └── background_overlay.png │ │ ├── matching │ │ │ ├── frames │ │ │ │ ├── fire_frame.json │ │ │ │ └── fire_frame.png │ │ │ └── lines │ │ │ │ ├── matchLinesAtlas.json │ │ │ │ └── matchLinesAtlas.png │ │ └── symbols │ │ │ ├── Experience_star.png │ │ │ ├── Experience_star_2.png │ │ │ ├── banana.json │ │ │ ├── banana.png │ │ │ ├── bar.json │ │ │ ├── bar.png │ │ │ ├── bell.json │ │ │ ├── bell.png │ │ │ ├── cherry.json │ │ │ ├── cherry.png │ │ │ ├── grapes.json │ │ │ ├── grapes.png │ │ │ ├── lemon.json │ │ │ ├── lemon.png │ │ │ ├── orange.json │ │ │ ├── orange.png │ │ │ ├── plum.json │ │ │ ├── plum.png │ │ │ ├── seven.json │ │ │ ├── seven.png │ │ │ ├── strawberry.json │ │ │ ├── strawberry.png │ │ │ ├── watermelon.json │ │ │ └── watermelon.png │ ├── game_logo.svg │ ├── game_name_logo_landscape.png │ ├── game_name_logo_portrait.png │ ├── loading_game_anim.svg │ ├── pay_lines.svg │ ├── symbol_describe_label.png │ ├── symbols_bg.png │ └── symbols_dark_mask.png ├── index-BVQBJWG7.js ├── index-CvhPOTdb.js ├── index-D2yllynE.css ├── index-DJcPWbBX.js ├── index-DS3eI2U1.js ├── ismobilejs-CHLuctl-.js ├── js-cookie-Cz0CWeBA.js ├── mini-signals-DMh6wOcT.js ├── object-inspect-CJVVCa5F.js ├── pixi.js--APxrgAh.js ├── qs-WFKaZsx0.js ├── react-CWbZ82Fp.js ├── react-dom-1bg23oq7.js ├── react-toastify-B8GeWnC-.js ├── react-toastify-CYivYX3d.css ├── scheduler-CzFDRTuY.js ├── set-function-length-Ct5B6P4y.js ├── side-channel-CzTPmnEc.js ├── socket.io-client-DFi9RC7o.js ├── socket.io-parser-BBkuslX-.js └── url-Czix6NCG.js ├── code ├── client │ ├── index.html │ ├── package.json │ ├── public │ │ ├── assets │ │ │ └── audio │ │ │ │ └── loadAudioData.json │ │ ├── favicon.svg │ │ └── style.css │ ├── src │ │ ├── App.css │ │ ├── App.jsx │ │ ├── UI │ │ │ ├── CSS │ │ │ │ └── UI.css │ │ │ ├── UI.jsx │ │ │ ├── bottomBar │ │ │ │ ├── BottomBar.jsx │ │ │ │ ├── CSS │ │ │ │ │ └── BottomBar.css │ │ │ │ └── balance │ │ │ │ │ ├── Balance.jsx │ │ │ │ │ └── CSS │ │ │ │ │ └── Balance.css │ │ │ └── middleBar │ │ │ │ ├── CSS │ │ │ │ └── MiddleBar.css │ │ │ │ └── MiddleBar.jsx │ │ ├── components │ │ │ ├── closeButton │ │ │ │ ├── CSS │ │ │ │ │ └── CloseButton.css │ │ │ │ └── CloseButton.jsx │ │ │ └── textureButton │ │ │ │ ├── CSS │ │ │ │ └── TextureButton.css │ │ │ │ └── TextureButton.jsx │ │ ├── config │ │ │ ├── assetsConfig.js │ │ │ └── screenConfig.js │ │ ├── game │ │ │ ├── CSS │ │ │ │ └── Game.css │ │ │ ├── StartGame.js │ │ │ ├── abstraction │ │ │ │ └── BaseScene.ts │ │ │ ├── components │ │ │ │ ├── Container.ts │ │ │ │ ├── sprite │ │ │ │ │ ├── Sprite.ts │ │ │ │ │ └── interface │ │ │ │ │ │ └── ISpriteConfig.ts │ │ │ │ └── text │ │ │ │ │ ├── Text.ts │ │ │ │ │ └── interface │ │ │ │ │ └── ITextConfig.ts │ │ │ ├── darkScreen │ │ │ │ ├── DarkScreen.ts │ │ │ │ ├── config │ │ │ │ │ └── darkScreenConfig.ts │ │ │ │ ├── controller │ │ │ │ │ └── DarkScreenController.ts │ │ │ │ ├── interface │ │ │ │ │ └── IDarkScreenConfig.ts │ │ │ │ ├── model │ │ │ │ │ ├── DarkScreenModel.ts │ │ │ │ │ └── interface │ │ │ │ │ │ └── IDarkScreenlConfig.ts │ │ │ │ └── view │ │ │ │ │ ├── DarkScreenView.ts │ │ │ │ │ └── interface │ │ │ │ │ └── IDarkScreenConfig.ts │ │ │ ├── gameLogo │ │ │ │ ├── GameLogo.ts │ │ │ │ ├── controller │ │ │ │ │ └── GameLogoController.ts │ │ │ │ ├── interface │ │ │ │ │ └── IGameLogoConfig.ts │ │ │ │ ├── model │ │ │ │ │ ├── GameLogoModel.ts │ │ │ │ │ └── interface │ │ │ │ │ │ └── IGameLogoModelConfig.ts │ │ │ │ └── view │ │ │ │ │ ├── GameLogoView.ts │ │ │ │ │ └── interface │ │ │ │ │ └── IGameLogoConfig.ts │ │ │ ├── machine │ │ │ │ ├── Machine.ts │ │ │ │ ├── config │ │ │ │ │ └── machineConfig.ts │ │ │ │ ├── controller │ │ │ │ │ └── interface │ │ │ │ │ │ └── IMachineControllerConfig.ts │ │ │ │ ├── creditsCounter │ │ │ │ │ ├── CreditsCounter.ts │ │ │ │ │ ├── controller │ │ │ │ │ │ └── CreditsCounterController.ts │ │ │ │ │ ├── model │ │ │ │ │ │ └── CreditsCounterModel.ts │ │ │ │ │ └── view │ │ │ │ │ │ └── CreditsCounterView.ts │ │ │ │ ├── describeLabel │ │ │ │ │ ├── DescribeLabel.ts │ │ │ │ │ ├── model │ │ │ │ │ │ └── DescribeLabelModel.ts │ │ │ │ │ └── view │ │ │ │ │ │ └── DescribeLabelView.ts │ │ │ │ ├── model │ │ │ │ │ └── MachineModel.ts │ │ │ │ ├── reel │ │ │ │ │ ├── Reel.ts │ │ │ │ │ ├── model │ │ │ │ │ │ └── ReelModel.ts │ │ │ │ │ └── symbol │ │ │ │ │ │ ├── Symbol.ts │ │ │ │ │ │ ├── controller │ │ │ │ │ │ └── SymbolController.ts │ │ │ │ │ │ ├── interface │ │ │ │ │ │ └── ISymbolConfig.ts │ │ │ │ │ │ ├── model │ │ │ │ │ │ ├── SymbolModel.ts │ │ │ │ │ │ └── interface │ │ │ │ │ │ │ └── ISymbolModelConfig.ts │ │ │ │ │ │ └── view │ │ │ │ │ │ ├── SymbolView.ts │ │ │ │ │ │ └── interface │ │ │ │ │ │ └── ISymbolViewConfig.ts │ │ │ │ └── view │ │ │ │ │ ├── MachineView.ts │ │ │ │ │ └── interface │ │ │ │ │ └── IMachineViewConfig.ts │ │ │ ├── main.js │ │ │ ├── manager │ │ │ │ └── GameManager.ts │ │ │ └── scenes │ │ │ │ ├── Game.ts │ │ │ │ └── Preload.ts │ │ ├── gameSignals │ │ │ └── GameSignals.js │ │ ├── index.css │ │ ├── interfaces │ │ │ ├── IAllPlayerJoinedServerData.ts │ │ │ ├── ICardData.ts │ │ │ ├── IGameResultData.ts │ │ │ ├── ILoginScreenConfig.ts │ │ │ ├── INextRoundData.ts │ │ │ ├── IPlayerTurnAction.ts │ │ │ ├── IPlayerTurnData.ts │ │ │ ├── IPlayersBets.ts │ │ │ ├── IPlayersCards.ts │ │ │ ├── IPlayersMoney.ts │ │ │ ├── IRegisterScreenConfig.ts │ │ │ ├── IServerPlayerData.ts │ │ │ └── IUpdatePlayerTurnAction.ts │ │ ├── managers │ │ │ ├── AppManager.js │ │ │ ├── ImageManager.js │ │ │ └── SceneManager.ts │ │ ├── pages │ │ │ ├── CSS │ │ │ │ └── Pages.css │ │ │ ├── Pages.jsx │ │ │ ├── loadingGame │ │ │ │ ├── CSS │ │ │ │ │ └── LoadingGame.css │ │ │ │ └── LoadingGame.jsx │ │ │ └── manager │ │ │ │ └── PagesManager.js │ │ ├── services │ │ │ ├── requests │ │ │ │ ├── config │ │ │ │ │ └── config.ts │ │ │ │ ├── helper │ │ │ │ │ └── helper.ts │ │ │ │ └── requests.ts │ │ │ └── webSocket │ │ │ │ └── SocketClient.ts │ │ ├── storage │ │ │ ├── AppStorage.js │ │ │ ├── AudioStorage.ts │ │ │ ├── ImageStorage.js │ │ │ └── SceneStorage.js │ │ └── utility │ │ │ ├── formatNumber.js │ │ │ ├── math │ │ │ └── MathUtils.ts │ │ │ └── unformatNumber.js │ └── vite.config.js └── server │ ├── JWT │ ├── JWTManager.js │ └── config.js │ ├── MongoDB │ ├── DatabaseManager.js │ ├── credentials.js │ └── models │ │ └── User.js │ ├── PayPal │ ├── PayPalManager.js │ └── credentials.js │ ├── Socket │ └── manager │ │ └── SocketManager.js │ ├── config.js │ ├── controllers │ ├── authorization │ │ ├── authentication.js │ │ ├── index.js │ │ └── registration.js │ └── payPal │ │ ├── cancel.js │ │ ├── createPayment.js │ │ ├── index.js │ │ └── success.js │ ├── dataHasher │ ├── PasswordHasher.js │ └── config.js │ ├── game │ ├── config │ │ └── config.js │ ├── orderData.js │ └── utility │ │ └── math │ │ └── MathUtils.js │ ├── index.html │ ├── index.js │ ├── main.js │ ├── package.json │ └── webpack.config.js ├── favicon.svg ├── index.html └── style.css /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .cache 3 | dist 4 | node_modules 5 | MainToEdit 6 | -------------------------------------------------------------------------------- /assets/@socket.io-Dkula2eQ.js: -------------------------------------------------------------------------------- 1 | function r(t){if(t)return n(t)}function n(t){for(var s in r.prototype)t[s]=r.prototype[s];return t}r.prototype.on=r.prototype.addEventListener=function(t,s){return this._callbacks=this._callbacks||{},(this._callbacks["$"+t]=this._callbacks["$"+t]||[]).push(s),this};r.prototype.once=function(t,s){function e(){this.off(t,e),s.apply(this,arguments)}return e.fn=s,this.on(t,e),this};r.prototype.off=r.prototype.removeListener=r.prototype.removeAllListeners=r.prototype.removeEventListener=function(t,s){if(this._callbacks=this._callbacks||{},arguments.length==0)return this._callbacks={},this;var e=this._callbacks["$"+t];if(!e)return this;if(arguments.length==1)return delete this._callbacks["$"+t],this;for(var a,i=0;i-1?y(n):n};export{M as a,D as b,F as c,I as g}; 2 | -------------------------------------------------------------------------------- /assets/clsx-l0sNRNKZ.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /assets/define-data-property-CUxyvwXF.js: -------------------------------------------------------------------------------- 1 | import{r as g}from"./es-define-property-28jGrh5V.js";import{s as f,t as b}from"./es-errors-DzOT6E3C.js";import{g as p}from"./gopd-O61WwtTx.js";var s=g(),d=f,r=b,i=p,c=function(e,o,u){if(!e||typeof e!="object"&&typeof e!="function")throw new r("`obj` must be an object or a function`");if(typeof o!="string"&&typeof o!="symbol")throw new r("`property` must be a string or a symbol`");if(arguments.length>3&&typeof arguments[3]!="boolean"&&arguments[3]!==null)throw new r("`nonEnumerable`, if provided, must be a boolean or null");if(arguments.length>4&&typeof arguments[4]!="boolean"&&arguments[4]!==null)throw new r("`nonWritable`, if provided, must be a boolean or null");if(arguments.length>5&&typeof arguments[5]!="boolean"&&arguments[5]!==null)throw new r("`nonConfigurable`, if provided, must be a boolean or null");if(arguments.length>6&&typeof arguments[6]!="boolean")throw new r("`loose`, if provided, must be a boolean");var t=arguments.length>3?arguments[3]:null,a=arguments.length>4?arguments[4]:null,l=arguments.length>5?arguments[5]:null,m=arguments.length>6?arguments[6]:!1,n=!!i&&i(e,o);if(s)s(e,o,{configurable:l===null&&n?n.configurable:!l,enumerable:t===null&&n?n.enumerable:!t,value:u,writable:a===null&&n?n.writable:!a});else if(m||!t&&!a&&!l)e[o]=u;else throw new d("This environment does not support defining a property as non-configurable, non-writable, or non-enumerable.")};export{c as d}; 2 | -------------------------------------------------------------------------------- /assets/engine.io-parser-BiEtp6m2.js: -------------------------------------------------------------------------------- 1 | const s=Object.create(null);s.open="0";s.close="1";s.ping="2";s.pong="3";s.message="4";s.upgrade="5";s.noop="6";const w=Object.create(null);Object.keys(s).forEach(e=>{w[s[e]]=e});const p={type:"error",data:"parser error"},U=typeof Blob=="function"||typeof Blob<"u"&&Object.prototype.toString.call(Blob)==="[object BlobConstructor]",T=typeof ArrayBuffer=="function",C=e=>typeof ArrayBuffer.isView=="function"?ArrayBuffer.isView(e):e&&e.buffer instanceof ArrayBuffer,m=({type:e,data:n},r,t)=>U&&n instanceof Blob?r?t(n):b(n,t):T&&(n instanceof ArrayBuffer||C(n))?r?t(n):b(new Blob([n]),t):t(s[e]+(n||"")),b=(e,n)=>{const r=new FileReader;return r.onload=function(){const t=r.result.split(",")[1];n("b"+(t||""))},r.readAsDataURL(e)};function B(e){return e instanceof Uint8Array?e:e instanceof ArrayBuffer?new Uint8Array(e):new Uint8Array(e.buffer,e.byteOffset,e.byteLength)}let g;function P(e,n){if(U&&e.data instanceof Blob)return e.data.arrayBuffer().then(B).then(n);if(T&&(e.data instanceof ArrayBuffer||C(e.data)))return n(B(e.data));m(e,!1,r=>{g||(g=new TextEncoder),n(g.encode(r))})}const E="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",y=typeof Uint8Array>"u"?[]:new Uint8Array(256);for(let e=0;e{let n=e.length*.75,r=e.length,t,f=0,o,c,a,i;e[e.length-1]==="="&&(n--,e[e.length-2]==="="&&n--);const l=new ArrayBuffer(n),u=new Uint8Array(l);for(t=0;t>4,u[f++]=(c&15)<<4|a>>2,u[f++]=(a&3)<<6|i&63;return l},V=typeof ArrayBuffer=="function",R=(e,n)=>{if(typeof e!="string")return{type:"message",data:D(e,n)};const r=e.charAt(0);return r==="b"?{type:"message",data:x(e.substring(1),n)}:w[r]?e.length>1?{type:w[r],data:e.substring(1)}:{type:w[r]}:p},x=(e,n)=>{if(V){const r=S(e);return D(r,n)}else return{base64:!0,data:e}},D=(e,n)=>{switch(n){case"blob":return e instanceof Blob?e:new Blob([e]);case"arraybuffer":default:return e instanceof ArrayBuffer?e:e.buffer}},O="",v=(e,n)=>{const r=e.length,t=new Array(r);let f=0;e.forEach((o,c)=>{m(o,!1,a=>{t[c]=a,++f===r&&n(t.join(O))})})},L=(e,n)=>{const r=e.split(O),t=[];for(let f=0;f{const t=r.length;let f;if(t<126)f=new Uint8Array(1),new DataView(f.buffer).setUint8(0,t);else if(t<65536){f=new Uint8Array(3);const o=new DataView(f.buffer);o.setUint8(0,126),o.setUint16(1,t)}else{f=new Uint8Array(9);const o=new DataView(f.buffer);o.setUint8(0,127),o.setBigUint64(1,BigInt(t))}e.data&&typeof e.data!="string"&&(f[0]|=128),n.enqueue(f),n.enqueue(r)})}})}let A;function d(e){return e.reduce((n,r)=>n+r.length,0)}function h(e,n){if(e[0].length===n)return e.shift();const r=new Uint8Array(n);let t=0;for(let f=0;fMath.pow(2,21)-1){a.enqueue(p);break}f=u*Math.pow(2,32)+l.getUint32(4),t=3}else{if(d(r)e){a.enqueue(p);break}}}})}const _=4;export{L as a,m as b,q as c,R as d,v as e,j as f,_ as p}; 2 | -------------------------------------------------------------------------------- /assets/es-define-property-28jGrh5V.js: -------------------------------------------------------------------------------- 1 | import{g as n}from"./get-intrinsic-B1Ut8WxJ.js";var r,t;function s(){if(t)return r;t=1;var i=n,e=i("%Object.defineProperty%",!0)||!1;if(e)try{e({},"a",{value:1})}catch{e=!1}return r=e,r}export{s as r}; 2 | -------------------------------------------------------------------------------- /assets/es-errors-DzOT6E3C.js: -------------------------------------------------------------------------------- 1 | var r=Error,a=EvalError,e=RangeError,s=ReferenceError,o=SyntaxError,v=TypeError,E=URIError;export{a as _,s as a,r as e,e as r,o as s,v as t,E as u}; 2 | -------------------------------------------------------------------------------- /assets/eventemitter3-Bav5T-Ru.js: -------------------------------------------------------------------------------- 1 | import{g as d}from"./call-bind-CkPzBTRv.js";var m={exports:{}};(function(g){var w=Object.prototype.hasOwnProperty,u="~";function h(){}Object.create&&(h.prototype=Object.create(null),new h().__proto__||(u=!1));function E(s,t,n){this.fn=s,this.context=t,this.once=n||!1}function x(s,t,n,r,l){if(typeof n!="function")throw new TypeError("The listener must be a function");var c=new E(n,r||s,l),o=u?u+t:t;return s._events[o]?s._events[o].fn?s._events[o]=[s._events[o],c]:s._events[o].push(c):(s._events[o]=c,s._eventsCount++),s}function y(s,t){--s._eventsCount===0?s._events=new h:delete s._events[t]}function f(){this._events=new h,this._eventsCount=0}f.prototype.eventNames=function(){var t=[],n,r;if(this._eventsCount===0)return t;for(r in n=this._events)w.call(n,r)&&t.push(u?r.slice(1):r);return Object.getOwnPropertySymbols?t.concat(Object.getOwnPropertySymbols(n)):t},f.prototype.listeners=function(t){var n=u?u+t:t,r=this._events[n];if(!r)return[];if(r.fn)return[r.fn];for(var l=0,c=r.length,o=new Array(c);l 2 | 3 | 4 | 19 | 39 | 41 | 46 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /assets/images/UI/buttons/bet_down_button_hover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 39 | 41 | 49 | 53 | 54 | 55 | 60 | 69 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /assets/images/UI/buttons/bet_down_button_push.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 39 | 41 | 46 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /assets/images/UI/buttons/bet_up_button.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 36 | 38 | 43 | 46 | 50 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /assets/images/UI/buttons/bet_up_button_hover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 36 | 38 | 46 | 50 | 51 | 52 | 57 | 61 | 70 | 80 | 81 | 85 | 89 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /assets/images/UI/buttons/bet_up_button_push.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 39 | 41 | 46 | 50 | 54 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /assets/images/UI/buttons/close_button.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 36 | 38 | 43 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /assets/images/UI/buttons/close_button_push.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 36 | 38 | 43 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /assets/images/UI/buttons/hamburger_button.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 36 | 38 | 43 | 48 | 53 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /assets/images/UI/buttons/information_button.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 39 | 41 | 46 | 49 | 58 | 64 | 68 | 74 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /assets/images/UI/buttons/sound_off_button.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 39 | 41 | 46 | 50 | 55 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /assets/images/UI/buttons/sound_on_button.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 39 | 41 | 46 | 50 | 55 | 60 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /assets/images/UI/buy_credits/buy_credits_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/UI/buy_credits/buy_credits_icon.png -------------------------------------------------------------------------------- /assets/images/UI/spin_button/spin_button_hover.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/UI/symbols/banana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/UI/symbols/banana.png -------------------------------------------------------------------------------- /assets/images/UI/symbols/bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/UI/symbols/bar.png -------------------------------------------------------------------------------- /assets/images/UI/symbols/bell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/UI/symbols/bell.png -------------------------------------------------------------------------------- /assets/images/UI/symbols/cherry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/UI/symbols/cherry.png -------------------------------------------------------------------------------- /assets/images/UI/symbols/grapes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/UI/symbols/grapes.png -------------------------------------------------------------------------------- /assets/images/UI/symbols/lemon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/UI/symbols/lemon.png -------------------------------------------------------------------------------- /assets/images/UI/symbols/orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/UI/symbols/orange.png -------------------------------------------------------------------------------- /assets/images/UI/symbols/plum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/UI/symbols/plum.png -------------------------------------------------------------------------------- /assets/images/UI/symbols/seven.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/UI/symbols/seven.png -------------------------------------------------------------------------------- /assets/images/UI/symbols/strawberry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/UI/symbols/strawberry.png -------------------------------------------------------------------------------- /assets/images/UI/symbols/watermelon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/UI/symbols/watermelon.png -------------------------------------------------------------------------------- /assets/images/bet_label_background.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 34 | 36 | 45 | 47 | 51 | 55 | 56 | 57 | 62 | 67 | 68 | -------------------------------------------------------------------------------- /assets/images/credits_counter_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/credits_counter_background.png -------------------------------------------------------------------------------- /assets/images/credits_counter_shine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/credits_counter_shine.png -------------------------------------------------------------------------------- /assets/images/dark_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/dark_screen.png -------------------------------------------------------------------------------- /assets/images/eagle.atlas: -------------------------------------------------------------------------------- 1 | eagle.png 2 | size:2048,512 3 | filter:Linear,Linear 4 | eagle_beak 5 | bounds:222,47,91,76 6 | offsets:0,10,91,86 7 | eagle_beak_down 8 | bounds:1809,430,100,74 9 | offsets:0,0,102,74 10 | eagle_beak_up 11 | bounds:829,244,85,52 12 | eagle_bg 13 | bounds:2,125,259,379 14 | eagle_bg_glow 15 | bounds:263,125,259,379 16 | eagle_body 17 | bounds:1181,278,226,312 18 | offsets:0,0,230,343 19 | rotate:90 20 | eagle_body_2 21 | bounds:524,235,303,269 22 | offsets:0,437,313,722 23 | eagle_body_light 24 | bounds:1495,278,226,312 25 | offsets:0,0,230,343 26 | rotate:90 27 | eagle_eye 28 | bounds:2,2,37,37 29 | eagle_wing 30 | bounds:524,149,84,200 31 | rotate:90 32 | eagle_wing_L 33 | bounds:2,41,82,218 34 | rotate:90 35 | wolf_frame 36 | bounds:829,298,206,350 37 | rotate:90 38 | -------------------------------------------------------------------------------- /assets/images/eagle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/eagle.png -------------------------------------------------------------------------------- /assets/images/feather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/feather.png -------------------------------------------------------------------------------- /assets/images/game/background/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/background/background.jpg -------------------------------------------------------------------------------- /assets/images/game/background/background.json: -------------------------------------------------------------------------------- 1 | { 2 | "frames": { 3 | "landscape_bg": { 4 | "frame": { 5 | "x": 1, 6 | "y": 1, 7 | "w": 2340, 8 | "h": 1440 9 | }, 10 | "rotated": false, 11 | "trimmed": false, 12 | "spriteSourceSize": { 13 | "x": 0, 14 | "y": 0, 15 | "w": 2340, 16 | "h": 1440 17 | }, 18 | "sourceSize": { 19 | "w": 2340, 20 | "h": 1440 21 | } 22 | }, 23 | "portrait_bg": { 24 | "frame": { 25 | "x": 2343, 26 | "y": 1, 27 | "w": 1440, 28 | "h": 2340 29 | }, 30 | "rotated": false, 31 | "trimmed": false, 32 | "spriteSourceSize": { 33 | "x": 0, 34 | "y": 0, 35 | "w": 1440, 36 | "h": 2340 37 | }, 38 | "sourceSize": { 39 | "w": 1440, 40 | "h": 2340 41 | } 42 | } 43 | }, 44 | "animations": { 45 | "portrait": ["portrait_bg"], 46 | "landscape": ["landscape_bg"] 47 | }, 48 | "meta": { 49 | "app": "http://www.codeandweb.com/texturepacker", 50 | "version": "1.0", 51 | "image": "background.jpg", 52 | "format": "RGBA8888", 53 | "size": { 54 | "w": 3784, 55 | "h": 2342 56 | }, 57 | "scale": "1" 58 | } 59 | } -------------------------------------------------------------------------------- /assets/images/game/background/background_overlay.json: -------------------------------------------------------------------------------- 1 | { 2 | "frames": { 3 | "landscape_overlay_bg": { 4 | "frame": { 5 | "x": 1, 6 | "y": 1, 7 | "w": 2340, 8 | "h": 1440 9 | }, 10 | "rotated": false, 11 | "trimmed": false, 12 | "spriteSourceSize": { 13 | "x": 0, 14 | "y": 0, 15 | "w": 2340, 16 | "h": 1440 17 | }, 18 | "sourceSize": { 19 | "w": 2340, 20 | "h": 1440 21 | } 22 | }, 23 | "portrait_overlay_bg": { 24 | "frame": { 25 | "x": 2343, 26 | "y": 1, 27 | "w": 1440, 28 | "h": 2340 29 | }, 30 | "rotated": false, 31 | "trimmed": false, 32 | "spriteSourceSize": { 33 | "x": 0, 34 | "y": 0, 35 | "w": 1440, 36 | "h": 2340 37 | }, 38 | "sourceSize": { 39 | "w": 1440, 40 | "h": 2340 41 | } 42 | } 43 | }, 44 | "animations": { 45 | "portrait": ["portrait_overlay_bg"], 46 | "landscape": ["landscape_overlay_bg"] 47 | }, 48 | "meta": { 49 | "app": "http://www.codeandweb.com/texturepacker", 50 | "version": "1.0", 51 | "image": "background_overlay.png", 52 | "format": "RGBA8888", 53 | "size": { 54 | "w": 3784, 55 | "h": 2342 56 | }, 57 | "scale": "1" 58 | } 59 | } -------------------------------------------------------------------------------- /assets/images/game/background/background_overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/background/background_overlay.png -------------------------------------------------------------------------------- /assets/images/game/matching/frames/fire_frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/matching/frames/fire_frame.png -------------------------------------------------------------------------------- /assets/images/game/matching/lines/matchLinesAtlas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/matching/lines/matchLinesAtlas.png -------------------------------------------------------------------------------- /assets/images/game/symbols/Experience_star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/symbols/Experience_star.png -------------------------------------------------------------------------------- /assets/images/game/symbols/Experience_star_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/symbols/Experience_star_2.png -------------------------------------------------------------------------------- /assets/images/game/symbols/banana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/symbols/banana.png -------------------------------------------------------------------------------- /assets/images/game/symbols/bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/symbols/bar.png -------------------------------------------------------------------------------- /assets/images/game/symbols/bell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/symbols/bell.png -------------------------------------------------------------------------------- /assets/images/game/symbols/cherry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/symbols/cherry.png -------------------------------------------------------------------------------- /assets/images/game/symbols/grapes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/symbols/grapes.png -------------------------------------------------------------------------------- /assets/images/game/symbols/lemon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/symbols/lemon.png -------------------------------------------------------------------------------- /assets/images/game/symbols/orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/symbols/orange.png -------------------------------------------------------------------------------- /assets/images/game/symbols/plum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/symbols/plum.png -------------------------------------------------------------------------------- /assets/images/game/symbols/seven.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/symbols/seven.png -------------------------------------------------------------------------------- /assets/images/game/symbols/strawberry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/symbols/strawberry.png -------------------------------------------------------------------------------- /assets/images/game/symbols/watermelon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game/symbols/watermelon.png -------------------------------------------------------------------------------- /assets/images/game_name_logo_landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game_name_logo_landscape.png -------------------------------------------------------------------------------- /assets/images/game_name_logo_portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/game_name_logo_portrait.png -------------------------------------------------------------------------------- /assets/images/loading_game_anim.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /assets/images/symbol_describe_label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/symbol_describe_label.png -------------------------------------------------------------------------------- /assets/images/symbols_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/symbols_bg.png -------------------------------------------------------------------------------- /assets/images/symbols_dark_mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/assets/images/symbols_dark_mask.png -------------------------------------------------------------------------------- /assets/ismobilejs-CHLuctl-.js: -------------------------------------------------------------------------------- 1 | var p=/iPhone/i,b=/iPod/i,h=/iPad/i,v=/\biOS-universal(?:.+)Mac\b/i,s=/\bAndroid(?:.+)Mobile\b/i,f=/Android/i,r=/(?:SD4930UR|\bSilk(?:.+)Mobile\b)/i,d=/Silk/i,t=/Windows Phone/i,u=/\bWindows(?:.+)ARM\b/i,c=/BlackBerry/i,m=/BB10/i,w=/Opera Mini/i,y=/\b(CriOS|Chrome)(?:.+)Mobile/i,A=/Mobile(?:.+)Firefox\b/i,P=function(i){return typeof i<"u"&&i.platform==="MacIntel"&&typeof i.maxTouchPoints=="number"&&i.maxTouchPoints>1&&typeof MSStream>"u"};function T(i){return function(n){return n.test(i)}}function g(i){var n={userAgent:"",platform:"",maxTouchPoints:0};!i&&typeof navigator<"u"?n={userAgent:navigator.userAgent,platform:navigator.platform,maxTouchPoints:navigator.maxTouchPoints||0}:typeof i=="string"?n.userAgent=i:i&&i.userAgent&&(n={userAgent:i.userAgent,platform:i.platform,maxTouchPoints:i.maxTouchPoints||0});var a=n.userAgent,l=a.split("[FBAN");typeof l[1]<"u"&&(a=l[0]),l=a.split("Twitter"),typeof l[1]<"u"&&(a=l[0]);var e=T(a),o={apple:{phone:e(p)&&!e(t),ipod:e(b),tablet:!e(p)&&(e(h)||P(n))&&!e(t),universal:e(v),device:(e(p)||e(b)||e(h)||e(v)||P(n))&&!e(t)},amazon:{phone:e(r),tablet:!e(r)&&e(d),device:e(r)||e(d)},android:{phone:!e(t)&&e(r)||!e(t)&&e(s),tablet:!e(t)&&!e(r)&&!e(s)&&(e(d)||e(f)),device:!e(t)&&(e(r)||e(d)||e(s)||e(f))||e(/\bokhttp\b/i)},windows:{phone:e(t),tablet:e(u),device:e(t)||e(u)},other:{blackberry:e(c),blackberry10:e(m),opera:e(w),firefox:e(A),chrome:e(y),device:e(c)||e(m)||e(w)||e(A)||e(y)},any:!1,phone:!1,tablet:!1};return o.any=o.apple.device||o.android.device||o.windows.device||o.other.device,o.phone=o.apple.phone||o.android.phone||o.windows.phone,o.tablet=o.apple.tablet||o.android.tablet||o.windows.tablet,o}export{g as i}; 2 | -------------------------------------------------------------------------------- /assets/js-cookie-Cz0CWeBA.js: -------------------------------------------------------------------------------- 1 | /*! js-cookie v3.0.5 | MIT */function d(r){for(var c=1;c"u")){e=d({},c,e),typeof e.expires=="number"&&(e.expires=new Date(Date.now()+e.expires*864e5)),e.expires&&(e.expires=e.expires.toUTCString()),n=encodeURIComponent(n).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape);var o="";for(var i in e)e[i]&&(o+="; "+i,e[i]!==!0&&(o+="="+e[i].split(";")[0]));return document.cookie=n+"="+r.write(t,n)+o}}function p(n){if(!(typeof document>"u"||arguments.length&&!n)){for(var t=document.cookie?document.cookie.split("; "):[],e={},o=0;o{Object.defineProperty(t,r,{get(){return i("7.1.0",`filters.${r} has moved to ${r}`),e}})}); 2 | -------------------------------------------------------------------------------- /assets/react-toastify-B8GeWnC-.js: -------------------------------------------------------------------------------- 1 | import"./react-CWbZ82Fp.js"; 2 | -------------------------------------------------------------------------------- /assets/scheduler-CzFDRTuY.js: -------------------------------------------------------------------------------- 1 | var H={exports:{}},J={};/** 2 | * @license React 3 | * scheduler.production.min.js 4 | * 5 | * Copyright (c) Facebook, Inc. and its affiliates. 6 | * 7 | * This source code is licensed under the MIT license found in the 8 | * LICENSE file in the root directory of this source tree. 9 | */(function(l){function P(n,e){var t=n.length;n.push(e);n:for(;0>>1,r=n[i];if(0>>1;ih(N,t))bh(I,N)?(n[i]=I,n[b]=t,i=b):(n[i]=N,n[v]=t,i=v);else if(bh(I,t))n[i]=I,n[b]=t,i=b;else break n}}return e}function h(n,e){var t=n.sortIndex-e.sortIndex;return t!==0?t:n.id-e.id}if(typeof performance=="object"&&typeof performance.now=="function"){var K=performance;l.unstable_now=function(){return K.now()}}else{var R=Date,O=R.now();l.unstable_now=function(){return R.now()-O}}var f=[],c=[],Q=1,a=null,u=3,m=!1,s=!1,y=!1,j=typeof setTimeout=="function"?setTimeout:null,B=typeof clearTimeout=="function"?clearTimeout:null,D=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function T(n){for(var e=o(c);e!==null;){if(e.callback===null)_(c);else if(e.startTime<=n)_(c),e.sortIndex=e.expirationTime,P(f,e);else break;e=o(c)}}function E(n){if(y=!1,T(n),!s)if(o(f)!==null)s=!0,M(C);else{var e=o(c);e!==null&&F(E,e.startTime-n)}}function C(n,e){s=!1,y&&(y=!1,B(d),d=-1),m=!0;var t=u;try{for(T(e),a=o(f);a!==null&&(!(a.expirationTime>e)||n&&!A());){var i=a.callback;if(typeof i=="function"){a.callback=null,u=a.priorityLevel;var r=i(a.expirationTime<=e);e=l.unstable_now(),typeof r=="function"?a.callback=r:a===o(f)&&_(f),T(e)}else _(f);a=o(f)}if(a!==null)var w=!0;else{var v=o(c);v!==null&&F(E,v.startTime-e),w=!1}return w}finally{a=null,u=t,m=!1}}var k=!1,p=null,d=-1,q=5,z=-1;function A(){return!(l.unstable_now()-zn||125i?(n.sortIndex=t,P(c,n),o(f)===null&&n===o(c)&&(y?(B(d),d=-1):y=!0,F(E,t-i))):(n.sortIndex=r,P(f,n),s||m||(s=!0,M(C))),n},l.unstable_shouldYield=A,l.unstable_wrapCallback=function(n){var e=u;return function(){var t=u;u=e;try{return n.apply(this,arguments)}finally{u=t}}}})(J);H.exports=J;var U=H.exports;export{U as s}; 10 | -------------------------------------------------------------------------------- /assets/set-function-length-Ct5B6P4y.js: -------------------------------------------------------------------------------- 1 | import{g as u}from"./get-intrinsic-B1Ut8WxJ.js";import{d as p}from"./define-data-property-CUxyvwXF.js";import{h as g}from"./has-property-descriptors-Cvfij9iw.js";import{g as m}from"./gopd-O61WwtTx.js";import{t as v}from"./es-errors-DzOT6E3C.js";var h=u,a=p,l=g(),n=m,s=v,F=h("%Math.floor%"),L=function(t,r){if(typeof t!="function")throw new s("`fn` is not a function");if(typeof r!="number"||r<0||r>4294967295||F(r)!==r)throw new s("`length` must be a positive 32-bit integer");var f=arguments.length>2&&!!arguments[2],o=!0,i=!0;if("length"in t&&n){var e=n(t,"length");e&&!e.configurable&&(o=!1),e&&!e.writable&&(i=!1)}return(o||i||!f)&&(l?a(t,"length",r,!0,!0):a(t,"length",r)),t};export{L as s}; 2 | -------------------------------------------------------------------------------- /assets/side-channel-CzTPmnEc.js: -------------------------------------------------------------------------------- 1 | import{g as c}from"./get-intrinsic-B1Ut8WxJ.js";import{b as l}from"./call-bind-CkPzBTRv.js";import{o as m}from"./object-inspect-CJVVCa5F.js";import{t as M}from"./es-errors-DzOT6E3C.js";var v=c,o=l,$=m,x=M,i=v("%WeakMap%",!0),p=v("%Map%",!0),d=o("WeakMap.prototype.get",!0),h=o("WeakMap.prototype.set",!0),w=o("WeakMap.prototype.has",!0),g=o("Map.prototype.get",!0),G=o("Map.prototype.set",!0),S=o("Map.prototype.has",!0),u=function(a,n){for(var r=a,e;(e=r.next)!==null;r=e)if(e.key===n)return r.next=e.next,e.next=a.next,a.next=e,e},W=function(a,n){var r=u(a,n);return r&&r.value},b=function(a,n,r){var e=u(a,n);e?e.value=r:a.next={key:n,next:a.next,value:r}},H=function(a,n){return!!u(a,n)},E=function(){var n,r,e,s={assert:function(t){if(!s.has(t))throw new x("Side channel does not contain "+$(t))},get:function(t){if(i&&t&&(typeof t=="object"||typeof t=="function")){if(n)return d(n,t)}else if(p){if(r)return g(r,t)}else if(e)return W(e,t)},has:function(t){if(i&&t&&(typeof t=="object"||typeof t=="function")){if(n)return w(n,t)}else if(p){if(r)return S(r,t)}else if(e)return H(e,t);return!1},set:function(t,f){i&&t&&(typeof t=="object"||typeof t=="function")?(n||(n=new i),h(n,t,f)):p?(r||(r=new p),G(r,t,f)):(e||(e={key:{},next:null}),b(e,t,f))}};return s};export{E as s}; 2 | -------------------------------------------------------------------------------- /assets/socket.io-parser-BBkuslX-.js: -------------------------------------------------------------------------------- 1 | import{E as N}from"./@socket.io-Dkula2eQ.js";const A=typeof ArrayBuffer=="function",E=e=>typeof ArrayBuffer.isView=="function"?ArrayBuffer.isView(e):e.buffer instanceof ArrayBuffer,y=Object.prototype.toString,d=typeof Blob=="function"||typeof Blob<"u"&&y.call(Blob)==="[object BlobConstructor]",g=typeof File=="function"||typeof File<"u"&&y.call(File)==="[object FileConstructor]";function a(e){return A&&(e instanceof ArrayBuffer||E(e))||d&&e instanceof Blob||g&&e instanceof File}function u(e,r){if(!e||typeof e!="object")return!1;if(Array.isArray(e)){for(let t=0,n=e.length;t=0&&e.num 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | Slot Machine 13 | 14 | 15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /code/client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-app", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "gsap": "^3.12.5", 14 | "howler": "^2.2.4", 15 | "js-cookie": "^3.0.5", 16 | "mini-signals": "^2.0.0", 17 | "pixi.js": "7.4", 18 | "react": "^18.2.0", 19 | "react-dom": "^18.2.0", 20 | "react-toastify": "^10.0.5", 21 | "socket.io-client": "^4.7.5" 22 | }, 23 | "devDependencies": { 24 | "@types/react": "^18.2.66", 25 | "@types/react-dom": "^18.2.22", 26 | "@vitejs/plugin-react": "^4.2.1", 27 | "eslint": "^8.57.0", 28 | "eslint-plugin-react": "^7.34.1", 29 | "eslint-plugin-react-hooks": "^4.6.0", 30 | "eslint-plugin-react-refresh": "^0.4.6", 31 | "vite": "^5.2.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /code/client/public/assets/audio/loadAudioData.json: -------------------------------------------------------------------------------- 1 | { 2 | "background": { 3 | "path": "music", 4 | "key": "background", 5 | "settings":{ 6 | "loop": true, 7 | "volume": 0.5 8 | } 9 | }, 10 | "reelRotation": { 11 | "path": "reel", 12 | "key": "reel_rotation", 13 | "settings":{ 14 | "loop": false, 15 | "volume": 1 16 | } 17 | }, 18 | "reelStop": { 19 | "path": "reel", 20 | "key": "reel_stop", 21 | "settings":{ 22 | "loop": false, 23 | "volume": 1 24 | } 25 | }, 26 | "buttonClick": { 27 | "path": "other", 28 | "key": "button_click", 29 | "settings":{ 30 | "loop": false, 31 | "volume": 1 32 | } 33 | }, 34 | "fireFrame": { 35 | "path": "other", 36 | "key": "fire_frame", 37 | "settings":{ 38 | "loop": false, 39 | "volume": 1 40 | } 41 | }, 42 | "creditsCount": { 43 | "path": "other", 44 | "key": "credits_count", 45 | "settings":{ 46 | "loop": false, 47 | "volume": 0.6 48 | } 49 | }, 50 | "lineMatch": { 51 | "path": "other", 52 | "key": "line_match", 53 | "settings":{ 54 | "loop": false, 55 | "volume": 0.6 56 | } 57 | }, 58 | "countLoop": { 59 | "path": "other", 60 | "key": "count_loop", 61 | "settings":{ 62 | "loop": false, 63 | "volume": 1 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /code/client/public/style.css: -------------------------------------------------------------------------------- 1 | /* body { 2 | margin: 0; 3 | padding: 0; 4 | color: rgba(255, 255, 255, 0.87); 5 | background-color: #000000; 6 | font-family: Arial, Helvetica, sans-serif; 7 | } 8 | 9 | #app { 10 | width: 100%; 11 | height: 100vh; 12 | overflow: hidden; 13 | display: flex; 14 | justify-content: center; 15 | align-items: center; 16 | } */ 17 | 18 | /* .spritePosition { 19 | margin: 10px 0 0 10px; 20 | font-size: 0.8em; 21 | } 22 | 23 | .button { 24 | width: 140px; 25 | margin: 10px; 26 | padding: 10px; 27 | background-color: #000000; 28 | color: rgba(255, 255, 255, 0.87); 29 | border: 1px solid rgba(255, 255, 255, 0.87); 30 | cursor: pointer; 31 | transition: all 0.3s; 32 | 33 | &:hover { 34 | border: 1px solid #0ec3c9; 35 | color: #0ec3c9; 36 | } 37 | 38 | &:active { 39 | background-color: #0ec3c9; 40 | } 41 | 42 | &:disabled { 43 | cursor: not-allowed; 44 | border: 1px solid rgba(255, 255, 255, 0.3); 45 | color: rgba(255, 255, 255, 0.3); 46 | } 47 | } */ -------------------------------------------------------------------------------- /code/client/src/App.css: -------------------------------------------------------------------------------- 1 | 2 | html { 3 | overflow: hidden; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | padding: 0; 9 | height: 100%; 10 | width: 100%; 11 | color: rgba(255, 255, 255, 0.87); 12 | background: #3a3a3a; 13 | font-family: Arial, Helvetica, sans-serif; 14 | } 15 | 16 | #app { 17 | margin: 0; 18 | padding: 0; 19 | height: 100%; 20 | width: 100%; 21 | overflow: hidden; 22 | } 23 | -------------------------------------------------------------------------------- /code/client/src/App.jsx: -------------------------------------------------------------------------------- 1 | import "./App.css"; 2 | import PixiGame from './game/PixiGame'; 3 | import { useRef, useState, useEffect } from 'react'; 4 | import { StartGame } from './game/StartGame'; 5 | import ScreenUtils from './utility/screen/ScreenUtils'; 6 | import UIManager from './UI/manager/UIManager.js'; 7 | import Pages from './pages/Pages'; 8 | import PagesManager from './pages/manager/PagesManager.js'; 9 | import UI from './UI/UI'; 10 | 11 | function App() { 12 | const pixiRef = useRef(); 13 | const UIRef = useRef(null); 14 | const pagesRef = useRef(null); 15 | 16 | useEffect(() => { 17 | const game = pixiRef.current; 18 | const UI = UIRef.current 19 | const pages = pagesRef.current 20 | 21 | StartGame(game); 22 | UIManager.create(UI) 23 | PagesManager.create(pages) 24 | ScreenUtils.resizeScreen(UI, game, pages) 25 | window.addEventListener("resize", () => ScreenUtils.resizeScreen(UI, game, pages)); 26 | }, []); 27 | 28 | return ( 29 |
30 | 31 | 32 | 33 |
34 | ); 35 | } 36 | 37 | export default App; 38 | -------------------------------------------------------------------------------- /code/client/src/UI/CSS/UI.css: -------------------------------------------------------------------------------- 1 | #UI { 2 | position: fixed; 3 | width: 1280px; 4 | height: 720px; 5 | pointer-events: none; 6 | transform-origin: 0 0 0; 7 | /* transform: scale(1.5); */ 8 | /* visibility:hidden; */ 9 | /* transform-origin: 0 0 0; 10 | align-content:space-between ; 11 | display: flex; 12 | flex-direction: column; 13 | justify-content: space-between; */ 14 | /* top: 0; 15 | left:0 */ 16 | /* transform: translate(0%, 50%); */ 17 | /* transform: scale(); */ 18 | /* width: 100%; 19 | height: 100%; */ 20 | /* top: 60%; 21 | left: 50%; 22 | transform: translate(-50%, 0%); 23 | width: auto; 24 | height: auto; 25 | max-width: 20%; 26 | max-height: 20%; 27 | object-fit: cover; */ 28 | } 29 | 30 | -------------------------------------------------------------------------------- /code/client/src/UI/UI.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component, createRef, useEffect } from 'react'; 2 | import "./CSS/UI.css"; 3 | import BottomBar from "./bottomBar/BottomBar"; 4 | import TopBar from "./topBar/TopBar"; 5 | import MiddleBar from "./middleBar/MiddleBar"; 6 | import ComponentsContextRefsStorage from "../componentsContextRefs/ComponentsContextRefsStorage"; 7 | 8 | class UI extends Component { 9 | constructor(props) { 10 | super(props); 11 | this.state = { 12 | width: '0px', 13 | height: '0px', 14 | left: '0px', 15 | top: '0px', 16 | transform: 'none', 17 | display: 'none' 18 | }; 19 | this.topBarRef = createRef() 20 | this.bottomBarRef = createRef() 21 | this.middleBarRef = createRef() 22 | 23 | ComponentsContextRefsStorage.add("bottomBar", this.bottomBarRef) 24 | ComponentsContextRefsStorage.add("middleBar", this.middleBarRef) 25 | ComponentsContextRefsStorage.add("topBar", this.topBarRef) 26 | } 27 | 28 | handleVisible(value){ 29 | value === true ? this.setState({display: 'block'}) : this.setState({display: 'none'}) 30 | this.middleBarRef.current.startOpenTween() 31 | this.topBarRef.current.startOpenTween() 32 | this.bottomBarRef.current.startOpenTween() 33 | } 34 | 35 | resize(resizeData){ 36 | this.setState(resizeData); 37 | } 38 | 39 | resizeBottomBar(resizeData){ 40 | this.bottomBarRef.current.resize(resizeData) 41 | } 42 | 43 | resizeTopBar(resizeData){ 44 | this.topBarRef.current.resize(resizeData) 45 | } 46 | 47 | get bottomBarHeight(){ 48 | return this.bottomBarRef.current.getHeight() 49 | } 50 | 51 | render() { 52 | const { width, height, left, top, transform, display } = this.state; 53 | const style = { width, height, left, top, transform, display }; 54 | 55 | return ( 56 |
57 | 58 | 59 | 60 |
61 | ); 62 | } 63 | } 64 | 65 | export default React.forwardRef((props, ref) => ); -------------------------------------------------------------------------------- /code/client/src/UI/bottomBar/BottomBar.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useImperativeHandle, useRef, useEffect } from "react"; 2 | import "./CSS/BottomBar.css"; 3 | import gsap from 'gsap'; 4 | import BetLabel from './betLabel/BetLabel.jsx'; 5 | import Balance from './balance/Balance.jsx' 6 | import Options from './options/Options.jsx' 7 | 8 | const BottomBar = React.forwardRef((props, ref) => { 9 | const [state, setState] = useState({ 10 | bottom: '0px', 11 | height: 100 12 | }); 13 | const bottomBarRef = useRef(null); 14 | const betLabelRef = useRef(null); 15 | const balanceRef = useRef(null); 16 | 17 | const update = (newData) => { 18 | betLabelRef.current.update(newData) 19 | balanceRef.current.update(newData.credits) 20 | } 21 | 22 | const updateBalanceValue = (newValue) => { 23 | balanceRef.current.update(newValue) 24 | } 25 | 26 | const getBalanceValue = () => { 27 | return balanceRef.current.getValue() 28 | } 29 | 30 | const getBetValue = () => { 31 | return betLabelRef.current.getBetValue() 32 | } 33 | 34 | const hasSufficientBalanceForSpin = (balance) => { 35 | return betLabelRef.current.hasSufficientBalance(balance) 36 | } 37 | 38 | const calculateAndUpdateBalance = (betValue) => { 39 | return balanceRef.current.calculateAndUpdateBalance(betValue) 40 | } 41 | 42 | useEffect(() => { 43 | window.addEventListener('resize', onResize); 44 | return () => window.removeEventListener('resize', onResize); 45 | }, []); 46 | 47 | const resize = (resizeData) => { 48 | setState((prevState) => ({ 49 | ...prevState, 50 | ...resizeData 51 | })); 52 | }; 53 | 54 | const getHeight = () => { 55 | return state.height 56 | } 57 | 58 | const startOpenTween = () => { 59 | gsap.fromTo( 60 | bottomBarRef.current, 61 | { scale: 0 }, 62 | { scale: 1, ease: "back.out", duration: 1 }) 63 | } 64 | 65 | const onResize = () => { 66 | 67 | } 68 | 69 | useImperativeHandle(ref, () => ({ 70 | resize, 71 | getHeight, 72 | startOpenTween, 73 | hasSufficientBalanceForSpin, 74 | calculateAndUpdateBalance, 75 | getBetValue, 76 | updateBalanceValue, 77 | update, 78 | getBalanceValue 79 | })); 80 | 81 | return ( 82 |
83 |
84 | 85 |
86 |
87 | 88 |
89 |
90 | 91 |
92 |
93 | ); 94 | }); 95 | 96 | export default BottomBar; 97 | -------------------------------------------------------------------------------- /code/client/src/UI/bottomBar/CSS/BottomBar.css: -------------------------------------------------------------------------------- 1 | #UI #bottom-bar { 2 | position: absolute; 3 | display: flex; 4 | /* justify-content:flex-start; */ 5 | justify-content:space-between; 6 | align-items: center; 7 | width: 100%; 8 | } 9 | 10 | #bottom-bar #separate-container { 11 | width: 100%; 12 | display: flex; 13 | align-items: center; 14 | justify-content:center; 15 | } 16 | 17 | @media (max-aspect-ratio: 1) { 18 | #bottom-bar #separate-container { 19 | transform:scale(1.1) !important; 20 | /* margin-top: -10px; */ 21 | } 22 | } -------------------------------------------------------------------------------- /code/client/src/UI/bottomBar/balance/Balance.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useImperativeHandle} from "react"; 2 | import "./CSS/Balance.css"; 3 | 4 | const Balance = React.forwardRef((props, ref) => { 5 | const [balanceValue, setBalanceValue] = useState(0); 6 | 7 | const update = (newValue) => { 8 | setBalanceValue(newValue) 9 | } 10 | 11 | const getValue = () => { 12 | return balanceValue 13 | } 14 | 15 | const calculateAndUpdateBalance = (betValue) => { 16 | const newBalance = balanceValue - betValue 17 | setBalanceValue(newBalance) 18 | } 19 | 20 | useImperativeHandle(ref, () => ({ 21 | update, 22 | getValue, 23 | calculateAndUpdateBalance 24 | })); 25 | 26 | return ( 27 |
28 |

Balance

29 |

{balanceValue.toFixed(2)}★

30 |
31 | ); 32 | }); 33 | 34 | export default Balance; 35 | -------------------------------------------------------------------------------- /code/client/src/UI/bottomBar/balance/CSS/Balance.css: -------------------------------------------------------------------------------- 1 | #balance-container { 2 | text-align: left; 3 | } 4 | 5 | #balance-container #title{ 6 | color: rgb(177, 175, 175); 7 | font-size: 18px; 8 | padding: 0px; 9 | margin: 0px; 10 | margin-bottom: -5px; 11 | } 12 | 13 | #balance-container #value{ 14 | margin: 0px; 15 | padding: 0px; 16 | font-size: 30px; 17 | } -------------------------------------------------------------------------------- /code/client/src/UI/middleBar/CSS/MiddleBar.css: -------------------------------------------------------------------------------- 1 | #UI #middle-bar { 2 | position: absolute; 3 | display: flex; 4 | justify-content:end; 5 | /* display: flex; 6 | justify-content:space-between; 7 | align-items: center; */ 8 | transform: translate(0%, -50%); 9 | /* transform-origin: 0.5 0.5 0.5; */ 10 | width: 100%; 11 | height: 600px; 12 | font-size: 24px; 13 | top: 10%; 14 | 15 | /* position: absolute; 16 | display: flex; 17 | justify-content:space-around; 18 | width: 100vw; 19 | background: rgba(0,0,0,.3); */ 20 | /* transform: translate(0%, 0%); */ 21 | /* top: 100vh; */ 22 | /* bottom: 0; */ 23 | 24 | /* transform-origin: bottom center; */ 25 | 26 | } 27 | 28 | #middle-bar #spin-button { 29 | position: absolute; 30 | top: 65%; 31 | left:79% 32 | /* margin-right: 140px; */ 33 | /* margin-top: 400px; */ 34 | } 35 | 36 | @media (max-aspect-ratio: 1) { 37 | #middle-bar #spin-button img { 38 | transform:scale(1.3) !important 39 | } 40 | 41 | #middle-bar #spin-button { 42 | top: 130%; 43 | left:79% 44 | /* margin-right: 40px; 45 | margin-top: 800px; */ 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /code/client/src/UI/middleBar/MiddleBar.jsx: -------------------------------------------------------------------------------- 1 | import React, { 2 | useRef, 3 | forwardRef, 4 | useImperativeHandle, 5 | } from "react"; 6 | import gsap from 'gsap'; 7 | import "./CSS/MiddleBar.css"; 8 | import SpinButton from '../bottomBar/spinButton/SpinButton'; 9 | 10 | const MiddleBar = forwardRef((props, ref) => { 11 | const spinButtonRef = useRef(null); 12 | const middleBarRef = useRef(null); 13 | 14 | const startOpenTween = () => { 15 | gsap.fromTo( 16 | middleBarRef.current, 17 | { scale: 0 }, 18 | { scale: 1, ease: "back.out", duration: 1 }) 19 | } 20 | 21 | const handleSpinButtonBlock = (state) => { 22 | return spinButtonRef.current.block(state) 23 | } 24 | const resetSpinButton = () => { 25 | return spinButtonRef.current.reset() 26 | } 27 | 28 | useImperativeHandle(ref, () => ({ 29 | update, 30 | handleSpinButtonBlock, 31 | resetSpinButton, 32 | startOpenTween 33 | })); 34 | 35 | return ( 36 |
37 |
38 |
39 |
40 | 41 |
42 |
43 | ); 44 | }); 45 | 46 | export default MiddleBar; 47 | -------------------------------------------------------------------------------- /code/client/src/components/closeButton/CSS/CloseButton.css: -------------------------------------------------------------------------------- 1 | #close-button { 2 | display: flex; 3 | width: 40px; 4 | height: 40px; 5 | background-color: rgba(255, 255, 255, 0.15); 6 | color: rgba(255, 255, 255, 0.87); 7 | cursor: pointer; 8 | transition: all 0.3s; 9 | border-radius: 50px; 10 | border: none; 11 | text-align: center; 12 | justify-content: center; 13 | align-items: center; 14 | 15 | &:hover { 16 | background-color: rgba(255, 255, 255, 0.3); 17 | } 18 | 19 | &:active { 20 | 21 | } 22 | 23 | &:disabled { 24 | 25 | } 26 | } -------------------------------------------------------------------------------- /code/client/src/components/closeButton/CloseButton.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useImperativeHandle, useState } from 'react'; 2 | import "./CSS/CloseButton.css"; 3 | 4 | const CloseButton = React.forwardRef((props, ref) => { 5 | 6 | return ( 7 | 14 | ); 15 | }); 16 | 17 | export default CloseButton; 18 | -------------------------------------------------------------------------------- /code/client/src/components/textureButton/CSS/TextureButton.css: -------------------------------------------------------------------------------- 1 | #texture-button { 2 | display: flex; 3 | justify-content: center; 4 | align-items: center; 5 | text-align: center; 6 | } 7 | 8 | #texture-button img { 9 | transition: transform 0.3s ease; 10 | cursor: pointer; 11 | pointer-events: all; 12 | } 13 | 14 | #texture-button #enlarged { 15 | transform: scale(1.1); 16 | } 17 | 18 | #texture-button #default { 19 | transform: scale(1); 20 | } 21 | -------------------------------------------------------------------------------- /code/client/src/components/textureButton/TextureButton.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useImperativeHandle, useState } from 'react'; 2 | import "./CSS/TextureButton.css"; 3 | 4 | const TextureButton = React.forwardRef((props, ref) => { 5 | const [isHovered, setIsHovered] = useState(false); 6 | const [isPush, setIsPush] = useState(false); 7 | 8 | const extension = props.svg ? ".svg" : ".png" 9 | const path = "\\assets\\images\\UI\\buttons\\" 10 | const defaultTexture = path + props.default + extension; 11 | const hoverTexture = path + props.hover + extension; 12 | const pushTexture = path + props.push + extension 13 | 14 | const handleButtonHover = () => { 15 | setIsHovered(true); 16 | }; 17 | 18 | const handleButtonLeave = () => { 19 | setIsHovered(false); 20 | }; 21 | 22 | const handleClick = () => { 23 | props.onClick() 24 | } 25 | 26 | const handleMouseDown = () => { 27 | setIsPush(true); 28 | }; 29 | 30 | const handleMouseUp = () => { 31 | setIsPush(false); 32 | }; 33 | 34 | const buttonImage = isPush ? pushTexture : (isHovered ? hoverTexture : defaultTexture); 35 | 36 | return ( 37 |
38 | button 39 |
40 | ); 41 | }); 42 | 43 | export default TextureButton; 44 | -------------------------------------------------------------------------------- /code/client/src/config/assetsConfig.js: -------------------------------------------------------------------------------- 1 | export const ASSETS_CONFIG = { 2 | images: { 3 | _path: "assets/images/", 4 | extension: ".png", 5 | }, 6 | json: { 7 | _path: "assets/images/", 8 | extension: ".json", 9 | }, 10 | audio: { 11 | _path: "assets/audio/", 12 | extension: ".ogg", 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /code/client/src/config/screenConfig.js: -------------------------------------------------------------------------------- 1 | export const GAME_SAFE_LANDSCAPE_WIDTH = 1280; 2 | export const GAME_SAFE_LANDSCAPE_HEIGHT = 720; 3 | export const GAME_SAFE_PORTRAIT_WIDTH = 720; 4 | export const GAME_SAFE_PORTRAIT_HEIGHT = 1280; 5 | export const SCREEN_TYPES = { 6 | landscape: "landscape", 7 | portrait: "portrait", 8 | }; 9 | -------------------------------------------------------------------------------- /code/client/src/game/CSS/Game.css: -------------------------------------------------------------------------------- 1 | #game-container{ 2 | position: fixed; 3 | } -------------------------------------------------------------------------------- /code/client/src/game/StartGame.js: -------------------------------------------------------------------------------- 1 | import AppStorage from "../storage/AppStorage"; 2 | import SceneManager from "../managers/SceneManager"; 3 | import Game from "./scenes/Game"; 4 | import Preload from "./scenes/Preload"; 5 | 6 | export const StartGame = (game) => { 7 | AppStorage.add(game); 8 | SceneManager.addScene([Preload, Game]); 9 | SceneManager.autoStartFirstScene(); 10 | globalThis.__PIXI_APP__ = game; 11 | }; 12 | -------------------------------------------------------------------------------- /code/client/src/game/abstraction/BaseScene.ts: -------------------------------------------------------------------------------- 1 | import * as PIXI from "pixi.js"; 2 | 3 | export default abstract class BaseScene extends PIXI.Container { 4 | sceneKey: string 5 | constructor(sceneKey: string) { 6 | super(); 7 | this.sceneKey = sceneKey 8 | } 9 | 10 | abstract init(): void 11 | } 12 | -------------------------------------------------------------------------------- /code/client/src/game/components/Container.ts: -------------------------------------------------------------------------------- 1 | import * as PIXI from "pixi.js"; 2 | 3 | export default class Container extends PIXI.Container { 4 | constructor() { 5 | super(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /code/client/src/game/components/sprite/Sprite.ts: -------------------------------------------------------------------------------- 1 | import * as PIXI from "pixi.js"; 2 | import ImageManager from "../../../managers/ImageManager"; 3 | import ISpriteConfig from "./interface/ISpriteConfig"; 4 | 5 | export default class Sprite extends PIXI.Sprite { 6 | constructor(config: ISpriteConfig) { 7 | const { 8 | textureKey, 9 | x = 0, 10 | y = 0, 11 | anchorX = 0.5, 12 | anchorY = 0.5, 13 | visible = true, 14 | scaleX = 1, 15 | scaleY = 1, 16 | angle = 0, 17 | tint = 0xFFFFFF, 18 | isStatic = true, 19 | interactive = false, 20 | eventMode = "none" 21 | } = config; 22 | const spriteTexture = ImageManager.getImage(textureKey) 23 | 24 | super(spriteTexture); 25 | this.anchor.set(anchorX, anchorY); 26 | this.position.set(x, y); 27 | this.scale.x = scaleX; 28 | this.scale.y = scaleY; 29 | this.angle = angle; 30 | this.tint = tint; 31 | this.visible = visible; 32 | this.filters = null;//@ts-ignorets 33 | this.eventMode = eventMode 34 | this.interactiveChildren = interactive; 35 | this.cacheAsBitmap = isStatic; 36 | } 37 | 38 | public changeTexture(newTexture: string) { 39 | const updatedTexture = ImageManager.getImage(newTexture); 40 | if (updatedTexture) { 41 | this.texture = updatedTexture 42 | } else { 43 | console.error(`Image with key "${newTexture}" not found.`); 44 | } 45 | } 46 | 47 | public setVisible(value: boolean) { 48 | this.visible = value; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /code/client/src/game/components/sprite/interface/ISpriteConfig.ts: -------------------------------------------------------------------------------- 1 | export default interface ISpriteConfig { 2 | textureKey: string; 3 | x?: number; 4 | y?: number; 5 | anchorX?: number; 6 | anchorY?: number; 7 | scaleX?: number, 8 | scaleY?: number, 9 | angle?: number, 10 | tint?: number, 11 | eventMode? : string, 12 | visible?: boolean; 13 | isStatic?: boolean; 14 | interactive?: boolean; 15 | } -------------------------------------------------------------------------------- /code/client/src/game/components/text/Text.ts: -------------------------------------------------------------------------------- 1 | import * as PIXI from "pixi.js"; 2 | import ITextConfig from "./interface/ITextConfig"; 3 | 4 | export default class Text extends PIXI.Text { 5 | constructor(config: ITextConfig) { 6 | const { 7 | message, 8 | x = 0, 9 | y = 0, 10 | anchorX = 0, 11 | anchorY = 0, 12 | visible = true, 13 | isStatic = false, 14 | scaleX = 1, 15 | scaleY = 1, 16 | textConfig: { 17 | fontFamily = "Arial", 18 | fontSize = 55, 19 | fill = 0x000000, 20 | wordWrap = false, 21 | wordWrapWidth = 100, 22 | } = {} 23 | } = config; 24 | //@ts-ignorets 25 | super(message, { fontFamily, fontSize, fill, wordWrap, wordWrapWidth}); 26 | 27 | this.anchor.set(anchorX, anchorY); 28 | this.position.set(x, y); 29 | this.visible = visible; 30 | this.scale.x = scaleX; 31 | this.scale.y = scaleY; 32 | this.cacheAsBitmap = isStatic; 33 | this.updateMessage(message); 34 | } 35 | 36 | public updateMessage(updatedText: string | number) { 37 | this.text = updatedText; 38 | } 39 | } -------------------------------------------------------------------------------- /code/client/src/game/components/text/interface/ITextConfig.ts: -------------------------------------------------------------------------------- 1 | export default interface ITextConfig { 2 | message: string | number; 3 | x?: number; 4 | y?: number; 5 | scaleX?: number, 6 | scaleY?: number, 7 | anchorX?: number; 8 | anchorY?: number; 9 | visible?: boolean; 10 | isStatic?: boolean 11 | textConfig?: { 12 | fontFamily?: string, 13 | fontSize?: number, 14 | fill?: number, 15 | wordWrap?: boolean 16 | wordWrapWidth?: number 17 | } 18 | } -------------------------------------------------------------------------------- /code/client/src/game/darkScreen/DarkScreen.ts: -------------------------------------------------------------------------------- 1 | import { GAME_SAFE_LANDSCAPE_HEIGHT, GAME_SAFE_LANDSCAPE_WIDTH } from "../../config/screenConfig"; 2 | import DarkScreenModel from "./model/DarkScreenModel"; 3 | import DarkScreenView from "./view/DarkScreenView"; 4 | import DarkScreenController from "./controller/DarkScreenController"; 5 | import Container from "../components/Container"; 6 | import darkScreenConfig from "./config/darkScreenConfig"; 7 | 8 | export default class DarkScreen extends Container{ 9 | protected _model: DarkScreenModel 10 | protected _view: DarkScreenView 11 | protected _controller: DarkScreenController 12 | 13 | constructor() { 14 | super() 15 | this._view = new DarkScreenView(darkScreenConfig.view, this) 16 | this._model = new DarkScreenModel(darkScreenConfig.model) 17 | this._controller = new DarkScreenController(this._model, this._view, this) 18 | this.pivot.set(0 , 0); 19 | this.x = GAME_SAFE_LANDSCAPE_WIDTH/2 20 | this.y = 300 21 | } 22 | 23 | public startOpenAnimation(){ 24 | this._controller.openTween() 25 | } 26 | 27 | public startCloseAnimation(){ 28 | this._controller.closeTween() 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /code/client/src/game/darkScreen/config/darkScreenConfig.ts: -------------------------------------------------------------------------------- 1 | import ScreenUtils from "../../../utility/screen/ScreenUtils"; 2 | 3 | export default { 4 | x: 0, 5 | y: 0, 6 | view: { 7 | sprite: { 8 | textureKey: "dark_screen", 9 | isStatic: true, 10 | visible: false 11 | }, 12 | }, 13 | model: { 14 | textureTypes: { 15 | landscape: "", 16 | portrait: "" 17 | }, 18 | } 19 | } -------------------------------------------------------------------------------- /code/client/src/game/darkScreen/controller/DarkScreenController.ts: -------------------------------------------------------------------------------- 1 | import DarkScreenModel from "../model/DarkScreenModel"; 2 | import DarkScreenView from "../view/DarkScreenView"; 3 | import Container from "../../components/Container"; 4 | import {SCREEN_TYPES} from "../../../config/screenConfig"; 5 | import gsap from 'gsap'; 6 | 7 | 8 | export default class GameLogoController { 9 | protected _model: DarkScreenModel 10 | protected _view: DarkScreenView 11 | protected _scene: Container 12 | constructor(model: DarkScreenModel, view: DarkScreenView, scene: Container) { 13 | this._scene = scene 14 | this._model = model 15 | this._view = view 16 | } 17 | 18 | private get sprite(){ 19 | return this._view.sprite 20 | } 21 | 22 | public openTween(){ 23 | this._scene.scale.x = 0.1 24 | this._scene.scale.y = 0.1 25 | this._view.sprite.visible = true 26 | gsap.to( this._scene.scale, { 27 | x: 1, 28 | y: 1, 29 | duration: 0.5, 30 | ease: "back.out", 31 | }); 32 | } 33 | 34 | public closeTween(){ 35 | gsap.to( this._scene.scale, { 36 | x: 0.1, 37 | y: 0.1, 38 | duration: 0.6, 39 | ease: "back.in", 40 | }); 41 | } 42 | 43 | 44 | } -------------------------------------------------------------------------------- /code/client/src/game/darkScreen/interface/IDarkScreenConfig.ts: -------------------------------------------------------------------------------- 1 | import IBackgroundViewConfig from "../view/interface/IBackgroundViewConfig"; 2 | 3 | export default interface IBackgroundConfig { 4 | x: number, 5 | y: number, 6 | view: IBackgroundViewConfig 7 | } -------------------------------------------------------------------------------- /code/client/src/game/darkScreen/model/DarkScreenModel.ts: -------------------------------------------------------------------------------- 1 | import ISpriteConfig from "./interface/IDarkScreenlConfig"; 2 | 3 | export default class DarkScreenModel { 4 | _landscapeTexture: string 5 | _portraitTexture: string 6 | config: ISpriteConfig 7 | constructor(config: ISpriteConfig) { 8 | this.config = config 9 | this._landscapeTexture = this.config.textureTypes.landscape 10 | this._portraitTexture = this.config.textureTypes.portrait 11 | } 12 | 13 | public get landscapeTexture(){ 14 | return this._landscapeTexture 15 | } 16 | 17 | public get portraitTexture(){ 18 | return this._portraitTexture 19 | } 20 | } -------------------------------------------------------------------------------- /code/client/src/game/darkScreen/model/interface/IDarkScreenlConfig.ts: -------------------------------------------------------------------------------- 1 | 2 | export default interface IBackgroundModelConfig { 3 | textureTypes: { 4 | landscape: string, 5 | portrait: string 6 | }, 7 | } -------------------------------------------------------------------------------- /code/client/src/game/darkScreen/view/DarkScreenView.ts: -------------------------------------------------------------------------------- 1 | // import AnimatedSprite from "../../components/animatedSprite/AnimatedSprite"; 2 | import Sprite from "../../components/sprite/Sprite"; 3 | import Container from "../../components/Container"; 4 | import IDarkScreenConfig from "./interface/IDarkScreenConfig"; 5 | 6 | export default class DarkScreenView { 7 | config: IDarkScreenConfig 8 | sprite: Sprite 9 | constructor(config: IDarkScreenConfig, scene: Container) {//@ts-ignorets 10 | this.scene = scene 11 | this.config = config 12 | this.sprite = this.createSprite() 13 | } 14 | 15 | private createSprite(): Sprite { 16 | const config = this.config.sprite 17 | const sprite = new Sprite(config)//@ts-ignorets 18 | this.scene.addChild(sprite); 19 | return sprite 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /code/client/src/game/darkScreen/view/interface/IDarkScreenConfig.ts: -------------------------------------------------------------------------------- 1 | import IAnimatedSpriteConfig from "../../../../components/animatedSprite/interface/IAnimatedSpriteConfig"; 2 | 3 | export default interface IBackgroundViewConfig { 4 | sprite: IAnimatedSpriteConfig 5 | } -------------------------------------------------------------------------------- /code/client/src/game/gameLogo/GameLogo.ts: -------------------------------------------------------------------------------- 1 | import { GAME_SAFE_LANDSCAPE_HEIGHT, GAME_SAFE_LANDSCAPE_WIDTH } from "../../config/screenConfig"; 2 | import BackgroundModel from "./model/GameLogoModel"; 3 | import BackgroundView from "./view/GameLogoView"; 4 | import GameLogoController from "./controller/GameLogoController"; 5 | import Container from "../components/Container"; 6 | import backgroundConfig from "./config/gameLogoConfig"; 7 | 8 | export default class GameLogo extends Container{ 9 | protected _model: BackgroundModel 10 | protected _view: BackgroundView 11 | protected _controller: GameLogoController 12 | 13 | constructor() { 14 | super() 15 | this._view = new BackgroundView(backgroundConfig.view, this) 16 | this._model = new BackgroundModel(backgroundConfig.model) 17 | this._controller = new GameLogoController(this._model, this._view, this) 18 | this.pivot.set(0 , 0); 19 | this.x = GAME_SAFE_LANDSCAPE_WIDTH/2 20 | this.y = 36 21 | } 22 | 23 | public changeOrientation(key: string){ 24 | this._controller.changeTextureOrientation(key) 25 | } 26 | 27 | public startOpenAnimation(){ 28 | this._controller.openTween() 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /code/client/src/game/gameLogo/controller/GameLogoController.ts: -------------------------------------------------------------------------------- 1 | import GameLogoModel from "../model/GameLogoModel"; 2 | import GameLogoView from "../view/GameLogoView"; 3 | import Container from "../../components/Container"; 4 | import {SCREEN_TYPES} from "../../../config/screenConfig"; 5 | import gsap from 'gsap'; 6 | 7 | 8 | export default class GameLogoController { 9 | protected _model: GameLogoModel 10 | protected _view: GameLogoView 11 | protected _scene: Container 12 | constructor(model: GameLogoModel, view: GameLogoView, scene: Container) { 13 | this._scene = scene 14 | this._model = model 15 | this._view = view 16 | } 17 | 18 | private get sprite(){ 19 | return this._view.sprite 20 | } 21 | 22 | private setViewTextureToPortrait(){ 23 | this.sprite.changeTexture(this._model.portraitTexture) 24 | } 25 | 26 | private setViewTextureToLandscape(){ 27 | this.sprite.changeTexture(this._model.landscapeTexture) 28 | } 29 | 30 | public changeTextureOrientation(key: string){ 31 | if(key === SCREEN_TYPES.portrait) { 32 | this.setViewTextureToPortrait() 33 | this.sprite.y = -35 34 | this.sprite.scale.x = 0.4, 35 | this.sprite.scale.y = 0.4 36 | } else { 37 | this.setViewTextureToLandscape() 38 | this.sprite.y = 10 39 | this.sprite.scale.x = 0.3, 40 | this.sprite.scale.y = 0.3 41 | } 42 | } 43 | 44 | public openTween(){ 45 | this._scene.scale.x = 5 46 | this._scene.scale.y = 5 47 | gsap.to( this._scene.scale, { 48 | x: 1, 49 | y: 1, 50 | duration: 1.5, 51 | ease: "back.out", 52 | }); 53 | } 54 | 55 | 56 | } -------------------------------------------------------------------------------- /code/client/src/game/gameLogo/interface/IGameLogoConfig.ts: -------------------------------------------------------------------------------- 1 | import IBackgroundViewConfig from "../view/interface/IBackgroundViewConfig"; 2 | 3 | export default interface IBackgroundConfig { 4 | x: number, 5 | y: number, 6 | view: IBackgroundViewConfig 7 | } -------------------------------------------------------------------------------- /code/client/src/game/gameLogo/model/GameLogoModel.ts: -------------------------------------------------------------------------------- 1 | import ISpriteConfig from "./interface/IGameLogoModelConfig"; 2 | 3 | export default class GameLogoModel { 4 | _landscapeTexture: string 5 | _portraitTexture: string 6 | config: ISpriteConfig 7 | constructor(config: ISpriteConfig) { 8 | this.config = config 9 | this._landscapeTexture = this.config.textureTypes.landscape 10 | this._portraitTexture = this.config.textureTypes.portrait 11 | } 12 | 13 | public get landscapeTexture(){ 14 | return this._landscapeTexture 15 | } 16 | 17 | public get portraitTexture(){ 18 | return this._portraitTexture 19 | } 20 | } -------------------------------------------------------------------------------- /code/client/src/game/gameLogo/model/interface/IGameLogoModelConfig.ts: -------------------------------------------------------------------------------- 1 | 2 | export default interface IBackgroundModelConfig { 3 | textureTypes: { 4 | landscape: string, 5 | portrait: string 6 | }, 7 | } -------------------------------------------------------------------------------- /code/client/src/game/gameLogo/view/GameLogoView.ts: -------------------------------------------------------------------------------- 1 | // import AnimatedSprite from "../../components/animatedSprite/AnimatedSprite"; 2 | import Sprite from "../../components/sprite/Sprite"; 3 | import Container from "../../components/Container"; 4 | import IGameLogoConfig from "./interface/IGameLogoConfig"; 5 | 6 | export default class GameLogoView { 7 | config: IGameLogoConfig 8 | sprite: Sprite 9 | constructor(config: IGameLogoConfig, scene: Container) {//@ts-ignorets 10 | this.scene = scene 11 | this.config = config 12 | this.sprite = this.createSprite() 13 | } 14 | 15 | private createSprite(): Sprite { 16 | const config = this.config.sprite 17 | const sprite = new Sprite(config)//@ts-ignorets 18 | this.scene.addChild(sprite); 19 | return sprite 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /code/client/src/game/gameLogo/view/interface/IGameLogoConfig.ts: -------------------------------------------------------------------------------- 1 | import IAnimatedSpriteConfig from "../../../../components/animatedSprite/interface/IAnimatedSpriteConfig"; 2 | 3 | export default interface IBackgroundViewConfig { 4 | sprite: IAnimatedSpriteConfig 5 | } -------------------------------------------------------------------------------- /code/client/src/game/machine/Machine.ts: -------------------------------------------------------------------------------- 1 | import MachineController from "./controller/MachineController"; 2 | import MachineView from "./view/MachineView"; 3 | import MachineModel from "./model/MachineModel"; 4 | import ReelsStorage from "./reelsStorage/ReelsStorage"; 5 | import MatchLine from "./matchLine/MatchLine"; 6 | import CreditsCounter from "./creditsCounter/CreditsCounter"; 7 | import MatchFrame from "./matchFrame/MatchFrame"; 8 | import Container from "../components/Container"; 9 | import DescribeLabel from "./describeLabel/DescribeLabel"; 10 | import { MACHINE_CONFIG } from "./config/machineConfig"; 11 | 12 | export default class Machine extends Container { 13 | protected _view: MachineView; 14 | protected _model: MachineModel; 15 | protected _controller: MachineController; 16 | protected _reelsStorage: ReelsStorage; 17 | protected _matchLine: MatchLine 18 | protected _matchFrame: MatchFrame 19 | protected _creditsCounter: CreditsCounter 20 | protected _describeLabel: DescribeLabel 21 | constructor() { 22 | const { x, y } = MACHINE_CONFIG; 23 | super(); 24 | this._model = new MachineModel() 25 | this._view = new MachineView(this); 26 | this._matchLine = new MatchLine(this) 27 | this._reelsStorage = new ReelsStorage(this); 28 | this._matchFrame = new MatchFrame(this) 29 | this._creditsCounter = new CreditsCounter(this) 30 | this._describeLabel = new DescribeLabel() 31 | this._controller = new MachineController(this, this._view, this._model, this._reelsStorage, this._matchLine, this._matchFrame, this._creditsCounter, this._describeLabel); 32 | this.pivot.set(this.width / 2 - 95, this.height / 2 + 35); 33 | this.x = x 34 | this.y = y 35 | } 36 | 37 | public startSpinning() { 38 | this._controller.startSpinReels(); 39 | } 40 | 41 | public async stopSpinning(newSymbols: number[]) { 42 | await this._controller.stopSpinReels(newSymbols); 43 | } 44 | 45 | public reset(){ 46 | this._controller.resetReels() 47 | } 48 | 49 | public async showMatches(horizontalMatches: any, verticalMatches: any, totalCreditsWin: any, matchLineCredits: any, async: boolean){ 50 | await this._controller.handleShowMatches(horizontalMatches, verticalMatches, totalCreditsWin, matchLineCredits, async) 51 | } 52 | 53 | public startOpenAnimation(){ 54 | this._controller.openTween() 55 | } 56 | 57 | public get isRestarted(){ 58 | return this._model._isRestarted 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /code/client/src/game/machine/config/machineConfig.ts: -------------------------------------------------------------------------------- 1 | import { GAME_SAFE_LANDSCAPE_HEIGHT, GAME_SAFE_LANDSCAPE_WIDTH } from "../../../config/screenConfig"; 2 | 3 | export const MACHINE_CONFIG = { 4 | x: GAME_SAFE_LANDSCAPE_WIDTH/2, 5 | y: GAME_SAFE_LANDSCAPE_HEIGHT/2 - 60, 6 | stopSpinTweenDelay: 2, 7 | }; 8 | 9 | export const REELS_CONFIG = { 10 | columns: 5, 11 | spaceX: 130, 12 | }; 13 | 14 | export const REEL_SYMBOLS_CONFIG = { 15 | count: 4, 16 | spaceY: 160, 17 | positionsY: [0, 160, 320, 480] 18 | }; 19 | 20 | export const REEL_SPIN_TWEEN_CONFIG = { 21 | delayMultiplier: 0.03, 22 | symbolMoveDownLimitY: 640, //FIRST SYMBOL POSITION X + SYMBOL COUNT IN REEL* SYMBOL OFFSET Y 23 | symbolMoveSpeed: 30, 24 | offsetY: 160, 25 | repeat: -1, 26 | }; 27 | 28 | export const REEL_STOP_SPIN_TWEEN_CONFIG = { 29 | newY: 160, 30 | duration: 0.5, //0.1 31 | ease: "back.out(1)", 32 | }; 33 | 34 | export const VIEW_CONFIG = { 35 | mask: { 36 | x: -78, 37 | y: 75, 38 | w: 675, 39 | h: 487, 40 | }, 41 | background: { 42 | textureKey: "symbols_bg", 43 | x: 260, 44 | y: 320, 45 | scaleX: 0.6, 46 | scaleY: 0.6, 47 | }, 48 | }; 49 | 50 | -------------------------------------------------------------------------------- /code/client/src/game/machine/controller/interface/IMachineControllerConfig.ts: -------------------------------------------------------------------------------- 1 | 2 | export default interface IMachineControllerConfig { 3 | columns: number, 4 | spaceX: number 5 | } 6 | -------------------------------------------------------------------------------- /code/client/src/game/machine/creditsCounter/CreditsCounter.ts: -------------------------------------------------------------------------------- 1 | import { GAME_SAFE_LANDSCAPE_HEIGHT, GAME_SAFE_LANDSCAPE_WIDTH } from "../../../config/screenConfig"; 2 | import CreditsCounterModel from "./model/CreditsCounterModel"; 3 | import CreditsCounterView from "./view/CreditsCounterView"; 4 | import CreditsCounterController from "./controller/CreditsCounterController"; 5 | import Container from "../../components/Container"; 6 | 7 | export default class CreditsCounter extends Container { 8 | private _model: CreditsCounterModel; 9 | private _view: CreditsCounterView;//@ts-ignorets 10 | private _controller: CreditsCounterController; 11 | 12 | constructor(scene: Container) { 13 | super(); 14 | scene.addChild(this) 15 | this.x = 260 16 | this.y = 319 17 | this._view = new CreditsCounterView(this); 18 | this._model = new CreditsCounterModel(); 19 | this._controller = new CreditsCounterController(this, this._model, this._view); 20 | } 21 | 22 | public async startCounter(creditCount: number){ 23 | await this._controller.startCounter(creditCount) 24 | } 25 | 26 | public async showCreditCount(credits: number){ 27 | await this._controller.showCreditCount(credits) 28 | } 29 | 30 | public hideCreditCount(){ 31 | this._controller.hideCreditCount() 32 | } 33 | 34 | public stopTweens(){ 35 | this._controller.stopTweens() 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /code/client/src/game/machine/creditsCounter/controller/CreditsCounterController.ts: -------------------------------------------------------------------------------- 1 | import CreditsCounterModel from "../model/CreditsCounterModel"; 2 | import CreditsCounterView from "../view/CreditsCounterView"; 3 | import Container from "../../../components/Container"; 4 | import AudioManager from "../../../../managers/AudioManager"; 5 | import gsap from "gsap"; 6 | 7 | export default class BetLabelController { 8 | protected _model: CreditsCounterModel; 9 | protected _view: CreditsCounterView; 10 | protected _scene: Container; 11 | protected countCreditsTween: any; 12 | protected scaleUpTween: any; 13 | protected scaleDownTween: any; 14 | protected counterPromise: any; 15 | protected showCreditsPromise: any; 16 | 17 | constructor(scene: Container, model: CreditsCounterModel, view: CreditsCounterView) { 18 | this._scene = scene 19 | this._model = model; 20 | this._view = view; 21 | this._scene.alpha = 0 22 | 23 | this.counterPromise = null 24 | this.showCreditsPromise = null 25 | this.countCreditsTween = null 26 | this.scaleUpTween = null 27 | this.scaleDownTween = null 28 | } 29 | 30 | public async startCounter(credits: number){ 31 | // if(credits == 0) return//@ts-ignorets 32 | this.setScale(1.3) 33 | await new Promise(resolve => { 34 | this.counterPromise = resolve 35 | this.setViewVisible(true) 36 | this._scene.alpha = 1 37 | this.startScaleUpViewTween() 38 | this.startCountCreditsTween(credits, resolve) 39 | AudioManager.playAudio("credits_count") 40 | AudioManager.playAudio("count_loop") 41 | }) 42 | } 43 | 44 | public async showCreditCount(credits: number){ 45 | this.setScale(0.9) 46 | // this.setViewVisible(true) 47 | this._scene.alpha = 0//@ts-ignorets 48 | this.updateCreditsText(credits.toFixed(2)) 49 | 50 | await new Promise(resolve => { 51 | this.showCreditsPromise = resolve 52 | gsap.to( this._scene, { 53 | duration: 0.6, 54 | alpha: 1, 55 | ease: 'back.out', 56 | onComplete:() =>{ 57 | this.startHideTween(resolve) 58 | } 59 | }); 60 | }) 61 | } 62 | 63 | private startHideTween(resolve){ 64 | gsap.to(this._scene, { 65 | duration: 0.6, 66 | delay:1, 67 | alpha:0, 68 | ease: 'back.out', 69 | onComplete:() =>{ 70 | // this.setViewVisible(false) 71 | resolve(0) 72 | } 73 | }); 74 | } 75 | 76 | public hideCreditCount(){ 77 | this.setViewVisible(false) 78 | } 79 | 80 | private startCountCreditsTween(credits: number, resolve: any){ 81 | const startValue = { value: 0 } 82 | this.countCreditsTween = gsap.to(startValue, { 83 | value: credits, 84 | duration: 2, 85 | ease: 'power4.out', 86 | onUpdate: ()=>{ 87 | const newValue = startValue.value.toFixed(2)//@ts-ignorets 88 | this.updateCreditsText(newValue) 89 | }, 90 | onComplete:() =>{ 91 | this.startScaleDownViewTween(resolve) 92 | } 93 | }); 94 | } 95 | 96 | private startScaleUpViewTween(){ 97 | this.setScale(0.1) 98 | this.scaleUpTween = gsap.to( this._scene.scale, { 99 | duration: 0.8, 100 | x:1.1, 101 | y:1.1, 102 | ease: 'back.out', 103 | }); 104 | } 105 | 106 | private startScaleDownViewTween(resolve){ 107 | this.setScale(1.1) 108 | this.scaleDownTween = gsap.to(this._scene.scale, { 109 | duration: 0.5, 110 | x: 0.1, 111 | y: 0.1, 112 | ease: 'back.in', 113 | onComplete:() =>{ 114 | // this.setViewVisible(false) 115 | this.setScale(0.9) 116 | this._scene.alpha = 1 117 | resolve(0) 118 | } 119 | }); 120 | } 121 | 122 | private setViewVisible(value: boolean){ 123 | this._scene.visible = value 124 | } 125 | //@ts-ignorets 126 | private updateCreditsText(newText: number){//@ts-ignorets 127 | this._view.creditsText.text = newText 128 | } 129 | 130 | private setScale(value: number){ 131 | this._scene.scale.x = value 132 | this._scene.scale.y = value 133 | } 134 | 135 | public stopTweens(){ 136 | if(this.counterPromise) this.counterPromise() 137 | if(this.showCreditsPromise) this.showCreditsPromise() 138 | if(this.countCreditsTween) this.countCreditsTween.pause() 139 | if(this.scaleUpTween) this.scaleUpTween.pause() 140 | if(this.scaleDownTween) this.scaleDownTween.pause() 141 | this.countCreditsTween = null 142 | this.scaleUpTween = null 143 | this.scaleDownTween = null 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /code/client/src/game/machine/creditsCounter/model/CreditsCounterModel.ts: -------------------------------------------------------------------------------- 1 | 2 | export default class CreditsCounterModel { 3 | constructor() { 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /code/client/src/game/machine/creditsCounter/view/CreditsCounterView.ts: -------------------------------------------------------------------------------- 1 | import Sprite from "../../../components/sprite/Sprite"; 2 | // import Text from "../../../components/text/Text"; 3 | import Container from "../../../components/Container"; 4 | import * as PIXI from "pixi.js"; 5 | 6 | // import { SPRITE_CONFIG } from "../config/spinButtonConfig"; 7 | 8 | export default class CreditsCounterView { 9 | public shine: Sprite; 10 | public creditsText: PIXI.BitmapText; 11 | constructor(scene: Container) {//@ts-ignorets 12 | this.scene = scene 13 | this.shine = this.createShine(); 14 | this.creditsText = this.createCreditsText(); 15 | } 16 | 17 | private createShine(): Sprite { 18 | const config = { 19 | textureKey: "credits_counter_background", 20 | isStatic: false, 21 | visible: true, 22 | scaleX: 0.6, 23 | scaleY: 0.6, 24 | }; 25 | const sprite = new Sprite(config);//@ts-ignorets 26 | this.scene.addChild(sprite); 27 | return sprite; 28 | } 29 | 30 | private createCreditsText(): PIXI.BitmapText { 31 | const config={ 32 | fontName: 'Desyrel', 33 | fontSize: 100, 34 | align: 'right', 35 | } 36 | //@ts-ignorets 37 | const text = new PIXI.BitmapText("0", config);//@ts-ignorets 38 | this.scene.addChild(text); 39 | text.visible = true 40 | text.x = 0 41 | text.y = 0 42 | text.scale.x = 0.5; 43 | text.scale.y = 0.5; 44 | text.anchor.set(0.5, 0.5); 45 | text.pivot.set(0.5 , 0.5); 46 | return text; 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /code/client/src/game/machine/describeLabel/DescribeLabel.ts: -------------------------------------------------------------------------------- 1 | import DescribeLabelModel from "./model/DescribeLabelModel"; 2 | import DescribeLabelView from "./view/DescribeLabelView"; 3 | import DescribeLabelController from "./controller/DescribeLabelController"; 4 | import Container from "../../components/Container"; 5 | 6 | export default class DescribeLabel extends Container { 7 | protected _model: DescribeLabelModel; 8 | protected _view: DescribeLabelView; 9 | protected _controller: DescribeLabelController; 10 | 11 | constructor() { 12 | super(); 13 | this._view = new DescribeLabelView(this); 14 | this._model = new DescribeLabelModel(); 15 | this._controller = new DescribeLabelController(this, this._model, this._view); 16 | } 17 | 18 | public set spriteTexture(textureKey: string){ 19 | this._controller.spriteTexture = textureKey 20 | } 21 | 22 | public set setVisible(value: boolean){ 23 | this._controller.setVisible = value 24 | } 25 | 26 | public playSymbolAnimation(){ 27 | this._controller.playSpriteAnimationOnce() 28 | } 29 | 30 | public show(symbolAtlasKey: string){ 31 | this._controller.showLabel(symbolAtlasKey) 32 | } 33 | 34 | public hide(){ 35 | this._controller.hideLabel() 36 | } 37 | public setRightSide(){ 38 | this._controller.setRightSide() 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /code/client/src/game/machine/describeLabel/model/DescribeLabelModel.ts: -------------------------------------------------------------------------------- 1 | 2 | export default class DescribeLabelModel { 3 | protected _rightTextXPosition: number 4 | protected _leftTextXPosition: number 5 | 6 | constructor() { 7 | this._rightTextXPosition = 170 8 | this._leftTextXPosition = -170 9 | } 10 | 11 | public set rightTextXPosition(value: number) { 12 | this._rightTextXPosition = value; 13 | } 14 | 15 | public get rightTextXPosition() { 16 | return this._rightTextXPosition; 17 | } 18 | 19 | 20 | public set leftTextXPosition(value: number) { 21 | this._leftTextXPosition = value; 22 | } 23 | 24 | public get leftTextXPosition() { 25 | return this._leftTextXPosition; 26 | } 27 | 28 | 29 | 30 | } -------------------------------------------------------------------------------- /code/client/src/game/machine/describeLabel/view/DescribeLabelView.ts: -------------------------------------------------------------------------------- 1 | import Sprite from "../../../components/sprite/Sprite"; 2 | import AnimatedSprite from "../../../components/animatedSprite/AnimatedSprite"; 3 | import Container from "../../../components/Container"; 4 | import Text from "../../../components/text/Text"; 5 | // import { SPRITE_CONFIG } from "../config/spinButtonConfig"; 6 | 7 | export default class DescribeLabelView { 8 | public background: Sprite; 9 | public animatedSprite: AnimatedSprite; 10 | public describeText: Text; 11 | 12 | constructor(scene: Container) {//@ts-ignorets 13 | this.scene = scene 14 | this.background = this.createBackground(); 15 | this.animatedSprite = this.createSprite() 16 | this.describeText = this.createDescribeText() 17 | } 18 | 19 | private createBackground(): Sprite { 20 | const config = { 21 | textureKey: "symbol_describe_label", 22 | x: -60, 23 | y: 0, 24 | scaleX:0.5, 25 | scaleY:0.5, 26 | anchorX: 0.5, 27 | anchorY: 0.5, 28 | }; 29 | const sprite = new Sprite(config);//@ts-ignorets 30 | this.scene.addChild(sprite); 31 | return sprite; 32 | } 33 | 34 | private createSprite(): AnimatedSprite { 35 | const config = { 36 | atlasKey: "orange", 37 | startWithAnimation: "move", 38 | isStatic: false, 39 | loop: false, 40 | playOnStart: false, 41 | scaleX: 0.5, 42 | scaleY: 0.5 43 | }; 44 | const sprite = new AnimatedSprite(config);//@ts-ignorets 45 | this.scene.addChild(sprite); 46 | return sprite; 47 | } 48 | 49 | 50 | private createDescribeText(): Text { 51 | const config = { 52 | message: "", 53 | x: -170, 54 | y: 0, 55 | anchorX: 0, 56 | anchorY: 0.5, 57 | scaleX:0.5, 58 | scaleY:0.5, 59 | // isStatic: true, 60 | textConfig: { 61 | fontFamily: "Trebuchet MS", 62 | fontSize: 50, 63 | fill: 0xFFFFFF, 64 | wordWrap: true, 65 | wordWrapWidth: 340, 66 | } 67 | }; 68 | 69 | const sprite = new Text(config);//@ts-ignorets 70 | this.scene.addChild(sprite); 71 | return sprite; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /code/client/src/game/machine/model/MachineModel.ts: -------------------------------------------------------------------------------- 1 | // import ISpriteConfig from "./interface/IDarkScreenlConfig"; 2 | 3 | export default class MachineModel { 4 | _landscapeTexture: string 5 | _portraitTexture: string 6 | _isRestarted: boolean 7 | _areMatchesPlaying: boolean 8 | constructor() { 9 | // this.config = config 10 | this._isRestarted = true 11 | this._areMatchesPlaying = false 12 | } 13 | 14 | public get isRestarted(){ 15 | return this._isRestarted 16 | } 17 | 18 | public set isRestarted(value: boolean){ 19 | this._isRestarted = value 20 | } 21 | 22 | public get areMatchesPlaying(){ 23 | return this._areMatchesPlaying 24 | } 25 | 26 | public set areMatchesPlaying(value: boolean){ 27 | this._areMatchesPlaying = value 28 | } 29 | } -------------------------------------------------------------------------------- /code/client/src/game/machine/reel/Reel.ts: -------------------------------------------------------------------------------- 1 | import RollView from "./view/ReelView"; 2 | import ReelModel from "./model/ReelModel"; 3 | import ReelController from "./controller/ReelController"; 4 | import SymbolsStorage from "./symbolsStorage/SymbolsStorage"; 5 | import Container from "../../components/Container";; 6 | 7 | export default class Reel extends Container { 8 | private _view: RollView; 9 | private _model: ReelModel 10 | private _controller: ReelController 11 | private _symbolsStorage: SymbolsStorage 12 | constructor(x: number) { 13 | super(); 14 | this.x = x; 15 | this._symbolsStorage = new SymbolsStorage() 16 | this._view = new RollView(this); 17 | this._model = new ReelModel() 18 | this._controller = new ReelController(this, this._view, this._model, this._symbolsStorage ) 19 | } 20 | 21 | public playReelAnimation(){ 22 | return this._controller.startSpinTween() 23 | } 24 | 25 | public set id(value: number){ 26 | this._controller.id = value 27 | } 28 | 29 | public async stopReelAnimation(newSymbolTextureIndexes: number[]){ 30 | await this._controller.startStopSpinTween(newSymbolTextureIndexes) 31 | } 32 | 33 | public reset(){ 34 | this._controller.resetReel() 35 | } 36 | 37 | public handlePlaySymbolAnimation(symbolIndex: number){ 38 | this._controller.handlePlaySymbolAnimation(symbolIndex) 39 | } 40 | 41 | public resetSymbolsALpha(){ 42 | this._controller.resetSymbolsALpha() 43 | } 44 | 45 | public setSymbolsAlpha(value: number){ 46 | this._controller.setSymbolsAlpha(value) 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /code/client/src/game/machine/reel/model/ReelModel.ts: -------------------------------------------------------------------------------- 1 | import gsap from "gsap"; 2 | import { REEL_SYMBOLS_CONFIG, REEL_SPIN_TWEEN_CONFIG } from "../../config/machineConfig"; 3 | 4 | export default class ReelModel { 5 | private _id: number; 6 | private _topSymbolY: number; 7 | private _spinTween: GSAPTween; 8 | private _symbolMoveSpeed: number; 9 | private _stopSpinTween: GSAPTween; 10 | private _symbolMoveDownLimitY: number; 11 | private _isSpinTweenDuringStop: boolean; 12 | private _stopSpinTweenPromise: Promise 13 | private _serverSymbolTextureIndexes: number[]; 14 | 15 | constructor() { 16 | this._id = 0; 17 | this._isSpinTweenDuringStop = false; 18 | this._symbolMoveDownLimitY = REEL_SPIN_TWEEN_CONFIG.symbolMoveDownLimitY 19 | this._symbolMoveSpeed = REEL_SPIN_TWEEN_CONFIG.symbolMoveSpeed 20 | this._serverSymbolTextureIndexes = []; 21 | this._topSymbolY = REEL_SYMBOLS_CONFIG.positionsY[0]; 22 | this._stopSpinTweenPromise = new Promise(()=>{}) 23 | this._spinTween = gsap.to({}, {}); 24 | this._stopSpinTween = gsap.to({}, {}); 25 | } 26 | 27 | public get id() { 28 | return this._id; 29 | } 30 | 31 | public set id(value: number) { 32 | this._id = value; 33 | } 34 | 35 | public get spinTween() { 36 | return this._spinTween; 37 | } 38 | 39 | public set spinTween(tween: GSAPTween) { 40 | this._spinTween = tween; 41 | } 42 | 43 | public get stopSpinTween() { 44 | return this._stopSpinTween; 45 | } 46 | 47 | public set stopSpinTween(tween: GSAPTween) { 48 | this._stopSpinTween = tween; 49 | } 50 | 51 | public get isSpinTweenDuringStop() { 52 | return this._isSpinTweenDuringStop; 53 | } 54 | 55 | public set isSpinTweenDuringStop(value: boolean) { 56 | this._isSpinTweenDuringStop = value; 57 | } 58 | 59 | public get serverSymbolTextureIndexes() { 60 | return this._serverSymbolTextureIndexes; 61 | } 62 | 63 | public set serverSymbolTextureIndexes(array: number[]) { 64 | this._serverSymbolTextureIndexes = array; 65 | } 66 | 67 | public get topSymbolY() { 68 | return this._topSymbolY; 69 | } 70 | 71 | public get symbolMoveDownLimitY(){ 72 | return this._symbolMoveDownLimitY 73 | } 74 | 75 | public get symbolMoveSpeed(){ 76 | return this._symbolMoveSpeed 77 | } 78 | 79 | public get stopSpinTweenPromise(){ 80 | return this._stopSpinTweenPromise 81 | } 82 | 83 | public set stopSpinTweenPromise(newPromise: Promise ){ 84 | this._stopSpinTweenPromise = newPromise 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /code/client/src/game/machine/reel/symbol/Symbol.ts: -------------------------------------------------------------------------------- 1 | import SymbolModel from "./model/SymbolModel"; 2 | import SymbolView from "./view/SymbolView"; 3 | import SymbolController from "./controller/SymbolController"; 4 | import Container from "../../../components/Container"; 5 | import ISymbolConfig from "./interface/ISymbolConfig"; 6 | 7 | export default class Symbol extends Container { 8 | protected _model: SymbolModel; 9 | protected _view: SymbolView; 10 | protected _controller: SymbolController; 11 | 12 | constructor(config: ISymbolConfig) { 13 | super(); 14 | this.y = config.y; 15 | this._view = new SymbolView(config.view, this); 16 | this._model = new SymbolModel(config.id); 17 | this._controller = new SymbolController(this, this._model, this._view); 18 | } 19 | 20 | public set texture(textureKey: string){ 21 | this._controller.spriteTexture = textureKey 22 | } 23 | 24 | public get texture(){ 25 | return this._controller.spriteTexture 26 | } 27 | 28 | public playAnimation(){ 29 | this._controller.playSpriteAnimationOnce() 30 | } 31 | 32 | public setAlpha(value: number){ 33 | this._controller.setTextureAlpha(value) 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /code/client/src/game/machine/reel/symbol/controller/SymbolController.ts: -------------------------------------------------------------------------------- 1 | import SymbolModel from "../model/SymbolModel"; 2 | import Container from "../../../../../components/Container"; 3 | import SymbolView from "../view/SymbolView"; 4 | import GameSignals from "../../../../../gameSignals/GameSignals";//@ts-ignorets 5 | import * as PIXI from "pixi.js"; 6 | 7 | export default class SymbolController { 8 | protected _scene: Container; 9 | protected _model: SymbolModel 10 | protected _view: SymbolView 11 | constructor( scene: Container, model: SymbolModel, view: SymbolView) { 12 | this._scene = scene 13 | this._model = model 14 | this._view = view 15 | this.handleEvents() 16 | } 17 | 18 | public set spriteTexture(textureKey: string){ 19 | this._view.sprite.changeTexture(textureKey)//@ts-ignorets 20 | this._view.sprite.atlasKey = textureKey 21 | } 22 | 23 | public setBlockSpriteInteractive(value: boolean){ 24 | this._model.isBlocked = value 25 | } 26 | 27 | public playSpriteAnimationOnce(){ 28 | this._view.sprite.playAnimationOnce() 29 | } 30 | 31 | public handleEvents() { 32 | this._view.sprite.on("pointerdown", () => { 33 | const data = { 34 | globalPosition: this.globalPosition, 35 | symbolAtlasKey: this.spriteAtlasKey, 36 | atlasKey: this.spriteAtlasKey 37 | } 38 | GameSignals.onShowSymbolDescribeLabel.dispatch(data) 39 | }); 40 | } 41 | 42 | public get spriteTexture(){//@ts-ignorets 43 | return this._view.sprite.texture 44 | } 45 | 46 | public get spriteAtlasKey(){//@ts-ignorets 47 | return this._view.sprite.atlasKey 48 | } 49 | 50 | public setTextureAlpha(value: number){ 51 | this._view.sprite.alpha = value 52 | } 53 | 54 | private get globalPosition(){ 55 | return this._view.sprite.toGlobal(new PIXI.Point(0, 0)); 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /code/client/src/game/machine/reel/symbol/interface/ISymbolConfig.ts: -------------------------------------------------------------------------------- 1 | import ISymbolViewConfig from "../view/interface/ISymbolViewConfig"; 2 | 3 | export default interface ISymbolConfig { 4 | id: number 5 | x: number, 6 | y: number, 7 | view: ISymbolViewConfig 8 | } -------------------------------------------------------------------------------- /code/client/src/game/machine/reel/symbol/model/SymbolModel.ts: -------------------------------------------------------------------------------- 1 | export default class SymbolModel { 2 | private _id :number 3 | private _height:number 4 | private _width:number 5 | private _isBlocked: boolean 6 | constructor(id: number) { 7 | this._id = id 8 | this._height = 0 9 | this._width = 0 10 | this._isBlocked = false 11 | } 12 | 13 | public setSize(w: number, h:number){ 14 | this._width = w 15 | this._height = h 16 | } 17 | 18 | public get id() { 19 | return this._id; 20 | } 21 | 22 | public set id(value: number) { 23 | this._id = value; 24 | } 25 | 26 | public get width(){ 27 | return this._width 28 | } 29 | 30 | public get height(){ 31 | return this._height 32 | } 33 | 34 | public get isBlocked(){ 35 | return this._isBlocked 36 | } 37 | 38 | public set isBlocked(value: boolean){ 39 | this._isBlocked = value 40 | } 41 | } -------------------------------------------------------------------------------- /code/client/src/game/machine/reel/symbol/model/interface/ISymbolModelConfig.ts: -------------------------------------------------------------------------------- 1 | 2 | export default interface ISymbolModelConfig { 3 | 4 | } -------------------------------------------------------------------------------- /code/client/src/game/machine/reel/symbol/view/SymbolView.ts: -------------------------------------------------------------------------------- 1 | import AnimatedSprite from "../../../../components/animatedSprite/AnimatedSprite"; 2 | import Container from "../../../../components/Container"; 3 | import ISymbolViewConfig from "./interface//ISymbolViewConfig"; 4 | 5 | export default class SymbolView { 6 | config: ISymbolViewConfig 7 | sprite: AnimatedSprite 8 | constructor(config: ISymbolViewConfig, scene: Container) {//@ts-ignorets 9 | this.scene = scene 10 | this.config = config 11 | this.sprite = this.createSprite() 12 | } 13 | 14 | private createSprite(): AnimatedSprite { 15 | const config = this.config.sprite 16 | const sprite = new AnimatedSprite(config)//@ts-ignorets 17 | this.scene.addChild(sprite); 18 | return sprite 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /code/client/src/game/machine/reel/symbol/view/interface/ISymbolViewConfig.ts: -------------------------------------------------------------------------------- 1 | import IAnimatedSpriteConfig from "../../../../../../components/animatedSprite/interface/IAnimatedSpriteConfig"; 2 | 3 | export default interface ISymbolViewConfig { 4 | sprite: IAnimatedSpriteConfig 5 | } -------------------------------------------------------------------------------- /code/client/src/game/machine/view/MachineView.ts: -------------------------------------------------------------------------------- 1 | import Container from "../../components/Container"; 2 | import Graphics from "../../components/graphics/Graphics"; 3 | import {VIEW_CONFIG} from "../config/machineConfig"; 4 | import Sprite from "../../components/sprite/Sprite"; 5 | 6 | export default class MachineView{ 7 | symbolsMask: Graphics 8 | background: Sprite 9 | constructor(scene: Container) {//@ts-ignorets 10 | this.scene = scene 11 | this.background = this.createBackground()//@ts-ignorets 12 | this.symbolsMask = this.createMask()//@ts-ignorets 13 | } 14 | 15 | private createMask(): Graphics { 16 | const config = VIEW_CONFIG.mask 17 | const graphics = new Graphics(config);//@ts-ignorets 18 | this.scene.addChild(graphics) 19 | return graphics 20 | } 21 | 22 | private createBackground(): Sprite { 23 | const config = VIEW_CONFIG.background 24 | const sprite = new Sprite(config);//@ts-ignorets 25 | this.scene.addChild(sprite) 26 | return sprite 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /code/client/src/game/machine/view/interface/IMachineViewConfig.ts: -------------------------------------------------------------------------------- 1 | import IGraphicsConfig from "../../../../components/graphics/interface/IGraphicsConfig"; 2 | import ISpriteConfig from "../../../../components/sprite/interface/ISpriteConfig"; 3 | 4 | export default interface IMachineViewConfig { 5 | mask: IGraphicsConfig, 6 | background: ISpriteConfig 7 | } -------------------------------------------------------------------------------- /code/client/src/game/main.js: -------------------------------------------------------------------------------- 1 | import * as PIXI from "pixi.js"; 2 | import appConfig from "../config/appConfig"; 3 | 4 | const config = appConfig; 5 | 6 | const StartGame = (parent) => { 7 | return new PIXI.Application({ ...config, parent: parent }); 8 | }; 9 | 10 | export default StartGame; 11 | -------------------------------------------------------------------------------- /code/client/src/game/manager/GameManager.ts: -------------------------------------------------------------------------------- 1 | import GameSignals from "../../gameSignals/GameSignals"; 2 | import SceneManager from "../../managers/SceneManager"; 3 | 4 | export default class GameManager { 5 | protected static game: any = null 6 | 7 | static startGame() { 8 | const game = SceneManager.getScene("Game") 9 | 10 | if(!game?.isActive) { 11 | SceneManager.startScene("Game") 12 | this.game = SceneManager.getScene("Game") 13 | this.bindSignals(); 14 | return 15 | } 16 | SceneManager.setVisible("Game", true) 17 | } 18 | 19 | private static updateGameData(gameData: any){ 20 | this.game.updateGameState(gameData) 21 | } 22 | 23 | public static changeOrientation(key: string){ 24 | if(this.game)this.game.changeOrientation(key) 25 | } 26 | 27 | public static handleSounds(value: string){ 28 | this.game.handleSounds(value) 29 | } 30 | 31 | private static bindSignals(){ 32 | GameSignals.onUpdateGameData.add((gameData: any) => this.updateGameData(gameData)); 33 | } 34 | } -------------------------------------------------------------------------------- /code/client/src/game/scenes/Game.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/code/client/src/game/scenes/Game.ts -------------------------------------------------------------------------------- /code/client/src/game/scenes/Preload.ts: -------------------------------------------------------------------------------- 1 | import {Assets} from "pixi.js"; 2 | import AudioManager from "../../managers/AudioManager"; 3 | import ImageManager from "../../managers/ImageManager"; 4 | import BaseScene from "../abstraction/BaseScene"; 5 | import symbolTypes from "../../game/machine/config/symbolTypes"; 6 | import loadAudioData from "../../../public/assets/audio/loadAudioData.json"; 7 | import {ASSETS_CONFIG} from "../../config/assetsConfig"; 8 | import PagesManager from '../../pages/manager/PagesManager.js'; 9 | 10 | class Preload extends BaseScene { 11 | constructor() { 12 | super("Preload"); 13 | } 14 | 15 | override async init(){ 16 | await this.loadAllAudio() 17 | await this.loadResponsiveImages() 18 | await this.loadSymbolsAtlases() 19 | await this.loadMatchFrames() 20 | await this.loadBackgroundFrames() 21 | await this.loadMatchLineImages() 22 | await this.loadFonts() 23 | // await this.loadSpineAnimation() 24 | this.handleStartNextScene(); 25 | } 26 | 27 | private async loadAllAudio() { 28 | await Object.entries(loadAudioData).forEach(async ([_key, audioData]) => { 29 | await this.loadAudio(audioData); 30 | }); 31 | } 32 | 33 | // private async loadSpineAnimation(){ 34 | // const key = "eagle" 35 | // let source = await Assets.load( 36 | // `assets/images/${key}.json` 37 | // ); 38 | // ImageManager.addImage(key, source); 39 | // } 40 | 41 | 42 | private async loadAudio({path, key, settings}: {path: string, key: string, settings:{ loop: boolean, volume: number}}) { 43 | const {_path, extension} = ASSETS_CONFIG.audio 44 | let source = _path + path + "/" + key + extension 45 | await AudioManager.addAudio(key, source, settings); 46 | } 47 | 48 | private async loadFonts(){ 49 | await Assets.load( 50 | `https://pixijs.com/assets/bitmap-font/desyrel.xml` 51 | ); 52 | } 53 | 54 | private async loadResponsiveImages(){ 55 | const images = [ 56 | "symbols_bg", 57 | "credits_counter_shine", 58 | "symbol_describe_label", 59 | "game_name_logo_landscape", 60 | "game_name_logo_portrait", 61 | "dark_screen", 62 | "feather", 63 | "credits_counter_background", 64 | ]; 65 | let totalImages = images.length; 66 | for (let i = 0; i < totalImages; i++) { 67 | let image = images[i]; 68 | let source = await Assets.load( 69 | `assets/images/${image}.png` 70 | ); 71 | ImageManager.addImage(image, source); 72 | } 73 | } 74 | 75 | private async loadSymbolsAtlases() { 76 | const symbolAtlasName = symbolTypes 77 | let totalImages = symbolAtlasName.length; 78 | for (let i = 0; i < totalImages; i++) { 79 | let key = symbolAtlasName[i]; 80 | let source = await Assets.load( 81 | `assets/images/game/symbols/${key}.json` 82 | ); 83 | ImageManager.addImage(key, source); 84 | } 85 | } 86 | 87 | private async loadMatchFrames() { 88 | const symbolAtlas = [ 89 | "fire_frame", //0 90 | ]; 91 | let totalImages = symbolAtlas.length; 92 | for (let i = 0; i < totalImages; i++) { 93 | let key = symbolAtlas[i]; 94 | let source = await Assets.load( 95 | `assets/images/game/matching/frames/${key}.json` 96 | ); 97 | ImageManager.addImage(key, source); 98 | } 99 | } 100 | 101 | private async loadBackgroundFrames(){ 102 | const images = ["background", "background_overlay"] 103 | let totalImages = images.length; 104 | for (let i = 0; i < totalImages; i++) { 105 | let key = images[i]; 106 | let source = await Assets.load( 107 | `assets/images/game/background/${key}.json` 108 | ); 109 | ImageManager.addImage(key, source); 110 | } 111 | } 112 | 113 | private async loadMatchLineImages(){ 114 | const key = "matchLinesAtlas" 115 | let source = await Assets.load( 116 | `assets/images/game/matching/lines/${key}.json` 117 | ); 118 | ImageManager.addImage(key, source); 119 | } 120 | 121 | private handleStartNextScene(){ 122 | PagesManager.handleLoginPageVisible(true) 123 | } 124 | 125 | } 126 | 127 | export default new Preload() -------------------------------------------------------------------------------- /code/client/src/gameSignals/GameSignals.js: -------------------------------------------------------------------------------- 1 | import { MiniSignal } from "mini-signals"; 2 | 3 | export default class GameSignals { 4 | static onUpdateGameData = new MiniSignal(); 5 | static onUserState = new MiniSignal(); 6 | static onShowSymbolDescribeLabel = new MiniSignal(); 7 | static spinButtonClick = new MiniSignal(); 8 | static onPlayerAndGameState = new MiniSignal(); 9 | 10 | static getPlayerAndGameState = new MiniSignal(); 11 | } 12 | -------------------------------------------------------------------------------- /code/client/src/index.css: -------------------------------------------------------------------------------- 1 | /* :root { 2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; 3 | line-height: 1.5; 4 | font-weight: 400; 5 | 6 | color-scheme: light dark; 7 | color: rgba(255, 255, 255, 0.87); 8 | background-color: #242424; 9 | 10 | font-synthesis: none; 11 | text-rendering: optimizeLegibility; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | } 15 | 16 | a { 17 | font-weight: 500; 18 | color: #646cff; 19 | text-decoration: inherit; 20 | } 21 | a:hover { 22 | color: #535bf2; 23 | } 24 | 25 | body { 26 | margin: 0; 27 | display: flex; 28 | place-items: center; 29 | min-width: 320px; 30 | min-height: 100vh; 31 | } 32 | 33 | h1 { 34 | font-size: 3.2em; 35 | line-height: 1.1; 36 | } 37 | 38 | button { 39 | border-radius: 8px; 40 | border: 1px solid transparent; 41 | padding: 0.6em 1.2em; 42 | font-size: 1em; 43 | font-weight: 500; 44 | font-family: inherit; 45 | background-color: #1a1a1a; 46 | cursor: pointer; 47 | transition: border-color 0.25s; 48 | } 49 | button:hover { 50 | border-color: #646cff; 51 | } 52 | button:focus, 53 | button:focus-visible { 54 | outline: 4px auto -webkit-focus-ring-color; 55 | } 56 | 57 | @media (prefers-color-scheme: light) { 58 | :root { 59 | color: #213547; 60 | background-color: #ffffff; 61 | } 62 | a:hover { 63 | color: #747bff; 64 | } 65 | button { 66 | background-color: #f9f9f9; 67 | } 68 | } */ 69 | -------------------------------------------------------------------------------- /code/client/src/interfaces/IAllPlayerJoinedServerData.ts: -------------------------------------------------------------------------------- 1 | import IPlayersCards from "./IPlayersCards"; 2 | import IPlayersBets from "./IPlayersBets"; 3 | import IPlayersMoney from "./IPlayersMoney"; 4 | import IPlayerTurnData from "./IPlayerTurnData"; 5 | import IPlayerGamePositions from "../game/interface/IPlayerGamePositions"; 6 | 7 | export default interface IServerGameUpdateOnStart { 8 | players: { 9 | playersGamePositions: IPlayerGamePositions; 10 | playersBets: IPlayersBets; 11 | playersChips: IPlayersMoney 12 | drawCards: IPlayersCards 13 | }, 14 | game: { 15 | playerTurnData: IPlayerTurnData 16 | } 17 | } -------------------------------------------------------------------------------- /code/client/src/interfaces/ICardData.ts: -------------------------------------------------------------------------------- 1 | export default interface ICardData { 2 | name: string; 3 | suit: string; 4 | value: string; 5 | } -------------------------------------------------------------------------------- /code/client/src/interfaces/IGameResultData.ts: -------------------------------------------------------------------------------- 1 | import IPlayersCards from "./IPlayersCards"; 2 | 3 | export default interface IGameResultData { 4 | players: { 5 | playersCards: IPlayersCards, 6 | }, 7 | game: { 8 | winnersPlayerId: string, 9 | winningPlayerChips: number, 10 | winningsPerPlayer: number, 11 | tableBets: number, 12 | }, 13 | } -------------------------------------------------------------------------------- /code/client/src/interfaces/ILoginScreenConfig.ts: -------------------------------------------------------------------------------- 1 | import IDefaultSpriteConfig from "../components/sprite/interface/IDefaultSpriteConfig"; 2 | import ITextInputConfig from "../components/textInput/interface/ITextInputConfig"; 3 | import IButtonConfig from "../components/button/interface/IButtonConfig"; 4 | import ITextConfig from "../components/text/interface/ITextConfig"; 5 | 6 | export default interface ILoginScreenConfig { 7 | background: IDefaultSpriteConfig, 8 | usernameTextInputConfig: ITextInputConfig 9 | passwordTextInputConfig: ITextInputConfig 10 | loginButtonConfig: IButtonConfig 11 | registerButtonConfig: IButtonConfig 12 | usernameText: ITextConfig 13 | passwordText:ITextConfig 14 | } 15 | 16 | -------------------------------------------------------------------------------- /code/client/src/interfaces/INextRoundData.ts: -------------------------------------------------------------------------------- 1 | import ICardData from "./ICardData"; 2 | import IPlayerTurnData from "./IPlayerTurnData"; 3 | 4 | export default interface INextRoundData { 5 | game: { 6 | tableBets: number, 7 | tableCards: ICardData[], 8 | playerTurnData: IPlayerTurnData 9 | }, 10 | } 11 | 12 | -------------------------------------------------------------------------------- /code/client/src/interfaces/IPlayerTurnAction.ts: -------------------------------------------------------------------------------- 1 | export default interface IPlayerTurnAction { 2 | action: string, 3 | data: string | number 4 | } -------------------------------------------------------------------------------- /code/client/src/interfaces/IPlayerTurnData.ts: -------------------------------------------------------------------------------- 1 | export default interface IPlayerTurnData { 2 | playerIdGameTurn: string, 3 | serverTime: number, 4 | turnRespondTime: number, 5 | isBetOnTable, 6 | playerBetDifference 7 | } -------------------------------------------------------------------------------- /code/client/src/interfaces/IPlayersBets.ts: -------------------------------------------------------------------------------- 1 | export default interface IPlayersBets { 2 | [playerId: string]: { 3 | bet: number; 4 | }; 5 | } -------------------------------------------------------------------------------- /code/client/src/interfaces/IPlayersCards.ts: -------------------------------------------------------------------------------- 1 | import Card from "./ICardData"; 2 | export default interface IPlayersCards { 3 | [key: string]: Card[]; 4 | } -------------------------------------------------------------------------------- /code/client/src/interfaces/IPlayersMoney.ts: -------------------------------------------------------------------------------- 1 | export default interface IPlayersMoney { 2 | [playerId: string]: { 3 | chips: number; 4 | }; 5 | } -------------------------------------------------------------------------------- /code/client/src/interfaces/IRegisterScreenConfig.ts: -------------------------------------------------------------------------------- 1 | import IDefaultSpriteConfig from "../components/sprite/interface/IDefaultSpriteConfig"; 2 | import ITextInputConfig from "../components/textInput/interface/ITextInputConfig"; 3 | import IButtonConfig from "../components/button/interface/IButtonConfig"; 4 | import ITextConfig from "../components/text/interface/ITextConfig"; 5 | 6 | export default interface IRegisterScreenConfig { 7 | background: IDefaultSpriteConfig, 8 | usernameTextInputConfig: ITextInputConfig 9 | passwordTextInputConfig: ITextInputConfig 10 | nicknameTextInputConfig: ITextInputConfig 11 | registerButtonConfig: IButtonConfig 12 | backButtonConfig: IButtonConfig 13 | usernameText: ITextConfig 14 | passwordText:ITextConfig 15 | nicknameText:ITextConfig 16 | } 17 | 18 | -------------------------------------------------------------------------------- /code/client/src/interfaces/IServerPlayerData.ts: -------------------------------------------------------------------------------- 1 | export default interface IServerPlayerData { 2 | nick: string, 3 | money: number, 4 | chips: number, 5 | id: string, 6 | sit: number, 7 | bet: number 8 | position: string 9 | inLobby: boolean 10 | profileImage: string 11 | } 12 | -------------------------------------------------------------------------------- /code/client/src/interfaces/IUpdatePlayerTurnAction.ts: -------------------------------------------------------------------------------- 1 | export default interface IUpdatePlayerTurnAction { 2 | playerId: string; 3 | type: string, 4 | bet: number, 5 | chips: number 6 | } -------------------------------------------------------------------------------- /code/client/src/managers/AppManager.js: -------------------------------------------------------------------------------- 1 | // import { Application } from "pixi.js"; 2 | import AppStorage from "../storage/AppStorage"; 3 | 4 | export default class AppManager { 5 | static get app() { 6 | return AppStorage.app; 7 | } 8 | static addChild(instance) { 9 | this.app.stage.addChild(instance); 10 | } 11 | static removeChild(instance) { 12 | this.app.stage.removeChild(instance); 13 | } 14 | static addToTicker(updateFunction) { 15 | this.app.ticker.add(updateFunction); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /code/client/src/managers/ImageManager.js: -------------------------------------------------------------------------------- 1 | import ImageStorage from "../storage/ImageStorage"; 2 | 3 | export default class ImageManager { 4 | static addImage(key, source) { 5 | ImageStorage.addImage(key, source); 6 | } 7 | 8 | static getImage(key) { 9 | return ImageStorage.getImage(key); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /code/client/src/managers/SceneManager.ts: -------------------------------------------------------------------------------- 1 | import AppManager from "../managers/AppManager"; 2 | import SceneStorage from "../storage/SceneStorage"; 3 | import BaseScene from "../game/abstraction/BaseScene"; 4 | 5 | export default class SceneManager { 6 | 7 | public static addScene(scene: BaseScene[]):void { 8 | scene.forEach((scene) => { 9 | SceneStorage.addScene(scene) 10 | AppManager.addChild(scene) 11 | }); 12 | } 13 | 14 | public static autoStartFirstScene(): void { 15 | const scenesMap = SceneStorage.scenes 16 | const scenesKeys = Array.from(scenesMap.keys()); 17 | const firstScene = scenesKeys.length > 0 ? scenesKeys[0] : undefined; 18 | if(firstScene) 19 | this.startScene(firstScene); 20 | } 21 | 22 | public static startScene(key: string, data?: any):void { 23 | const scene = SceneStorage.getScene(key) 24 | scene?.init(data) 25 | } 26 | 27 | public static removeScene(key: string):void { 28 | const sceneInstance = this.getScene(key) 29 | if(sceneInstance) 30 | AppManager.removeChild(sceneInstance) 31 | } 32 | 33 | public static getScene(key: string){ 34 | return SceneStorage.getScene(key) 35 | } 36 | 37 | public static deleteScene(key: string):void { 38 | this.removeScene(key) 39 | SceneStorage.deleteScene(key) 40 | } 41 | 42 | public static setVisible(key: string, value: any) { 43 | const sceneInstance = this.getScene(key); 44 | sceneInstance.visible = value; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /code/client/src/pages/CSS/Pages.css: -------------------------------------------------------------------------------- 1 | #pages { 2 | position: fixed; 3 | width: 1280px; 4 | height: 720px; 5 | transform-origin: 0 0 0; 6 | pointer-events: all; 7 | } 8 | 9 | #pages-not-active { 10 | pointer-events: none; 11 | position: fixed; 12 | width: 1280px; 13 | height: 720px; 14 | transform-origin: 0 0 0; 15 | } -------------------------------------------------------------------------------- /code/client/src/pages/Pages.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useState, useImperativeHandle } from 'react'; 2 | import "./CSS/Pages.css"; 3 | import LoadingScreen from "./loadingScreen/LoadingScreen"; 4 | import LoginScreen from "./loginScreen/LoginScreen"; 5 | import LoadingGame from "./loadingGame/LoadingGame"; 6 | import GameInformation from "./gameInformation/GameInformation"; 7 | 8 | const Pages = React.forwardRef((props, ref) => { 9 | const [responsiveState, setResponsiveState] = useState({ 10 | width: '0px', 11 | height: '0px', 12 | left: '0px', 13 | top: '0px', 14 | transform: 'none', 15 | display: 'none' 16 | }); 17 | const [active, setActive] = useState(true); 18 | const [loadingScreenVisible, setLoadingScreenVisible] = useState(false); 19 | const [loginScreenVisible, setLoginScreenVisible] = useState(false); 20 | const [loadingGameVisible, setLoadingGameVisible] = useState(true); 21 | const [gameInformationVisible, setGameInformationVisible] = useState(false); 22 | 23 | const loadingScreenRef = useRef(null); 24 | const loginScreenRef = useRef(null); 25 | const loadingGameRef = useRef(null); 26 | const gameInformationRef = useRef(null); 27 | 28 | const handleLoadingPageVisible =(value) => { 29 | setLoadingScreenVisible(value); 30 | } 31 | 32 | const handleGameInformationVisible = async (value) => { 33 | setGameInformationVisible(value); 34 | setPointerEventActive(true) 35 | } 36 | 37 | const handleLoginPageVisible = (value) => { 38 | setLoginScreenVisible(value); 39 | } 40 | 41 | const handleLoadingGameVisible = (value) => { 42 | setLoadingGameVisible(value) 43 | } 44 | 45 | const handleLobbyPageVisible = (value) => { 46 | if(value === false) lobbyScreenRef.current.removeListeners() 47 | setLobbyScreenVisible(value) 48 | } 49 | 50 | const resize = (resizeData) => { 51 | setResponsiveState(resizeData); 52 | } 53 | 54 | const setPointerEventActive = (value) => { 55 | setActive(value) 56 | } 57 | 58 | useImperativeHandle(ref, () => ({ 59 | handleLoadingPageVisible, 60 | handleLoginPageVisible, 61 | handleLoadingGameVisible, 62 | handleLobbyPageVisible, 63 | setPointerEventActive, 64 | handleGameInformationVisible, 65 | resize 66 | })); 67 | const { width, height, left, top, transform, display } = responsiveState 68 | const style = { width, height, left, top, transform, display }; 69 | 70 | return ( 71 |
72 | {loadingGameVisible && } 73 | {loginScreenVisible && } 74 | {loadingScreenVisible && } 75 | {gameInformationVisible && } 76 |
77 | ); 78 | }); 79 | 80 | export default Pages; -------------------------------------------------------------------------------- /code/client/src/pages/loadingGame/CSS/LoadingGame.css: -------------------------------------------------------------------------------- 1 | #loading-game { 2 | position:fixed; 3 | width: 200%; 4 | height: 200%; 5 | background-color: #1f1e1e; 6 | top: -50%; 7 | left: -50%; 8 | } 9 | 10 | #loading-game #logo { 11 | position: absolute; 12 | top: 50%; 13 | left: 50%; 14 | transform: translate(-50%, -100%); 15 | width: auto; 16 | height: auto; 17 | /* max-width: 30%; 18 | max-height: 30%; */ 19 | object-fit: cover; 20 | } 21 | #loading-game #loading-icon { 22 | position: absolute; 23 | top: 50%; 24 | left: 50%; 25 | transform: translate(-50%, 0%); 26 | width: auto; 27 | height: auto; 28 | /* max-width: 20%; 29 | max-height: 20%; */ 30 | object-fit: cover; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /code/client/src/pages/loadingGame/LoadingGame.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useImperativeHandle } from 'react'; 2 | import "./CSS/LoadingGame.css"; 3 | 4 | const LoadingGame = React.forwardRef((props, ref) => { 5 | const loadingScreenRef = useRef(null); 6 | 7 | return ( 8 |
9 | 10 | Loading_icon 11 |
12 | ); 13 | }); 14 | 15 | export default LoadingGame; -------------------------------------------------------------------------------- /code/client/src/pages/manager/PagesManager.js: -------------------------------------------------------------------------------- 1 | // import GameManager from "../../game/manager/GameManager"; 2 | 3 | class PagesManager { 4 | constructor() { 5 | this.pages = null; 6 | } 7 | 8 | create(PagesElement) { 9 | this.pages = PagesElement; 10 | } 11 | 12 | handleLoadingPageVisible(value) { 13 | this.pages.handleLoadingPageVisible(value); 14 | } 15 | 16 | handleLoginPageVisible(value) { 17 | this.pages.handleLoginPageVisible(value); 18 | } 19 | 20 | handleLoadingGameVisible = (value) => { 21 | this.pages.handleLoadingGameVisible(value); 22 | }; 23 | 24 | handleLobbyPageVisible = (value) => { 25 | this.pages.handleLobbyPageVisible(value); 26 | }; 27 | 28 | handleRoomsPageVisible = (value) => { 29 | this.pages.handleRoomsPageVisible(value); 30 | }; 31 | 32 | setPointerEventActive = (value) => { 33 | this.pages.setPointerEventActive(value); 34 | }; 35 | 36 | handleGameInformationVisible = (value) => { 37 | this.pages.handleGameInformationVisible(value); 38 | if (!value) this.setPointerEventActive(false); 39 | }; 40 | } 41 | export default new PagesManager(); 42 | -------------------------------------------------------------------------------- /code/client/src/services/requests/config/config.ts: -------------------------------------------------------------------------------- 1 | export const SERVER_PORT = 8081; 2 | export const SOCKET_PORT = 8081; 3 | -------------------------------------------------------------------------------- /code/client/src/services/requests/helper/helper.ts: -------------------------------------------------------------------------------- 1 | import { SERVER_URL } from "../../config"; 2 | 3 | const headers = { 4 | "Content-Type": "application/json", 5 | Accept: "application/json", 6 | }; 7 | 8 | export const requestPost = (data, url) => { 9 | return fetch(`${SERVER_URL}/${url}`, { 10 | method: "post", 11 | headers: headers, 12 | body: JSON.stringify(data), 13 | }); 14 | }; 15 | 16 | export const requestGet = (url) => { 17 | return fetch(`${SERVER_URL}/${url}`, { 18 | headers: headers, 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /code/client/src/services/requests/requests.ts: -------------------------------------------------------------------------------- 1 | import { requestGet, requestPost } from "./helper/helper"; 2 | 3 | export const AUTHENTICATION = (data) => { 4 | return requestPost(data, "authentication"); 5 | }; 6 | 7 | export const REGISTRATION = (data) => { 8 | return requestPost(data, "registration"); 9 | }; 10 | -------------------------------------------------------------------------------- /code/client/src/services/webSocket/SocketClient.ts: -------------------------------------------------------------------------------- 1 | import Socket from "socket.io-client"; 2 | import { WEBSOCKET_URL } from "../config"; 3 | import GameSignals from "../../gameSignals/GameSignals"; 4 | 5 | class SocketClient { 6 | client: any 7 | constructor() { 8 | this.client = null 9 | this.bindSignals() 10 | } 11 | 12 | public async connectWithServer() { 13 | this.client = await Socket(`${WEBSOCKET_URL}`) 14 | } 15 | 16 | public setupServerListeners() { 17 | this.client.on("userState", (data: any) => { 18 | GameSignals.onPlayerAndGameState.dispatch(data) 19 | }); 20 | 21 | this.client.on("updateGameData", (data: any) => { 22 | GameSignals.onUpdateGameData.dispatch(data) 23 | }); 24 | } 25 | 26 | private spinButtonClick(userData: any){ 27 | this.client.emit("spinAction", userData); 28 | } 29 | 30 | private getPlayerAndGameState(authToken: string | undefined) { 31 | this.client.emit("getUserState", authToken); 32 | } 33 | 34 | private bindSignals(){ 35 | GameSignals.spinButtonClick.add((userData: any) => this.spinButtonClick(userData)); 36 | GameSignals.getPlayerAndGameState.add((data: string | undefined) => this.getPlayerAndGameState(data)); 37 | } 38 | } 39 | 40 | 41 | export default new SocketClient() -------------------------------------------------------------------------------- /code/client/src/storage/AppStorage.js: -------------------------------------------------------------------------------- 1 | export default class AppStorage { 2 | static _app = null; 3 | 4 | static add(app) { 5 | this._app = app; 6 | } 7 | 8 | static get app() { 9 | return this._app; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /code/client/src/storage/AudioStorage.ts: -------------------------------------------------------------------------------- 1 | import { Howl} from "howler"; 2 | 3 | export default class AudioStorage { 4 | private static audio: Map = new Map(); 5 | 6 | public static addAudio(key:string, source: Howl) { 7 | this.audio.set(key, source); 8 | } 9 | 10 | public static getAudio(key: string): Howl | undefined { 11 | return this.audio.get(key); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /code/client/src/storage/ImageStorage.js: -------------------------------------------------------------------------------- 1 | export default class ImageStorage { 2 | static images = new Map(); 3 | 4 | static addImage(key, source) { 5 | this.images.set(key, source); 6 | } 7 | 8 | static getImage(key) { 9 | return this.images.get(key); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /code/client/src/storage/SceneStorage.js: -------------------------------------------------------------------------------- 1 | export default class SceneStorage { 2 | static _scenes = new Map(); 3 | 4 | static addScene(scene) { 5 | const key = scene.sceneKey; 6 | this._scenes.set(key, scene); 7 | } 8 | 9 | static getScene(key) { 10 | return this._scenes.get(key); 11 | } 12 | 13 | static get scenes() { 14 | return this._scenes; 15 | } 16 | 17 | static deleteScene(key) { 18 | this._scenes.delete(key); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /code/client/src/utility/formatNumber.js: -------------------------------------------------------------------------------- 1 | export function formatNumber(text) { 2 | const textToNumber = parseInt(text); 3 | const formattedText = textToNumber.toLocaleString("en", { 4 | useGrouping: true, 5 | }); 6 | 7 | // return formattedText.replace(",", "."); 8 | return formattedText; 9 | } 10 | -------------------------------------------------------------------------------- /code/client/src/utility/math/MathUtils.ts: -------------------------------------------------------------------------------- 1 | export default class MathUtils { 2 | static getRandomNumberFloor(min: number, max: number) { 3 | return Math.floor(Math.random() * (max - min + 1)) + min; 4 | } 5 | 6 | static getRandomNumber(min: number, max: number) { 7 | return Math.random() * (max - min + 1) + min; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /code/client/src/utility/unformatNumber.js: -------------------------------------------------------------------------------- 1 | export function unformatNumber(text) { 2 | const numberWithoutDots = parseFloat(text.replace(/,/g, "")); 3 | return parseFloat(numberWithoutDots); 4 | } 5 | -------------------------------------------------------------------------------- /code/client/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import react from "@vitejs/plugin-react"; 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | build: { 8 | rollupOptions: { 9 | output: { 10 | manualChunks(id) { 11 | if (id.includes("node_modules")) { 12 | return id 13 | .toString() 14 | .split("node_modules/")[1] 15 | .split("/")[0] 16 | .toString(); 17 | } 18 | }, 19 | }, 20 | }, 21 | }, 22 | }); 23 | -------------------------------------------------------------------------------- /code/server/JWT/JWTManager.js: -------------------------------------------------------------------------------- 1 | const jwt = require("jsonwebtoken"); 2 | const { SECRET_KEY } = require("./config"); 3 | 4 | module.exports = class JWTManager { 5 | static secretKey = SECRET_KEY; 6 | 7 | static generateToken(data) { 8 | return jwt.sign(data, this.secretKey); 9 | } 10 | 11 | static decode(token) { 12 | try { 13 | return jwt.verify(token, this.secretKey); 14 | } catch (error) { 15 | return null; 16 | } 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /code/server/JWT/config.js: -------------------------------------------------------------------------------- 1 | const SECRET_KEY = process.env.JWT_SECRET_KEY; 2 | 3 | module.exports = { 4 | SECRET_KEY, 5 | }; 6 | -------------------------------------------------------------------------------- /code/server/MongoDB/DatabaseManager.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const { DB_URL } = require("./credentials"); 3 | mongoose.set("strictQuery", true); 4 | const User = require("./models/User"); 5 | 6 | class DatabaseManager { 7 | constructor() {} 8 | 9 | async connectDatabase() { 10 | await mongoose 11 | .connect(DB_URL, { 12 | useNewUrlParser: true, 13 | useUnifiedTopology: true, 14 | }) 15 | .then(async () => { 16 | console.log("DB init"); 17 | }); 18 | } 19 | 20 | async createUser(data) { 21 | const { nick, money, passwordHash } = data; 22 | const user = new User({ 23 | nick: nick, 24 | money: money, 25 | passwordHash: passwordHash, 26 | }); 27 | 28 | await user 29 | .save() 30 | .then((savedDoc) => { 31 | console.log("User saved in database"); 32 | }) 33 | .catch((error) => { 34 | console.log(error + " User NOT saved in database"); 35 | }); 36 | 37 | return true; 38 | } 39 | 40 | updateUser(data) { 41 | return User.updateOne( 42 | { id: data.id }, 43 | { 44 | $set: { 45 | score: data.score, 46 | }, 47 | } 48 | ); 49 | } 50 | 51 | async findUser(data) { 52 | return User.findOne(data).select("-_id -passwordHash -__v").lean(); 53 | } 54 | 55 | downloadUser(data) { 56 | return this.findUser(data).then((user) => { 57 | if (!user) { 58 | return "User does not exist"; 59 | } 60 | return user; 61 | }); 62 | } 63 | 64 | downloadUsers() { 65 | return User.find({}); 66 | } 67 | } 68 | 69 | mongoose.connection.on("connected", function () { 70 | console.log("Connected to mongo"); 71 | }); 72 | 73 | mongoose.connection.on("error", (error) => { 74 | console.log("Mongo connection ERROR", error); 75 | }); 76 | 77 | const databaseManager = new DatabaseManager(); 78 | module.exports = databaseManager; 79 | -------------------------------------------------------------------------------- /code/server/MongoDB/credentials.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | const USERNAME = process.env.USERNAME; 3 | const PASSWORD = process.env.PASSWORD; 4 | const HOST = process.env.HOST; 5 | const DB_URL = process.env.DB_URL; 6 | 7 | module.exports = { DB_URL, USERNAME, PASSWORD, HOST }; 8 | -------------------------------------------------------------------------------- /code/server/MongoDB/models/User.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const UserSchema = new mongoose.Schema({ 4 | passwordHash: String, 5 | money: Number, 6 | payment: { 7 | id: String, 8 | }, 9 | }); 10 | 11 | module.exports = mongoose.model("Users", UserSchema); 12 | -------------------------------------------------------------------------------- /code/server/PayPal/PayPalManager.js: -------------------------------------------------------------------------------- 1 | const paypal = require("paypal-rest-sdk"); 2 | const { 3 | CLIENT_ID, 4 | CLIENT_SECRET, 5 | MODE, 6 | SERVER_URL, 7 | } = require("../PayPal/credentials"); 8 | 9 | class PayPalManager { 10 | constructor() { 11 | this.configurePayPal(); 12 | } 13 | 14 | configurePayPal() { 15 | paypal.configure({ 16 | mode: MODE, 17 | client_id: CLIENT_ID, 18 | client_secret: CLIENT_SECRET, 19 | }); 20 | } 21 | 22 | createPaymentJSON(price, purchasedCoinsCount) { 23 | return { 24 | intent: "sale", 25 | payer: { payment_method: "paypal" }, 26 | redirect_urls: { 27 | return_url: `${SERVER_URL}/success?price=${price}&purchasedCoinsCount=${purchasedCoinsCount}`, 28 | cancel_url: `${SERVER_URL}/cancel`, 29 | }, 30 | transactions: [ 31 | { 32 | item_list: { 33 | items: [ 34 | { 35 | name: "Coins", 36 | sku: "ITEM", 37 | price: price, 38 | currency: "USD", 39 | quantity: 1, 40 | }, 41 | ], 42 | }, 43 | amount: { 44 | currency: "USD", 45 | total: price, 46 | }, 47 | description: "Buying game coins", 48 | }, 49 | ], 50 | }; 51 | } 52 | 53 | createPayment(paymentJSON, cb) { 54 | paypal.payment.create(paymentJSON, async (error, payment) => { 55 | await cb(error, payment); 56 | }); 57 | } 58 | 59 | executePaymentJSON(playerID, price) { 60 | return { 61 | payer_id: playerID, 62 | transactions: [ 63 | { 64 | amount: { 65 | currency: "USD", 66 | total: price, 67 | }, 68 | }, 69 | ], 70 | }; 71 | } 72 | 73 | executePayment(paymentId, executePaymentJSON, cb) { 74 | paypal.payment.execute( 75 | paymentId, 76 | executePaymentJSON, 77 | async (error, payment) => { 78 | cb(error, payment); 79 | } 80 | ); 81 | } 82 | } 83 | 84 | const paypalManager = new PayPalManager(); 85 | 86 | module.exports = paypalManager; 87 | -------------------------------------------------------------------------------- /code/server/PayPal/credentials.js: -------------------------------------------------------------------------------- 1 | const { port } = require("../index"); 2 | 3 | const MODE = "sandbox"; 4 | const CLIENT_ID = "123"; 5 | const CLIENT_SECRET = "123"; 6 | 7 | const SERVER_URL = `http://localhost:${port}`; 8 | 9 | module.exports = { CLIENT_ID, CLIENT_SECRET, MODE, SERVER_URL }; 10 | -------------------------------------------------------------------------------- /code/server/Socket/manager/SocketManager.js: -------------------------------------------------------------------------------- 1 | const GameManager = require("../../game/manager/GameManager"); 2 | 3 | class SocketManager { 4 | constructor(socketServer) { 5 | this.socketServer = socketServer; 6 | 7 | this.socketServer.on("connection", (socket) => { 8 | console.log("new user", socket.id); 9 | GameManager.createNewUser(socket.id); 10 | this.setupSocketListeners(socket); 11 | }); 12 | this.setupGameListeners(); 13 | } 14 | 15 | setupSocketListeners(socket) { 16 | socket.once("getUserState", (data) => { 17 | const userState = GameManager.getUserState(socket.id, data); 18 | socket.emit("userState", userState); 19 | }); 20 | 21 | socket.on("spinAction", async (data) => { 22 | const updatedGameData = await GameManager.userSpinAction(socket.id, data); 23 | socket.emit("updateGameData", updatedGameData); 24 | }); 25 | 26 | socket.on("disconnect", () => { 27 | console.log(`user ${socket.id} disconnect`); 28 | GameManager.deleteUser(socket.id); 29 | }); 30 | } 31 | } 32 | 33 | module.exports = SocketManager; 34 | -------------------------------------------------------------------------------- /code/server/config.js: -------------------------------------------------------------------------------- 1 | const SERVER_PORT = 8081; 2 | const SOCKET_PORT = 2567; 3 | 4 | module.exports = { 5 | SERVER_PORT, 6 | SOCKET_PORT, 7 | }; 8 | -------------------------------------------------------------------------------- /code/server/controllers/authorization/authentication.js: -------------------------------------------------------------------------------- 1 | const databaseManager = require("../../MongoDB/DatabaseManager"); 2 | const PasswordHasher = require("../../dataHasher/PasswordHasher"); 3 | const JWT = require("../../JWT/JWTManager"); 4 | 5 | async function authentication(req, res) { 6 | const { username, password } = req.body; 7 | const usernameString = String(username); 8 | const passwordString = String(password); 9 | 10 | try { 11 | const userPassword = usernameString + passwordString; 12 | const hashedPassword = await PasswordHasher.hashPassword(userPassword); 13 | const user = await databaseManager.findUser({ 14 | passwordHash: hashedPassword, 15 | }); 16 | 17 | if (!user) { 18 | console.log("User does not exist in database"); 19 | return res.status(404).json({ 20 | success: false, 21 | token: null, 22 | }); 23 | } 24 | 25 | console.log("User exists in database"); 26 | const jwt = JWT.generateToken(hashedPassword); 27 | 28 | return res.json({ success: true, jwt }); 29 | } catch (error) { 30 | console.error("An error occurred during registration", error); 31 | return res.status(500).json({ 32 | success: false, 33 | error: "Internal server error", 34 | }); 35 | } 36 | } 37 | 38 | module.exports = authentication; 39 | -------------------------------------------------------------------------------- /code/server/controllers/authorization/index.js: -------------------------------------------------------------------------------- 1 | const registration = require("./registration"); 2 | const authentication = require("./authentication"); 3 | 4 | module.exports = { registration, authentication }; 5 | -------------------------------------------------------------------------------- /code/server/controllers/authorization/registration.js: -------------------------------------------------------------------------------- 1 | const databaseManager = require("../../MongoDB/DatabaseManager"); 2 | const PasswordHasher = require("../../dataHasher/PasswordHasher"); 3 | 4 | async function register(req, res) { 5 | const { username, password, nick } = req.body; 6 | 7 | try { 8 | const userPassword = username + password; 9 | 10 | if (checkCharactersCorrect(username, password, nick)) { 11 | console.log("one of the login characters is empty"); 12 | return res.status(404).json({ 13 | success: false, 14 | token: null, 15 | }); 16 | } 17 | 18 | const hashedPassword = await PasswordHasher.hashPassword(userPassword); 19 | 20 | const user = await databaseManager.findUser({ 21 | passwordHash: hashedPassword, 22 | }); 23 | 24 | if (user) { 25 | console.log("User password hash exists in database"); 26 | return res.status(404).json({ 27 | success: false, 28 | }); 29 | } 30 | 31 | console.log("User password hash does not exist in database"); 32 | const userData = { 33 | nick: nick, 34 | money: 0, 35 | passwordHash: hashedPassword, 36 | }; 37 | 38 | databaseManager.createUser(userData); 39 | 40 | return res.json({ success: true }); 41 | } catch (error) { 42 | console.error("An error occurred during registration", error); 43 | return res.status(500).json({ 44 | success: false, 45 | error: "Internal server error", 46 | }); 47 | } 48 | } 49 | 50 | function checkCharacterCorrect(money) { 51 | // if (typeof money === 'number' && !isNaN(money)) { 52 | // return false; 53 | // } 54 | // if (typeof money === 'string' && money.trim() !== '') { 55 | // return false; 56 | // } 57 | return ( 58 | !(typeof money === "number" && !isNaN(money)) && 59 | !(typeof money === "string" && money.trim() !== "") 60 | ); 61 | // return true; 62 | } 63 | 64 | function checkCharactersCorrect(username, password, nickname) { 65 | const usernameResult = checkCharacterCorrect(username); 66 | const passwordResult = checkCharacterCorrect(password); 67 | const nicknameResult = checkCharacterCorrect(nickname); 68 | return usernameResult && passwordResult && nicknameResult; 69 | } 70 | 71 | module.exports = register; 72 | -------------------------------------------------------------------------------- /code/server/controllers/payPal/cancel.js: -------------------------------------------------------------------------------- 1 | function cancel(req, res) { 2 | console.log("PAYMENT CANCEL"); 3 | } 4 | 5 | module.exports = cancel; 6 | -------------------------------------------------------------------------------- /code/server/controllers/payPal/createPayment.js: -------------------------------------------------------------------------------- 1 | const orderData = require("../../game/orderData"); 2 | // const loginToken = require("../../LoginToken/LoginToken"); 3 | // const JWT = require("../../JWT/JWTManager"); 4 | const payPalManager = require("../../PayPal/PayPalManager"); 5 | const databaseManager = require("../../MongoDB/DatabaseManager"); 6 | 7 | function createPayment(req, res) { 8 | const { clientToken, orderNumber } = req.body; 9 | const { price, purchasedCoinsCount } = getOrderData(orderNumber); 10 | const decodedToken = loginToken.decode(clientToken).accountID; 11 | 12 | const paymentJSON = payPalManager.createPaymentJSON( 13 | price, 14 | purchasedCoinsCount 15 | ); 16 | 17 | payPalManager.createPayment(paymentJSON, async (error, payment) => { 18 | if (error) { 19 | console.error(error); 20 | } else { 21 | const approvalUrl = payment.links.find( 22 | (link) => link.rel === "approval_url" 23 | ).href; 24 | 25 | const paymentId = payment.id; 26 | 27 | await databaseManager.updatePaymentId({ 28 | decodedToken, 29 | paymentId, 30 | }); 31 | 32 | res.json({ redirectUrl: approvalUrl }); 33 | } 34 | }); 35 | } 36 | 37 | function getOrderData(orderNumber) { 38 | if (!orderData.has(orderNumber)) { 39 | throw new Error("Invalid order number"); 40 | } 41 | 42 | return orderData.get(orderNumber); 43 | } 44 | 45 | module.exports = createPayment; 46 | -------------------------------------------------------------------------------- /code/server/controllers/payPal/index.js: -------------------------------------------------------------------------------- 1 | const createPayment = require("./createPayment"); 2 | const success = require("./success"); 3 | const cancel = require("./cancel"); 4 | 5 | module.exports = { createPayment, success, cancel }; 6 | -------------------------------------------------------------------------------- /code/server/controllers/payPal/success.js: -------------------------------------------------------------------------------- 1 | const databaseManager = require("../../MongoDB/DatabaseManager"); 2 | const payPalManager = require("../../PayPal/PayPalManager"); 3 | 4 | async function success(req, res) { 5 | const payerId = req.query.PayerID; 6 | const paymentId = req.query.paymentId; 7 | const price = req.query.price; 8 | const purchasedCoinsCount = req.query.purchasedCoinsCount; 9 | 10 | const executePaymentJSON = payPalManager.executePaymentJSON(payerId, price); 11 | 12 | payPalManager.executePayment( 13 | paymentId, 14 | executePaymentJSON, 15 | async (error, payment) => { 16 | if (error) { 17 | console.log(error.response); 18 | throw error; 19 | } else { 20 | const orderingPlayer = await databaseManager.downloadPlayer({ 21 | paymentId, 22 | }); 23 | const { money, accountID } = orderingPlayer; 24 | const updatedMoney = money + Number(purchasedCoinsCount); 25 | await updatePlayerData(accountID, updatedMoney); 26 | console.log("PAYMENT SUCCESS"); 27 | } 28 | } 29 | ); 30 | } 31 | 32 | async function updatePlayerData(accountID, money) { 33 | await databaseManager.updatePlayer({ accountID, money }); 34 | } 35 | 36 | module.exports = success; 37 | -------------------------------------------------------------------------------- /code/server/dataHasher/PasswordHasher.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/code/server/dataHasher/PasswordHasher.js -------------------------------------------------------------------------------- /code/server/dataHasher/config.js: -------------------------------------------------------------------------------- 1 | const SPECIAL_SIGN = process.env.PASSWORD_HASHER_SPECIAL_SIGN; 2 | 3 | module.exports = { 4 | SPECIAL_SIGN, 5 | }; 6 | -------------------------------------------------------------------------------- /code/server/game/config/config.js: -------------------------------------------------------------------------------- 1 | const SERVER_PORT = 8081; 2 | const ROWS = 4; 3 | const COLUMNS = 5; 4 | const SYMBOL_TEXTURE_COUNT = 11; 5 | const REEL_POSITIONS = [0, 130, 260, 390, 520]; 6 | const BALANCE = 1000000; 7 | const SYMBOLS_MULTIPLIER = [3, 4, 5]; 8 | const BET_STEPS = [ 9 | "0.25", 10 | "0.50", 11 | "0.75", 12 | "1.00", 13 | "1.50", 14 | "2.00", 15 | "2.50", 16 | "5.00", 17 | "7.50", 18 | "10.00", 19 | "15.00", 20 | "20.00", 21 | "25.00", 22 | "50.00", 23 | "75.00", 24 | "100.00", 25 | "150.00", 26 | "200.00", 27 | "250.00", 28 | ]; 29 | 30 | module.exports = { 31 | SERVER_PORT, 32 | ROWS, 33 | COLUMNS, 34 | SYMBOL_TEXTURE_COUNT, 35 | REEL_POSITIONS, 36 | BALANCE, 37 | BET_STEPS, 38 | SYMBOLS_MULTIPLIER, 39 | }; 40 | -------------------------------------------------------------------------------- /code/server/game/orderData.js: -------------------------------------------------------------------------------- 1 | const orderData = new Map([ 2 | [1, { price: "50.00", purchasedCoinsCount: 50 }], 3 | [2, { price: "100.00", purchasedCoinsCount: 100 }], 4 | [3, { price: "150.00", purchasedCoinsCount: 150 }], 5 | [4, { price: "200.00", purchasedCoinsCount: 200 }], 6 | [5, { price: "300.00", purchasedCoinsCount: 500 }], 7 | [6, { price: "500.00", purchasedCoinsCount: 1000 }], 8 | ]); 9 | 10 | module.exports = orderData; 11 | -------------------------------------------------------------------------------- /code/server/game/utility/math/MathUtils.js: -------------------------------------------------------------------------------- 1 | module.exports = class MathUtils { 2 | static getRandomNumberFloor(min, max) { 3 | return Math.floor(Math.random() * (max - min + 1)) + min; 4 | } 5 | 6 | static getRandomNumber(min, max) { 7 | return Math.random() * (max - min + 1) + min; 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /code/server/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrzemoProgrammer/Slot-Machine/718f1a30edd09e178329d5f6d3acf16bd3c00eee/code/server/index.html -------------------------------------------------------------------------------- /code/server/index.js: -------------------------------------------------------------------------------- 1 | const { SERVER_PORT } = require("./config"); 2 | const http = require("http"); 3 | const compression = require("compression"); 4 | const express = require("express"); 5 | const app = express(); 6 | const server = http.createServer(app); 7 | const cors = require("cors"); 8 | const port = process.env.PORT || SERVER_PORT; 9 | const socketIo = require("socket.io"); 10 | const socketServer = socketIo(server, { 11 | cors: { 12 | origin: "*", 13 | }, 14 | }); 15 | 16 | app.use( 17 | cors({ 18 | origin: "*", 19 | }) 20 | ); 21 | 22 | app.use(compression()); 23 | app.use(express.json()); 24 | app.use(express.static(`${__dirname}/../client`)); 25 | 26 | app.get("/", function (req, res) { 27 | res.sendFile(__dirname + "/index.html"); 28 | }); 29 | 30 | module.exports = { 31 | server, 32 | app, 33 | port, 34 | socketServer, 35 | }; 36 | -------------------------------------------------------------------------------- /code/server/main.js: -------------------------------------------------------------------------------- 1 | const { app, server, port, socketServer } = require("./index"); 2 | const { 3 | authentication, 4 | registration, 5 | } = require("./controllers/authorization/index"); 6 | const SocketManager = require("./Socket/manager/SocketManager"); 7 | 8 | server.listen(port, async () => { 9 | app.post("/authentication", authentication); 10 | app.post("/registration", registration); 11 | this.socketManager = new SocketManager(socketServer); 12 | 13 | console.log(`Listening on ${server.address().port}`); 14 | }); 15 | -------------------------------------------------------------------------------- /code/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "nodemon main.js", 9 | "build": "webpack --config webpack.config.js" 10 | }, 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "bcrypt": "^5.1.1", 15 | "colyseus": "^0.15.9", 16 | "compression": "^1.7.4", 17 | "cors": "^2.8.5", 18 | "dotenv": "^16.3.1", 19 | "express": "^4.18.2", 20 | "jsonwebtoken": "^9.0.2", 21 | "mongodb": "^5.2.0", 22 | "mongoose": "^7.0.3", 23 | "paypal-rest-sdk": "^1.8.1", 24 | "socket.io": "^4.7.4" 25 | }, 26 | "devDependencies": { 27 | "nodemon": "^3.0.1", 28 | "webpack": "^5.79.0", 29 | "webpack-cli": "^5.0.1", 30 | "webpack-node-externals": "^3.0.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /code/server/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const nodeExternals = require("webpack-node-externals"); 3 | 4 | module.exports = { 5 | entry: "/main.js", 6 | mode: "production", 7 | target: "node", 8 | externals: [nodeExternals()], 9 | output: { 10 | filename: "bundle.js", 11 | path: path.resolve(__dirname, "dist"), 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | Slot Machine 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |
53 | 54 | 55 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | /* body { 2 | margin: 0; 3 | padding: 0; 4 | color: rgba(255, 255, 255, 0.87); 5 | background-color: #000000; 6 | font-family: Arial, Helvetica, sans-serif; 7 | } 8 | 9 | #app { 10 | width: 100%; 11 | height: 100vh; 12 | overflow: hidden; 13 | display: flex; 14 | justify-content: center; 15 | align-items: center; 16 | } */ 17 | 18 | /* .spritePosition { 19 | margin: 10px 0 0 10px; 20 | font-size: 0.8em; 21 | } 22 | 23 | .button { 24 | width: 140px; 25 | margin: 10px; 26 | padding: 10px; 27 | background-color: #000000; 28 | color: rgba(255, 255, 255, 0.87); 29 | border: 1px solid rgba(255, 255, 255, 0.87); 30 | cursor: pointer; 31 | transition: all 0.3s; 32 | 33 | &:hover { 34 | border: 1px solid #0ec3c9; 35 | color: #0ec3c9; 36 | } 37 | 38 | &:active { 39 | background-color: #0ec3c9; 40 | } 41 | 42 | &:disabled { 43 | cursor: not-allowed; 44 | border: 1px solid rgba(255, 255, 255, 0.3); 45 | color: rgba(255, 255, 255, 0.3); 46 | } 47 | } */ --------------------------------------------------------------------------------