sigurd-startup 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +203 -0
  2. package/dist/assets/bomb/bomb1.png +0 -0
  3. package/dist/assets/bomb/bomb2.png +0 -0
  4. package/dist/assets/complete/complete1.png +0 -0
  5. package/dist/assets/complete/complete2.png +0 -0
  6. package/dist/assets/complete/complete3.png +0 -0
  7. package/dist/assets/complete/complete4.png +0 -0
  8. package/dist/assets/complete/complete5.png +0 -0
  9. package/dist/assets/float/float1.png +0 -0
  10. package/dist/assets/float-dir/float-dir1.png +0 -0
  11. package/dist/assets/ghost-Idle/ghost-idle1.png +0 -0
  12. package/dist/assets/ghost-Idle/ghost-idle2.png +0 -0
  13. package/dist/assets/ghost-Idle/ghost-idle3.png +0 -0
  14. package/dist/assets/ghost-Idle/ghost-idle4.png +0 -0
  15. package/dist/assets/ghost-Idle/ghost-idle5.png +0 -0
  16. package/dist/assets/ghost-Idle/ghost-idle6.png +0 -0
  17. package/dist/assets/ghost-float/ghost-float1.png +0 -0
  18. package/dist/assets/ghost-float/ghost-float2.png +0 -0
  19. package/dist/assets/ghost-jump/ghost-jump1.png +0 -0
  20. package/dist/assets/ghost-jump/ghost-jump2.png +0 -0
  21. package/dist/assets/ghost-jump/ghost-jump3.png +0 -0
  22. package/dist/assets/ghost-landing/ghost-landing1.png +0 -0
  23. package/dist/assets/ghost-landing/ghost-landing2.png +0 -0
  24. package/dist/assets/ghost-landing/ghost-landing3.png +0 -0
  25. package/dist/assets/ghost-map-complete/ghost-map-complete1.png +0 -0
  26. package/dist/assets/ghost-map-complete/ghost-map-complete2.png +0 -0
  27. package/dist/assets/ghost-map-complete/ghost-map-complete3.png +0 -0
  28. package/dist/assets/ghost-map-complete/ghost-map-complete4.png +0 -0
  29. package/dist/assets/ghost-walk/ghost-walk1.png +0 -0
  30. package/dist/assets/ghost-walk/ghost-walk2.png +0 -0
  31. package/dist/assets/ghost-walk/ghost-walk3.png +0 -0
  32. package/dist/assets/ghost-walk/ghost-walk4.png +0 -0
  33. package/dist/assets/ghost-walk/ghost-walk5.png +0 -0
  34. package/dist/assets/ghost-walk/ghost-walk6.png +0 -0
  35. package/dist/assets/ghost-walk/ghost-walk7.png +0 -0
  36. package/dist/assets/ghost-walk/ghost-walk8.png +0 -0
  37. package/dist/assets/jumping/jump1.png +0 -0
  38. package/dist/assets/jumping/jump2.png +0 -0
  39. package/dist/assets/jumping/jump3.png +0 -0
  40. package/dist/assets/landing/landing1.png +0 -0
  41. package/dist/assets/map-images/future-city/1.png +0 -0
  42. package/dist/assets/map-images/future-city/2.png +0 -0
  43. package/dist/assets/map-images/future-city/3.png +0 -0
  44. package/dist/assets/map-images/future-city/4.png +0 -0
  45. package/dist/assets/map-images/future-city/5.png +0 -0
  46. package/dist/assets/map-images/future-city/6.png +0 -0
  47. package/dist/assets/map-images/future-city/7.png +0 -0
  48. package/dist/assets/map-images/future-city/8.png +0 -0
  49. package/dist/assets/map-images/future-city/9.png +0 -0
  50. package/dist/assets/map-images/future-city-2/1.png +0 -0
  51. package/dist/assets/map-images/future-city-2/2.png +0 -0
  52. package/dist/assets/map-images/future-city-2/3.png +0 -0
  53. package/dist/assets/map-images/future-city-2/4.png +0 -0
  54. package/dist/assets/map-images/future-city-2/5.png +0 -0
  55. package/dist/assets/map-images/future-city-2/6.png +0 -0
  56. package/dist/assets/map-images/future-city-2/7.png +0 -0
  57. package/dist/assets/map-images/future-city-2/8.png +0 -0
  58. package/dist/assets/map-images/future-city-2/9.png +0 -0
  59. package/dist/assets/map-images/mountain/1.png +0 -0
  60. package/dist/assets/map-images/mountain/2.png +0 -0
  61. package/dist/assets/map-images/mountain/3.png +0 -0
  62. package/dist/assets/map-images/mountain/4.png +0 -0
  63. package/dist/assets/map-images/mountain/5.png +0 -0
  64. package/dist/assets/map-images/mountain/6.png +0 -0
  65. package/dist/assets/map-images/mountain/7.png +0 -0
  66. package/dist/assets/map-images/mountain/8.png +0 -0
  67. package/dist/assets/map-images/mountain/9.png +0 -0
  68. package/dist/assets/map-images/ocean/1.png +0 -0
  69. package/dist/assets/map-images/ocean/2.png +0 -0
  70. package/dist/assets/map-images/ocean/3.png +0 -0
  71. package/dist/assets/map-images/ocean/4.png +0 -0
  72. package/dist/assets/map-images/taco-street/1.png +0 -0
  73. package/dist/assets/map-images/taco-street/2.png +0 -0
  74. package/dist/assets/map-images/taco-street/3.png +0 -0
  75. package/dist/assets/map-images/taco-street/4.png +0 -0
  76. package/dist/assets/map-images/taco-street/5.png +0 -0
  77. package/dist/assets/map-images/taco-street/6.png +0 -0
  78. package/dist/assets/map-images/valley/1.png +0 -0
  79. package/dist/assets/map-images/valley/2.png +0 -0
  80. package/dist/assets/map-images/valley/3.png +0 -0
  81. package/dist/assets/maps-bg-images/alltinn-norge.png +0 -0
  82. package/dist/assets/maps-bg-images/innovasjon-norge.png +0 -0
  83. package/dist/assets/maps-bg-images/kommunehuset.png +0 -0
  84. package/dist/assets/maps-bg-images/nav.png +0 -0
  85. package/dist/assets/maps-bg-images/silicone-vally.png +0 -0
  86. package/dist/assets/maps-bg-images/skatteetaten.png +0 -0
  87. package/dist/assets/maps-bg-images/startup-lab.png +0 -0
  88. package/dist/assets/react.svg +1 -0
  89. package/dist/assets/running/run1.png +0 -0
  90. package/dist/assets/running/run2.png +0 -0
  91. package/dist/assets/running/run3.png +0 -0
  92. package/dist/assets/sigurd-idle/sigurd-idle1.png +0 -0
  93. package/dist/assets/sigurd-idle/sigurd-idle2.png +0 -0
  94. package/dist/assets/sigurd-idle/sigurd-idle3.png +0 -0
  95. package/dist/assets/sigurd-idle/sigurd-idle4.png +0 -0
  96. package/dist/audio/background-music.wav +0 -0
  97. package/dist/index.d.ts +1 -0
  98. package/dist/sigurd-startup.css +1 -0
  99. package/dist/sigurd-startup.es.js +6492 -0
  100. package/dist/sigurd-startup.es.js.map +1 -0
  101. package/dist/sigurd-startup.umd.js +31 -0
  102. package/dist/sigurd-startup.umd.js.map +1 -0
  103. package/dist/vite.svg +1 -0
  104. package/package.json +84 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sigurd-startup.es.js","sources":["../node_modules/react/cjs/react-jsx-runtime.production.min.js","../node_modules/react/cjs/react-jsx-runtime.development.js","../node_modules/react/jsx-runtime.js","../node_modules/react-dom/client.js","../src/types/constants.ts","../src/stores/slices/playerSlice.ts","../src/types/enums.ts","../src/lib/logger.ts","../src/lib/communicationUtils.ts","../src/managers/MonsterFactory.ts","../src/maps/mapDefinitions.ts","../src/stores/slices/gameStateSlice.ts","../src/lib/scoringUtils.ts","../src/stores/slices/bombSlice.ts","../src/managers/bombManager.ts","../src/stores/slices/levelSlice.ts","../src/stores/slices/levelHistorySlice.ts","../src/stores/slices/multiplierSlice.ts","../src/stores/slices/audioSettingsSlice.ts","../src/stores/slices/coinSlice.ts","../src/stores/slices/floatingTextSlice.ts","../src/managers/ScalingManager.ts","../src/config/coinTypes.ts","../src/managers/coinPhysics.ts","../src/managers/coinManager.ts","../src/stores/gameStore.ts","../src/managers/InputManager.ts","../src/managers/CollisionManager.ts","../src/lib/SpriteInstance.ts","../src/config/assets.ts","../src/entities/Player.ts","../src/entities/Bomb.ts","../src/managers/BackgroundManager.ts","../src/managers/OptimizedRespawnManager.ts","../src/managers/RenderManager.ts","../src/types/interfaces.ts","../src/managers/monster-movements/MovementUtils.ts","../src/managers/monster-movements/PatrolMovement.ts","../src/managers/monster-movements/ChaserMovement.ts","../src/managers/monster-movements/AmbusherMovement.ts","../src/managers/monster-movements/FloaterMovement.ts","../src/managers/MonsterBehaviorManager.ts","../src/managers/OptimizedSpawnManager.ts","../src/managers/AudioManager.ts","../src/lib/AnimationController.ts","../src/managers/GameManager.ts","../src/hooks/useFullscreen.ts","../src/components/GameCanvas.tsx","../src/lib/utils.ts","../src/components/ui/button.tsx","../src/components/ui/tooltip.tsx","../src/components/menu/menus/StartMenu.tsx","../src/components/menu/menus/CountdownOverlay.tsx","../src/components/menu/menus/InGameMenu.tsx","../src/components/menu/menus/PauseMenu.tsx","../src/components/menu/menus/SettingsMenu.tsx","../src/hooks/useAnimatedCounter.ts","../src/components/menu/menus/BonusScreen.tsx","../src/components/menu/menus/VictoryMenu.tsx","../src/components/menu/menus/GameOverScreen.tsx","../src/components/menu/menus/AudioSettingsMenu.tsx","../src/components/menu/Menu.tsx","../src/hooks/useKeyboardShortcuts.ts","../src/hooks/useBackgroundPreloading.ts","../src/version.ts","../src/components/MainGame.tsx","../src/game-wrapper.tsx","../src/index.ts"],"sourcesContent":["/**\n * @license React\n * react-jsx-runtime.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';var f=require(\"react\"),k=Symbol.for(\"react.element\"),l=Symbol.for(\"react.fragment\"),m=Object.prototype.hasOwnProperty,n=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,p={key:!0,ref:!0,__self:!0,__source:!0};\nfunction q(c,a,g){var b,d={},e=null,h=null;void 0!==g&&(e=\"\"+g);void 0!==a.key&&(e=\"\"+a.key);void 0!==a.ref&&(h=a.ref);for(b in a)m.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a)void 0===d[b]&&(d[b]=a[b]);return{$$typeof:k,type:c,key:e,ref:h,props:d,_owner:n.current}}exports.Fragment=l;exports.jsx=q;exports.jsxs=q;\n","/**\n * @license React\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n (function() {\n'use strict';\n\nvar React = require('react');\n\n// ATTENTION\n// When adding new symbols to this file,\n// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'\n// The Symbol used to tag the ReactElement-like types.\nvar REACT_ELEMENT_TYPE = Symbol.for('react.element');\nvar REACT_PORTAL_TYPE = Symbol.for('react.portal');\nvar REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');\nvar REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode');\nvar REACT_PROFILER_TYPE = Symbol.for('react.profiler');\nvar REACT_PROVIDER_TYPE = Symbol.for('react.provider');\nvar REACT_CONTEXT_TYPE = Symbol.for('react.context');\nvar REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');\nvar REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');\nvar REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');\nvar REACT_MEMO_TYPE = Symbol.for('react.memo');\nvar REACT_LAZY_TYPE = Symbol.for('react.lazy');\nvar REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen');\nvar MAYBE_ITERATOR_SYMBOL = Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator';\nfunction getIteratorFn(maybeIterable) {\n if (maybeIterable === null || typeof maybeIterable !== 'object') {\n return null;\n }\n\n var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];\n\n if (typeof maybeIterator === 'function') {\n return maybeIterator;\n }\n\n return null;\n}\n\nvar ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\nfunction error(format) {\n {\n {\n for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n\n printWarning('error', format, args);\n }\n }\n}\n\nfunction printWarning(level, format, args) {\n // When changing this logic, you might want to also\n // update consoleWithStackDev.www.js as well.\n {\n var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n var stack = ReactDebugCurrentFrame.getStackAddendum();\n\n if (stack !== '') {\n format += '%s';\n args = args.concat([stack]);\n } // eslint-disable-next-line react-internal/safe-string-coercion\n\n\n var argsWithFormat = args.map(function (item) {\n return String(item);\n }); // Careful: RN currently depends on this prefix\n\n argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\n // breaks IE9: https://github.com/facebook/react/issues/13610\n // eslint-disable-next-line react-internal/no-production-logging\n\n Function.prototype.apply.call(console[level], console, argsWithFormat);\n }\n}\n\n// -----------------------------------------------------------------------------\n\nvar enableScopeAPI = false; // Experimental Create Event Handle API.\nvar enableCacheElement = false;\nvar enableTransitionTracing = false; // No known bugs, but needs performance testing\n\nvar enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber\n// stuff. Intended to enable React core members to more easily debug scheduling\n// issues in DEV builds.\n\nvar enableDebugTracing = false; // Track which Fiber(s) schedule render work.\n\nvar REACT_MODULE_REFERENCE;\n\n{\n REACT_MODULE_REFERENCE = Symbol.for('react.module.reference');\n}\n\nfunction isValidElementType(type) {\n if (typeof type === 'string' || typeof type === 'function') {\n return true;\n } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).\n\n\n if (type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || enableDebugTracing || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || enableLegacyHidden || type === REACT_OFFSCREEN_TYPE || enableScopeAPI || enableCacheElement || enableTransitionTracing ) {\n return true;\n }\n\n if (typeof type === 'object' && type !== null) {\n if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object\n // types supported by any Flight configuration anywhere since\n // we don't know which Flight build this will end up being used\n // with.\n type.$$typeof === REACT_MODULE_REFERENCE || type.getModuleId !== undefined) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction getWrappedName(outerType, innerType, wrapperName) {\n var displayName = outerType.displayName;\n\n if (displayName) {\n return displayName;\n }\n\n var functionName = innerType.displayName || innerType.name || '';\n return functionName !== '' ? wrapperName + \"(\" + functionName + \")\" : wrapperName;\n} // Keep in sync with react-reconciler/getComponentNameFromFiber\n\n\nfunction getContextName(type) {\n return type.displayName || 'Context';\n} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead.\n\n\nfunction getComponentNameFromType(type) {\n if (type == null) {\n // Host root, text node or just invalid type.\n return null;\n }\n\n {\n if (typeof type.tag === 'number') {\n error('Received an unexpected object in getComponentNameFromType(). ' + 'This is likely a bug in React. Please file an issue.');\n }\n }\n\n if (typeof type === 'function') {\n return type.displayName || type.name || null;\n }\n\n if (typeof type === 'string') {\n return type;\n }\n\n switch (type) {\n case REACT_FRAGMENT_TYPE:\n return 'Fragment';\n\n case REACT_PORTAL_TYPE:\n return 'Portal';\n\n case REACT_PROFILER_TYPE:\n return 'Profiler';\n\n case REACT_STRICT_MODE_TYPE:\n return 'StrictMode';\n\n case REACT_SUSPENSE_TYPE:\n return 'Suspense';\n\n case REACT_SUSPENSE_LIST_TYPE:\n return 'SuspenseList';\n\n }\n\n if (typeof type === 'object') {\n switch (type.$$typeof) {\n case REACT_CONTEXT_TYPE:\n var context = type;\n return getContextName(context) + '.Consumer';\n\n case REACT_PROVIDER_TYPE:\n var provider = type;\n return getContextName(provider._context) + '.Provider';\n\n case REACT_FORWARD_REF_TYPE:\n return getWrappedName(type, type.render, 'ForwardRef');\n\n case REACT_MEMO_TYPE:\n var outerName = type.displayName || null;\n\n if (outerName !== null) {\n return outerName;\n }\n\n return getComponentNameFromType(type.type) || 'Memo';\n\n case REACT_LAZY_TYPE:\n {\n var lazyComponent = type;\n var payload = lazyComponent._payload;\n var init = lazyComponent._init;\n\n try {\n return getComponentNameFromType(init(payload));\n } catch (x) {\n return null;\n }\n }\n\n // eslint-disable-next-line no-fallthrough\n }\n }\n\n return null;\n}\n\nvar assign = Object.assign;\n\n// Helpers to patch console.logs to avoid logging during side-effect free\n// replaying on render function. This currently only patches the object\n// lazily which won't cover if the log function was extracted eagerly.\n// We could also eagerly patch the method.\nvar disabledDepth = 0;\nvar prevLog;\nvar prevInfo;\nvar prevWarn;\nvar prevError;\nvar prevGroup;\nvar prevGroupCollapsed;\nvar prevGroupEnd;\n\nfunction disabledLog() {}\n\ndisabledLog.__reactDisabledLog = true;\nfunction disableLogs() {\n {\n if (disabledDepth === 0) {\n /* eslint-disable react-internal/no-production-logging */\n prevLog = console.log;\n prevInfo = console.info;\n prevWarn = console.warn;\n prevError = console.error;\n prevGroup = console.group;\n prevGroupCollapsed = console.groupCollapsed;\n prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099\n\n var props = {\n configurable: true,\n enumerable: true,\n value: disabledLog,\n writable: true\n }; // $FlowFixMe Flow thinks console is immutable.\n\n Object.defineProperties(console, {\n info: props,\n log: props,\n warn: props,\n error: props,\n group: props,\n groupCollapsed: props,\n groupEnd: props\n });\n /* eslint-enable react-internal/no-production-logging */\n }\n\n disabledDepth++;\n }\n}\nfunction reenableLogs() {\n {\n disabledDepth--;\n\n if (disabledDepth === 0) {\n /* eslint-disable react-internal/no-production-logging */\n var props = {\n configurable: true,\n enumerable: true,\n writable: true\n }; // $FlowFixMe Flow thinks console is immutable.\n\n Object.defineProperties(console, {\n log: assign({}, props, {\n value: prevLog\n }),\n info: assign({}, props, {\n value: prevInfo\n }),\n warn: assign({}, props, {\n value: prevWarn\n }),\n error: assign({}, props, {\n value: prevError\n }),\n group: assign({}, props, {\n value: prevGroup\n }),\n groupCollapsed: assign({}, props, {\n value: prevGroupCollapsed\n }),\n groupEnd: assign({}, props, {\n value: prevGroupEnd\n })\n });\n /* eslint-enable react-internal/no-production-logging */\n }\n\n if (disabledDepth < 0) {\n error('disabledDepth fell below zero. ' + 'This is a bug in React. Please file an issue.');\n }\n }\n}\n\nvar ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;\nvar prefix;\nfunction describeBuiltInComponentFrame(name, source, ownerFn) {\n {\n if (prefix === undefined) {\n // Extract the VM specific prefix used by each line.\n try {\n throw Error();\n } catch (x) {\n var match = x.stack.trim().match(/\\n( *(at )?)/);\n prefix = match && match[1] || '';\n }\n } // We use the prefix to ensure our stacks line up with native stack frames.\n\n\n return '\\n' + prefix + name;\n }\n}\nvar reentry = false;\nvar componentFrameCache;\n\n{\n var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;\n componentFrameCache = new PossiblyWeakMap();\n}\n\nfunction describeNativeComponentFrame(fn, construct) {\n // If something asked for a stack inside a fake render, it should get ignored.\n if ( !fn || reentry) {\n return '';\n }\n\n {\n var frame = componentFrameCache.get(fn);\n\n if (frame !== undefined) {\n return frame;\n }\n }\n\n var control;\n reentry = true;\n var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe It does accept undefined.\n\n Error.prepareStackTrace = undefined;\n var previousDispatcher;\n\n {\n previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function\n // for warnings.\n\n ReactCurrentDispatcher.current = null;\n disableLogs();\n }\n\n try {\n // This should throw.\n if (construct) {\n // Something should be setting the props in the constructor.\n var Fake = function () {\n throw Error();\n }; // $FlowFixMe\n\n\n Object.defineProperty(Fake.prototype, 'props', {\n set: function () {\n // We use a throwing setter instead of frozen or non-writable props\n // because that won't throw in a non-strict mode function.\n throw Error();\n }\n });\n\n if (typeof Reflect === 'object' && Reflect.construct) {\n // We construct a different control for this case to include any extra\n // frames added by the construct call.\n try {\n Reflect.construct(Fake, []);\n } catch (x) {\n control = x;\n }\n\n Reflect.construct(fn, [], Fake);\n } else {\n try {\n Fake.call();\n } catch (x) {\n control = x;\n }\n\n fn.call(Fake.prototype);\n }\n } else {\n try {\n throw Error();\n } catch (x) {\n control = x;\n }\n\n fn();\n }\n } catch (sample) {\n // This is inlined manually because closure doesn't do it for us.\n if (sample && control && typeof sample.stack === 'string') {\n // This extracts the first frame from the sample that isn't also in the control.\n // Skipping one frame that we assume is the frame that calls the two.\n var sampleLines = sample.stack.split('\\n');\n var controlLines = control.stack.split('\\n');\n var s = sampleLines.length - 1;\n var c = controlLines.length - 1;\n\n while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) {\n // We expect at least one stack frame to be shared.\n // Typically this will be the root most one. However, stack frames may be\n // cut off due to maximum stack limits. In this case, one maybe cut off\n // earlier than the other. We assume that the sample is longer or the same\n // and there for cut off earlier. So we should find the root most frame in\n // the sample somewhere in the control.\n c--;\n }\n\n for (; s >= 1 && c >= 0; s--, c--) {\n // Next we find the first one that isn't the same which should be the\n // frame that called our sample function and the control.\n if (sampleLines[s] !== controlLines[c]) {\n // In V8, the first line is describing the message but other VMs don't.\n // If we're about to return the first line, and the control is also on the same\n // line, that's a pretty good indicator that our sample threw at same line as\n // the control. I.e. before we entered the sample frame. So we ignore this result.\n // This can happen if you passed a class to function component, or non-function.\n if (s !== 1 || c !== 1) {\n do {\n s--;\n c--; // We may still have similar intermediate frames from the construct call.\n // The next one that isn't the same should be our match though.\n\n if (c < 0 || sampleLines[s] !== controlLines[c]) {\n // V8 adds a \"new\" prefix for native classes. Let's remove it to make it prettier.\n var _frame = '\\n' + sampleLines[s].replace(' at new ', ' at '); // If our component frame is labeled \"<anonymous>\"\n // but we have a user-provided \"displayName\"\n // splice it in to make the stack more readable.\n\n\n if (fn.displayName && _frame.includes('<anonymous>')) {\n _frame = _frame.replace('<anonymous>', fn.displayName);\n }\n\n {\n if (typeof fn === 'function') {\n componentFrameCache.set(fn, _frame);\n }\n } // Return the line we found.\n\n\n return _frame;\n }\n } while (s >= 1 && c >= 0);\n }\n\n break;\n }\n }\n }\n } finally {\n reentry = false;\n\n {\n ReactCurrentDispatcher.current = previousDispatcher;\n reenableLogs();\n }\n\n Error.prepareStackTrace = previousPrepareStackTrace;\n } // Fallback to just using the name if we couldn't make it throw.\n\n\n var name = fn ? fn.displayName || fn.name : '';\n var syntheticFrame = name ? describeBuiltInComponentFrame(name) : '';\n\n {\n if (typeof fn === 'function') {\n componentFrameCache.set(fn, syntheticFrame);\n }\n }\n\n return syntheticFrame;\n}\nfunction describeFunctionComponentFrame(fn, source, ownerFn) {\n {\n return describeNativeComponentFrame(fn, false);\n }\n}\n\nfunction shouldConstruct(Component) {\n var prototype = Component.prototype;\n return !!(prototype && prototype.isReactComponent);\n}\n\nfunction describeUnknownElementTypeFrameInDEV(type, source, ownerFn) {\n\n if (type == null) {\n return '';\n }\n\n if (typeof type === 'function') {\n {\n return describeNativeComponentFrame(type, shouldConstruct(type));\n }\n }\n\n if (typeof type === 'string') {\n return describeBuiltInComponentFrame(type);\n }\n\n switch (type) {\n case REACT_SUSPENSE_TYPE:\n return describeBuiltInComponentFrame('Suspense');\n\n case REACT_SUSPENSE_LIST_TYPE:\n return describeBuiltInComponentFrame('SuspenseList');\n }\n\n if (typeof type === 'object') {\n switch (type.$$typeof) {\n case REACT_FORWARD_REF_TYPE:\n return describeFunctionComponentFrame(type.render);\n\n case REACT_MEMO_TYPE:\n // Memo may contain any component type so we recursively resolve it.\n return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn);\n\n case REACT_LAZY_TYPE:\n {\n var lazyComponent = type;\n var payload = lazyComponent._payload;\n var init = lazyComponent._init;\n\n try {\n // Lazy may contain any component type so we recursively resolve it.\n return describeUnknownElementTypeFrameInDEV(init(payload), source, ownerFn);\n } catch (x) {}\n }\n }\n }\n\n return '';\n}\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\nvar loggedTypeFailures = {};\nvar ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n\nfunction setCurrentlyValidatingElement(element) {\n {\n if (element) {\n var owner = element._owner;\n var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);\n ReactDebugCurrentFrame.setExtraStackFrame(stack);\n } else {\n ReactDebugCurrentFrame.setExtraStackFrame(null);\n }\n }\n}\n\nfunction checkPropTypes(typeSpecs, values, location, componentName, element) {\n {\n // $FlowFixMe This is okay but Flow doesn't know it.\n var has = Function.call.bind(hasOwnProperty);\n\n for (var typeSpecName in typeSpecs) {\n if (has(typeSpecs, typeSpecName)) {\n var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to\n // fail the render phase where it didn't fail before. So we log it.\n // After these have been cleaned up, we'll let them throw.\n\n try {\n // This is intentionally an invariant that gets caught. It's the same\n // behavior as without this statement except with a better message.\n if (typeof typeSpecs[typeSpecName] !== 'function') {\n // eslint-disable-next-line react-internal/prod-error-codes\n var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');\n err.name = 'Invariant Violation';\n throw err;\n }\n\n error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');\n } catch (ex) {\n error$1 = ex;\n }\n\n if (error$1 && !(error$1 instanceof Error)) {\n setCurrentlyValidatingElement(element);\n\n error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);\n\n setCurrentlyValidatingElement(null);\n }\n\n if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {\n // Only monitor this failure once because there tends to be a lot of the\n // same error.\n loggedTypeFailures[error$1.message] = true;\n setCurrentlyValidatingElement(element);\n\n error('Failed %s type: %s', location, error$1.message);\n\n setCurrentlyValidatingElement(null);\n }\n }\n }\n }\n}\n\nvar isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare\n\nfunction isArray(a) {\n return isArrayImpl(a);\n}\n\n/*\n * The `'' + value` pattern (used in in perf-sensitive code) throws for Symbol\n * and Temporal.* types. See https://github.com/facebook/react/pull/22064.\n *\n * The functions in this module will throw an easier-to-understand,\n * easier-to-debug exception with a clear errors message message explaining the\n * problem. (Instead of a confusing exception thrown inside the implementation\n * of the `value` object).\n */\n// $FlowFixMe only called in DEV, so void return is not possible.\nfunction typeName(value) {\n {\n // toStringTag is needed for namespaced types like Temporal.Instant\n var hasToStringTag = typeof Symbol === 'function' && Symbol.toStringTag;\n var type = hasToStringTag && value[Symbol.toStringTag] || value.constructor.name || 'Object';\n return type;\n }\n} // $FlowFixMe only called in DEV, so void return is not possible.\n\n\nfunction willCoercionThrow(value) {\n {\n try {\n testStringCoercion(value);\n return false;\n } catch (e) {\n return true;\n }\n }\n}\n\nfunction testStringCoercion(value) {\n // If you ended up here by following an exception call stack, here's what's\n // happened: you supplied an object or symbol value to React (as a prop, key,\n // DOM attribute, CSS property, string ref, etc.) and when React tried to\n // coerce it to a string using `'' + value`, an exception was thrown.\n //\n // The most common types that will cause this exception are `Symbol` instances\n // and Temporal objects like `Temporal.Instant`. But any object that has a\n // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this\n // exception. (Library authors do this to prevent users from using built-in\n // numeric operators like `+` or comparison operators like `>=` because custom\n // methods are needed to perform accurate arithmetic or comparison.)\n //\n // To fix the problem, coerce this object or symbol value to a string before\n // passing it to React. The most reliable way is usually `String(value)`.\n //\n // To find which value is throwing, check the browser or debugger console.\n // Before this exception was thrown, there should be `console.error` output\n // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the\n // problem and how that type was used: key, atrribute, input value prop, etc.\n // In most cases, this console output also shows the component and its\n // ancestor components where the exception happened.\n //\n // eslint-disable-next-line react-internal/safe-string-coercion\n return '' + value;\n}\nfunction checkKeyStringCoercion(value) {\n {\n if (willCoercionThrow(value)) {\n error('The provided key is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', typeName(value));\n\n return testStringCoercion(value); // throw (to help callers find troubleshooting comments)\n }\n }\n}\n\nvar ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;\nvar RESERVED_PROPS = {\n key: true,\n ref: true,\n __self: true,\n __source: true\n};\nvar specialPropKeyWarningShown;\nvar specialPropRefWarningShown;\nvar didWarnAboutStringRefs;\n\n{\n didWarnAboutStringRefs = {};\n}\n\nfunction hasValidRef(config) {\n {\n if (hasOwnProperty.call(config, 'ref')) {\n var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n\n if (getter && getter.isReactWarning) {\n return false;\n }\n }\n }\n\n return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n {\n if (hasOwnProperty.call(config, 'key')) {\n var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n\n if (getter && getter.isReactWarning) {\n return false;\n }\n }\n }\n\n return config.key !== undefined;\n}\n\nfunction warnIfStringRefCannotBeAutoConverted(config, self) {\n {\n if (typeof config.ref === 'string' && ReactCurrentOwner.current && self && ReactCurrentOwner.current.stateNode !== self) {\n var componentName = getComponentNameFromType(ReactCurrentOwner.current.type);\n\n if (!didWarnAboutStringRefs[componentName]) {\n error('Component \"%s\" contains the string ref \"%s\". ' + 'Support for string refs will be removed in a future major release. ' + 'This case cannot be automatically converted to an arrow function. ' + 'We ask you to manually fix this case by using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref', getComponentNameFromType(ReactCurrentOwner.current.type), config.ref);\n\n didWarnAboutStringRefs[componentName] = true;\n }\n }\n }\n}\n\nfunction defineKeyPropWarningGetter(props, displayName) {\n {\n var warnAboutAccessingKey = function () {\n if (!specialPropKeyWarningShown) {\n specialPropKeyWarningShown = true;\n\n error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n }\n };\n\n warnAboutAccessingKey.isReactWarning = true;\n Object.defineProperty(props, 'key', {\n get: warnAboutAccessingKey,\n configurable: true\n });\n }\n}\n\nfunction defineRefPropWarningGetter(props, displayName) {\n {\n var warnAboutAccessingRef = function () {\n if (!specialPropRefWarningShown) {\n specialPropRefWarningShown = true;\n\n error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n }\n };\n\n warnAboutAccessingRef.isReactWarning = true;\n Object.defineProperty(props, 'ref', {\n get: warnAboutAccessingRef,\n configurable: true\n });\n }\n}\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, instanceof check\n * will not work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} props\n * @param {*} key\n * @param {string|object} ref\n * @param {*} owner\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @internal\n */\n\n\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n var element = {\n // This tag allows us to uniquely identify this as a React Element\n $$typeof: REACT_ELEMENT_TYPE,\n // Built-in properties that belong on the element\n type: type,\n key: key,\n ref: ref,\n props: props,\n // Record the component responsible for creating this element.\n _owner: owner\n };\n\n {\n // The validation flag is currently mutative. We put it on\n // an external backing store so that we can freeze the whole object.\n // This can be replaced with a WeakMap once they are implemented in\n // commonly used development environments.\n element._store = {}; // To make comparing ReactElements easier for testing purposes, we make\n // the validation flag non-enumerable (where possible, which should\n // include every environment we run tests in), so the test framework\n // ignores it.\n\n Object.defineProperty(element._store, 'validated', {\n configurable: false,\n enumerable: false,\n writable: true,\n value: false\n }); // self and source are DEV only properties.\n\n Object.defineProperty(element, '_self', {\n configurable: false,\n enumerable: false,\n writable: false,\n value: self\n }); // Two elements created in two different places should be considered\n // equal for testing purposes and therefore we hide it from enumeration.\n\n Object.defineProperty(element, '_source', {\n configurable: false,\n enumerable: false,\n writable: false,\n value: source\n });\n\n if (Object.freeze) {\n Object.freeze(element.props);\n Object.freeze(element);\n }\n }\n\n return element;\n};\n/**\n * https://github.com/reactjs/rfcs/pull/107\n * @param {*} type\n * @param {object} props\n * @param {string} key\n */\n\nfunction jsxDEV(type, config, maybeKey, source, self) {\n {\n var propName; // Reserved names are extracted\n\n var props = {};\n var key = null;\n var ref = null; // Currently, key can be spread in as a prop. This causes a potential\n // issue if key is also explicitly declared (ie. <div {...props} key=\"Hi\" />\n // or <div key=\"Hi\" {...props} /> ). We want to deprecate key spread,\n // but as an intermediary step, we will use jsxDEV for everything except\n // <div {...props} key=\"Hi\" />, because we aren't currently able to tell if\n // key is explicitly declared to be undefined or not.\n\n if (maybeKey !== undefined) {\n {\n checkKeyStringCoercion(maybeKey);\n }\n\n key = '' + maybeKey;\n }\n\n if (hasValidKey(config)) {\n {\n checkKeyStringCoercion(config.key);\n }\n\n key = '' + config.key;\n }\n\n if (hasValidRef(config)) {\n ref = config.ref;\n warnIfStringRefCannotBeAutoConverted(config, self);\n } // Remaining properties are added to a new props object\n\n\n for (propName in config) {\n if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n props[propName] = config[propName];\n }\n } // Resolve default props\n\n\n if (type && type.defaultProps) {\n var defaultProps = type.defaultProps;\n\n for (propName in defaultProps) {\n if (props[propName] === undefined) {\n props[propName] = defaultProps[propName];\n }\n }\n }\n\n if (key || ref) {\n var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n if (key) {\n defineKeyPropWarningGetter(props, displayName);\n }\n\n if (ref) {\n defineRefPropWarningGetter(props, displayName);\n }\n }\n\n return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n }\n}\n\nvar ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner;\nvar ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame;\n\nfunction setCurrentlyValidatingElement$1(element) {\n {\n if (element) {\n var owner = element._owner;\n var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);\n ReactDebugCurrentFrame$1.setExtraStackFrame(stack);\n } else {\n ReactDebugCurrentFrame$1.setExtraStackFrame(null);\n }\n }\n}\n\nvar propTypesMisspellWarningShown;\n\n{\n propTypesMisspellWarningShown = false;\n}\n/**\n * Verifies the object is a ReactElement.\n * See https://reactjs.org/docs/react-api.html#isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a ReactElement.\n * @final\n */\n\n\nfunction isValidElement(object) {\n {\n return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n }\n}\n\nfunction getDeclarationErrorAddendum() {\n {\n if (ReactCurrentOwner$1.current) {\n var name = getComponentNameFromType(ReactCurrentOwner$1.current.type);\n\n if (name) {\n return '\\n\\nCheck the render method of `' + name + '`.';\n }\n }\n\n return '';\n }\n}\n\nfunction getSourceInfoErrorAddendum(source) {\n {\n if (source !== undefined) {\n var fileName = source.fileName.replace(/^.*[\\\\\\/]/, '');\n var lineNumber = source.lineNumber;\n return '\\n\\nCheck your code at ' + fileName + ':' + lineNumber + '.';\n }\n\n return '';\n }\n}\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\n\n\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n {\n var info = getDeclarationErrorAddendum();\n\n if (!info) {\n var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n\n if (parentName) {\n info = \"\\n\\nCheck the top-level render call using <\" + parentName + \">.\";\n }\n }\n\n return info;\n }\n}\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\n\n\nfunction validateExplicitKey(element, parentType) {\n {\n if (!element._store || element._store.validated || element.key != null) {\n return;\n }\n\n element._store.validated = true;\n var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n\n if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {\n return;\n }\n\n ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a\n // property, it may be the creator of the child that's responsible for\n // assigning it a key.\n\n var childOwner = '';\n\n if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) {\n // Give the component that originally created this child.\n childOwner = \" It was passed a child from \" + getComponentNameFromType(element._owner.type) + \".\";\n }\n\n setCurrentlyValidatingElement$1(element);\n\n error('Each child in a list should have a unique \"key\" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner);\n\n setCurrentlyValidatingElement$1(null);\n }\n}\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\n\n\nfunction validateChildKeys(node, parentType) {\n {\n if (typeof node !== 'object') {\n return;\n }\n\n if (isArray(node)) {\n for (var i = 0; i < node.length; i++) {\n var child = node[i];\n\n if (isValidElement(child)) {\n validateExplicitKey(child, parentType);\n }\n }\n } else if (isValidElement(node)) {\n // This element was passed in a valid location.\n if (node._store) {\n node._store.validated = true;\n }\n } else if (node) {\n var iteratorFn = getIteratorFn(node);\n\n if (typeof iteratorFn === 'function') {\n // Entry iterators used to provide implicit keys,\n // but now we print a separate warning for them later.\n if (iteratorFn !== node.entries) {\n var iterator = iteratorFn.call(node);\n var step;\n\n while (!(step = iterator.next()).done) {\n if (isValidElement(step.value)) {\n validateExplicitKey(step.value, parentType);\n }\n }\n }\n }\n }\n }\n}\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\n\n\nfunction validatePropTypes(element) {\n {\n var type = element.type;\n\n if (type === null || type === undefined || typeof type === 'string') {\n return;\n }\n\n var propTypes;\n\n if (typeof type === 'function') {\n propTypes = type.propTypes;\n } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.\n // Inner props are checked in the reconciler.\n type.$$typeof === REACT_MEMO_TYPE)) {\n propTypes = type.propTypes;\n } else {\n return;\n }\n\n if (propTypes) {\n // Intentionally inside to avoid triggering lazy initializers:\n var name = getComponentNameFromType(type);\n checkPropTypes(propTypes, element.props, 'prop', name, element);\n } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {\n propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers:\n\n var _name = getComponentNameFromType(type);\n\n error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown');\n }\n\n if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {\n error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');\n }\n }\n}\n/**\n * Given a fragment, validate that it can only be provided with fragment props\n * @param {ReactElement} fragment\n */\n\n\nfunction validateFragmentProps(fragment) {\n {\n var keys = Object.keys(fragment.props);\n\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n\n if (key !== 'children' && key !== 'key') {\n setCurrentlyValidatingElement$1(fragment);\n\n error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);\n\n setCurrentlyValidatingElement$1(null);\n break;\n }\n }\n\n if (fragment.ref !== null) {\n setCurrentlyValidatingElement$1(fragment);\n\n error('Invalid attribute `ref` supplied to `React.Fragment`.');\n\n setCurrentlyValidatingElement$1(null);\n }\n }\n}\n\nvar didWarnAboutKeySpread = {};\nfunction jsxWithValidation(type, props, key, isStaticChildren, source, self) {\n {\n var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to\n // succeed and there will likely be errors in render.\n\n if (!validType) {\n var info = '';\n\n if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {\n info += ' You likely forgot to export your component from the file ' + \"it's defined in, or you might have mixed up default and named imports.\";\n }\n\n var sourceInfo = getSourceInfoErrorAddendum(source);\n\n if (sourceInfo) {\n info += sourceInfo;\n } else {\n info += getDeclarationErrorAddendum();\n }\n\n var typeString;\n\n if (type === null) {\n typeString = 'null';\n } else if (isArray(type)) {\n typeString = 'array';\n } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {\n typeString = \"<\" + (getComponentNameFromType(type.type) || 'Unknown') + \" />\";\n info = ' Did you accidentally export a JSX literal instead of a component?';\n } else {\n typeString = typeof type;\n }\n\n error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);\n }\n\n var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used.\n // TODO: Drop this when these are no longer allowed as the type argument.\n\n if (element == null) {\n return element;\n } // Skip key warning if the type isn't valid since our key validation logic\n // doesn't expect a non-string/function type and can throw confusing errors.\n // We don't want exception behavior to differ between dev and prod.\n // (Rendering will throw with a helpful message and as soon as the type is\n // fixed, the key warnings will appear.)\n\n\n if (validType) {\n var children = props.children;\n\n if (children !== undefined) {\n if (isStaticChildren) {\n if (isArray(children)) {\n for (var i = 0; i < children.length; i++) {\n validateChildKeys(children[i], type);\n }\n\n if (Object.freeze) {\n Object.freeze(children);\n }\n } else {\n error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.');\n }\n } else {\n validateChildKeys(children, type);\n }\n }\n }\n\n {\n if (hasOwnProperty.call(props, 'key')) {\n var componentName = getComponentNameFromType(type);\n var keys = Object.keys(props).filter(function (k) {\n return k !== 'key';\n });\n var beforeExample = keys.length > 0 ? '{key: someKey, ' + keys.join(': ..., ') + ': ...}' : '{key: someKey}';\n\n if (!didWarnAboutKeySpread[componentName + beforeExample]) {\n var afterExample = keys.length > 0 ? '{' + keys.join(': ..., ') + ': ...}' : '{}';\n\n error('A props object containing a \"key\" prop is being spread into JSX:\\n' + ' let props = %s;\\n' + ' <%s {...props} />\\n' + 'React keys must be passed directly to JSX without using spread:\\n' + ' let props = %s;\\n' + ' <%s key={someKey} {...props} />', beforeExample, componentName, afterExample, componentName);\n\n didWarnAboutKeySpread[componentName + beforeExample] = true;\n }\n }\n }\n\n if (type === REACT_FRAGMENT_TYPE) {\n validateFragmentProps(element);\n } else {\n validatePropTypes(element);\n }\n\n return element;\n }\n} // These two functions exist to still get child warnings in dev\n// even with the prod transform. This means that jsxDEV is purely\n// opt-in behavior for better messages but that we won't stop\n// giving you warnings if you use production apis.\n\nfunction jsxWithValidationStatic(type, props, key) {\n {\n return jsxWithValidation(type, props, key, true);\n }\n}\nfunction jsxWithValidationDynamic(type, props, key) {\n {\n return jsxWithValidation(type, props, key, false);\n }\n}\n\nvar jsx = jsxWithValidationDynamic ; // we may want to special case jsxs internally to take advantage of static children.\n// for now we can ship identical prod functions\n\nvar jsxs = jsxWithValidationStatic ;\n\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsx;\nexports.jsxs = jsxs;\n })();\n}\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.min.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","'use strict';\n\nvar m = require('react-dom');\nif (process.env.NODE_ENV === 'production') {\n exports.createRoot = m.createRoot;\n exports.hydrateRoot = m.hydrateRoot;\n} else {\n var i = m.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n exports.createRoot = function(c, o) {\n i.usingClientEntryPoint = true;\n try {\n return m.createRoot(c, o);\n } finally {\n i.usingClientEntryPoint = false;\n }\n };\n exports.hydrateRoot = function(c, h, o) {\n i.usingClientEntryPoint = true;\n try {\n return m.hydrateRoot(c, h, o);\n } finally {\n i.usingClientEntryPoint = false;\n }\n };\n}\n","import { AudioSettings } from \"@/stores/slices/audioSettingsSlice\";\n\nexport const GAME_CONFIG = {\n CANVAS_WIDTH: 800,\n CANVAS_HEIGHT: 600,\n PLAYER_HEIGHT: 35,\n PLAYER_WIDTH: 25,\n BOMB_SIZE: 25,\n MONSTER_SIZE: 25,\n PLATFORM_HEIGHT: 25,\n COIN_SIZE: 25, // Size of coins\n USE_SPRITES: true,\n PARALLAX_ENABLED: true, // Re-enabled parallax with fixed implementation\n\n // Physics - Reduced for moon-like gravity\n GRAVITY: 0.3,\n FLOAT_GRAVITY: 0.005, // Reduced from 0.1 for much slower floating fall\n MOVE_SPEED: 4,\n JUMP_POWER: 8,\n SUPER_JUMP_POWER: 12,\n\n // Coin physics\n COIN_BOUNCE_SPEED: 3, // Initial speed when coin bounces\n COIN_BOUNCE_DAMPING: 0.8, // How much the coin slows down on bounce\n COIN_GRAVITY: 0.1, // Gravity affecting coins (reduced from 0.2)\n\n // Jump mechanics\n MIN_JUMP_DURATION: 50, // Minimum time for a jump (ms)\n MAX_JUMP_DURATION: 300, // Maximum time for variable jump height (ms)\n\n // Game rules\n TOTAL_BOMBS: 23,\n STARTING_LIVES: 3,\n\n // Coin spawning rules\n POWER_COIN_SPAWN_INTERVAL: 9, // Power coin appears after every 9 firebombs\n BONUS_COIN_SPAWN_INTERVAL: 5000, // Bonus multiplier coin appears every 5000 points\n EXTRA_LIFE_COIN_RATIO: 10, // Extra life coin appears for every 10 bonus multiplier coins\n\n // Coin effects\n POWER_COIN_DURATION: 7000, // Power coin effect duration in milliseconds (7 seconds)\n POWER_COIN_POINTS: 2000, // Points awarded for collecting power coin\n MONSTER_KILL_POINTS: 100, // Points for killing monsters during power mode\n\n // Coin base points\n BONUS_MULTIPLIER_COIN_POINTS: 1000, // Base points for bonus multiplier coin\n EXTRA_LIFE_COIN_POINTS: 1000, // Base points for extra life coin\n\n // Multiplier system - incremental thresholds\n MULTIPLIER_THRESHOLDS: {\n 1: 0, // 1x multiplier (default)\n 2: 1800, // 2x multiplier (1800 points needed)\n 3: 3600, // 3x multiplier (1800 more points needed = 3600 total)\n 4: 5400, // 4x multiplier (1800 more points needed = 5400 total)\n 5: 7200, // 5x multiplier (1800 more points needed = 7200 total)\n },\n MAX_MULTIPLIER: 5,\n\n // Scoring\n BOMB_POINTS: {\n NORMAL: 100, // Normal bomb base points\n FIREBOMB: 200, // Firebomb (next correct bomb) base points\n },\n\n // Bonus points\n BONUS_POINTS: {\n 23: 50000,\n 22: 30000,\n 21: 20000,\n 20: 10000,\n },\n};\n\nexport const DEFAULT_AUDIO_SETTINGS: AudioSettings = {\n masterVolume: 80,\n musicVolume: 70,\n sfxVolume: 90,\n masterMuted: false,\n musicMuted: false,\n sfxMuted: false,\n};\n\n// Development Mode Configuration\nexport const DEV_CONFIG = {\n ENABLED: false, // Set to false to disable dev mode\n TARGET_STATE: \"PLAYING\", // Options: 'START_MENU', 'COUNTDOWN', 'PLAYING', 'PAUSED', 'SETTINGS', 'BONUS', 'VICTORY', 'GAME_OVER'\n TARGET_LEVEL: 6, // Which level to load in dev mode (1-7, corresponds to mapDefinitions index + 1)\n\n GOD_MODE: false, // Set to true to enable god mode (player is invincible to monsters)\n\n MOCK_DATA: {\n score: 15000,\n lives: 2,\n currentLevel: 2,\n correctOrderCount: 18,\n multiplier: 2, // Mock multiplier level (1-5)\n multiplierScore: 2600, // Mock points toward next multiplier (0-1800)\n },\n};\n\n// Set global dev logging flag\nif (typeof window !== \"undefined\") {\n (window as any).__DEV_LOGGING_ENABLED__ = DEV_CONFIG.ENABLED;\n}\n\nexport const COLORS = {\n PLAYER: \"#00FF00\",\n BOMB: \"#FFD700\",\n BOMB_COLLECTED: \"#666666\",\n BOMB_NEXT: \"#FF0000\",\n MONSTER: \"#FF4444\", // Default monster color (fallback)\n MONSTER_FROZEN: \"#4444FF\", // Blue color for frozen monsters\n\n // Unique monster type colors\n MONSTER_HORIZONTAL_PATROL: \"#FF4444\", // Red - horizontal patrol\n MONSTER_VERTICAL_PATROL: \"#44FF44\", // Green - vertical patrol\n MONSTER_CHASER: \"#FF8844\", // Orange - chaser\n MONSTER_AMBUSHER: \"#8844FF\", // Purple - ambusher\n MONSTER_FLOATER: \"#44FFFF\", // Cyan - floater\n\n PLATFORM: \"#484744\",\n BACKGROUND: \"#262521\",\n GROUND: \"#484744\",\n UI_PRIMARY: \"#00FFFF\",\n UI_SECONDARY: \"#FFFFFF\",\n COIN_POWER: \"#0066FF\", // Blue for power coin\n COIN_BONUS: \"#FF6600\", // Orange for bonus multiplier coin\n COIN_LIFE: \"#FF0066\", // Pink for extra life coin\n};\n","import { StateCreator } from 'zustand';\nimport { Player } from '../../types/interfaces';\nimport { GAME_CONFIG, COLORS } from '../../types/constants';\n\nexport interface PlayerSlice {\n player: Player;\n updatePlayer: (player: Partial<Player>) => void;\n resetPlayer: () => void;\n setPlayerPosition: (x: number, y: number) => void;\n}\n\nconst createInitialPlayer = (): Player => ({\n x: GAME_CONFIG.CANVAS_WIDTH / 2,\n y: GAME_CONFIG.CANVAS_HEIGHT - 100,\n width: GAME_CONFIG.PLAYER_WIDTH,\n height: GAME_CONFIG.PLAYER_HEIGHT,\n color: COLORS.PLAYER,\n velocityX: 0,\n velocityY: 0,\n isGrounded: false,\n isFloating: false,\n isJumping: false,\n jumpStartTime: 0,\n moveSpeed: GAME_CONFIG.MOVE_SPEED,\n jumpPower: GAME_CONFIG.JUMP_POWER,\n gravity: GAME_CONFIG.GRAVITY,\n floatGravity: GAME_CONFIG.FLOAT_GRAVITY\n});\n\nexport const createPlayerSlice: StateCreator<PlayerSlice> = (set, get) => ({\n player: createInitialPlayer(),\n \n updatePlayer: (playerUpdate: Partial<Player>) => {\n set({ player: { ...get().player, ...playerUpdate } });\n },\n \n resetPlayer: () => {\n set({ player: createInitialPlayer() });\n },\n \n setPlayerPosition: (x: number, y: number) => {\n set({ \n player: { \n ...get().player, \n x, \n y,\n velocityX: 0,\n velocityY: 0,\n isGrounded: false,\n isFloating: false,\n isJumping: false,\n jumpStartTime: 0\n } \n });\n }\n});","export enum GameState {\n MENU = 'MENU',\n COUNTDOWN = 'COUNTDOWN',\n PLAYING = 'PLAYING',\n PAUSED = 'PAUSED',\n BONUS = 'BONUS',\n VICTORY = 'VICTORY',\n GAME_OVER = 'GAME_OVER',\n MAP_CLEARED = 'MAP_CLEARED'\n }\n \n export enum MenuType {\n START = 'START',\n COUNTDOWN = 'COUNTDOWN',\n IN_GAME = 'IN_GAME',\n PAUSE = 'PAUSE',\n SETTINGS = 'SETTINGS',\n BONUS = 'BONUS',\n VICTORY = 'VICTORY',\n GAME_OVER = 'GAME_OVER',\n AUDIO_SETTINGS = 'AUDIO_SETTINGS'\n }\n \n export enum MonsterType {\n HORIZONTAL_PATROL = 'HORIZONTAL_PATROL',\n VERTICAL_PATROL = 'VERTICAL_PATROL',\n CHASER = 'CHASER',\n AMBUSHER = 'AMBUSHER',\n FLOATER = 'FLOATER'\n}\n \n export enum CoinType {\n POWER = 'POWER',\n BONUS_MULTIPLIER = 'BONUS_MULTIPLIER',\n EXTRA_LIFE = 'EXTRA_LIFE',\n MONSTER_FREEZE = 'MONSTER_FREEZE'\n }\n \n export enum AudioEvent {\n GAME_START = 'GAME_START',\n LEVEL_COMPLETE = 'LEVEL_COMPLETE',\n PLAYER_DEATH = 'PLAYER_DEATH',\n GAME_OVER = 'GAME_OVER',\n BONUS_SCREEN = 'BONUS_SCREEN',\n BOMB_COLLECT = 'BOMB_COLLECT',\n MAP_CLEARED = 'MAP_CLEARED',\n BACKGROUND_MUSIC = 'BACKGROUND_MUSIC',\n MONSTER_HIT = 'MONSTER_HIT',\n COIN_COLLECT = 'COIN_COLLECT',\n POWER_COIN_ACTIVATE = 'POWER_COIN_ACTIVATE'\n }\n \n export enum CollisionType {\n PLATFORM = 'PLATFORM',\n BOMB = 'BOMB',\n MONSTER = 'MONSTER',\n BOUNDARY = 'BOUNDARY',\n COIN = 'COIN'\n }\n ","// Logging utility for the game\n// Can be controlled via environment variables or dev mode\n\nexport enum LogLevel {\n ERROR = 0,\n WARN = 1,\n INFO = 2,\n DEBUG = 3,\n TRACE = 4,\n DATAPASSING = 5, // New level for data passing only\n}\n\ninterface LogConfig {\n level: LogLevel;\n enableConsole: boolean;\n enableDevMode: boolean;\n}\n\nexport class Logger {\n private logLevel: LogLevel = LogLevel.INFO;\n private lastLogTime: Map<string, number> = new Map();\n private logThrottle: Map<string, number> = new Map();\n\n constructor(level: LogLevel = LogLevel.INFO) {\n // Read log level from environment variable\n const envLogLevel = import.meta.env?.VITE_LOG_LEVEL;\n if (envLogLevel) {\n switch (envLogLevel.toLowerCase()) {\n case 'error':\n this.logLevel = LogLevel.ERROR;\n break;\n case 'warn':\n this.logLevel = LogLevel.WARN;\n break;\n case 'info':\n this.logLevel = LogLevel.INFO;\n break;\n case 'debug':\n this.logLevel = LogLevel.DEBUG;\n break;\n case 'trace':\n this.logLevel = LogLevel.TRACE;\n break;\n case 'datapassing':\n this.logLevel = LogLevel.DATAPASSING;\n break;\n default:\n this.logLevel = level;\n }\n } else {\n this.logLevel = level;\n }\n }\n\n setLogLevel(level: LogLevel): void {\n this.logLevel = level;\n }\n\n // Throttled logging - only log once per specified interval\n private shouldLog(key: string, throttleMs: number = 1000): boolean {\n const now = Date.now();\n const lastTime = this.lastLogTime.get(key) || 0;\n \n if (now - lastTime >= throttleMs) {\n this.lastLogTime.set(key, now);\n return true;\n }\n return false;\n }\n\n // Game state events (important events that should always be logged)\n game(message: string, ...args: any[]): void {\n if (this.logLevel === LogLevel.INFO || this.logLevel === LogLevel.DEBUG || this.logLevel === LogLevel.TRACE) {\n console.log(`🎮 ${message}`, ...args);\n }\n }\n\n // Game flow events (level start, completion, etc.)\n flow(message: string, ...args: any[]): void {\n if (this.logLevel === LogLevel.INFO || this.logLevel === LogLevel.DEBUG || this.logLevel === LogLevel.TRACE) {\n console.log(`🌊 ${message}`, ...args);\n }\n }\n\n // Player actions (collecting items, dying, etc.)\n player(message: string, ...args: any[]): void {\n if (this.logLevel === LogLevel.INFO || this.logLevel === LogLevel.DEBUG || this.logLevel === LogLevel.TRACE) {\n console.log(`👤 ${message}`, ...args);\n }\n }\n\n // Monster events (spawning, dying, behavior changes)\n monster(message: string, ...args: any[]): void {\n if (this.logLevel === LogLevel.INFO || this.logLevel === LogLevel.DEBUG || this.logLevel === LogLevel.TRACE) {\n console.log(`👹 ${message}`, ...args);\n }\n }\n\n // Coin events (spawning, collecting)\n coin(message: string, ...args: any[]): void {\n if (this.logLevel === LogLevel.INFO || this.logLevel === LogLevel.DEBUG || this.logLevel === LogLevel.TRACE) {\n console.log(`🪙 ${message}`, ...args);\n }\n }\n\n // Bomb events (collecting, completing)\n bomb(message: string, ...args: any[]): void {\n if (this.logLevel === LogLevel.INFO || this.logLevel === LogLevel.DEBUG || this.logLevel === LogLevel.TRACE) {\n console.log(`💣 ${message}`, ...args);\n }\n }\n\n // Power mode events\n power(message: string, ...args: any[]): void {\n if (this.logLevel === LogLevel.INFO || this.logLevel === LogLevel.DEBUG || this.logLevel === LogLevel.TRACE) {\n console.log(`⚡ ${message}`, ...args);\n }\n }\n\n // Data passing events (data sent to external website)\n dataPassing(message: string, ...args: any[]): void {\n if (this.logLevel === LogLevel.DATAPASSING) {\n console.log(`📡 ${message}`, ...args);\n }\n }\n\n // Pause/resume events (throttled to avoid spam)\n pause(message: string, ...args: any[]): void {\n if (this.logLevel === LogLevel.INFO || this.logLevel === LogLevel.DEBUG || this.logLevel === LogLevel.TRACE) {\n const key = 'pause';\n if (this.shouldLog(key, 500)) { // Only log pause events every 500ms\n console.log(`⏸️ ${message}`, ...args);\n }\n }\n }\n\n // Scaling events (throttled to avoid spam)\n scaling(message: string, ...args: any[]): void {\n if (this.logLevel === LogLevel.INFO || this.logLevel === LogLevel.DEBUG || this.logLevel === LogLevel.TRACE) {\n const key = 'scaling';\n if (this.shouldLog(key, 2000)) { // Only log scaling events every 2 seconds\n console.log(`📈 ${message}`, ...args);\n }\n }\n }\n\n // Debug info (only when debug level is enabled)\n debug(message: string, ...args: any[]): void {\n if (this.logLevel === LogLevel.DEBUG || this.logLevel === LogLevel.TRACE) {\n console.log(`🔧 ${message}`, ...args);\n }\n }\n\n // Audio events\n audio(message: string, ...args: any[]): void {\n if (this.logLevel === LogLevel.INFO || this.logLevel === LogLevel.DEBUG || this.logLevel === LogLevel.TRACE) {\n console.log(`🎵 ${message}`, ...args);\n }\n }\n\n // Error events\n error(message: string, ...args: any[]): void {\n if (this.logLevel >= LogLevel.ERROR) {\n console.error(`❌ ${message}`, ...args);\n }\n }\n\n // Warning events\n warn(message: string, ...args: any[]): void {\n if (this.logLevel >= LogLevel.WARN) {\n console.warn(`⚠️ ${message}`, ...args);\n }\n }\n\n // Info events\n info(message: string, ...args: any[]): void {\n if (this.logLevel === LogLevel.INFO || this.logLevel === LogLevel.DEBUG || this.logLevel === LogLevel.TRACE) {\n console.log(`ℹ️ ${message}`, ...args);\n }\n }\n\n // Trace events (only when trace level is enabled)\n trace(message: string, ...args: any[]): void {\n if (this.logLevel === LogLevel.TRACE) {\n console.log(`🔍 ${message}`, ...args);\n }\n }\n\n // Dev mode events (only when DEV_CONFIG.ENABLED is true)\n dev(message: string, ...args: any[]): void {\n // Only log dev messages when explicitly enabled\n // This prevents spam when DEV_CONFIG.ENABLED is false\n if (import.meta.env?.DEV && (window as any).__DEV_LOGGING_ENABLED__) {\n console.log(`🔧 ${message}`, ...args);\n }\n }\n\n // Score events\n score(message: string, ...args: any[]): void {\n if (this.logLevel === LogLevel.INFO || this.logLevel === LogLevel.DEBUG || this.logLevel === LogLevel.TRACE) {\n console.log(`📊 ${message}`, ...args);\n }\n }\n\n // Clear throttled log timestamps\n clearThrottle(): void {\n this.lastLogTime.clear();\n }\n\n // Method to disable all logging\n disable(): void {\n this.logLevel = LogLevel.ERROR;\n }\n\n // Method to enable logging\n enable(): void {\n this.logLevel = LogLevel.INFO;\n }\n\n // Method to set log level\n setLevel(level: LogLevel): void {\n this.logLevel = level;\n }\n}\n\n// Export singleton instance\nexport const logger = new Logger();\n\n// Export convenience methods\nexport const log = {\n error: (message: string, ...args: unknown[]) =>\n logger.error(message, ...args),\n warn: (message: string, ...args: unknown[]) => logger.warn(message, ...args),\n info: (message: string, ...args: unknown[]) => logger.info(message, ...args),\n debug: (message: string, ...args: unknown[]) =>\n logger.debug(message, ...args),\n trace: (message: string, ...args: unknown[]) =>\n logger.trace(message, ...args),\n game: (message: string, ...args: unknown[]) => logger.game(message, ...args),\n dev: (message: string, ...args: unknown[]) => logger.dev(message, ...args),\n audio: (message: string, ...args: unknown[]) =>\n logger.audio(message, ...args),\n coin: (message: string, ...args: unknown[]) => logger.coin(message, ...args),\n bomb: (message: string, ...args: unknown[]) => logger.bomb(message, ...args),\n score: (message: string, ...args: unknown[]) =>\n logger.score(message, ...args),\n dataPassing: (message: string, ...args: unknown[]) =>\n logger.dataPassing(message, ...args),\n};\n","import { log } from \"./logger\";\n\nexport interface MapCompletionData {\n mapName: string;\n level: number;\n correctOrderCount: number;\n totalBombs: number;\n score: number;\n bonus: number;\n hasBonus: boolean;\n timestamp: number;\n lives: number;\n multiplier: number;\n completionTime?: number; // Time taken to complete the map in milliseconds\n coinsCollected?: number; // Number of coins collected during the map\n powerModeActivations?: number; // Number of times power mode was activated\n}\n\nexport interface LevelHistoryEntry {\n level: number;\n mapName: string;\n score: number;\n bonus: number;\n completionTime: number;\n coinsCollected: number;\n powerModeActivations: number;\n timestamp: number;\n correctOrderCount: number;\n totalBombs: number;\n lives: number;\n multiplier: number;\n}\n\nexport interface GameCompletionData {\n finalScore: number;\n totalLevels: number;\n completedLevels: number;\n timestamp: number;\n lives: number;\n multiplier: number;\n levelHistory: LevelHistoryEntry[];\n totalCoinsCollected: number;\n totalPowerModeActivations: number;\n totalBombs: number;\n totalCorrectOrders: number;\n averageCompletionTime: number;\n gameEndReason: \"completed\" | \"failed\";\n sessionId: string;\n startTime: number;\n endTime: number;\n userDisplayName?: string;\n userEmail?: string;\n userId?: string;\n}\n\nexport const sendScoreToHost = (\n score: number,\n map: string,\n level?: number,\n lives?: number,\n multiplier?: number\n) => {\n const scoreData = {\n score,\n map,\n timestamp: Date.now(),\n level,\n lives,\n multiplier,\n };\n\n log.dataPassing(\"Sending score to host:\", scoreData);\n\n // Send current score update\n const scoreEvent = new CustomEvent(\"scoreUpdate\", {\n detail: { score },\n bubbles: true,\n composed: true,\n });\n window.dispatchEvent(scoreEvent);\n\n // Send detailed score data\n const detailedScoreEvent = new CustomEvent(\"game:score-updated\", {\n detail: scoreData,\n bubbles: true,\n composed: true,\n });\n window.dispatchEvent(detailedScoreEvent);\n};\n\nexport const sendGameReady = () => {\n log.dataPassing(\"Game ready signal sent to host\");\n const event = new CustomEvent(\"game:ready\", {\n detail: { timestamp: Date.now() },\n bubbles: true,\n composed: true,\n });\n window.dispatchEvent(event);\n};\n\nexport const sendGameStateUpdate = (state: string, map?: string) => {\n log.dataPassing(\"Game state update sent to host:\", { state, map });\n const event = new CustomEvent(\"game:state-updated\", {\n detail: { state, map, timestamp: Date.now() },\n bubbles: true,\n composed: true,\n });\n window.dispatchEvent(event);\n};\n\nexport const sendMapCompletionData = (data: MapCompletionData) => {\n log.dataPassing(\"Sending map completion data to host:\", data);\n const event = new CustomEvent(\"game:map-completed\", {\n detail: data,\n bubbles: true,\n composed: true,\n });\n window.dispatchEvent(event);\n};\n\nexport const sendGameCompletionData = (data: GameCompletionData) => {\n log.dataPassing(\"Sending game completion data to host:\", data);\n const event = new CustomEvent(\"game:completed\", {\n detail: data,\n bubbles: true,\n composed: true,\n });\n window.dispatchEvent(event);\n};\n\n// Helper function to calculate comprehensive game statistics\nexport const calculateGameStats = (\n levelHistory: LevelHistoryEntry[],\n finalScore: number,\n lives: number,\n multiplier: number,\n gameEndReason: \"completed\" | \"failed\",\n startTime: number,\n endTime: number\n) => {\n const totalBombs = levelHistory.reduce(\n (sum, level) => sum + level.totalBombs,\n 0\n );\n const totalCorrectOrders = levelHistory.reduce(\n (sum, level) => sum + level.correctOrderCount,\n 0\n );\n const totalCoinsCollected = levelHistory.reduce(\n (sum, level) => sum + level.coinsCollected,\n 0\n );\n const totalPowerModeActivations = levelHistory.reduce(\n (sum, level) => sum + level.powerModeActivations,\n 0\n );\n const totalPlayTime = endTime - startTime;\n const averageCompletionTime =\n levelHistory.length > 0 ? totalPlayTime / levelHistory.length / 1000 : 0; // Convert to seconds\n\n return {\n totalBombs,\n totalCorrectOrders,\n totalCoinsCollected,\n totalPowerModeActivations,\n averageCompletionTime: Math.round(averageCompletionTime),\n totalPlayTime: Math.round(totalPlayTime / 1000), // Convert to seconds\n };\n};\n\n// Declare global game interface for TypeScript\ndeclare global {\n interface Window {\n sigurdGame?: {\n sendScore: (score: number, map: string) => void;\n updateCurrentScore: (score: number) => void;\n _handleScoreUpdate: (score: number, map: string) => void;\n _updateCurrentScore: (score: number) => void;\n };\n }\n}\n","import { Monster } from \"../types/interfaces\";\nimport { GAME_CONFIG, COLORS } from \"../types/constants\";\nimport { MonsterType } from \"../types/enums\";\n\n/**\n * Monster Factory - Centralized monster creation functions\n * All monster creation logic is contained here for better organization\n */\n\n// Get the appropriate color for a monster type\nconst getMonsterColor = (type: MonsterType): string => {\n switch (type) {\n case MonsterType.HORIZONTAL_PATROL:\n return COLORS.MONSTER_HORIZONTAL_PATROL;\n case MonsterType.VERTICAL_PATROL:\n return COLORS.MONSTER_VERTICAL_PATROL;\n case MonsterType.CHASER:\n return COLORS.MONSTER_CHASER;\n case MonsterType.AMBUSHER:\n return COLORS.MONSTER_AMBUSHER;\n case MonsterType.FLOATER:\n return COLORS.MONSTER_FLOATER;\n default:\n return COLORS.MONSTER;\n }\n};\n\n// Base monster properties that all monsters share\nconst createBaseMonster = (\n x: number,\n y: number,\n type: MonsterType,\n speed: number = 1,\n spawnDelay: number = 0\n): Partial<Monster> => ({\n x,\n y,\n width: GAME_CONFIG.MONSTER_SIZE,\n height: GAME_CONFIG.MONSTER_SIZE,\n color: getMonsterColor(type),\n type,\n speed,\n direction: 1,\n isActive: true,\n spawnDelay,\n});\n\n/**\n * Creates a horizontal patrol monster that moves back and forth on a platform\n * @param platformX - X position of the platform\n * @param platformY - Y position of the platform \n * @param platformWidth - Width of the platform\n * @param spawnSide - Which side of the platform to spawn on (\"left\" or \"right\")\n * @param walkLengths - Number of walks before falling (legacy parameter, kept for compatibility)\n * @param speed - Movement speed\n * @param direction - Initial direction (optional, auto-determined by spawn side)\n * @param spawnDelay - When this monster should spawn (in milliseconds, optional)\n */\nexport const createHorizontalPatrolMonster = (\n platformX: number,\n platformY: number,\n platformWidth: number,\n spawnSide: \"left\" | \"right\" = \"left\",\n walkLengths: number = 1,\n speed: number = 1,\n direction?: number,\n spawnDelay: number = 0\n): Monster => {\n const x =\n spawnSide === \"left\"\n ? platformX\n : platformX + platformWidth - GAME_CONFIG.MONSTER_SIZE;\n const y = platformY - GAME_CONFIG.MONSTER_SIZE;\n const initialDirection = direction || (spawnSide === \"left\" ? 1 : -1);\n\n return {\n ...createBaseMonster(x, y, MonsterType.HORIZONTAL_PATROL, speed, spawnDelay),\n patrolStartX: platformX,\n patrolEndX: platformX + platformWidth,\n direction: initialDirection,\n walkLengths,\n } as Monster;\n};\n\n/**\n * Creates a vertical patrol monster that moves up and down along a vertical platform\n * @param platformX - X position of the vertical platform\n * @param startY - Starting Y position\n * @param patrolHeight - Height of the patrol area\n * @param side - Which side of the platform to patrol on (\"left\" or \"right\")\n * @param speed - Movement speed\n * @param direction - Initial direction (1 = down, -1 = up)\n * @param spawnDelay - When this monster should spawn (in milliseconds, optional)\n */\nexport const createVerticalPatrolMonster = (\n platformX: number,\n startY: number,\n patrolHeight: number,\n side: \"left\" | \"right\" = \"left\",\n speed: number = 1,\n direction: number = 1,\n spawnDelay: number = 0\n): Monster => {\n // Calculate monster X position based on side\n const x = side === \"left\" \n ? platformX - GAME_CONFIG.MONSTER_SIZE // Left side of platform\n : platformX + 15; // Right side of platform (15 is the standard wall thickness)\n\n return {\n ...createBaseMonster(x, startY, MonsterType.VERTICAL_PATROL, speed, spawnDelay),\n patrolStartY: startY,\n patrolEndY: startY + patrolHeight,\n direction,\n patrolSide: side, // Store which side to patrol on\n targetPlatformX: platformX, // Store the target platform X position\n } as Monster;\n};\n\n/**\n * Creates a floater monster that moves in straight lines and bounces off walls/platforms\n * @param startX - Starting X position\n * @param startY - Starting Y position\n * @param startAngle - Starting angle in degrees (0-360)\n * @param speed - Movement speed\n * @param spawnDelay - When this monster should spawn (in milliseconds, optional)\n */\nexport const createFloaterMonster = (\n startX: number,\n startY: number,\n startAngle: number = 45,\n speed: number = 1,\n spawnDelay: number = 0\n): Monster => {\n return {\n ...createBaseMonster(startX, startY, MonsterType.FLOATER, speed, spawnDelay),\n startAngle,\n spawnTime: Date.now(),\n } as Monster;\n};\n\n/**\n * Creates a chaser monster that follows the player\n * @param startX - Starting X position\n * @param startY - Starting Y position\n * @param speed - Movement speed\n * @param directness - How directly it follows the player (0.0-1.0)\n * @param updateInterval - How often to update the chase target (ms)\n * @param spawnDelay - When this monster should spawn (in milliseconds, optional)\n */\nexport const createChaserMonster = (\n startX: number,\n startY: number,\n speed: number = 0.8, // Reduced from 1\n directness: number = 0.2, // Reduced from 1\n updateInterval: number = 200, // Reduced from 500\n spawnDelay: number = 0\n): Monster => {\n return {\n ...createBaseMonster(startX, startY, MonsterType.CHASER, speed, spawnDelay),\n direction: 0, // Chaser doesn't use direction property\n directness,\n chaseUpdateInterval: updateInterval,\n } as Monster;\n};\n\n/**\n * Creates an ambusher monster that wanders freely and periodically ambushes\n * @param startX - Starting X position\n * @param startY - Starting Y position\n * @param speed - Movement speed\n * @param ambushInterval - Time between ambushes (ms)\n * @param spawnDelay - When this monster should spawn (in milliseconds, optional)\n */\nexport const createAmbusherMonster = (\n startX: number,\n startY: number,\n speed: number = 0.8, // Reduced from 1\n ambushInterval: number = 8000, // Increased from 5000\n spawnDelay: number = 0\n): Monster => {\n return {\n ...createBaseMonster(startX, startY, MonsterType.AMBUSHER, speed, spawnDelay),\n ambushCooldown: 0, // Initialize ambush cooldown\n } as Monster;\n};\n\n/**\n * Utility function to create a monster from a spawn point configuration\n * This is useful for dynamic monster spawning during gameplay\n */\nexport const createMonsterFromSpawnPoint = (spawnPoint: any): Monster => {\n const { x, y, type, speed = 1, ...config } = spawnPoint;\n\n switch (type) {\n case MonsterType.HORIZONTAL_PATROL:\n return createHorizontalPatrolMonster(\n config.patrolStartX || x,\n y + GAME_CONFIG.MONSTER_SIZE,\n (config.patrolEndX || x + 200) - (config.patrolStartX || x),\n config.spawnSide || \"left\",\n config.walkLengths || 1,\n speed\n );\n\n case MonsterType.VERTICAL_PATROL:\n return createVerticalPatrolMonster(\n x,\n config.patrolStartY || y,\n config.patrolHeight || 200,\n speed,\n config.direction || 1\n );\n\n case MonsterType.FLOATER:\n return createFloaterMonster(\n x,\n y,\n config.startAngle || 45,\n speed\n );\n\n case MonsterType.CHASER:\n return createChaserMonster(\n x,\n y,\n speed,\n config.directness || 0.3,\n config.updateInterval || 200\n );\n\n case MonsterType.AMBUSHER:\n return createAmbusherMonster(\n x,\n y,\n speed,\n config.ambushInterval || 8000\n );\n\n default:\n throw new Error(`Unknown monster type: ${type}`);\n }\n}; ","import { MapDefinition, Bomb, Platform } from \"../types/interfaces\";\nimport { GAME_CONFIG, COLORS } from \"../types/constants\";\nimport { MonsterType, CoinType } from \"../types/enums\";\nimport {\n createHorizontalPatrolMonster,\n createVerticalPatrolMonster,\n createFloaterMonster,\n createChaserMonster,\n createAmbusherMonster,\n} from \"../managers/MonsterFactory\";\n\n// Helper function to create bombs with default size\nconst createBomb = (\n x: number,\n y: number,\n order: number,\n group: number\n): Bomb => ({\n x,\n y,\n width: GAME_CONFIG.BOMB_SIZE,\n height: GAME_CONFIG.BOMB_SIZE,\n order,\n group,\n isCollected: false,\n isBlinking: false,\n});\n\n// Helper function to create platforms with default height and color\nconst createPlatform = (\n x: number,\n y: number,\n dimensions: { width: number; height: number },\n color: string = COLORS.PLATFORM,\n borderColor: string = \"#000\"\n) => ({\n x,\n y,\n width: dimensions.width,\n height: dimensions.height,\n borderColor,\n color,\n});\n\n// Helper function to create vertical platforms (walls)\nconst createVerticalPlatform = (\n x: number,\n y: number,\n height: number,\n color: string = COLORS.PLATFORM,\n borderColor: string = \"#000\"\n) => ({\n x,\n y,\n width: 15, // Standard wall thickness\n height,\n borderColor,\n color,\n isVertical: true, // Mark as vertical platform\n});\n\nconst centerX = (offsetWidth: number) =>\n (GAME_CONFIG.CANVAS_WIDTH - offsetWidth) / 2;\nconst centerY = (offsetHeight: number) =>\n (GAME_CONFIG.CANVAS_HEIGHT - offsetHeight) / 2;\n\nconst centerPoint = (offsetWidth: number, offsetHeight: number) => {\n return {\n x: centerX(offsetWidth),\n y: centerY(offsetHeight),\n };\n};\n\n// Level 1 - Startup Lab - Norge\nexport const level1Map: MapDefinition = {\n id: \"level1\",\n name: \"startup lab\",\n width: GAME_CONFIG.CANVAS_WIDTH,\n height: GAME_CONFIG.CANVAS_HEIGHT,\n playerStart: centerPoint(GAME_CONFIG.PLAYER_WIDTH, GAME_CONFIG.PLAYER_HEIGHT),\n spawnIndicatorColor: \"#00ffff\", // Cyan for light background\n\n groupSequence: [1, 2, 3, 4, 5],\n\n ground: {\n x: 0,\n y: GAME_CONFIG.CANVAS_HEIGHT - 40,\n width: GAME_CONFIG.CANVAS_WIDTH,\n height: 40,\n color: \"#88a2bc\",\n },\n\n platforms: [\n // bottom left\n createVerticalPlatform(96, 220, 150, \"#abccee\", \"#4f6a8f\"),\n createVerticalPlatform(684, 220, 150, \"#abccee\", \"#4f6a8f\"),\n\n // Top right\n createPlatform(95, 450, { width: 200, height: 15 }, \"#abccee\", \"#4f6a8f\"),\n createPlatform(480, 150, { width: 200, height: 15 }, \"#abccee\", \"#4f6a8f\"),\n\n createPlatform(430, 430, { width: 200, height: 15 }, \"#abccee\", \"#4f6a8f\"),\n createPlatform(170, 170, { width: 200, height: 15 }, \"#abccee\", \"#4f6a8f\"),\n ],\n\n bombs: [\n // Group 1\n createBomb(440, 400, 1, 1),\n createBomb(490, 400, 2, 1),\n createBomb(540, 400, 3, 1),\n createBomb(590, 400, 4, 1),\n\n // Group 2\n createBomb(180, 140, 5, 2),\n createBomb(230, 140, 6, 2),\n createBomb(280, 140, 7, 2),\n createBomb(330, 140, 8, 2),\n\n // Group 3\n createBomb(710, 230, 9, 3),\n createBomb(710, 280, 10, 3),\n createBomb(710, 330, 11, 3),\n\n // Group 4\n createBomb(130, 470, 12, 4),\n createBomb(180, 470, 13, 4),\n createBomb(230, 470, 14, 4),\n\n // Group 5\n createBomb(520, 70, 15, 5),\n createBomb(570, 70, 16, 5),\n createBomb(620, 70, 17, 5),\n\n // Group 6\n createBomb(120, 230, 18, 6),\n createBomb(120, 280, 19, 6),\n createBomb(120, 330, 20, 6),\n\n // Group 7\n createBomb(130, 420, 21, 7),\n createBomb(180, 420, 22, 7),\n createBomb(230, 420, 23, 7),\n ],\n\n coinSpawnPoints: [\n {\n x: centerX(GAME_CONFIG.COIN_SIZE),\n y: centerY(GAME_CONFIG.COIN_SIZE),\n type: CoinType.POWER,\n spawnAngle: 45,\n },\n {\n x: 570,\n y: 50,\n type: CoinType.POWER,\n spawnAngle: 135,\n },\n // {\n // x: centerX(GAME_CONFIG.COIN_SIZE),\n // y: 75,\n // type: CoinType.BONUS_MULTIPLIER,\n // },\n {\n x: 200,\n y: 75,\n type: CoinType.BONUS_MULTIPLIER,\n },\n {\n x: 200,\n y: 75,\n type: CoinType.BONUS_MULTIPLIER,\n },\n {\n x: 200,\n y: 75,\n type: CoinType.EXTRA_LIFE,\n },\n {\n x: 200,\n y: 75,\n type: CoinType.EXTRA_LIFE,\n },\n ],\n\n monsterSpawnPoints: [\n // // Test monster - spawns immediately\n {\n spawnDelay: 4000,\n createMonster: () =>\n createHorizontalPatrolMonster(\n 430, // platformX\n 430, // platformWidth\n 200,\n \"left\", // spawnSide\n 1, // walkLengths\n 1.0 // speed\n ),\n },\n // // Another test monster - spawns immediately at different location\n // {\n // spawnDelay: 10000, // 10 seconds\n // createMonster: () => createFloaterMonster(50, 500, 45, 1),\n // },\n {\n spawnDelay: 5000,\n createMonster: () => createAmbusherMonster(500, 500, 1),\n },\n ],\n\n monsters: [\n createVerticalPatrolMonster(105, 220, 220, \"right\"),\n createVerticalPatrolMonster(695, 220, 220, \"right\", 2, 1),\n createHorizontalPatrolMonster(170, 170, 200, \"left\"),\n createChaserMonster(250, 300, 1, 0.3, 1000),\n ],\n};\n\n// Level 2 - Innovasjon Norge\nexport const level2Map: MapDefinition = {\n id: \"level2\",\n name: \"innovasjon norge\",\n width: GAME_CONFIG.CANVAS_WIDTH,\n height: GAME_CONFIG.CANVAS_HEIGHT,\n playerStart: centerPoint(GAME_CONFIG.PLAYER_WIDTH, GAME_CONFIG.PLAYER_HEIGHT),\n spawnIndicatorColor: \"#ff6b6b\", // Red-orange for dark background\n\n groupSequence: [1, 2, 3, 4, 5],\n\n ground: {\n x: 0,\n y: GAME_CONFIG.CANVAS_HEIGHT - 40,\n width: GAME_CONFIG.CANVAS_WIDTH,\n height: 40,\n color: \"#262335\",\n },\n\n platforms: [\n // Bottom platforms\n createPlatform(165, 475, { width: 150, height: 15 }, \"#d4896a\", \"#262335\"),\n createPlatform(485, 475, { width: 150, height: 15 }, \"#d4896a\", \"#262335\"),\n // Middle platforms\n createPlatform(300, 380, { width: 200, height: 15 }, \"#d4896a\", \"#262335\"),\n createPlatform(300, 240, { width: 200, height: 15 }, \"#d4896a\", \"#262335\"),\n // Top platforms\n createPlatform(165, 130, { width: 150, height: 15 }, \"#d4896a\", \"#262335\"),\n createPlatform(485, 130, { width: 150, height: 15 }, \"#d4896a\", \"#262335\"),\n ],\n\n bombs: [\n // Group 1\n createBomb(600, 95, 1, 1),\n createBomb(550, 95, 2, 1),\n createBomb(500, 95, 3, 1),\n\n // Group 2\n createBomb(180, 440, 4, 2),\n createBomb(230, 440, 5, 2),\n createBomb(280, 440, 6, 2),\n\n // Group 3\n createBomb(280, 95, 7, 3),\n createBomb(230, 95, 8, 3),\n createBomb(180, 95, 9, 3),\n\n // Group 4\n createBomb(600, 440, 10, 4),\n createBomb(550, 440, 11, 4),\n createBomb(500, 440, 12, 4),\n\n // Group 5\n createBomb(385, 70, 13, 5),\n createBomb(385, 120, 14, 5),\n createBomb(385, 170, 15, 5),\n\n // Group 6\n createBomb(500, 500, 16, 6),\n createBomb(550, 500, 17, 6),\n createBomb(600, 500, 18, 6),\n\n // Group 7\n createBomb(180, 500, 19, 7),\n createBomb(230, 500, 20, 7),\n createBomb(280, 500, 21, 7),\n\n // Group 8\n createBomb(360, 345, 22, 8),\n createBomb(410, 345, 23, 8),\n ],\n\n coinSpawnPoints: [\n {\n x: 400,\n y: GAME_CONFIG.CANVAS_HEIGHT - 150,\n type: CoinType.POWER,\n spawnAngle: 60,\n },\n {\n x: 400,\n y: GAME_CONFIG.CANVAS_HEIGHT - 250,\n type: CoinType.POWER,\n spawnAngle: 120,\n },\n {\n x: 520,\n y: 100,\n type: CoinType.BONUS_MULTIPLIER,\n spawnAngle: 120,\n },\n {\n x: 180,\n y: 100,\n type: CoinType.BONUS_MULTIPLIER,\n spawnAngle: 120,\n },\n {\n x: 520,\n y: 100,\n type: CoinType.EXTRA_LIFE,\n spawnAngle: 120,\n },\n {\n x: 180,\n y: 100,\n type: CoinType.EXTRA_LIFE,\n spawnAngle: 120,\n },\n ],\n\n monsterSpawnPoints: [\n // // More aggressive early spawns for level 2\n {\n spawnDelay: 7000,\n createMonster: () => createChaserMonster(750, 500, 1),\n },\n {\n spawnDelay: 15000,\n createMonster: () => createAmbusherMonster(50, 500, 1),\n },\n ],\n\n monsters: [\n // Monster on top left platform (left side, 3 walks)\n createHorizontalPatrolMonster(165, 130, 150, \"left\", 0, 0.7),\n // Monster on top right platform (right side, 2 walks)\n createHorizontalPatrolMonster(485, 130, 150, \"right\", 0, 1),\n // Monster on upper middle platform (left side, 1 walk)\n createHorizontalPatrolMonster(300, 240, 200, \"left\", 0, 1),\n createFloaterMonster(50, 300, 45, 1),\n createFloaterMonster(750, 500, 155, 1),\n // createAmbusherMonster(50, 500),\n ],\n};\n\n// Level 3 - Skatteetaten\nexport const level3Map: MapDefinition = {\n id: \"level3\",\n name: \"skatteetaten\",\n width: GAME_CONFIG.CANVAS_WIDTH,\n height: GAME_CONFIG.CANVAS_HEIGHT,\n playerStart: centerPoint(GAME_CONFIG.PLAYER_WIDTH, GAME_CONFIG.PLAYER_HEIGHT),\n spawnIndicatorColor: \"#4ecdc4\", // Teal for blue-gray background\n\n groupSequence: [1, 2, 3, 4, 5, 6, 7],\n\n ground: {\n x: 0,\n y: GAME_CONFIG.CANVAS_HEIGHT - 40,\n width: GAME_CONFIG.CANVAS_WIDTH,\n height: 40,\n color: \"#3c4c56\",\n },\n\n platforms: [\n // Bottom long platform\n createPlatform(150, 490, { width: 500, height: 15 }, \"#acc7d0\", \"#556d7b\"),\n // Middle lower platforms\n createPlatform(100, 400, { width: 200, height: 15 }, \"#acc7d0\", \"#556d7b\"),\n createPlatform(500, 400, { width: 200, height: 15 }, \"#acc7d0\", \"#556d7b\"),\n // Middle upper platforms\n createPlatform(100, 250, { width: 200, height: 15 }, \"#acc7d0\", \"#556d7b\"),\n createPlatform(500, 250, { width: 200, height: 15 }, \"#acc7d0\", \"#556d7b\"),\n // Top platforms\n createPlatform(150, 130, { width: 500, height: 15 }, \"#acc7d0\", \"#556d7b\"),\n ],\n\n bombs: [\n // Group 1\n createBomb(540, 275, 1, 1),\n createBomb(590, 275, 2, 1),\n createBomb(640, 275, 3, 1),\n // Group 2\n createBomb(240, 275, 4, 2),\n createBomb(190, 275, 5, 2),\n createBomb(140, 275, 6, 2),\n // Group 3\n createBomb(325, 515, 7, 3),\n createBomb(375, 515, 8, 3),\n createBomb(425, 515, 9, 3),\n // Group 4\n createBomb(760, 360, 10, 4),\n createBomb(760, 310, 11, 4),\n createBomb(760, 260, 12, 4),\n // Group 5\n createBomb(15, 360, 13, 5),\n createBomb(15, 310, 14, 5),\n createBomb(15, 260, 15, 5),\n // Group 6\n createBomb(325, 155, 16, 6),\n createBomb(375, 155, 17, 6),\n createBomb(425, 155, 18, 6),\n createBomb(375, 205, 19, 6),\n createBomb(375, 255, 20, 6),\n // Group 7\n createBomb(580, 455, 21, 7),\n createBomb(195, 455, 22, 7),\n createBomb(375, 95, 23, 7),\n ],\n\n coinSpawnPoints: [],\n\n monsters: [\n // Static monster on horizontal platform\n createHorizontalPatrolMonster(150, 490, 500, \"left\", 0, 1),\n createHorizontalPatrolMonster(150, 130, 500, \"left\", 0, 1),\n createHorizontalPatrolMonster(150, 130, 500, \"right\", 0, 1),\n createHorizontalPatrolMonster(100, 400, 200, \"right\", 0, 1),\n createHorizontalPatrolMonster(500, 400, 200, \"left\", 0, 1),\n createChaserMonster(200, 200, 1, 0.1, 500),\n ],\n\n monsterSpawnPoints: [\n // Vertical patrol monster - spawns after 3 seconds\n {\n spawnDelay: 3000,\n createMonster: () =>\n createFloaterMonster(\n centerX(GAME_CONFIG.MONSTER_SIZE),\n centerY(GAME_CONFIG.MONSTER_SIZE),\n 150,\n 1\n ),\n },\n {\n spawnDelay: 6000,\n createMonster: () =>\n createFloaterMonster(\n centerX(GAME_CONFIG.MONSTER_SIZE),\n centerY(GAME_CONFIG.MONSTER_SIZE),\n 50,\n 1\n ),\n },\n // Chaser monster - spawns after 6 seconds\n\n {\n spawnDelay: 5000,\n createMonster: () =>\n createAmbusherMonster(\n 50, // startX\n 550, // startY\n 1.0, // speed (reduced from 1.5)\n 8000 // ambushInterval (increased from 500 to match new base value)\n ),\n },\n ],\n};\n\n// Level 4 - NAV\nexport const level4Map: MapDefinition = {\n id: \"level4\",\n name: \"nav\",\n width: GAME_CONFIG.CANVAS_WIDTH,\n height: GAME_CONFIG.CANVAS_HEIGHT,\n playerStart: centerPoint(GAME_CONFIG.PLAYER_WIDTH, GAME_CONFIG.PLAYER_HEIGHT),\n spawnIndicatorColor: \"#ffe66d\", // Yellow for green background\n\n groupSequence: [1, 2, 3, 4, 5],\n\n ground: {\n x: 0,\n y: GAME_CONFIG.CANVAS_HEIGHT - 40,\n width: GAME_CONFIG.CANVAS_WIDTH,\n height: 40,\n color: \"#586c5c\",\n },\n\n platforms: [\n /* BOTTOM TUNNELs */\n // Bottom horizontal tunnel\n createPlatform(580, 500, { width: 150, height: 15 }, \"#586c5c\", \"#202e32\"),\n // Upper horizontal tunnel\n createPlatform(580, 445, { width: 150, height: 15 }, \"#586c5c\", \"#202e32\"),\n // left vetical tunnel\n createVerticalPlatform(500, 245, 150, \"#586c5c\", \"#202e32\"),\n // right vetical tunnel\n createVerticalPlatform(555, 245, 150, \"#586c5c\", \"#202e32\"),\n\n /* UPPER TUNNEL */\n // Upper horizontal tunnel\n createPlatform(90, 45, { width: 150, height: 15 }, \"#586c5c\", \"#202e32\"),\n // Bottom horizontal tunnel\n createPlatform(90, 100, { width: 150, height: 15 }, \"#586c5c\", \"#202e32\"),\n // left vetical tunnel\n createVerticalPlatform(240, 160, 150, \"#586c5c\", \"#202e32\"),\n // right vetical tunnel\n createVerticalPlatform(295, 160, 150, \"#586c5c\", \"#202e32\"),\n\n // DIAGONAL PLATFORMS\n // bottom platform\n createPlatform(90, 500, { width: 200, height: 15 }, \"#586c5c\", \"#202e32\"),\n // lower middel platform\n createPlatform(235, 400, { width: 150, height: 15 }, \"#586c5c\", \"#202e32\"),\n // upper middel platform\n createPlatform(415, 145, { width: 150, height: 15 }, \"#586c5c\", \"#202e32\"),\n // upper platform\n createPlatform(530, 45, { width: 200, height: 15 }, \"#586c5c\", \"#202e32\"),\n ],\n\n bombs: [\n // Bottom horizontal tunnel bombs - GROUP 1\n createBomb(595, 467, 1, 1),\n createBomb(645, 467, 2, 1),\n createBomb(695, 467, 3, 1),\n\n // Bottom vetical tunnel bombs - GROUP 2\n createBomb(522, 255, 4, 2),\n createBomb(522, 305, 5, 2),\n createBomb(522, 355, 6, 2),\n\n // Bottom platform - GROUP 3\n createBomb(130, 467, 7, 3),\n createBomb(180, 467, 8, 3),\n createBomb(230, 467, 9, 3),\n\n // Lower middel platform bombs - GROUP 4\n createBomb(250, 367, 10, 4),\n createBomb(300, 367, 11, 4),\n createBomb(350, 367, 12, 4),\n\n // Upper vetical tunnel bombs - GROUP 5\n createBomb(263, 170, 13, 5),\n createBomb(263, 220, 14, 5),\n createBomb(263, 270, 15, 5),\n\n // Upper horizontal tunnel bombs - GROUP 6\n createBomb(100, 67, 16, 6),\n createBomb(150, 67, 17, 6),\n createBomb(200, 67, 18, 6),\n\n // Upper middel platform bombs - GROUP 7\n createBomb(430, 113, 19, 7),\n createBomb(480, 113, 20, 7),\n createBomb(530, 113, 21, 7),\n // Upper platform bombs - GROUP 8\n createBomb(630, 68, 22, 8),\n createBomb(680, 68, 23, 8),\n ],\n\n coinSpawnPoints: [\n // {\n // x: 400,\n // y: GAME_CONFIG.CANVAS_HEIGHT - 150,\n // type: CoinType.POWER,\n // spawnAngle: 30,\n // },\n // {\n // x: 400,\n // y: GAME_CONFIG.CANVAS_HEIGHT - 250,\n // type: CoinType.POWER,\n // spawnAngle: 150,\n // },\n ],\n monsterSpawnPoints: [\n // Vertical patrol monster - spawns after 3 seconds\n {\n spawnDelay: 4000,\n createMonster: () =>\n createFloaterMonster(\n centerX(GAME_CONFIG.MONSTER_SIZE),\n centerY(GAME_CONFIG.MONSTER_SIZE),\n 65,\n 1\n ),\n },\n {\n spawnDelay: 6000,\n createMonster: () => createFloaterMonster(240, 350, 40, 1),\n },\n // // Chaser monster - spawns after 6 seconds\n\n {\n spawnDelay: 2000,\n createMonster: () =>\n createAmbusherMonster(\n 50, // startX\n 50, // startY\n 1.2, // speed (reduced from 2)\n 8000 // ambushInterval (increased from 300 to match new base value)\n ),\n },\n {\n spawnDelay: 4000,\n createMonster: () =>\n createAmbusherMonster(\n 50, // startX\n 50, // startY\n 1.2, // speed (reduced from 2)\n 8000 // ambushInterval (increased from 300 to match new base value)\n ),\n },\n {\n spawnDelay: 4000,\n createMonster: () =>\n createChaserMonster(\n centerX(GAME_CONFIG.MONSTER_SIZE), // startX\n centerY(GAME_CONFIG.MONSTER_SIZE), // startY\n 3, // Speed\n 0.5 // Directness\n // updateInterval\n ),\n },\n {\n spawnDelay: 9000,\n createMonster: () =>\n createChaserMonster(\n 590, // startX\n 400, // startY\n 3, // Speed\n 0.5 // Directness\n // updateInterval\n ),\n },\n ],\n\n monsters: [\n createVerticalPatrolMonster(500, 170, 350, \"right\"),\n createVerticalPatrolMonster(240, 60, 340, \"right\"),\n createHorizontalPatrolMonster(90, 500, 200, \"left\"),\n createHorizontalPatrolMonster(90, 45, 150, \"right\"),\n ],\n};\n\n// Level 5 - Kommunehuset\nexport const level5Map: MapDefinition = {\n id: \"level5\",\n name: \"kommunehuset\",\n width: GAME_CONFIG.CANVAS_WIDTH,\n height: GAME_CONFIG.CANVAS_HEIGHT,\n playerStart: centerPoint(GAME_CONFIG.PLAYER_WIDTH, GAME_CONFIG.PLAYER_HEIGHT),\n spawnIndicatorColor: \"#a8e6cf\", // Light green for purple background\n\n groupSequence: [1, 2, 3, 4, 5, 6],\n\n ground: {\n x: 0,\n y: GAME_CONFIG.CANVAS_HEIGHT - 40,\n width: GAME_CONFIG.CANVAS_WIDTH,\n height: 40,\n color: \"#8d4fc9\",\n },\n\n platforms: [\n createPlatform(375, 300, { width: 50, height: 15 }, \"#ff4700\", \"#631b09\"),\n createPlatform(88, 300, { width: 50, height: 15 }, \"#ff4700\", \"#631b09\"),\n createPlatform(667, 300, { width: 50, height: 15 }, \"#ff4700\", \"#631b09\"),\n ],\n\n bombs: [\n // Top left\n createBomb(150, 60, 1, 1),\n createBomb(100, 60, 2, 1),\n createBomb(50, 60, 3, 1),\n // Top right\n createBomb(625, 60, 4, 2),\n createBomb(675, 60, 5, 2),\n createBomb(725, 60, 6, 2),\n\n // Bottom left\n createBomb(150, 525, 7, 3),\n createBomb(100, 525, 8, 3),\n createBomb(50, 525, 9, 3),\n // Bottom right\n createBomb(625, 525, 10, 4),\n createBomb(675, 525, 11, 4),\n createBomb(725, 525, 12, 4),\n\n // Top middle\n createBomb(438, 100, 13, 5),\n createBomb(388, 100, 14, 5),\n createBomb(338, 100, 15, 5),\n\n // Bottom middle\n createBomb(338, 525, 16, 6),\n createBomb(388, 525, 17, 6),\n createBomb(438, 525, 18, 6),\n\n // Bottom middle vertical\n createBomb(388, 330, 19, 6),\n createBomb(388, 380, 20, 6),\n createBomb(388, 430, 21, 6),\n\n // left platform\n createBomb(101, 270, 22, 7),\n createBomb(680, 270, 23, 7),\n ],\n\n monsters: [\n createVerticalPatrolMonster(520, 200, 350, \"right\"),\n createVerticalPatrolMonster(225, 200, 350, \"right\"),\n\n createVerticalPatrolMonster(520, 20, 350, \"right\"),\n createVerticalPatrolMonster(225, 20, 350, \"right\"),\n createHorizontalPatrolMonster(0, 550, 800, \"left\"),\n ],\n\n monsterSpawnPoints: [\n // // Test monster - spawns immediately\n {\n spawnDelay: 5000,\n createMonster: () => createAmbusherMonster(700, 150),\n },\n {\n spawnDelay: 7000,\n createMonster: () => createFloaterMonster(100, 150),\n },\n {\n spawnDelay: 10000,\n createMonster: () =>\n createChaserMonster(\n centerX(GAME_CONFIG.MONSTER_SIZE),\n centerY(GAME_CONFIG.MONSTER_SIZE + 200)\n ),\n },\n {\n spawnDelay: 15000,\n createMonster: () =>\n createFloaterMonster(\n centerX(GAME_CONFIG.MONSTER_SIZE),\n centerY(GAME_CONFIG.MONSTER_SIZE - 200)\n ),\n },\n ],\n\n coinSpawnPoints: [\n // Power coin spawn points for level 5 - only 2 per map with non-cardinal angles\n {\n x: 400,\n y: 500,\n type: CoinType.POWER,\n spawnAngle: 46,\n },\n {\n x: 500,\n y: 200,\n type: CoinType.POWER,\n spawnAngle: 45,\n },\n {\n x: 388,\n y: 50,\n type: CoinType.BONUS_MULTIPLIER,\n },\n {\n x: 388,\n y: 50,\n type: CoinType.EXTRA_LIFE,\n },\n {\n x: 101,\n y: 50,\n type: CoinType.BONUS_MULTIPLIER,\n },\n {\n x: 101,\n y: 50,\n type: CoinType.EXTRA_LIFE,\n },\n {\n x: 680,\n y: 50,\n type: CoinType.BONUS_MULTIPLIER,\n },\n {\n x: 680,\n y: 50,\n type: CoinType.EXTRA_LIFE,\n },\n ],\n};\n\n// Level 6 - Alltinn Norge\nexport const level6Map: MapDefinition = {\n id: \"level6\",\n name: \"alltinn norge\",\n width: GAME_CONFIG.CANVAS_WIDTH,\n height: GAME_CONFIG.CANVAS_HEIGHT,\n playerStart: centerPoint(GAME_CONFIG.PLAYER_WIDTH, GAME_CONFIG.PLAYER_HEIGHT),\n spawnIndicatorColor: \"#ff9ff3\", // Pink for blue background\n\n groupSequence: [1, 2, 3, 4, 5, 6],\n\n ground: {\n x: 0,\n y: GAME_CONFIG.CANVAS_HEIGHT - 40,\n width: GAME_CONFIG.CANVAS_WIDTH,\n height: 40,\n color: \"#47567f\",\n },\n\n platforms: [\n // Floating platforms in spiral pattern\n createPlatform(\n 200,\n GAME_CONFIG.CANVAS_HEIGHT - 120,\n { width: 200, height: 15 },\n \"#ebb185\"\n ),\n createPlatform(\n 600,\n GAME_CONFIG.CANVAS_HEIGHT - 110,\n { width: 200, height: 15 },\n \"#ebb185\"\n ),\n\n createPlatform(\n 100,\n GAME_CONFIG.CANVAS_HEIGHT - 180,\n { width: 200, height: 15 },\n \"#ebb185\"\n ),\n createPlatform(\n 700,\n GAME_CONFIG.CANVAS_HEIGHT - 180,\n { width: 200, height: 15 },\n \"#ebb185\"\n ),\n\n createPlatform(\n 300,\n GAME_CONFIG.CANVAS_HEIGHT - 240,\n { width: 200, height: 15 },\n \"#ebb185\"\n ),\n createPlatform(\n 500,\n GAME_CONFIG.CANVAS_HEIGHT - 240,\n { width: 200, height: 15 },\n \"#ebb185\"\n ),\n\n createPlatform(\n 150,\n GAME_CONFIG.CANVAS_HEIGHT - 300,\n { width: 200, height: 15 },\n \"#ebb185\"\n ),\n createPlatform(\n 650,\n GAME_CONFIG.CANVAS_HEIGHT - 300,\n { width: 200, height: 15 },\n \"#ebb185\"\n ),\n\n createPlatform(\n 400,\n GAME_CONFIG.CANVAS_HEIGHT - 370,\n { width: 200, height: 15 },\n \"#ebb185\"\n ),\n\n createPlatform(\n 250,\n GAME_CONFIG.CANVAS_HEIGHT - 420,\n { width: 200, height: 15 },\n \"#ebb185\"\n ),\n createPlatform(\n 550,\n GAME_CONFIG.CANVAS_HEIGHT - 420,\n { width: 200, height: 15 },\n \"#ebb185\"\n ),\n ],\n\n bombs: [\n // Ground level\n {\n x: 70,\n y: GAME_CONFIG.CANVAS_HEIGHT - 70,\n width: 16,\n height: 16,\n order: 1,\n group: 1,\n isCollected: false,\n isBlinking: false,\n },\n {\n x: 750,\n y: GAME_CONFIG.CANVAS_HEIGHT - 70,\n width: 16,\n height: 16,\n order: 2,\n group: 1,\n isCollected: false,\n isBlinking: false,\n },\n\n // First floating level\n {\n x: 220,\n y: GAME_CONFIG.CANVAS_HEIGHT - 150,\n width: 16,\n height: 16,\n order: 3,\n group: 2,\n isCollected: false,\n isBlinking: false,\n },\n {\n x: 620,\n y: GAME_CONFIG.CANVAS_HEIGHT - 150,\n width: 16,\n height: 16,\n order: 4,\n group: 2,\n isCollected: false,\n isBlinking: false,\n },\n\n // Second level\n {\n x: 120,\n y: GAME_CONFIG.CANVAS_HEIGHT - 210,\n width: 16,\n height: 16,\n order: 5,\n group: 3,\n isCollected: false,\n isBlinking: false,\n },\n {\n x: 720,\n y: GAME_CONFIG.CANVAS_HEIGHT - 210,\n width: 16,\n height: 16,\n order: 6,\n group: 3,\n isCollected: false,\n isBlinking: false,\n },\n\n // Third level\n {\n x: 320,\n y: GAME_CONFIG.CANVAS_HEIGHT - 270,\n width: 16,\n height: 16,\n order: 7,\n group: 4,\n isCollected: false,\n isBlinking: false,\n },\n {\n x: 540,\n y: GAME_CONFIG.CANVAS_HEIGHT - 270,\n width: 16,\n height: 16,\n order: 8,\n group: 4,\n isCollected: false,\n isBlinking: false,\n },\n\n // Fourth level\n {\n x: 170,\n y: GAME_CONFIG.CANVAS_HEIGHT - 330,\n width: 16,\n height: 16,\n order: 9,\n group: 5,\n isCollected: false,\n isBlinking: false,\n },\n {\n x: 670,\n y: GAME_CONFIG.CANVAS_HEIGHT - 330,\n width: 16,\n height: 16,\n order: 10,\n group: 5,\n isCollected: false,\n isBlinking: false,\n },\n\n // Fifth level\n {\n x: 420,\n y: GAME_CONFIG.CANVAS_HEIGHT - 390,\n width: 16,\n height: 16,\n order: 11,\n group: 6,\n isCollected: false,\n isBlinking: false,\n },\n\n // Sixth level\n {\n x: 270,\n y: GAME_CONFIG.CANVAS_HEIGHT - 450,\n width: 16,\n height: 16,\n order: 12,\n group: 6,\n isCollected: false,\n isBlinking: false,\n },\n {\n x: 570,\n y: GAME_CONFIG.CANVAS_HEIGHT - 450,\n width: 16,\n height: 16,\n order: 13,\n group: 6,\n isCollected: false,\n isBlinking: false,\n },\n\n // Additional scattered bombs\n {\n x: 25,\n y: GAME_CONFIG.CANVAS_HEIGHT - 90,\n width: 16,\n height: 16,\n order: 14,\n group: 6,\n isCollected: false,\n isBlinking: false,\n },\n {\n x: 775,\n y: GAME_CONFIG.CANVAS_HEIGHT - 90,\n width: 16,\n height: 16,\n order: 15,\n group: 6,\n isCollected: false,\n isBlinking: false,\n },\n {\n x: 180,\n y: GAME_CONFIG.CANVAS_HEIGHT - 150,\n width: 16,\n height: 16,\n order: 16,\n group: 6,\n isCollected: false,\n isBlinking: false,\n },\n {\n x: 620,\n y: GAME_CONFIG.CANVAS_HEIGHT - 150,\n width: 16,\n height: 16,\n order: 17,\n group: 6,\n isCollected: false,\n isBlinking: false,\n },\n {\n x: 280,\n y: GAME_CONFIG.CANVAS_HEIGHT - 210,\n width: 16,\n height: 16,\n order: 18,\n group: 6,\n isCollected: false,\n isBlinking: false,\n },\n {\n x: 520,\n y: GAME_CONFIG.CANVAS_HEIGHT - 210,\n width: 16,\n height: 16,\n order: 19,\n group: 6,\n isCollected: false,\n isBlinking: false,\n },\n {\n x: 370,\n y: GAME_CONFIG.CANVAS_HEIGHT - 270,\n width: 16,\n height: 16,\n order: 20,\n group: 6,\n isCollected: false,\n isBlinking: false,\n },\n {\n x: 470,\n y: GAME_CONFIG.CANVAS_HEIGHT - 270,\n width: 16,\n height: 16,\n order: 21,\n group: 6,\n isCollected: false,\n isBlinking: false,\n },\n {\n x: 220,\n y: GAME_CONFIG.CANVAS_HEIGHT - 330,\n width: 16,\n height: 16,\n order: 22,\n group: 6,\n isCollected: false,\n isBlinking: false,\n },\n {\n x: 580,\n y: GAME_CONFIG.CANVAS_HEIGHT - 330,\n width: 16,\n height: 16,\n order: 23,\n group: 6,\n isCollected: false,\n isBlinking: false,\n },\n ],\n\n monsters: [\n {\n x: 150,\n y: GAME_CONFIG.CANVAS_HEIGHT - 70,\n width: GAME_CONFIG.MONSTER_SIZE,\n height: GAME_CONFIG.MONSTER_SIZE,\n color: COLORS.MONSTER,\n type: MonsterType.HORIZONTAL_PATROL,\n patrolStartX: 100,\n patrolEndX: 300,\n speed: 4,\n direction: 1,\n isActive: true,\n },\n {\n x: 650,\n y: GAME_CONFIG.CANVAS_HEIGHT - 130,\n width: GAME_CONFIG.MONSTER_SIZE,\n height: GAME_CONFIG.MONSTER_SIZE,\n color: COLORS.MONSTER,\n type: MonsterType.HORIZONTAL_PATROL,\n patrolStartX: 600,\n patrolEndX: 800,\n speed: 4.2,\n direction: -1,\n isActive: true,\n },\n {\n x: 300,\n y: GAME_CONFIG.CANVAS_HEIGHT - 170,\n width: GAME_CONFIG.MONSTER_SIZE,\n height: GAME_CONFIG.MONSTER_SIZE,\n color: COLORS.MONSTER,\n type: MonsterType.HORIZONTAL_PATROL,\n patrolStartX: 250,\n patrolEndX: 450,\n speed: 3.8,\n direction: 1,\n isActive: true,\n },\n {\n x: 500,\n y: GAME_CONFIG.CANVAS_HEIGHT - 290,\n width: GAME_CONFIG.MONSTER_SIZE,\n height: GAME_CONFIG.MONSTER_SIZE,\n color: COLORS.MONSTER,\n type: MonsterType.HORIZONTAL_PATROL,\n patrolStartX: 450,\n patrolEndX: 650,\n speed: 3.6,\n direction: -1,\n isActive: true,\n },\n {\n x: 400,\n y: GAME_CONFIG.CANVAS_HEIGHT - 350,\n width: GAME_CONFIG.MONSTER_SIZE,\n height: GAME_CONFIG.MONSTER_SIZE,\n color: COLORS.MONSTER,\n type: MonsterType.HORIZONTAL_PATROL,\n patrolStartX: 350,\n patrolEndX: 550,\n speed: 4,\n direction: 1,\n isActive: true,\n },\n ],\n\n coinSpawnPoints: [\n // Power coin spawn points for level 5 - only 2 per map with non-cardinal angles\n {\n x: 300,\n y: GAME_CONFIG.CANVAS_HEIGHT - 100,\n type: CoinType.POWER,\n spawnAngle: 165,\n },\n {\n x: 500,\n y: GAME_CONFIG.CANVAS_HEIGHT - 140,\n type: CoinType.POWER,\n spawnAngle: 15,\n },\n ],\n};\n\nexport const level7Map: MapDefinition = {\n id: \"level7\",\n name: \"silicone vally\",\n width: GAME_CONFIG.CANVAS_WIDTH,\n height: GAME_CONFIG.CANVAS_HEIGHT,\n playerStart: centerPoint(GAME_CONFIG.PLAYER_WIDTH, GAME_CONFIG.PLAYER_HEIGHT),\n spawnIndicatorColor: \"#feca57\", // Orange for dark gray background\n\n groupSequence: [1, 2, 3, 4, 5],\n\n ground: {\n x: 0,\n y: GAME_CONFIG.CANVAS_HEIGHT - 40,\n width: GAME_CONFIG.CANVAS_WIDTH,\n height: 40,\n color: \"#46474c\",\n },\n\n platforms: [],\n\n bombs: [\n // Group 1\n createBomb(440, 530, 1, 1),\n createBomb(490, 530, 2, 1),\n createBomb(540, 530, 3, 1),\n createBomb(590, 530, 4, 1),\n\n // Group 2\n createBomb(760, 530, 5, 2),\n createBomb(760, 480, 6, 2),\n createBomb(760, 430, 7, 2),\n createBomb(760, 380, 8, 2),\n\n // Group 3\n createBomb(590, 330, 9, 3),\n createBomb(540, 330, 10, 3),\n createBomb(490, 330, 11, 3),\n createBomb(440, 330, 12, 3),\n\n // Group 4\n createBomb(290, 530, 13, 4),\n createBomb(240, 530, 14, 4),\n createBomb(190, 530, 15, 4),\n createBomb(140, 530, 16, 4),\n\n // Group 5\n createBomb(15, 530, 17, 5),\n createBomb(15, 480, 18, 5),\n createBomb(15, 430, 19, 5),\n createBomb(15, 380, 20, 5),\n\n // Group 6\n createBomb(190, 330, 21, 6),\n createBomb(240, 330, 22, 6),\n createBomb(290, 330, 23, 6),\n ],\n\n coinSpawnPoints: [],\n\n monsterSpawnPoints: [],\n\n monsters: [],\n};\n\nexport const mapDefinitions = [\n level1Map,\n level2Map,\n level3Map,\n level4Map,\n level5Map,\n // level6Map,\n level7Map,\n];\n","import { StateCreator } from \"zustand\";\nimport { GameState, MenuType } from \"../../types/enums\";\nimport { GAME_CONFIG } from \"../../types/constants\";\nimport { calculateBombScore, formatScoreLog } from \"../../lib/scoringUtils\";\nimport {\n sendScoreToHost,\n sendGameStateUpdate,\n sendGameCompletionData,\n LevelHistoryEntry,\n calculateGameStats,\n GameCompletionData\n} from \"@/lib/communicationUtils\";\nimport { mapDefinitions } from \"@/maps/mapDefinitions\";\nimport { log } from \"../../lib/logger\";\n\ninterface StoreAPI {\n currentMap?: { name: string };\n resetMultiplier: () => void;\n getLevelHistory: () => Array<{ coinsCollected: number; powerModeActivations: number }>;\n getLevelResults: () => LevelHistoryEntry[];\n getGameStartTime: () => number;\n getSessionId: () => string;\n multiplier: number;\n}\n\nexport interface GameStateSlice {\n currentState: GameState;\n score: number;\n levelScore: number;\n lives: number;\n currentLevel: number;\n showMenu: MenuType;\n previousMenu: MenuType | null;\n isPaused: boolean;\n bonusAnimationComplete: boolean;\n\n setState: (state: GameState) => void;\n setMenuType: (menuType: MenuType) => void;\n setBonusAnimationComplete: (complete: boolean) => void;\n loseLife: () => void;\n addLife: () => void;\n nextLevel: () => void;\n addScore: (points: number) => void;\n resetLevelScores: () => void;\n resetGameState: () => void;\n}\n\nexport const createGameStateSlice: StateCreator<GameStateSlice> = (\n set,\n get\n) => {\n log.info(\n `Initializing game state slice with ${GAME_CONFIG.STARTING_LIVES} lives`\n );\n return {\n currentState: GameState.MENU,\n score: 0,\n levelScore: 0,\n lives: GAME_CONFIG.STARTING_LIVES,\n currentLevel: 1,\n showMenu: MenuType.START,\n previousMenu: null,\n isPaused: false,\n bonusAnimationComplete: false,\n\n setState: (state: GameState) => {\n set({\n currentState: state,\n isPaused: state === GameState.PAUSED,\n });\n if (state === GameState.MENU) {\n set({ showMenu: MenuType.START });\n } else if (state === GameState.PLAYING) {\n set({ showMenu: MenuType.IN_GAME });\n }\n\n // Get current map for state update\n const api = get();\n const currentMap = \"currentMap\" in api ? (api as { currentMap?: { name: string } }).currentMap : undefined;\n sendGameStateUpdate(state, currentMap?.name);\n },\n\n setMenuType: (menuType: MenuType) => {\n const currentState = get();\n if (menuType === MenuType.SETTINGS) {\n // Store the current menu as previous when opening settings\n set({ showMenu: menuType, previousMenu: currentState.showMenu });\n } else {\n set({ showMenu: menuType });\n }\n },\n\n setBonusAnimationComplete: (complete: boolean) => {\n set({ bonusAnimationComplete: complete });\n },\n\n loseLife: () => {\n const { lives } = get();\n const newLives = lives - 1;\n \n log.info(`Losing life: ${lives} → ${newLives}`);\n set({ lives: newLives });\n\n // Get current map for state update\n const api = get();\n const currentMap = \"currentMap\" in api ? (api as { currentMap?: { name: string } }).currentMap : undefined;\n sendGameStateUpdate(GameState.PLAYING, currentMap?.name);\n\n // Check if game over after setting new lives\n if (newLives <= 0) {\n log.info(`GAME OVER triggered at ${newLives} lives`);\n set({\n currentState: GameState.GAME_OVER,\n showMenu: MenuType.GAME_OVER,\n });\n const currentMap = \"currentMap\" in api ? (api as { currentMap?: { name: string } }).currentMap : undefined;\n sendGameStateUpdate(GameState.GAME_OVER, currentMap?.name);\n\n // Send comprehensive game completion data for game over\n const levelResults = \"getLevelResults\" in api ? (api as { getLevelResults: () => LevelHistoryEntry[] }).getLevelResults() : [];\n const multiplier = \"multiplier\" in api ? (api as { multiplier: number }).multiplier : 1;\n const gameStartTime = \"getGameStartTime\" in api ? (api as { getGameStartTime: () => number }).getGameStartTime() : Date.now();\n const sessionId = \"getSessionId\" in api ? (api as { getSessionId: () => string }).getSessionId() : `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n\n const gameStats = calculateGameStats(levelResults, get().score, newLives, multiplier, 'failed', gameStartTime, Date.now());\n\n const gameCompletionData: GameCompletionData = {\n finalScore: get().score,\n totalLevels: mapDefinitions.length,\n completedLevels: levelResults.length,\n timestamp: Date.now(),\n lives: newLives,\n multiplier,\n levelHistory: levelResults,\n totalCoinsCollected: gameStats.totalCoinsCollected,\n totalPowerModeActivations: gameStats.totalPowerModeActivations,\n totalBombs: gameStats.totalBombs,\n totalCorrectOrders: gameStats.totalCorrectOrders,\n averageCompletionTime: gameStats.averageCompletionTime,\n gameEndReason: 'failed',\n sessionId,\n startTime: gameStartTime,\n endTime: Date.now()\n };\n\n sendGameCompletionData(gameCompletionData);\n }\n },\n\n addLife: () => {\n const { lives } = get();\n const newLives = lives + 1;\n \n log.info(`Adding life: ${lives} → ${newLives}`);\n set({ lives: newLives });\n },\n\n nextLevel: () => {\n const { currentLevel } = get();\n set({ currentLevel: currentLevel + 1 });\n\n // Reset level scores and multiplier for new level\n set({ levelScore: 0 });\n\n // Reset multiplier directly\n const api = get();\n if (\"resetMultiplier\" in api) {\n log.debug(\"Resetting multiplier on level change...\");\n (api as { resetMultiplier: () => void }).resetMultiplier();\n }\n\n // Send state update with new level info\n const currentMap = \"currentMap\" in api ? (api as { currentMap?: { name: string } }).currentMap : undefined;\n sendGameStateUpdate(GameState.PLAYING, currentMap?.name);\n },\n\n addScore: (points: number) => {\n const { score, levelScore, currentLevel, lives } = get();\n const newScore = score + points;\n\n set({\n score: newScore,\n levelScore: levelScore + points,\n });\n\n // Get multiplier and currentMap from the store if available\n const api = get();\n const multiplier = \"multiplier\" in api ? (api as { multiplier: number }).multiplier : 1;\n const currentMap = \"currentMap\" in api ? (api as { currentMap?: { name: string } }).currentMap : undefined;\n\n // Send comprehensive score data to host\n sendScoreToHost(\n newScore,\n currentMap?.name || `Level ${currentLevel}`,\n currentLevel,\n lives,\n multiplier\n );\n },\n\n resetLevelScores: () => {\n set({ levelScore: 0 });\n },\n\n resetGameState: () => {\n set({\n currentState: GameState.MENU,\n score: 0,\n levelScore: 0,\n lives: GAME_CONFIG.STARTING_LIVES,\n currentLevel: 1,\n showMenu: MenuType.START,\n previousMenu: null,\n isPaused: false,\n bonusAnimationComplete: false,\n });\n },\n };\n};\n","import { GAME_CONFIG } from '../types/constants';\n\nexport interface ScoreCalculation {\n basePoints: number;\n actualPoints: number;\n multiplier: number;\n isFirebomb: boolean;\n}\n\nexport const calculateBombScore = (\n isFirebomb: boolean, \n multiplier: number\n): ScoreCalculation => {\n const basePoints = isFirebomb \n ? GAME_CONFIG.BOMB_POINTS.FIREBOMB \n : GAME_CONFIG.BOMB_POINTS.NORMAL;\n \n const actualPoints = basePoints * multiplier;\n \n return {\n basePoints,\n actualPoints,\n multiplier,\n isFirebomb\n };\n};\n\nexport const formatScoreLog = (calculation: ScoreCalculation): string => {\n const { actualPoints, isFirebomb, multiplier } = calculation;\n const bombType = isFirebomb ? 'Firebomb' : 'Normal';\n return `🎯 Score: +${actualPoints} (${bombType} x${multiplier})`;\n};\n\nexport const calculateMultiplierProgress = (multiplierScore: number, currentMultiplier: number): number => {\n const { MULTIPLIER_THRESHOLDS, MAX_MULTIPLIER } = GAME_CONFIG;\n \n // If we're at max multiplier, show 100% progress\n if (currentMultiplier >= MAX_MULTIPLIER) {\n return 1;\n }\n \n // Calculate progress to next multiplier\n const currentThreshold = MULTIPLIER_THRESHOLDS[currentMultiplier as keyof typeof MULTIPLIER_THRESHOLDS];\n const nextThreshold = MULTIPLIER_THRESHOLDS[(currentMultiplier + 1) as keyof typeof MULTIPLIER_THRESHOLDS];\n \n if (!nextThreshold) {\n return 1; // No next threshold, so we're at max\n }\n \n const progress = (multiplierScore - currentThreshold) / (nextThreshold - currentThreshold);\n return Math.max(0, Math.min(1, progress)); // Clamp between 0 and 1\n}; ","import { StateCreator } from \"zustand\";\nimport { Bomb } from \"../../types/interfaces\";\nimport { BombManager } from \"../../managers/bombManager\";\nimport { calculateBombScore, formatScoreLog } from \"../../lib/scoringUtils\";\nimport { log } from \"../../lib/logger\";\n\nexport interface BombSlice {\n bombs: Bomb[];\n collectedBombs: number[];\n correctOrderCount: number;\n nextBombOrder: number;\n bombManager: BombManager | null;\n \n collectBomb: (bombOrder: number) => { isValid: boolean; isCorrect: boolean };\n setBombs: (bombs: Bomb[]) => void;\n setBombManager: (bombManager: BombManager) => void;\n resetBombState: () => void;\n}\n\nexport const createBombSlice: StateCreator<BombSlice> = (set, get) => ({\n bombs: [],\n collectedBombs: [],\n correctOrderCount: 0,\n nextBombOrder: 1,\n bombManager: null,\n \n collectBomb: (bombOrder: number) => {\n const { bombs, bombManager } = get();\n \n const bomb = bombs.find((b) => b.order === bombOrder);\n if (!bomb || !bombManager) {\n log.warn(\"Bomb or bomb manager not found\");\n return { isValid: false, isCorrect: false };\n }\n\n const result = bombManager.handleBombClick(bomb.group, bomb.order);\n \n if (!result.isValid) {\n return { isValid: false, isCorrect: false };\n }\n\n // Determine if this is a firebomb (next correct bomb in sequence)\n const isFirebomb = result.isCorrect;\n \n // Get current multiplier from the store\n const api = get();\n const currentMultiplier = \"multiplier\" in api ? (api as { multiplier: number }).multiplier : 1;\n \n // Calculate score using utility function\n const scoreCalculation = calculateBombScore(isFirebomb, currentMultiplier);\n \n // Add score to game state\n if (\"addScore\" in api) {\n (api as { addScore: (points: number) => void }).addScore(scoreCalculation.actualPoints);\n }\n \n // Add points to multiplier system\n if (\"addMultiplierScore\" in api) {\n (api as { addMultiplierScore: (points: number) => void }).addMultiplierScore(scoreCalculation.actualPoints);\n }\n\n // Notify coin manager about points earned (not bonus)\n if (\"coinManager\" in api && (api as { coinManager?: { onPointsEarned: (points: number, isBonus: boolean) => void } }).coinManager) {\n (api as { coinManager: { onPointsEarned: (points: number, isBonus: boolean) => void } }).coinManager.onPointsEarned(\n scoreCalculation.actualPoints,\n false\n );\n }\n \n // Log the score (only for firebombs or high scores to reduce spam)\n if (isFirebomb || scoreCalculation.actualPoints >= 400) {\n log.score(formatScoreLog(scoreCalculation));\n }\n\n // Add floating text for correct bomb collection\n if (isFirebomb && \"addFloatingText\" in api) {\n const bomb = bombs.find((b) => b.order === bombOrder);\n if (bomb) {\n const text = `${scoreCalculation.actualPoints}`;\n (api as { addFloatingText: (text: string, x: number, y: number, duration: number, color: string, fontSize: number) => void }).addFloatingText(\n text,\n bomb.x + bomb.width / 2,\n bomb.y + bomb.height / 2,\n 1000, // duration\n '#FFD700', // color\n 15 // fontSize\n );\n }\n }\n\n const updatedBombs = bombs.map((b) => {\n if (b.order === bombOrder) {\n return { ...b, isCollected: true, isCorrect: result.isCorrect };\n }\n \n const nextGroup = bombManager.getActiveGroup();\n const nextOrder = bombManager.getNextBombOrder();\n const isNextBomb =\n nextGroup !== null &&\n nextOrder !== null &&\n b.group === nextGroup &&\n b.order === nextOrder &&\n !b.isCollected;\n \n return { ...b, isBlinking: isNextBomb };\n });\n \n set({\n bombs: updatedBombs,\n correctOrderCount: bombManager.getCorrectOrderCount(),\n collectedBombs: Array.from(bombManager.getCollectedBombs()).map((id) => {\n const [group, order] = id.split(\"-\").map(Number);\n return order;\n }),\n });\n\n return { isValid: true, isCorrect: result.isCorrect };\n },\n \n setBombs: (bombs: Bomb[]) => {\n set({ bombs });\n },\n \n setBombManager: (bombManager: BombManager) => {\n set({ bombManager });\n },\n \n resetBombState: () => {\n set({\n bombs: [],\n collectedBombs: [],\n correctOrderCount: 0,\n nextBombOrder: 1,\n bombManager: null,\n });\n },\n});\n","import { Bomb } from \"../types/interfaces\";\nimport { DEV_CONFIG } from \"../types/constants\";\nimport { log } from \"../lib/logger\";\n\nexport class BombManager {\n private bombs: Bomb[] = [];\n private collectedBombs = new Set<string>();\n private correctBombs = new Set<string>();\n private activeGroup: number | null = null;\n private nextBombOrder: number | null = null;\n private gameStarted = false;\n\n constructor(bombs: Bomb[]) {\n this.setBombs(bombs);\n }\n\n reset(): void {\n this.collectedBombs.clear();\n this.correctBombs.clear();\n this.activeGroup = null;\n this.nextBombOrder = null;\n this.gameStarted = false;\n }\n\n setBombs(bombs: Bomb[]): void {\n this.bombs = bombs;\n }\n\n handleBombClick(\n group: number,\n order: number\n ): { isValid: boolean; isCorrect: boolean; gameCompleted: boolean } {\n const bombId = `${group}-${order}`;\n\n if (DEV_CONFIG.ENABLED) {\n log.dev(`USER CLICK: Group ${group}, Order ${order}`);\n }\n\n // Check if bomb is already collected\n if (this.collectedBombs.has(bombId)) {\n if (DEV_CONFIG.ENABLED) {\n log.dev(\"Bomb already collected!\");\n }\n return { isValid: false, isCorrect: false, gameCompleted: false };\n }\n\n // If game hasn't started yet, start it with this bomb\n if (!this.gameStarted) {\n if (DEV_CONFIG.ENABLED) {\n log.dev(\"Starting new game...\");\n }\n this.startGame(group, order);\n this.collectBomb(bombId, true);\n this.updateNextBomb();\n return {\n isValid: true,\n isCorrect: true,\n gameCompleted: this.isGameCompleted(),\n };\n }\n\n // Check if this is a valid bomb to click (correct order)\n const isCorrectOrder = this.isValidBomb(group, order);\n\n if (isCorrectOrder) {\n if (DEV_CONFIG.ENABLED) {\n log.dev(\"Correct order - collecting bomb\");\n }\n this.collectBomb(bombId, true);\n this.updateNextBomb();\n } else {\n if (DEV_CONFIG.ENABLED) {\n log.dev(\"Wrong order - but collecting anyway\");\n log.dev(\n ` Expected: Group ${this.activeGroup}, Order ${this.nextBombOrder}`\n );\n log.dev(` Clicked: Group ${group}, Order ${order}`);\n }\n this.collectBomb(bombId, false);\n // Don't update next bomb - keep the same target\n }\n\n return {\n isValid: true,\n isCorrect: isCorrectOrder,\n gameCompleted: this.isGameCompleted(),\n };\n }\n\n private startGame(group: number, order: number): void {\n this.gameStarted = true;\n this.activeGroup = group;\n this.nextBombOrder = this.findLowestOrderInGroup(group);\n\n if (DEV_CONFIG.ENABLED) {\n log.dev(`GAME STARTED:`);\n log.dev(` Started with: Group ${group}, Order ${order}`);\n log.dev(` Active group: ${this.activeGroup}`);\n log.dev(` Next target: Order ${this.nextBombOrder}`);\n }\n }\n\n private isValidBomb(group: number, order: number): boolean {\n if (this.activeGroup === null || this.nextBombOrder === null) {\n return false;\n }\n\n return (\n group === this.activeGroup &&\n order === this.nextBombOrder &&\n !this.collectedBombs.has(`${group}-${order}`)\n );\n }\n\n private collectBomb(bombId: string, isCorrect: boolean): void {\n this.collectedBombs.add(bombId);\n\n if (isCorrect) {\n this.correctBombs.add(bombId);\n if (DEV_CONFIG.ENABLED) {\n log.dev(\n `Correct bomb collected (${this.correctBombs.size} correct so far)`\n );\n }\n } else {\n if (DEV_CONFIG.ENABLED) {\n log.dev(\n `Wrong bomb collected (${this.correctBombs.size} correct so far)`\n );\n }\n }\n\n if (DEV_CONFIG.ENABLED) {\n log.bomb(`BOMB COLLECTED: ${bombId}`);\n log.bomb(\n `Progress: ${this.collectedBombs.size}/${this.bombs.length} bombs collected`\n );\n }\n }\n\n private updateNextBomb(): void {\n if (this.activeGroup === null) return;\n\n if (DEV_CONFIG.ENABLED) {\n log.dev(`UPDATING NEXT BOMB:`);\n }\n\n // Check if current group is completed\n if (this.isGroupCompleted(this.activeGroup)) {\n log.dev(`GROUP ${this.activeGroup} COMPLETED!`);\n const nextGroup = this.findNextAvailableGroup();\n\n if (nextGroup !== null) {\n this.activeGroup = nextGroup;\n this.nextBombOrder = this.findLowestOrderInGroup(nextGroup);\n if (DEV_CONFIG.ENABLED) {\n log.dev(\n `Moving to next group: Group ${this.activeGroup}, Order ${this.nextBombOrder}`\n );\n }\n } else {\n if (DEV_CONFIG.ENABLED) {\n log.dev(\"ALL GROUPS COMPLETED!\");\n }\n this.activeGroup = null;\n this.nextBombOrder = null;\n return;\n }\n } else {\n // Find the next available order in the current group\n const nextOrder = this.findNextAvailableOrderInGroup(this.activeGroup);\n if (nextOrder !== null) {\n this.nextBombOrder = nextOrder;\n if (DEV_CONFIG.ENABLED) {\n log.dev(`Next in current group: Order ${this.nextBombOrder}`);\n }\n }\n }\n }\n\n private isGroupCompleted(group: number): boolean {\n const groupBombs = this.bombs.filter((bomb) => bomb.group === group);\n return groupBombs.every((bomb) => {\n const bombId = `${bomb.group}-${bomb.order}`;\n return this.collectedBombs.has(bombId);\n });\n }\n\n private findNextAvailableGroup(): number | null {\n const allGroups = [...new Set(this.bombs.map((bomb) => bomb.group))].sort(\n (a, b) => a - b\n );\n\n for (const group of allGroups) {\n if (!this.isGroupCompleted(group)) {\n return group;\n }\n }\n return null;\n }\n\n private findLowestOrderInGroup(group: number): number | null {\n const groupBombs = this.bombs.filter((bomb) => bomb.group === group);\n const uncollectedBombs = groupBombs.filter((bomb) => {\n const bombId = `${bomb.group}-${bomb.order}`;\n return !this.collectedBombs.has(bombId);\n });\n\n if (uncollectedBombs.length > 0) {\n return Math.min(...uncollectedBombs.map((bomb) => bomb.order));\n }\n return null;\n }\n\n private findNextAvailableOrderInGroup(group: number): number | null {\n return this.findLowestOrderInGroup(group);\n }\n\n private isGameCompleted(): boolean {\n return this.collectedBombs.size === this.bombs.length;\n }\n\n // Getters for accessing state\n getCollectedBombs(): Set<string> {\n return new Set(this.collectedBombs);\n }\n\n getCorrectBombs(): Set<string> {\n return new Set(this.correctBombs);\n }\n\n getActiveGroup(): number | null {\n return this.activeGroup;\n }\n\n getNextBombOrder(): number | null {\n return this.nextBombOrder;\n }\n\n isGameStarted(): boolean {\n return this.gameStarted;\n }\n\n getCorrectOrderCount(): number {\n return this.correctBombs.size;\n }\n}\n","import { StateCreator } from 'zustand';\nimport { Monster, Platform, Ground, MapDefinition } from '../../types/interfaces';\nimport { LevelHistoryEntry } from '../../lib/communicationUtils';\nimport { BombManager } from '../../managers/bombManager';\nimport { mapDefinitions } from '../../maps/mapDefinitions';\nimport { sendMapCompletionData } from '../../lib/communicationUtils';\nimport { log } from '../../lib/logger';\nimport { MonsterType } from '../../types/enums';\nimport { COLORS } from '../../types/constants';\n\nexport interface LevelSlice {\n currentMap: MapDefinition | null;\n levelStartTime: number;\n levelCompletionTime: number | null;\n monsters: Monster[];\n platforms: Platform[];\n ground: Ground | null;\n \n initializeLevel: (mapData: MapDefinition) => { bombManager: BombManager; firstBomb: unknown };\n updateMonsters: (monsters: Monster[]) => void;\n resetLevelState: () => void;\n sendLevelCompletionData: (data: {\n mapName: string;\n level: number;\n correctOrderCount: number;\n totalBombs: number;\n score: number;\n bonus: number;\n hasBonus: boolean;\n lives: number;\n multiplier: number;\n coinsCollected?: number;\n powerModeActivations?: number;\n }) => void;\n}\n\nexport const createLevelSlice: StateCreator<LevelSlice> = (set, get) => ({\n currentMap: null,\n levelStartTime: 0,\n levelCompletionTime: null,\n monsters: [],\n platforms: [],\n ground: null,\n \n initializeLevel: (mapData: MapDefinition) => {\n const bombManager = new BombManager(mapData.bombs);\n \n const sortedBombs = [...mapData.bombs].sort((a, b) => a.group - b.group || a.order - b.order);\n const firstBomb = sortedBombs[0];\n \n // Assign colors to monsters based on their type\n const getMonsterColor = (type: string): string => {\n switch (type) {\n case MonsterType.HORIZONTAL_PATROL:\n return COLORS.MONSTER;\n case MonsterType.VERTICAL_PATROL:\n return '#FF6B6B'; // Red\n case MonsterType.CHASER:\n return '#FFD93D'; // Yellow\n case MonsterType.AMBUSHER:\n return '#FF8800'; // Orange\n case MonsterType.FLOATER:\n return '#4ECDC4'; // Cyan\n default:\n return COLORS.MONSTER;\n }\n };\n \n const monstersWithColors = mapData.monsters.map(monster => ({\n ...monster,\n color: monster.color || getMonsterColor(monster.type)\n }));\n \n set({\n currentMap: mapData,\n platforms: mapData.platforms,\n ground: mapData.ground,\n monsters: monstersWithColors\n });\n \n return { bombManager, firstBomb };\n },\n \n updateMonsters: (monsters: Monster[]) => {\n set({ monsters });\n },\n \n resetLevelState: () => {\n set({\n currentMap: null,\n levelStartTime: 0,\n levelCompletionTime: null,\n monsters: [],\n platforms: [],\n ground: null\n });\n },\n \n sendLevelCompletionData: (data) => {\n const { levelStartTime } = get();\n const completionTime = Date.now() - levelStartTime;\n \n const completionData = {\n ...data,\n timestamp: Date.now(),\n completionTime,\n };\n \n log.debug(\"Sending level completion data:\", completionData);\n sendMapCompletionData(completionData);\n \n // Note: Level history is now handled by LevelHistorySlice\n },\n});","import { StateCreator } from 'zustand';\n\nexport interface LevelResult {\n level: number;\n mapName: string;\n correctOrderCount: number;\n totalBombs: number;\n score: number;\n bonus: number;\n hasBonus: boolean;\n coinsCollected: number;\n powerModeActivations: number;\n completionTime: number;\n timestamp: number;\n lives: number;\n multiplier: number;\n}\n\nexport interface LevelHistorySlice {\n levelHistory: LevelResult[];\n gameStartTime: number;\n sessionId: string;\n \n addLevelResult: (result: LevelResult) => void;\n getLevelResults: () => LevelResult[];\n resetLevelHistory: () => void;\n setGameStartTime: (startTime: number) => void;\n getGameStartTime: () => number;\n getSessionId: () => string;\n}\n\nexport const createLevelHistorySlice: StateCreator<LevelHistorySlice> = (set, get) => ({\n levelHistory: [],\n gameStartTime: 0,\n sessionId: `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n \n addLevelResult: (result: LevelResult) => {\n set((state) => ({\n levelHistory: [...state.levelHistory, {\n ...result,\n completionTime: result.completionTime || 0,\n timestamp: result.timestamp || Date.now(),\n lives: result.lives || 0,\n multiplier: result.multiplier || 1,\n totalBombs: result.totalBombs || 0,\n correctOrderCount: result.correctOrderCount || 0\n }]\n }));\n },\n \n getLevelResults: () => {\n return get().levelHistory;\n },\n \n resetLevelHistory: () => {\n set({ \n levelHistory: [],\n gameStartTime: Date.now(),\n sessionId: `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`\n });\n },\n\n setGameStartTime: (startTime: number) => {\n set({ gameStartTime: startTime });\n },\n\n getGameStartTime: () => {\n return get().gameStartTime;\n },\n\n getSessionId: () => {\n return get().sessionId;\n }\n}); ","import { StateCreator } from 'zustand';\nimport { GAME_CONFIG } from '../../types/constants';\n\nexport interface MultiplierSlice {\n multiplier: number;\n multiplierScore: number;\n \n calculateMultiplier: (multiplierScore: number) => number;\n addMultiplierScore: (points: number) => { newMultiplier: number; multiplierIncreased: boolean };\n resetMultiplier: () => void;\n setMultiplier: (multiplier: number, multiplierScore: number) => void;\n}\n\nexport const createMultiplierSlice: StateCreator<MultiplierSlice> = (set, get) => ({\n multiplier: 1,\n multiplierScore: 0,\n \n calculateMultiplier: (multiplierScore: number) => {\n const { MULTIPLIER_THRESHOLDS, MAX_MULTIPLIER } = GAME_CONFIG;\n \n for (let multiplier = MAX_MULTIPLIER; multiplier >= 1; multiplier--) {\n if (multiplierScore >= MULTIPLIER_THRESHOLDS[multiplier as keyof typeof MULTIPLIER_THRESHOLDS]) {\n return multiplier;\n }\n }\n return 1;\n },\n \n addMultiplierScore: (points: number) => {\n const { multiplier, multiplierScore, calculateMultiplier } = get();\n \n const newMultiplierScore = multiplierScore + points;\n const newMultiplier = calculateMultiplier(newMultiplierScore);\n const multiplierIncreased = newMultiplier > multiplier;\n \n set({\n multiplier: Math.max(multiplier, newMultiplier),\n multiplierScore: multiplierIncreased ? 0 : newMultiplierScore\n });\n \n return { newMultiplier: Math.max(multiplier, newMultiplier), multiplierIncreased };\n },\n \n resetMultiplier: () => {\n set({ multiplier: 1, multiplierScore: 0 });\n },\n \n setMultiplier: (multiplier: number, multiplierScore: number) => {\n \n set({ multiplier, multiplierScore });\n }\n}); ","import { StateCreator } from \"zustand\";\nimport { DEFAULT_AUDIO_SETTINGS } from \"../../types/constants\";\n\nexport interface AudioSettings {\n masterVolume: number;\n musicVolume: number;\n sfxVolume: number;\n masterMuted: boolean;\n musicMuted: boolean;\n sfxMuted: boolean;\n}\n\ninterface AudioManagerInterface {\n updateVolumes: () => void;\n}\n\nexport interface AudioSettingsSlice {\n audioSettings: AudioSettings;\n audioManager: AudioManagerInterface | null;\n updateAudioSettings: (settings: Partial<AudioSettings>) => void;\n resetAudioSettings: () => void;\n setAudioManager: (audioManager: AudioManagerInterface) => void;\n}\n\nexport const createAudioSettingsSlice: StateCreator<AudioSettingsSlice> = (\n set,\n get\n) => ({\n audioSettings: DEFAULT_AUDIO_SETTINGS,\n audioManager: null,\n\n updateAudioSettings: (newSettings: Partial<AudioSettings>) => {\n set({\n audioSettings: { ...get().audioSettings, ...newSettings },\n });\n\n // Update AudioManager if available\n const audioManager = get().audioManager;\n if (audioManager && audioManager.updateVolumes) {\n audioManager.updateVolumes();\n }\n },\n\n resetAudioSettings: () => {\n set({ audioSettings: DEFAULT_AUDIO_SETTINGS });\n\n // Update AudioManager if available\n const audioManager = get().audioManager;\n if (audioManager && audioManager.updateVolumes) {\n audioManager.updateVolumes();\n }\n },\n\n setAudioManager: (audioManager: AudioManagerInterface) => {\n set({ audioManager });\n },\n});\n","import { StateCreator } from 'zustand';\nimport { Coin, CoinSpawnPoint, Monster } from '../../types/interfaces';\nimport { CoinManager } from '../../managers/coinManager';\nimport { GAME_CONFIG } from '../../types/constants';\nimport { log } from '../../lib/logger';\n\nexport interface CoinSlice {\n coins: Coin[];\n coinManager: CoinManager | null;\n activeEffects: {\n powerMode: boolean;\n powerModeEndTime: number;\n };\n firebombCount: number;\n totalCoinsCollected: number;\n totalPowerCoinsCollected: number;\n totalBonusMultiplierCoinsCollected: number;\n totalExtraLifeCoinsCollected: number;\n \n // Actions\n setCoins: (coins: Coin[]) => void;\n setCoinManager: (manager: CoinManager) => void;\n collectCoin: (coin: Coin) => void;\n onFirebombCollected: () => void;\n resetCoinState: () => void;\n updateMonsterStates: (monsters: Monster[]) => void;\n resetEffects: () => void;\n getCoinStats: () => { totalCoinsCollected: number; totalPowerCoinsCollected: number; totalBonusMultiplierCoinsCollected: number };\n}\n\nexport const createCoinSlice: StateCreator<CoinSlice> = (set, get) => ({\n coins: [],\n coinManager: null,\n activeEffects: {\n powerMode: false,\n powerModeEndTime: 0\n },\n firebombCount: 0,\n totalCoinsCollected: 0,\n totalPowerCoinsCollected: 0,\n totalBonusMultiplierCoinsCollected: 0,\n totalExtraLifeCoinsCollected: 0,\n \n setCoins: (coins: Coin[]) => {\n set({ coins });\n },\n \n setCoinManager: (manager: CoinManager) => {\n set({ coinManager: manager });\n },\n \n collectCoin: (coin: Coin) => {\n const { coinManager } = get();\n if (!coinManager) return;\n \n coinManager.collectCoin(coin);\n \n // Update coins list\n const updatedCoins = get().coins.map(c => \n c === coin ? { ...c, isCollected: true } : c\n );\n \n // Update active effects with dynamic duration for P-coins\n let powerModeEndTime = 0;\n if (coinManager.isPowerModeActive()) {\n if (coin.type === 'POWER' && coin.spawnTime !== undefined) {\n // Get duration based on coin color\n const colorData = coinManager.getPcoinColorForTime(coin.spawnTime);\n powerModeEndTime = Date.now() + colorData.duration;\n }\n // No fallback needed - if it's not a P-coin, power mode shouldn't be active\n }\n \n const activeEffects = {\n powerMode: coinManager.isPowerModeActive(),\n powerModeEndTime\n };\n \n // Update total collection counters\n const currentState = get();\n const newTotalCoinsCollected = currentState.totalCoinsCollected + 1;\n const newTotalPowerCoinsCollected = currentState.totalPowerCoinsCollected + (coin.type === 'POWER' ? 1 : 0);\n const newTotalBonusMultiplierCoinsCollected = currentState.totalBonusMultiplierCoinsCollected + (coin.type === 'BONUS_MULTIPLIER' ? 1 : 0);\n const newTotalExtraLifeCoinsCollected = currentState.totalExtraLifeCoinsCollected + (coin.type === 'EXTRA_LIFE' ? 1 : 0);\n \n set({ \n coins: updatedCoins,\n activeEffects,\n totalCoinsCollected: newTotalCoinsCollected,\n totalPowerCoinsCollected: newTotalPowerCoinsCollected,\n totalBonusMultiplierCoinsCollected: newTotalBonusMultiplierCoinsCollected,\n totalExtraLifeCoinsCollected: newTotalExtraLifeCoinsCollected\n });\n \n // Handle coin-specific effects\n const api = get();\n \n if (coin.type === 'POWER') {\n // Add points for POWER coin\n if ('addScore' in api) {\n (api as { addScore: (points: number) => void }).addScore(GAME_CONFIG.POWER_COIN_POINTS);\n }\n } else if (coin.type === 'BONUS_MULTIPLIER') {\n // Handle BONUS_MULTIPLIER coin effects\n if ('addScore' in api && 'multiplier' in api) {\n const currentMultiplier = (api as { multiplier: number }).multiplier;\n const points = 1000 * currentMultiplier;\n (api as { addScore: (points: number) => void }).addScore(points);\n \n // Increase multiplier if not at max\n if (currentMultiplier < GAME_CONFIG.MAX_MULTIPLIER) {\n // Use the multiplier slice's method to properly increase multiplier\n if ('addMultiplierScore' in api && 'multiplierScore' in api) {\n // Add enough points to reach the next multiplier threshold\n const { MULTIPLIER_THRESHOLDS } = GAME_CONFIG;\n const nextThreshold = MULTIPLIER_THRESHOLDS[(currentMultiplier + 1) as keyof typeof MULTIPLIER_THRESHOLDS];\n if (nextThreshold !== undefined) {\n const pointsNeeded = nextThreshold - (api as { multiplierScore: number }).multiplierScore;\n (api as { addMultiplierScore: (points: number) => void }).addMultiplierScore(pointsNeeded);\n }\n }\n }\n }\n } else if (coin.type === 'EXTRA_LIFE') {\n // Handle EXTRA_LIFE coin effects\n if ('addScore' in api && 'multiplier' in api && 'addLife' in api) {\n const currentMultiplier = (api as { multiplier: number }).multiplier;\n const points = GAME_CONFIG.EXTRA_LIFE_COIN_POINTS * currentMultiplier;\n (api as { addScore: (points: number) => void }).addScore(points);\n \n // Add extra life\n (api as { addLife: () => void }).addLife();\n log.debug(`Extra life added via coin slice!`);\n }\n }\n \n log.debug(`Coin collected: ${coin.type} (Total: ${newTotalCoinsCollected}, Power: ${newTotalPowerCoinsCollected}, Bonus: ${newTotalBonusMultiplierCoinsCollected})`);\n },\n \n onFirebombCollected: () => {\n const { coinManager } = get();\n if (!coinManager) return;\n \n coinManager.onFirebombCollected();\n set({ \n firebombCount: coinManager.getFirebombCount(),\n coins: coinManager.getCoins()\n });\n },\n \n resetCoinState: () => {\n const { coinManager } = get();\n if (coinManager) {\n coinManager.reset();\n }\n \n set({\n coins: [],\n activeEffects: {\n powerMode: false,\n powerModeEndTime: 0\n },\n firebombCount: 0,\n totalCoinsCollected: 0,\n totalPowerCoinsCollected: 0,\n totalBonusMultiplierCoinsCollected: 0,\n totalExtraLifeCoinsCollected: 0\n });\n },\n \n getCoinStats: () => {\n const state = get();\n return {\n totalCoinsCollected: state.totalCoinsCollected,\n totalPowerCoinsCollected: state.totalPowerCoinsCollected,\n totalBonusMultiplierCoinsCollected: state.totalBonusMultiplierCoinsCollected,\n totalExtraLifeCoinsCollected: state.totalExtraLifeCoinsCollected\n };\n },\n \n updateMonsterStates: (monsters: Monster[]) => {\n const { coinManager } = get();\n if (!coinManager) return;\n \n // Check if power mode just ended\n const wasPowerModeActive = get().activeEffects.powerMode;\n const isPowerModeActive = coinManager.isPowerModeActive();\n \n if (wasPowerModeActive && !isPowerModeActive) {\n // Power mode just ended, unfreeze all monsters\n monsters.forEach(monster => {\n monster.isFrozen = false;\n });\n } else {\n // Update monster states based on current power mode\n coinManager.updateMonsters(monsters);\n }\n \n // Update active effects state\n let powerModeEndTime = 0;\n if (isPowerModeActive && coinManager) {\n // For ongoing power mode, get the actual end time from the effect\n powerModeEndTime = coinManager.getPowerModeEndTime();\n }\n \n set({\n activeEffects: {\n powerMode: isPowerModeActive,\n powerModeEndTime\n }\n });\n },\n \n resetEffects: () => {\n const { coinManager } = get();\n if (coinManager) {\n coinManager.resetEffects();\n }\n \n set({\n activeEffects: {\n powerMode: false,\n powerModeEndTime: 0\n }\n });\n }\n}); ","import { StateCreator } from 'zustand';\nimport { FloatingText } from '../../types/interfaces';\n\nexport interface FloatingTextSlice {\n floatingTexts: FloatingText[];\n \n addFloatingText: (text: string, x: number, y: number, duration?: number, color?: string, fontSize?: number) => void;\n removeFloatingText: (id: string) => void;\n updateFloatingTexts: () => void;\n clearAllFloatingTexts: () => void;\n}\n\nexport const createFloatingTextSlice: StateCreator<FloatingTextSlice> = (set, get) => ({\n floatingTexts: [],\n \n addFloatingText: (text: string, x: number, y: number, duration: number = 1000, color: string = '#FFFFFF', fontSize: number = 16) => {\n const id = `floating-text-${Date.now()}-${Math.random()}`;\n const floatingText: FloatingText = {\n id,\n text,\n x,\n y,\n startTime: Date.now(),\n duration,\n color,\n fontSize\n };\n \n set(state => ({\n floatingTexts: [...state.floatingTexts, floatingText]\n }));\n },\n \n removeFloatingText: (id: string) => {\n set(state => ({\n floatingTexts: state.floatingTexts.filter(text => text.id !== id)\n }));\n },\n \n updateFloatingTexts: () => {\n const currentTime = Date.now();\n set(state => ({\n floatingTexts: state.floatingTexts.filter(text => \n currentTime - text.startTime < text.duration\n )\n }));\n },\n \n clearAllFloatingTexts: () => {\n set({ floatingTexts: [] });\n }\n}); ","import { Monster } from \"../types/interfaces\";\nimport { logger } from \"../lib/logger\";\n\n// Unified scaling configuration\nexport interface ScalingConfig {\n base: MonsterScalingValues;\n scaling: MonsterScalingValues;\n max: MonsterScalingValues;\n}\n\nexport interface MonsterScalingValues {\n ambusher: { ambushInterval: number; speed: number };\n chaser: { speed: number; directness: number; updateInterval: number };\n floater: { speed: number; bounceAngle: number };\n patrol: { speed: number };\n}\n\nexport interface PauseState {\n isPaused: boolean;\n pauseStartTime: number;\n totalPausedTime: number;\n pauseReasons: Set<string>;\n}\n\nexport class ScalingManager {\n private static instance: ScalingManager;\n private config: ScalingConfig;\n private globalPauseState: PauseState;\n private monsterCache: Map<\n string,\n { values: MonsterScalingValues; lastUpdate: number }\n >;\n private globalCache: {\n values: MonsterScalingValues;\n lastUpdate: number;\n } | null;\n private cacheTimeout: number = 1000; // 1 second cache\n\n private constructor() {\n this.config = this.getDefaultConfig();\n this.globalPauseState = this.createPauseState();\n this.monsterCache = new Map();\n this.globalCache = null;\n }\n\n public static getInstance(): ScalingManager {\n if (!ScalingManager.instance) {\n ScalingManager.instance = new ScalingManager();\n }\n return ScalingManager.instance;\n }\n\n // ===== CONFIGURATION =====\n private getDefaultConfig(): ScalingConfig {\n return {\n base: {\n ambusher: { ambushInterval: 5000, speed: 2 }, // Slower, less frequent ambushes\n chaser: { speed: 1, directness: 0.3, updateInterval: 200 }, // Slower, less direct, less frequent updates\n floater: { speed: 2, bounceAngle: 0.2 }, // Slower, less erratic\n patrol: { speed: 1 }, // Slower patrol\n },\n scaling: {\n ambusher: { ambushInterval: -500, speed: 0.08 }, // Increased scaling factors\n chaser: { speed: 0.2, directness: 0.08, updateInterval: -8 }, // Increased scaling factors\n floater: { speed: 0.5, bounceAngle: 0.008 }, // Increased scaling factors\n patrol: { speed: 0.2 }, // Increased scaling factors\n },\n max: {\n ambusher: { ambushInterval: 500, speed: 10 }, // Increased max values for more challenge\n chaser: { speed: 5.0, directness: 1, updateInterval: 100 }, // Increased max values for more challenge\n floater: { speed: 5.0, bounceAngle: 0.5 }, // Increased max values for more challenge\n patrol: { speed: 5.0 }, // Increased max values for more challenge\n },\n };\n }\n\n public updateConfig(newConfig: Partial<ScalingConfig>): void {\n this.config = { ...this.config, ...newConfig };\n this.clearCache();\n logger.debug(\"ScalingManager: Configuration updated\");\n }\n\n // ===== PAUSE MANAGEMENT =====\n private createPauseState(): PauseState {\n return {\n isPaused: false,\n pauseStartTime: 0,\n totalPausedTime: 0,\n pauseReasons: new Set(),\n };\n }\n\n public pause(reason: string = \"default\"): void {\n if (!this.globalPauseState.isPaused) {\n this.globalPauseState.isPaused = true;\n this.globalPauseState.pauseStartTime = Date.now();\n }\n this.globalPauseState.pauseReasons.add(reason);\n logger.pause(`Scaling paused (${reason})`);\n }\n\n public resume(reason: string = \"default\"): void {\n this.globalPauseState.pauseReasons.delete(reason);\n\n if (\n this.globalPauseState.pauseReasons.size === 0 &&\n this.globalPauseState.isPaused\n ) {\n const pauseDuration = Date.now() - this.globalPauseState.pauseStartTime;\n this.globalPauseState.totalPausedTime += pauseDuration;\n this.globalPauseState.isPaused = false;\n this.clearCache();\n logger.pause(\n `Scaling resumed (paused for ${(pauseDuration / 1000).toFixed(1)}s)`\n );\n }\n }\n\n public isPaused(): boolean {\n return this.globalPauseState.isPaused;\n }\n\n public getPauseReasons(): string[] {\n return Array.from(this.globalPauseState.pauseReasons);\n }\n\n public getPauseStatus(): any {\n return {\n isPaused: this.globalPauseState.isPaused,\n pauseReasons: this.getPauseReasons(),\n totalPausedTime: this.globalPauseState.totalPausedTime,\n timeElapsed: this.getGlobalTimeElapsed(),\n globalStartTime: this.globalStartTime,\n currentTime: Date.now(),\n };\n }\n\n // ===== GLOBAL SCALING (DifficultyManager replacement) =====\n private globalStartTime: number = 0;\n\n public startMap(): void {\n this.globalStartTime = Date.now();\n this.globalPauseState = this.createPauseState();\n this.clearCache();\n logger.flow(\"New map started - difficulty reset\");\n }\n\n public resetOnDeath(): void {\n this.globalStartTime = Date.now();\n this.globalPauseState = this.createPauseState();\n this.clearCache();\n logger.player(\"Player died - difficulty reset to base values\");\n }\n\n public getGlobalScaledValues(): MonsterScalingValues {\n const now = Date.now();\n\n // Check cache first\n if (\n this.globalCache &&\n now - this.globalCache.lastUpdate < this.cacheTimeout\n ) {\n return this.globalCache.values;\n }\n\n const values = this.calculateScaledValues(this.getGlobalTimeElapsed());\n this.globalCache = { values, lastUpdate: now };\n return values;\n }\n\n private getGlobalTimeElapsed(): number {\n if (this.globalStartTime === 0) return 0;\n const currentTime = Date.now();\n const actualElapsed = currentTime - this.globalStartTime;\n return (actualElapsed - this.globalPauseState.totalPausedTime) / 1000;\n }\n\n public pauseForPowerMode(): void {\n this.pause(\"power_mode\");\n logger.power(\"Power mode activated - scaling paused\");\n }\n\n public resumeFromPowerMode(): void {\n this.resume(\"power_mode\");\n logger.power(\"Power mode ended - scaling resumed\");\n }\n\n public isCurrentlyPausedByPowerMode(): boolean {\n return this.globalPauseState.pauseReasons.has(\"power_mode\");\n }\n\n // ===== GLOBAL MONSTER SCALING CONTROL =====\n public pauseAllMonsterScaling(): void {\n this.pause(\"monster_scaling\");\n // Only log if this is a new pause (not already paused)\n if (this.globalPauseState.pauseReasons.size === 1) {\n logger.pause(\"All monster scaling paused\");\n }\n }\n\n public resumeAllMonsterScaling(): void {\n this.resume(\"monster_scaling\");\n // Only log if this was the last pause reason (completely resumed)\n if (this.globalPauseState.pauseReasons.size === 0) {\n logger.pause(\"All monster scaling resumed\");\n }\n }\n\n // ===== INDIVIDUAL MONSTER SCALING =====\n public getMonsterScaledValues(monster: Monster): MonsterScalingValues {\n this.initializeMonster(monster);\n\n // Check both individual and global pause states\n if (monster.individualScalingPaused || this.globalPauseState.isPaused) {\n return this.config.base;\n }\n\n const cacheKey = this.getMonsterCacheKey(monster);\n const now = Date.now();\n\n // Check cache first\n const cached = this.monsterCache.get(cacheKey);\n if (cached && now - cached.lastUpdate < this.cacheTimeout) {\n return cached.values;\n }\n\n const oldValues = cached?.values || this.config.base;\n const values = this.calculateScaledValues(this.getMonsterAge(monster));\n\n // Log scaling changes if values have changed significantly\n this.logScalingChanges(monster, oldValues, values);\n\n this.monsterCache.set(cacheKey, { values, lastUpdate: now });\n return values;\n }\n\n public initializeMonster(monster: Monster): void {\n if (!monster.individualSpawnTime) {\n monster.individualSpawnTime = Date.now();\n monster.individualScalingPaused = false;\n // Store the total paused time when monster was spawned to account for future pauses\n (monster as any).spawnPauseTime = this.globalPauseState.totalPausedTime;\n\n // Log initial scaling values\n const baseValues = this.config.base;\n let initialInfo = \"\";\n\n switch (monster.type) {\n case \"AMBUSHER\":\n initialInfo = `ambush interval: ${\n baseValues.ambusher.ambushInterval\n }ms, speed: ${baseValues.ambusher.speed.toFixed(2)}`;\n break;\n case \"CHASER\":\n initialInfo = `speed: ${baseValues.chaser.speed.toFixed(\n 2\n )}, directness: ${baseValues.chaser.directness.toFixed(\n 3\n )}, update interval: ${baseValues.chaser.updateInterval}ms`;\n break;\n case \"FLOATER\":\n initialInfo = `speed: ${baseValues.floater.speed.toFixed(\n 2\n )}, bounce angle: ${baseValues.floater.bounceAngle.toFixed(3)}`;\n break;\n case \"HORIZONTAL_PATROL\":\n case \"VERTICAL_PATROL\":\n initialInfo = `speed: ${baseValues.patrol.speed.toFixed(2)}`;\n break;\n default:\n initialInfo = \"base values\";\n }\n\n logger.scaling(`${monster.type} initialized with ${initialInfo}`);\n }\n }\n\n public resetMonsterScaling(monster: Monster): void {\n monster.individualSpawnTime = Date.now();\n monster.individualScalingPaused = false;\n (monster as any).spawnPauseTime = this.globalPauseState.totalPausedTime;\n this.monsterCache.delete(this.getMonsterCacheKey(monster));\n logger.monster(`${monster.type} scaling reset`);\n }\n\n public pauseMonsterScaling(monster: Monster): void {\n monster.individualScalingPaused = true;\n this.monsterCache.delete(this.getMonsterCacheKey(monster));\n }\n\n public resumeMonsterScaling(monster: Monster): void {\n monster.individualScalingPaused = false;\n this.monsterCache.delete(this.getMonsterCacheKey(monster));\n }\n\n public getMonsterAge(monster: Monster): number {\n if (!monster.individualSpawnTime) return 0;\n const currentTime = Date.now();\n const actualElapsed = currentTime - monster.individualSpawnTime;\n // Account for pause time that occurred after this monster was spawned\n const pauseTimeAfterSpawn =\n this.globalPauseState.totalPausedTime -\n ((monster as any).spawnPauseTime || 0);\n const adjustedElapsed = actualElapsed - pauseTimeAfterSpawn;\n const age = Math.max(0, adjustedElapsed) / 1000;\n\n // Debug logging for pause system verification (only in debug mode)\n if (this.globalPauseState.isPaused && age > 0) {\n logger.debug(\n `Monster age: ${monster.type} - Actual: ${(\n actualElapsed / 1000\n ).toFixed(1)}s, Paused: ${(pauseTimeAfterSpawn / 1000).toFixed(\n 1\n )}s, Adjusted: ${age.toFixed(1)}s`\n );\n }\n\n return age;\n }\n\n // ===== UTILITY METHODS =====\n private getMonsterCacheKey(monster: Monster): string {\n // Use monster's position and spawn time to make cache key unique per instance\n // This ensures multiple monsters of the same type don't share the same cache\n const position = `${Math.round(monster.x)}-${Math.round(monster.y)}`;\n return `${monster.type}-${position}-${monster.individualSpawnTime || 0}`;\n }\n\n private logScalingChanges(\n monster: Monster,\n oldValues: MonsterScalingValues,\n newValues: MonsterScalingValues\n ): void {\n const age = this.getMonsterAge(monster);\n const intervals = Math.floor(age / 5);\n\n // Only log if we're in a new interval (to avoid spam)\n if (intervals > 0 && intervals % 1 === 0) {\n const changes: string[] = [];\n\n // Only show relevant changes for the specific monster type\n switch (monster.type) {\n case \"AMBUSHER\":\n if (\n Math.abs(oldValues.ambusher.speed - newValues.ambusher.speed) > 0.01\n ) {\n changes.push(\n `speed: ${oldValues.ambusher.speed.toFixed(\n 2\n )} → ${newValues.ambusher.speed.toFixed(2)}`\n );\n }\n if (\n Math.abs(\n oldValues.ambusher.ambushInterval -\n newValues.ambusher.ambushInterval\n ) > 50\n ) {\n changes.push(\n `ambush interval: ${oldValues.ambusher.ambushInterval}ms → ${newValues.ambusher.ambushInterval}ms`\n );\n }\n break;\n\n case \"CHASER\":\n if (\n Math.abs(oldValues.chaser.speed - newValues.chaser.speed) > 0.01\n ) {\n changes.push(\n `speed: ${oldValues.chaser.speed.toFixed(\n 2\n )} → ${newValues.chaser.speed.toFixed(2)}`\n );\n }\n if (\n Math.abs(\n oldValues.chaser.directness - newValues.chaser.directness\n ) > 0.01\n ) {\n changes.push(\n `directness: ${oldValues.chaser.directness.toFixed(\n 3\n )} → ${newValues.chaser.directness.toFixed(3)}`\n );\n }\n if (\n Math.abs(\n oldValues.chaser.updateInterval - newValues.chaser.updateInterval\n ) > 5\n ) {\n changes.push(\n `update interval: ${oldValues.chaser.updateInterval}ms → ${newValues.chaser.updateInterval}ms`\n );\n }\n break;\n\n case \"FLOATER\":\n if (\n Math.abs(oldValues.floater.speed - newValues.floater.speed) > 0.01\n ) {\n changes.push(\n `speed: ${oldValues.floater.speed.toFixed(\n 2\n )} → ${newValues.floater.speed.toFixed(2)}`\n );\n }\n if (\n Math.abs(\n oldValues.floater.bounceAngle - newValues.floater.bounceAngle\n ) > 0.001\n ) {\n changes.push(\n `bounce angle: ${oldValues.floater.bounceAngle.toFixed(\n 3\n )} → ${newValues.floater.bounceAngle.toFixed(3)}`\n );\n }\n break;\n\n case \"HORIZONTAL_PATROL\":\n case \"VERTICAL_PATROL\":\n if (\n Math.abs(oldValues.patrol.speed - newValues.patrol.speed) > 0.01\n ) {\n changes.push(\n `speed: ${oldValues.patrol.speed.toFixed(\n 2\n )} → ${newValues.patrol.speed.toFixed(2)}`\n );\n }\n break;\n }\n\n if (changes.length > 0) {\n logger.scaling(\n `${monster.type} scaling (${age.toFixed(\n 1\n )}s, interval ${intervals}): ${changes.join(\", \")}`\n );\n }\n }\n }\n\n private calculateScaledValues(timeElapsed: number): MonsterScalingValues {\n const intervals = Math.floor(timeElapsed / 5); // Changed from 10 to 5 seconds\n\n return {\n ambusher: {\n ambushInterval: this.calculateScaledValue(\n this.config.base.ambusher.ambushInterval,\n this.config.scaling.ambusher.ambushInterval,\n this.config.max.ambusher.ambushInterval,\n intervals\n ),\n speed: this.calculateScaledValue(\n this.config.base.ambusher.speed,\n this.config.scaling.ambusher.speed,\n this.config.max.ambusher.speed,\n intervals\n ),\n },\n chaser: {\n speed: this.calculateScaledValue(\n this.config.base.chaser.speed,\n this.config.scaling.chaser.speed,\n this.config.max.chaser.speed,\n intervals\n ),\n directness: this.calculateScaledValue(\n this.config.base.chaser.directness,\n this.config.scaling.chaser.directness,\n this.config.max.chaser.directness,\n intervals\n ),\n updateInterval: this.calculateScaledValue(\n this.config.base.chaser.updateInterval,\n this.config.scaling.chaser.updateInterval,\n this.config.max.chaser.updateInterval,\n intervals\n ),\n },\n floater: {\n speed: this.calculateScaledValue(\n this.config.base.floater.speed,\n this.config.scaling.floater.speed,\n this.config.max.floater.speed,\n intervals\n ),\n bounceAngle: this.calculateScaledValue(\n this.config.base.floater.bounceAngle,\n this.config.scaling.floater.bounceAngle,\n this.config.max.floater.bounceAngle,\n intervals\n ),\n },\n patrol: {\n speed: this.calculateScaledValue(\n this.config.base.patrol.speed,\n this.config.scaling.patrol.speed,\n this.config.max.patrol.speed,\n intervals\n ),\n },\n };\n }\n\n private calculateScaledValue(\n baseValue: number,\n scalingFactor: number,\n maxValue: number,\n intervals: number\n ): number {\n const scaledValue = baseValue + scalingFactor * intervals;\n return scalingFactor > 0\n ? Math.min(scaledValue, maxValue)\n : Math.max(scaledValue, maxValue);\n }\n\n private clearCache(): void {\n this.monsterCache.clear();\n this.globalCache = null;\n }\n\n public getBaseValues(): MonsterScalingValues {\n return { ...this.config.base };\n }\n\n public cleanup(): void {\n this.clearCache();\n this.globalPauseState = this.createPauseState();\n }\n}\n","import {\n CoinTypeConfig,\n CoinEffect,\n CoinPhysicsConfig,\n GameStateInterface,\n Coin,\n Platform,\n Ground,\n} from \"../types/interfaces\";\nimport { CoinType } from \"../types/enums\";\nimport { GAME_CONFIG } from \"../types/constants\";\nimport { ScalingManager } from \"../managers/ScalingManager\";\n\n// Define coin effects\nexport const COIN_EFFECTS = {\n POWER_MODE: {\n type: \"POWER_MODE\",\n duration: GAME_CONFIG.POWER_COIN_DURATION, // Default duration (will be overridden)\n points: GAME_CONFIG.POWER_COIN_POINTS,\n apply: (gameState: GameStateInterface, coin?: any) => {\n // Calculate duration based on coin color if available\n let duration = GAME_CONFIG.POWER_COIN_DURATION; // Default fallback\n\n if (coin && coin.spawnTime !== undefined) {\n // Get the color data for this specific coin\n const coinManager = gameState.coinManager;\n if (\n coinManager &&\n typeof coinManager.getPcoinColorForTime === \"function\"\n ) {\n try {\n const colorData = coinManager.getPcoinColorForTime(coin.spawnTime);\n duration = colorData.duration || GAME_CONFIG.POWER_COIN_DURATION;\n } catch (error) {\n console.warn(\n \"Failed to get P-coin color data, using default duration:\",\n error\n );\n }\n }\n }\n\n // Freeze monsters (safely handle undefined monsters)\n if (gameState.monsters && Array.isArray(gameState.monsters)) {\n gameState.monsters.forEach((monster) => {\n monster.isFrozen = true;\n });\n }\n\n // Enable monster killing\n gameState.activeEffects.powerMode = true;\n gameState.activeEffects.powerModeEndTime = Date.now() + duration;\n\n // Reset monster kill count for new power mode session\n if (gameState.coinManager) {\n gameState.coinManager.resetMonsterKillCount();\n }\n\n // Pause difficulty scaling during power mode\n try {\n const scalingManager = ScalingManager.getInstance();\n scalingManager.pauseForPowerMode();\n } catch (error) {\n console.log(\n \"Could not pause difficulty scaling (ScalingManager not available)\"\n );\n }\n\n // Log the actual duration being used\n // Removed console.log to avoid duplicate logging\n },\n remove: (gameState: GameStateInterface) => {\n // Unfreeze monsters (safely handle undefined monsters)\n if (gameState.monsters && Array.isArray(gameState.monsters)) {\n gameState.monsters.forEach((monster) => {\n monster.isFrozen = false;\n });\n }\n gameState.activeEffects.powerMode = false;\n\n // Resume difficulty scaling when power mode ends\n try {\n const scalingManager = ScalingManager.getInstance();\n scalingManager.resumeFromPowerMode();\n // Removed console.log to avoid duplicate logging\n } catch (error) {\n console.log(\n \"Could not resume difficulty scaling (ScalingManager not available)\"\n );\n }\n },\n },\n\n BONUS_MULTIPLIER: {\n type: \"BONUS_MULTIPLIER\",\n points: 0, // Points will be calculated dynamically\n apply: (gameState: GameStateInterface) => {\n // Give points based on current multiplier (1000 * multiplier)\n const points = 1000 * gameState.multiplier;\n gameState.addScore(points);\n\n // Increase multiplier\n if (gameState.multiplier < GAME_CONFIG.MAX_MULTIPLIER) {\n gameState.setMultiplier(gameState.multiplier + 1, 0);\n }\n },\n },\n\n EXTRA_LIFE: {\n type: \"EXTRA_LIFE\",\n points: 1000,\n apply: (gameState: GameStateInterface) => {\n // Add extra life\n gameState.lives += 1;\n },\n },\n};\n\n// Define coin physics configurations\nexport const COIN_PHYSICS = {\n STANDARD: {\n hasGravity: true,\n bounces: true,\n reflects: false,\n },\n\n POWER: {\n hasGravity: false,\n bounces: false,\n reflects: true,\n },\n\n GRAVITY_ONLY: {\n hasGravity: false, // We'll handle gravity manually\n bounces: false,\n reflects: false,\n customUpdate: (coin, platforms, ground) => {\n const FALL_SPEED = 2;\n const HORIZONTAL_SPEED = 1;\n const LANDING_TOLERANCE = 4; // For detecting when coin lands on platform\n const EDGE_TOLERANCE = 0; // For detecting when coin should fall off platform\n\n // If falling\n if (coin.velocityY > 0 || coin.velocityY === undefined) {\n coin.velocityX = 0;\n coin.velocityY = FALL_SPEED;\n }\n\n // Check for ground collision\n if (ground && coin.y + coin.height >= ground.y) {\n coin.y = ground.y - coin.height;\n coin.velocityY = 0;\n // If not already moving horizontally, pick a direction\n if (!coin.groundDirection) {\n coin.groundDirection = Math.random() < 0.5 ? -1 : 1;\n coin.velocityX = coin.groundDirection * HORIZONTAL_SPEED;\n }\n // Move horizontally\n coin.x += coin.velocityX;\n // Bounce off map boundaries\n if (coin.x <= 0) {\n coin.x = 0;\n coin.groundDirection = 1;\n coin.velocityX = HORIZONTAL_SPEED;\n } else if (coin.x + coin.width >= GAME_CONFIG.CANVAS_WIDTH) {\n coin.x = GAME_CONFIG.CANVAS_WIDTH - coin.width;\n coin.groundDirection = -1;\n coin.velocityX = -HORIZONTAL_SPEED;\n }\n return;\n }\n\n // Check for platform collision (landing)\n let landedOnPlatform = false;\n let currentPlatform = null;\n for (const platform of platforms) {\n const coinBottom = coin.y + coin.height;\n const platformTop = platform.y;\n const isOnTop =\n coinBottom >= platformTop &&\n coinBottom <= platformTop + LANDING_TOLERANCE;\n const isHorizontallyAligned =\n coin.x < platform.x + platform.width &&\n coin.x + coin.width > platform.x;\n if (isOnTop && isHorizontallyAligned) {\n landedOnPlatform = true;\n currentPlatform = platform;\n coin.y = platformTop - coin.height;\n coin.velocityY = 0;\n // Pick a random horizontal direction if not already moving\n if (!coin.platformDirection) {\n coin.platformDirection = Math.random() < 0.5 ? -1 : 1;\n coin.velocityX = coin.platformDirection * HORIZONTAL_SPEED;\n }\n break;\n }\n }\n\n if (landedOnPlatform && currentPlatform) {\n // Move horizontally\n coin.x += coin.velocityX;\n // If at edge, fall off\n if (\n coin.x + coin.width <= currentPlatform.x + EDGE_TOLERANCE ||\n coin.x >= currentPlatform.x + currentPlatform.width - EDGE_TOLERANCE\n ) {\n coin.platformDirection = null;\n coin.velocityX = 0;\n coin.velocityY = FALL_SPEED;\n }\n } else if (!landedOnPlatform) {\n // If not on platform or ground, fall\n coin.platformDirection = null;\n coin.velocityX = 0;\n coin.velocityY = FALL_SPEED;\n }\n },\n },\n};\n\n// P-coin color progression system with duration scaling\nexport const P_COIN_COLORS = [\n { color: \"#3c82f6\", points: 100, name: \"Blue\", duration: 3000 }, // Blue - 3 seconds\n { color: \"#ef4444\", points: 200, name: \"Red\", duration: 4000 }, // Red - 4 seconds\n { color: \"#a855f7\", points: 300, name: \"Purple\", duration: 5000 }, // Purple - 5 seconds\n { color: \"#22c55d\", points: 500, name: \"Green\", duration: 6000 }, // Green - 6 seconds\n { color: \"#07b6d4\", points: 800, name: \"Cyan\", duration: 7000 }, // Cyan - 7 seconds\n { color: \"#ebb305\", points: 1200, name: \"Yellow\", duration: 8000 }, // Yellow - 8 seconds\n { color: \"#6b7280\", points: 2000, name: \"Gray\", duration: 10000 }, // Gray - 10 seconds\n];\n\n// Define all coin types according to user specifications\nexport const COIN_TYPES: Record<string, CoinTypeConfig> = {\n [CoinType.POWER]: {\n type: CoinType.POWER,\n color: \"#FF0000\", // Initial color (will be dynamic)\n points: 0, // Points will be calculated dynamically based on color\n physics: COIN_PHYSICS.POWER,\n effects: [COIN_EFFECTS.POWER_MODE],\n spawnCondition: (gameState: GameStateInterface) => {\n // Spawn every 9 firebombs collected in correct order\n return gameState.firebombCount % 9 === 0;\n },\n maxActive: 1,\n },\n\n [CoinType.BONUS_MULTIPLIER]: {\n type: CoinType.BONUS_MULTIPLIER,\n color: \"#e9b300\", // Yellow-Orange\n points: GAME_CONFIG.BONUS_MULTIPLIER_COIN_POINTS,\n physics: COIN_PHYSICS.GRAVITY_ONLY,\n effects: [COIN_EFFECTS.BONUS_MULTIPLIER],\n spawnCondition: (gameState: GameStateInterface) => {\n // Spawn every BONUS_COIN_SPAWN_INTERVAL points\n // Use bombAndMonsterPoints if available, otherwise fall back to total score\n const score =\n (gameState as any).bombAndMonsterPoints || gameState.score || 0;\n return score > 0 && score % GAME_CONFIG.BONUS_COIN_SPAWN_INTERVAL === 0;\n },\n maxActive: 1,\n },\n\n [CoinType.EXTRA_LIFE]: {\n type: CoinType.EXTRA_LIFE,\n color: \"#ef4444\", // Red\n points: GAME_CONFIG.EXTRA_LIFE_COIN_POINTS,\n physics: COIN_PHYSICS.GRAVITY_ONLY,\n effects: [COIN_EFFECTS.EXTRA_LIFE],\n spawnCondition: (gameState: GameStateInterface) => {\n // Spawn for every EXTRA_LIFE_COIN_RATIO bonus multiplier coins collected\n const bonusCount = gameState.totalBonusMultiplierCoinsCollected || 0;\n return (\n bonusCount > 0 && bonusCount % GAME_CONFIG.EXTRA_LIFE_COIN_RATIO === 0\n );\n },\n maxActive: 1,\n },\n};\n\n// Example of how to add new coin types easily:\n/*\nexport const COIN_TYPES = {\n ...COIN_TYPES,\n \n SPEED_BOOST: {\n type: 'SPEED_BOOST',\n color: '#9B59B6', // Purple\n points: 300,\n physics: COIN_PHYSICS.FLOATING,\n effects: [{\n type: 'SPEED_BOOST',\n duration: 3000,\n apply: (gameState: GameStateInterface) => {\n gameState.player.moveSpeed *= 1.5;\n },\n remove: (gameState: GameStateInterface) => {\n gameState.player.moveSpeed /= 1.5;\n }\n }],\n spawnCondition: (gameState: GameStateInterface) => gameState.score % 3000 === 0\n },\n \n MAGNET: {\n type: 'MAGNET',\n color: '#3498DB', // Blue\n points: 400,\n physics: COIN_PHYSICS.HOMING,\n effects: [{\n type: 'MAGNET',\n duration: 4000,\n apply: (gameState: GameStateInterface) => {\n gameState.activeEffects.magnetMode = true;\n },\n remove: (gameState: GameStateInterface) => {\n gameState.activeEffects.magnetMode = false;\n }\n }]\n }\n};\n*/\n","import { Coin, Platform, Ground, CoinPhysicsConfig } from \"../types/interfaces\";\nimport { GAME_CONFIG } from \"../types/constants\";\nimport { COIN_PHYSICS } from \"../config/coinTypes\";\nimport { log } from \"../lib/logger\";\n\nexport class CoinPhysics {\n /**\n * Updates the physics and movement of a coin based on its physics configuration\n */\n static updateCoin(\n coin: Coin,\n platforms: Platform[],\n ground: Ground,\n physicsConfig?: CoinPhysicsConfig\n ): void {\n if (coin.isCollected) return;\n\n if (physicsConfig) {\n // Use the provided physics configuration\n if (physicsConfig.hasGravity) {\n coin.velocityY += GAME_CONFIG.COIN_GRAVITY;\n }\n\n coin.x += coin.velocityX;\n coin.y += coin.velocityY;\n\n if (physicsConfig.reflects) {\n this.handleReflectiveCollisions(coin, platforms, ground);\n } else if (physicsConfig.bounces) {\n this.handleBouncingCollisions(coin, platforms, ground);\n }\n\n // Use custom update function if provided\n if (physicsConfig.customUpdate) {\n physicsConfig.customUpdate(coin, platforms, ground);\n }\n } else {\n // Fallback to standard physics\n this.updateStandardCoin(coin, platforms, ground);\n }\n }\n\n /**\n * Legacy method for backward compatibility - uses standard physics\n */\n static updateStandardCoin(\n coin: Coin,\n platforms: Platform[],\n ground: Ground\n ): void {\n this.updateCoin(coin, platforms, ground, COIN_PHYSICS.STANDARD);\n }\n\n /**\n * Legacy method for backward compatibility - uses power coin physics\n */\n static updatePowerCoin(\n coin: Coin,\n platforms: Platform[],\n ground: Ground\n ): void {\n this.updateCoin(coin, platforms, ground, COIN_PHYSICS.POWER);\n }\n\n /**\n * Handles collisions with bouncing behavior (damped bounces)\n */\n private static handleBouncingCollisions(\n coin: Coin,\n platforms: Platform[],\n ground: Ground\n ): void {\n // Check collisions with boundaries\n this.handleBoundaryCollisions(coin);\n\n // Check collisions with platforms\n this.handlePlatformCollisions(coin, platforms);\n\n // Check collisions with ground\n this.handleGroundCollisions(coin, ground);\n }\n\n /**\n * Handles collisions with reflective behavior (perfect reflection)\n */\n private static handleReflectiveCollisions(\n coin: Coin,\n platforms: Platform[],\n ground: Ground\n ): void {\n // Check collisions with boundaries and reflect\n this.handlePowerCoinBoundaryCollisions(coin);\n\n // Check collisions with platforms and reflect\n this.handlePowerCoinPlatformCollisions(coin, platforms);\n\n // Check collisions with ground and reflect\n this.handlePowerCoinGroundCollisions(coin, ground);\n }\n\n /**\n * Handles collisions with canvas boundaries\n */\n private static handleBoundaryCollisions(coin: Coin): void {\n // Left and right boundaries\n if (coin.x <= 0) {\n coin.x = 0;\n coin.velocityX =\n Math.abs(coin.velocityX) * GAME_CONFIG.COIN_BOUNCE_DAMPING;\n } else if (coin.x + coin.width >= GAME_CONFIG.CANVAS_WIDTH) {\n coin.x = GAME_CONFIG.CANVAS_WIDTH - coin.width;\n coin.velocityX =\n -Math.abs(coin.velocityX) * GAME_CONFIG.COIN_BOUNCE_DAMPING;\n }\n\n // Top boundary (ceiling)\n if (coin.y <= 0) {\n coin.y = 0;\n coin.velocityY =\n Math.abs(coin.velocityY) * GAME_CONFIG.COIN_BOUNCE_DAMPING;\n }\n }\n\n /**\n * Handles collisions with canvas boundaries for power coins (simple reflection)\n */\n private static handlePowerCoinBoundaryCollisions(coin: Coin): void {\n // Left boundary\n if (coin.x <= 0) {\n coin.x = 0;\n coin.velocityX = Math.abs(coin.velocityX); // Reflect horizontally\n }\n // Right boundary\n else if (coin.x + coin.width >= GAME_CONFIG.CANVAS_WIDTH) {\n coin.x = GAME_CONFIG.CANVAS_WIDTH - coin.width;\n coin.velocityX = -Math.abs(coin.velocityX); // Reflect horizontally\n }\n\n // Top boundary\n if (coin.y <= 0) {\n coin.y = 0;\n coin.velocityY = Math.abs(coin.velocityY); // Reflect vertically\n }\n // Bottom boundary - this should rarely happen since we have ground collision\n else if (coin.y + coin.height >= GAME_CONFIG.CANVAS_HEIGHT) {\n coin.y = GAME_CONFIG.CANVAS_HEIGHT - coin.height;\n coin.velocityY = -Math.abs(coin.velocityY); // Reflect vertically\n }\n }\n\n /**\n * Handles collisions with platforms\n */\n private static handlePlatformCollisions(\n coin: Coin,\n platforms: Platform[]\n ): void {\n platforms.forEach((platform) => {\n if (this.isColliding(coin, platform)) {\n // Determine collision side and bounce accordingly\n const coinCenterX = coin.x + coin.width / 2;\n const coinCenterY = coin.y + coin.height / 2;\n const platformCenterX = platform.x + platform.width / 2;\n const platformCenterY = platform.y + platform.height / 2;\n\n const deltaX = coinCenterX - platformCenterX;\n const deltaY = coinCenterY - platformCenterY;\n\n if (Math.abs(deltaX) > Math.abs(deltaY)) {\n // Horizontal collision\n if (deltaX > 0) {\n coin.x = platform.x + platform.width;\n coin.velocityX =\n Math.abs(coin.velocityX) * GAME_CONFIG.COIN_BOUNCE_DAMPING;\n } else {\n coin.x = platform.x - coin.width;\n coin.velocityX =\n -Math.abs(coin.velocityX) * GAME_CONFIG.COIN_BOUNCE_DAMPING;\n }\n } else {\n // Vertical collision\n if (deltaY > 0) {\n coin.y = platform.y + platform.height;\n coin.velocityY =\n Math.abs(coin.velocityY) * GAME_CONFIG.COIN_BOUNCE_DAMPING;\n } else {\n coin.y = platform.y - coin.height;\n coin.velocityY =\n -Math.abs(coin.velocityY) * GAME_CONFIG.COIN_BOUNCE_DAMPING;\n }\n }\n }\n });\n }\n\n /**\n * Handles collisions with platforms for power coins (using FloaterMovement logic)\n */\n private static handlePowerCoinPlatformCollisions(\n coin: Coin,\n platforms: Platform[]\n ): void {\n // Check collisions with platforms in order, but only handle the first collision\n for (const platform of platforms) {\n if (this.isColliding(coin, platform)) {\n // Use FloaterMovement's collision detection logic\n const collisionNormal = this.calculateCollisionNormal(coin, platform);\n\n // Debug: Log collision info (throttled)\n if (Math.random() < 0.1) {\n log.debug(\n `P-coin platform collision - Normal: (${collisionNormal.x.toFixed(\n 2\n )}, ${collisionNormal.y.toFixed(\n 2\n )}), Velocity before: (${coin.velocityX.toFixed(\n 2\n )}, ${coin.velocityY.toFixed(2)})`\n );\n }\n\n // Reflect the velocity vector using the normal (same as FloaterMovement)\n const dotProduct =\n coin.velocityX * collisionNormal.x +\n coin.velocityY * collisionNormal.y;\n const oldVX = coin.velocityX;\n const oldVY = coin.velocityY;\n coin.velocityX = coin.velocityX - 2 * dotProduct * collisionNormal.x;\n coin.velocityY = coin.velocityY - 2 * dotProduct * collisionNormal.y;\n\n // Debug: Log velocity after reflection\n if (Math.random() < 0.1) {\n log.debug(\n `P-coin platform collision - Velocity after: (${coin.velocityX.toFixed(\n 2\n )}, ${coin.velocityY.toFixed(2)})`\n );\n }\n\n // Simple repositioning - just move coin out of collision\n if (collisionNormal.x !== 0) {\n // Horizontal collision\n if (collisionNormal.x > 0) {\n coin.x = platform.x + platform.width + 1;\n } else {\n coin.x = platform.x - coin.width - 1;\n }\n } else {\n // Vertical collision\n if (collisionNormal.y > 0) {\n coin.y = platform.y + platform.height + 1;\n } else {\n coin.y = platform.y - coin.height - 1;\n }\n }\n\n // Only handle one collision per frame to avoid multiple reflections\n break;\n }\n }\n }\n\n /**\n * Handles collisions with ground\n */\n private static handleGroundCollisions(coin: Coin, ground: Ground): void {\n if (this.isColliding(coin, ground)) {\n coin.y = ground.y - coin.height;\n coin.velocityY =\n -Math.abs(coin.velocityY) * GAME_CONFIG.COIN_BOUNCE_DAMPING;\n\n // Stop very small bounces\n if (Math.abs(coin.velocityY) < 0.5) {\n coin.velocityY = 0;\n }\n }\n }\n\n /**\n * Handles collisions with ground for power coins (using FloaterMovement logic)\n */\n private static handlePowerCoinGroundCollisions(\n coin: Coin,\n ground: Ground\n ): void {\n if (this.isColliding(coin, ground)) {\n // Use FloaterMovement's collision detection logic\n const collisionNormal = this.calculateCollisionNormal(coin, ground);\n\n // Reflect the velocity vector using the normal (same as FloaterMovement)\n const dotProduct =\n coin.velocityX * collisionNormal.x + coin.velocityY * collisionNormal.y;\n coin.velocityX = coin.velocityX - 2 * dotProduct * collisionNormal.x;\n coin.velocityY = coin.velocityY - 2 * dotProduct * collisionNormal.y;\n\n // Simple repositioning - move coin above ground\n coin.y = ground.y - coin.height - 1;\n }\n }\n\n /**\n * Checks if two objects are colliding\n */\n private static isColliding(\n coin: Coin,\n object: { x: number; y: number; width: number; height: number }\n ): boolean {\n return (\n coin.x < object.x + object.width &&\n coin.x + coin.width > object.x &&\n coin.y < object.y + object.height &&\n coin.y + coin.height > object.y\n );\n }\n\n /**\n * Creates initial velocity for a newly spawned coin\n */\n static createInitialVelocity(): { velocityX: number; velocityY: number } {\n return {\n velocityX: (Math.random() - 0.5) * GAME_CONFIG.COIN_BOUNCE_SPEED * 2,\n velocityY: -GAME_CONFIG.COIN_BOUNCE_SPEED,\n };\n }\n\n /**\n * Creates initial velocity for power coins (pure freedom)\n */\n static createPowerCoinVelocity(spawnAngle?: number): {\n velocityX: number;\n velocityY: number;\n } {\n const speed = GAME_CONFIG.COIN_BOUNCE_SPEED;\n\n if (spawnAngle !== undefined) {\n // Use predefined angle (convert from degrees to radians)\n const angleRad = (spawnAngle * Math.PI) / 180;\n return {\n velocityX: Math.cos(angleRad) * speed,\n velocityY: Math.sin(angleRad) * speed,\n };\n }\n\n // Pure freedom: random angle from 0 to 360 degrees\n const randomAngle = Math.random() * 360;\n const angleRad = (randomAngle * Math.PI) / 180;\n\n return {\n velocityX: Math.cos(angleRad) * speed,\n velocityY: Math.sin(angleRad) * speed,\n };\n }\n\n /**\n * Calculates the surface normal at the collision point\n */\n private static calculateSurfaceNormal(\n coin: Coin,\n object: { x: number; y: number; width: number; height: number }\n ): { x: number; y: number } {\n const coinCenterX = coin.x + coin.width / 2;\n const coinCenterY = coin.y + coin.height / 2;\n\n // Find the closest point on the surface to the coin center\n const closestX = Math.max(\n object.x,\n Math.min(coinCenterX, object.x + object.width)\n );\n const closestY = Math.max(\n object.y,\n Math.min(coinCenterY, object.y + object.height)\n );\n\n // Calculate the normal vector from the closest point to the coin center\n const normalX = coinCenterX - closestX;\n const normalY = coinCenterY - closestY;\n\n // Normalize the normal vector\n const length = Math.sqrt(normalX * normalX + normalY * normalY);\n\n if (length > 0.1) {\n // Normal case: normalize the vector\n return { x: normalX / length, y: normalY / length };\n } else {\n // Coin is very close to or on the surface - determine which side it's on\n const coinLeft = coin.x;\n const coinRight = coin.x + coin.width;\n const coinTop = coin.y;\n const coinBottom = coin.y + coin.height;\n\n const objectLeft = object.x;\n const objectRight = object.x + object.width;\n const objectTop = object.y;\n const objectBottom = object.y + object.height;\n\n // Determine which side the collision is on by checking distances\n const distToLeft = Math.abs(coinRight - objectLeft);\n const distToRight = Math.abs(coinLeft - objectRight);\n const distToTop = Math.abs(coinBottom - objectTop);\n const distToBottom = Math.abs(coinTop - objectBottom);\n\n const minDist = Math.min(\n distToLeft,\n distToRight,\n distToTop,\n distToBottom\n );\n\n if (minDist === distToLeft) {\n return { x: -1, y: 0 }; // Left side\n } else if (minDist === distToRight) {\n return { x: 1, y: 0 }; // Right side\n } else if (minDist === distToTop) {\n return { x: 0, y: -1 }; // Top side\n } else {\n return { x: 0, y: 1 }; // Bottom side\n }\n }\n }\n\n /**\n * Reflects velocity vector using the normal vector\n */\n private static reflectVelocity(\n coin: Coin,\n normal: { x: number; y: number }\n ): void {\n // Vector reflection formula: v' = v - 2(v · n)n\n const dotProduct = coin.velocityX * normal.x + coin.velocityY * normal.y;\n\n const oldVX = coin.velocityX;\n const oldVY = coin.velocityY;\n\n coin.velocityX = coin.velocityX - 2 * dotProduct * normal.x;\n coin.velocityY = coin.velocityY - 2 * dotProduct * normal.y;\n\n // Ensure the speed remains constant (power coins should maintain their speed)\n const oldSpeed = Math.sqrt(oldVX * oldVX + oldVY * oldVY);\n const newSpeed = Math.sqrt(\n coin.velocityX * coin.velocityX + coin.velocityY * coin.velocityY\n );\n\n if (newSpeed > 0.001) {\n const speedRatio = oldSpeed / newSpeed;\n coin.velocityX *= speedRatio;\n coin.velocityY *= speedRatio;\n }\n }\n\n /**\n * Moves coin out of collision with an object\n */\n private static moveCoinOutOfCollision(\n coin: Coin,\n object: { x: number; y: number; width: number; height: number }\n ): void {\n const coinCenterX = coin.x + coin.width / 2;\n const coinCenterY = coin.y + coin.height / 2;\n\n // Find the closest point on the surface\n const closestX = Math.max(\n object.x,\n Math.min(coinCenterX, object.x + object.width)\n );\n const closestY = Math.max(\n object.y,\n Math.min(coinCenterY, object.y + object.height)\n );\n\n // Calculate the penetration depth\n const penetrationX = coinCenterX - closestX;\n const penetrationY = coinCenterY - closestY;\n\n // Move coin out based on penetration\n if (Math.abs(penetrationX) > Math.abs(penetrationY)) {\n // Horizontal penetration - move horizontally\n coin.x +=\n penetrationX > 0 ? Math.abs(penetrationX) : -Math.abs(penetrationX);\n } else {\n // Vertical penetration - move vertically\n coin.y +=\n penetrationY > 0 ? Math.abs(penetrationY) : -Math.abs(penetrationY);\n }\n }\n\n /**\n * Moves coin out of collision with simple positioning\n */\n private static moveCoinOutOfCollisionSimple(\n coin: Coin,\n platform: { x: number; y: number; width: number; height: number }\n ): void {\n const coinCenterX = coin.x + coin.width / 2;\n const coinCenterY = coin.y + coin.height / 2;\n const platformCenterX = platform.x + platform.width / 2;\n const platformCenterY = platform.y + platform.height / 2;\n\n const deltaX = Math.abs(coinCenterX - platformCenterX);\n const deltaY = Math.abs(coinCenterY - platformCenterY);\n\n // Move coin out based on which axis had more overlap\n if (deltaX > deltaY) {\n // Horizontal collision - move coin to the side\n if (coinCenterX < platformCenterX) {\n coin.x = platform.x - coin.width - 1; // Move to left\n } else {\n coin.x = platform.x + platform.width + 1; // Move to right\n }\n } else {\n // Vertical collision - move coin above or below\n if (coinCenterY < platformCenterY) {\n coin.y = platform.y - coin.height - 1; // Move above\n } else {\n coin.y = platform.y + platform.height + 1; // Move below\n }\n }\n }\n\n private static calculateCollisionNormal(\n coin: Coin,\n platform: { x: number; y: number; width: number; height: number }\n ): { x: number; y: number } {\n const coinCenterX = coin.x + coin.width / 2;\n const coinCenterY = coin.y + coin.height / 2;\n\n // Find the closest point on the platform to the coin center\n const closestX = Math.max(\n platform.x,\n Math.min(coinCenterX, platform.x + platform.width)\n );\n const closestY = Math.max(\n platform.y,\n Math.min(coinCenterY, platform.y + platform.height)\n );\n\n // Calculate the normal vector from the closest point to the coin center\n const normalX = coinCenterX - closestX;\n const normalY = coinCenterY - closestY;\n\n // Normalize the normal vector\n const length = Math.sqrt(normalX * normalX + normalY * normalY);\n\n if (length > 0.1) {\n return { x: normalX / length, y: normalY / length };\n } else {\n // Coin is very close to the platform - determine which side\n const distToLeft = Math.abs(coin.x + coin.width - platform.x);\n const distToRight = Math.abs(coin.x - (platform.x + platform.width));\n const distToTop = Math.abs(coin.y + coin.height - platform.y);\n const distToBottom = Math.abs(coin.y - (platform.y + platform.height));\n\n const minDist = Math.min(\n distToLeft,\n distToRight,\n distToTop,\n distToBottom\n );\n\n if (minDist === distToLeft) return { x: -1, y: 0 };\n if (minDist === distToRight) return { x: 1, y: 0 };\n if (minDist === distToTop) return { x: 0, y: -1 };\n return { x: 0, y: 1 };\n }\n }\n}\n","import {\n Coin,\n CoinSpawnPoint,\n Monster,\n Platform,\n Ground,\n CoinTypeConfig,\n GameStateInterface,\n CoinEffect,\n} from \"../types/interfaces\";\nimport { CoinType } from \"../types/enums\";\nimport { GAME_CONFIG } from \"../types/constants\";\nimport { CoinPhysics } from \"./coinPhysics\";\nimport { COIN_TYPES, P_COIN_COLORS, COIN_EFFECTS } from \"../config/coinTypes\";\nimport { log } from \"../lib/logger\";\nimport { ScalingManager } from \"./ScalingManager\";\n\ninterface EffectData {\n endTime: number;\n effect: CoinEffect;\n}\n\nexport class CoinManager {\n private coins: Coin[] = [];\n private spawnPoints: CoinSpawnPoint[] = [];\n private firebombCount: number = 0;\n private powerModeActive: boolean = false;\n private powerModeEndTime: number = 0;\n private activeEffects: Map<string, EffectData> = new Map();\n private triggeredSpawnConditions: Set<string> = new Set(); // Track which spawn conditions have been triggered\n private lastProcessedScore: number = 0; // Track the last score threshold that was processed\n private lastScoreCheck: number = 0; // Track the last score we checked\n private bombAndMonsterPoints: number = 0; // Track points from bombs and monsters only (no bonus)\n private monsterKillCount: number = 0; // Track monsters killed in current power mode session\n private pCoinColorIndex: number = 0; // Track current P-coin color index\n\n constructor(spawnPoints: CoinSpawnPoint[] = []) {\n this.spawnPoints = spawnPoints;\n log.debug(\"CoinManager initialized\");\n }\n\n reset(): void {\n this.coins = [];\n this.firebombCount = 0;\n this.powerModeActive = false;\n this.powerModeEndTime = 0;\n this.activeEffects.clear();\n this.triggeredSpawnConditions.clear();\n this.lastProcessedScore = 0;\n this.lastScoreCheck = 0;\n this.bombAndMonsterPoints = 0;\n this.monsterKillCount = 0;\n // Don't reset pCoinColorIndex - let it persist across sessions\n }\n\n update(platforms: Platform[], ground: Ground, gameState?: GameStateInterface): void {\n // Update coin physics based on coin type\n this.coins.forEach((coin) => {\n if (coin.isCollected) return;\n \n const coinConfig = COIN_TYPES[coin.type];\n if (coinConfig) {\n CoinPhysics.updateCoin(coin, platforms, ground, coinConfig.physics);\n } else {\n // Fallback to legacy behavior\n if (coin.type === CoinType.POWER) {\n CoinPhysics.updatePowerCoin(coin, platforms, ground);\n } else {\n CoinPhysics.updateCoin(coin, platforms, ground);\n }\n }\n });\n\n // Check if effects should end\n this.checkEffectsEnd(gameState as unknown as Record<string, unknown>);\n\n // Remove collected coins\n this.coins = this.coins.filter((coin) => !coin.isCollected);\n }\n\n spawnCoin(type: CoinType, x: number, y: number, spawnAngle?: number): void {\n const coinConfig = COIN_TYPES[type];\n\n // Check if a coin of this type already exists and respect maxActive limit\n if (coinConfig?.maxActive) {\n const existingCoins = this.coins.filter(\n (coin) => coin.type === type && !coin.isCollected\n );\n if (existingCoins.length >= coinConfig.maxActive) {\n log.debug(\n `${type} coin limit reached (${coinConfig.maxActive}), skipping spawn`\n );\n return;\n }\n } else {\n // Legacy behavior - check if any coin of this type exists\n const existingCoin = this.coins.find((coin) => coin.type === type);\n if (existingCoin) {\n log.debug(`${type} coin already exists, skipping spawn`);\n return;\n }\n }\n\n let initialVelocity;\n if (type === CoinType.POWER) {\n initialVelocity = CoinPhysics.createPowerCoinVelocity(spawnAngle);\n } else {\n initialVelocity = CoinPhysics.createInitialVelocity();\n }\n \n const coin: Coin = {\n type,\n x,\n y,\n width: GAME_CONFIG.COIN_SIZE,\n height: GAME_CONFIG.COIN_SIZE,\n velocityX: initialVelocity.velocityX,\n velocityY: initialVelocity.velocityY,\n isCollected: false,\n spawnX: x,\n spawnY: y,\n };\n\n // Set initial color and spawn time for P-coins\n if (type === CoinType.POWER) {\n coin.colorIndex = 0; // Start with blue (index 0)\n coin.spawnTime = Date.now();\n log.debug(\"Spawning P-coin with Blue color (100 points)\");\n }\n\n this.coins.push(coin);\n log.debug(\n `Spawned ${type} coin at (${x}, ${y}) with angle ${\n spawnAngle || \"random\"\n }`\n );\n }\n\n onFirebombCollected(): void {\n this.firebombCount++;\n log.debug(`Firebomb count: ${this.firebombCount}`);\n\n // Check spawn conditions immediately when firebomb count changes\n this.checkSpawnConditionsOnFirebombChange();\n }\n\n // Track points from bombs and monsters (excluding bonus points)\n onPointsEarned(points: number, isBonus: boolean = false): void {\n if (!isBonus) {\n this.bombAndMonsterPoints += points;\n log.debug(\n `Points earned: ${points}, total bomb/monster points: ${this.bombAndMonsterPoints}`\n );\n\n // Check for B-coin spawn conditions immediately when points are earned\n this.checkBcoinSpawnConditions();\n }\n }\n\n // Check B-coin spawn conditions specifically when points are earned\n private checkBcoinSpawnConditions(): void {\n const coinConfig = COIN_TYPES.BONUS_MULTIPLIER;\n if (!coinConfig) return;\n\n // Check if we've crossed a new threshold\n const currentThreshold =\n Math.floor(\n this.bombAndMonsterPoints / GAME_CONFIG.BONUS_COIN_SPAWN_INTERVAL\n ) * GAME_CONFIG.BONUS_COIN_SPAWN_INTERVAL;\n const lastThreshold =\n Math.floor(this.lastScoreCheck / GAME_CONFIG.BONUS_COIN_SPAWN_INTERVAL) *\n GAME_CONFIG.BONUS_COIN_SPAWN_INTERVAL;\n\n // If we've crossed a new threshold, spawn a coin\n if (\n currentThreshold > lastThreshold &&\n currentThreshold >= GAME_CONFIG.BONUS_COIN_SPAWN_INTERVAL\n ) {\n const spawnKey = `${coinConfig.type}_${currentThreshold}`;\n\n // Check if we've already triggered this spawn condition\n if (this.triggeredSpawnConditions.has(spawnKey)) {\n log.debug(\n `B-coin spawn condition already triggered for threshold ${currentThreshold}`\n );\n return;\n }\n\n log.debug(\n `B-coin threshold crossed: ${lastThreshold} -> ${currentThreshold} (bomb/monster points: ${this.bombAndMonsterPoints})`\n );\n\n // Mark this spawn condition as triggered\n this.triggeredSpawnConditions.add(spawnKey);\n\n // Update the last score we checked\n this.lastScoreCheck = this.bombAndMonsterPoints;\n\n // Find spawn point for this coin type\n const spawnPoints = this.spawnPoints.filter(\n (point) => point.type === coinConfig.type\n );\n \n if (spawnPoints.length > 0) {\n const spawnPoint =\n spawnPoints[Math.floor(Math.random() * spawnPoints.length)];\n this.spawnCoin(\n coinConfig.type as CoinType,\n spawnPoint.x,\n spawnPoint.y,\n spawnPoint.spawnAngle\n );\n }\n }\n }\n\n // Check spawn conditions when firebomb count changes (for firebomb-based spawns)\n private checkSpawnConditionsOnFirebombChange(): void {\n Object.values(COIN_TYPES).forEach((coinConfig) => {\n // Only check spawn conditions that depend on firebomb count (P-coin)\n if (\n coinConfig.spawnCondition &&\n coinConfig.spawnCondition.toString().includes(\"firebombCount\")\n ) {\n const combinedState = {\n firebombCount: this.firebombCount,\n };\n\n if (coinConfig.spawnCondition(combinedState as unknown as GameStateInterface)) {\n // Create a unique key for this spawn condition\n const spawnKey = `${coinConfig.type}_${this.firebombCount}`;\n\n // Check if we've already triggered this spawn condition\n if (this.triggeredSpawnConditions.has(spawnKey)) {\n return; // Already triggered this spawn condition\n }\n\n log.debug(\n `P-coin spawn condition met (firebombCount: ${this.firebombCount}, key: ${spawnKey})`\n );\n\n // Mark this spawn condition as triggered\n this.triggeredSpawnConditions.add(spawnKey);\n\n // Find spawn point for this coin type\n const spawnPoints = this.spawnPoints.filter(\n (point) => point.type === coinConfig.type\n );\n\n if (spawnPoints.length > 0) {\n const spawnPoint =\n spawnPoints[Math.floor(Math.random() * spawnPoints.length)];\n this.spawnCoin(\n coinConfig.type as CoinType,\n spawnPoint.x,\n spawnPoint.y,\n spawnPoint.spawnAngle\n );\n } else {\n // Fallback spawn position for P-coin (random bouncing)\n const spawnX = 400 + (Math.random() - 0.5) * 200;\n const spawnY = 100 + Math.random() * 100;\n this.spawnCoin(coinConfig.type as CoinType, spawnX, spawnY);\n }\n }\n }\n });\n }\n\n // Check spawn conditions for other types (score-based, time-based, etc.)\n checkSpawnConditions(gameState: Record<string, unknown>): void {\n Object.values(COIN_TYPES).forEach((coinConfig) => {\n // Skip firebomb-based spawns as they're handled separately\n if (\n coinConfig.spawnCondition &&\n !coinConfig.spawnCondition.toString().includes(\"firebombCount\") &&\n coinConfig.type !== \"POWER\"\n ) {\n const combinedState = {\n ...gameState,\n firebombCount: this.firebombCount,\n bombAndMonsterPoints: this.bombAndMonsterPoints,\n };\n\n if (coinConfig.spawnCondition(combinedState as unknown as GameStateInterface)) {\n // Create a unique key for this spawn condition based on the current state\n let spawnKey = `${coinConfig.type}`;\n\n // For score-based spawns, include the score threshold\n if (coinConfig.spawnCondition.toString().includes(\"score\")) {\n if (coinConfig.type === \"BONUS_MULTIPLIER\") {\n // Use bombAndMonsterPoints instead of total score for B-coin spawning\n const currentThreshold =\n Math.floor(\n this.bombAndMonsterPoints /\n GAME_CONFIG.BONUS_COIN_SPAWN_INTERVAL\n ) * GAME_CONFIG.BONUS_COIN_SPAWN_INTERVAL;\n const lastThreshold =\n Math.floor(\n this.lastScoreCheck / GAME_CONFIG.BONUS_COIN_SPAWN_INTERVAL\n ) * GAME_CONFIG.BONUS_COIN_SPAWN_INTERVAL;\n\n // If we've crossed a new threshold, spawn a coin\n if (\n currentThreshold > lastThreshold &&\n currentThreshold >= GAME_CONFIG.BONUS_COIN_SPAWN_INTERVAL\n ) {\n spawnKey = `${coinConfig.type}_${currentThreshold}`;\n log.debug(\n `B-coin threshold crossed: ${lastThreshold} -> ${currentThreshold} (bomb/monster points: ${this.bombAndMonsterPoints})`\n );\n } else {\n return; // Skip this spawn condition\n }\n\n // Update the last score we checked\n this.lastScoreCheck = this.bombAndMonsterPoints;\n }\n }\n\n // For bonus multiplier-based spawns (EXTRA_LIFE)\n if (\n coinConfig.spawnCondition\n .toString()\n .includes(\"totalBonusMultiplierCoinsCollected\")\n ) {\n const bonusCount =\n (gameState.totalBonusMultiplierCoinsCollected as number) || 0;\n const threshold = Math.floor(bonusCount / GAME_CONFIG.EXTRA_LIFE_COIN_RATIO) * GAME_CONFIG.EXTRA_LIFE_COIN_RATIO;\n spawnKey = `${coinConfig.type}_${threshold}`;\n // log.debug(\n // `E-coin spawn check: bonusCount=${bonusCount}, threshold=${threshold}, ratio=${GAME_CONFIG.EXTRA_LIFE_COIN_RATIO}, shouldSpawn=${bonusCount > 0 && bonusCount % GAME_CONFIG.EXTRA_LIFE_COIN_RATIO === 0}`\n // );\n }\n\n // Check if we've already triggered this spawn condition\n if (this.triggeredSpawnConditions.has(spawnKey)) {\n return; // Already triggered this spawn condition\n }\n\n log.debug(\n `Spawn condition met for ${coinConfig.type} coin (key: ${spawnKey})`\n );\n\n // Mark this spawn condition as triggered\n this.triggeredSpawnConditions.add(spawnKey);\n\n // Find spawn point for this coin type\n const spawnPoints = this.spawnPoints.filter(\n (point) => point.type === coinConfig.type\n );\n\n if (spawnPoints.length > 0) {\n const spawnPoint =\n spawnPoints[Math.floor(Math.random() * spawnPoints.length)];\n this.spawnCoin(\n coinConfig.type as CoinType,\n spawnPoint.x,\n spawnPoint.y,\n spawnPoint.spawnAngle\n );\n } else {\n // Fallback spawn position - spawn from top for gravity coins\n const spawnX = 400 + (Math.random() - 0.5) * 200;\n let spawnY = 50; // Start from top of screen\n // For gravity-only coins, spawn from top\n if (\n coinConfig.physics.hasGravity &&\n !coinConfig.physics.bounces &&\n !coinConfig.physics.reflects\n ) {\n spawnY = 50; // Top of screen\n } else {\n spawnY = 100 + Math.random() * 100; // Random position for other coins\n }\n this.spawnCoin(coinConfig.type as CoinType, spawnX, spawnY);\n }\n }\n }\n });\n }\n\n collectCoin(coin: Coin, gameState?: Record<string, unknown>): void {\n coin.isCollected = true;\n log.debug(`Collected ${coin.type} coin`);\n \n const coinConfig = COIN_TYPES[coin.type];\n if (coinConfig && gameState) {\n // Calculate points earned from this coin\n let pointsEarned = coinConfig.points;\n\n // Special handling for P-coin - points based on current color\n if (coin.type === CoinType.POWER) {\n const spawnTime = coin.spawnTime || Date.now();\n const colorData = this.getPcoinColorForTime(spawnTime);\n const currentMultiplier = (gameState.multiplier as number) || 1;\n pointsEarned = colorData.points * currentMultiplier;\n\n log.debug(\n `P-coin collected: ${colorData.name} color, ${colorData.points} × ${currentMultiplier} = ${pointsEarned} points`\n );\n }\n // Special handling for B-coin (Bonus Multiplier) - points = 1000 * current multiplier\n else if (coin.type === CoinType.BONUS_MULTIPLIER) {\n const currentMultiplier = (gameState.multiplier as number) || 1;\n pointsEarned = 1000 * currentMultiplier;\n }\n // Special handling for E-coin (Extra Life) - add extra life and award points\n else if (coin.type === CoinType.EXTRA_LIFE) {\n const currentMultiplier = (gameState.multiplier as number) || 1;\n pointsEarned = coinConfig.points * currentMultiplier;\n }\n\n // Show floating text for points earned\n if ('addFloatingText' in gameState && typeof gameState.addFloatingText === 'function') {\n const text = pointsEarned.toString();\n (gameState.addFloatingText as (text: string, x: number, y: number, duration: number, color: string, fontSize: number) => void)(\n text,\n coin.x + coin.width / 2,\n coin.y + coin.height / 2,\n 1000, // duration\n \"#fff\",\n 15 // fontSize\n );\n }\n\n // Apply all effects for this coin type\n coinConfig.effects.forEach((effect) => {\n // Create a proper GameStateInterface object with coinManager and activeEffects\n const gameStateWithManager: GameStateInterface = {\n ...gameState as any,\n activeEffects: {\n powerMode: false,\n powerModeEndTime: 0,\n ...(gameState as any).activeEffects\n },\n coinManager: {\n resetMonsterKillCount: () => this.resetMonsterKillCount(),\n getPcoinColorForTime: (spawnTime: number) => this.getPcoinColorForTime(spawnTime),\n getPowerModeEndTime: () => this.getPowerModeEndTime()\n },\n difficultyManager: {\n pause: () => {\n // Access the global scaling manager instance\n const scalingManager = ScalingManager.getInstance();\n scalingManager.pause();\n log.debug(\"Difficulty scaling paused (power mode active)\");\n },\n resume: () => {\n // Access the global scaling manager instance\n const scalingManager = ScalingManager.getInstance();\n scalingManager.resume();\n log.debug(\"Difficulty scaling resumed (power mode ended)\");\n }\n }\n };\n \n effect.apply(gameStateWithManager, coin);\n\n // Track timed effects\n if (effect.duration) {\n this.activeEffects.set(effect.type, {\n endTime: Date.now() + effect.duration,\n effect,\n });\n }\n });\n } else {\n // Legacy behavior - just use the old system for now\n // Only warn if it's not a known coin type (to avoid spam)\n if (coin.type !== CoinType.POWER && coin.type !== CoinType.BONUS_MULTIPLIER && coin.type !== CoinType.EXTRA_LIFE) {\n log.warn(`Unknown coin type: ${coin.type}, using legacy behavior`);\n }\n if (coin.type === CoinType.POWER) {\n this.activatePowerMode();\n }\n }\n }\n\n private checkEffectsEnd(gameState?: Record<string, unknown>): void {\n const currentTime = Date.now();\n const effectsToRemove: string[] = [];\n\n this.activeEffects.forEach((effectData, effectType) => {\n log.debug(`Checking effect: ${effectType}, endTime: ${effectData.endTime}, currentTime: ${currentTime}, shouldEnd: ${currentTime >= effectData.endTime}`);\n if (currentTime >= effectData.endTime) {\n effectsToRemove.push(effectType);\n if (effectData.effect.remove && gameState) {\n // Create a proper GameStateInterface for the remove function\n const gameStateWithManager: GameStateInterface = {\n ...gameState as any,\n activeEffects: {\n powerMode: false,\n powerModeEndTime: 0,\n ...(gameState as any).activeEffects\n },\n coinManager: {\n resetMonsterKillCount: () => this.resetMonsterKillCount(),\n getPcoinColorForTime: (spawnTime: number) => this.getPcoinColorForTime(spawnTime),\n getPowerModeEndTime: () => this.getPowerModeEndTime()\n },\n difficultyManager: {\n pause: () => {\n const scalingManager = ScalingManager.getInstance();\n scalingManager.pause();\n log.debug(\"Difficulty scaling paused (power mode active)\");\n },\n resume: () => {\n const scalingManager = ScalingManager.getInstance();\n scalingManager.resumeFromPowerMode();\n log.debug(\"Difficulty scaling resumed (power mode ended)\");\n }\n }\n };\n effectData.effect.remove(gameStateWithManager);\n }\n }\n });\n\n effectsToRemove.forEach((effectType) => {\n this.activeEffects.delete(effectType);\n \n // Handle legacy power mode state when POWER_MODE effect is removed\n if (effectType === \"POWER_MODE\") {\n this.powerModeActive = false;\n log.debug(\"Power mode deactivated\");\n // Note: Difficulty scaling resume is handled by the effect's remove function\n }\n });\n }\n\n // Calculate monster kill points based on kill count progression\n calculateMonsterKillPoints(multiplier: number): number {\n this.monsterKillCount++;\n\n // Progressive monster kill bonus system\n let basePoints: number;\n switch (this.monsterKillCount) {\n case 1:\n basePoints = 100;\n break;\n case 2:\n basePoints = 200;\n break;\n case 3:\n basePoints = 300;\n break;\n case 4:\n basePoints = 500;\n break;\n case 5:\n basePoints = 800;\n break;\n case 6:\n basePoints = 1200;\n break;\n case 7:\n basePoints = 1700;\n break;\n case 8:\n basePoints = 2300;\n break;\n case 9:\n basePoints = 3000;\n break;\n case 10:\n basePoints = 4000;\n break;\n default:\n // For kills beyond 10, add 1000 per additional kill\n basePoints = 4000 + (this.monsterKillCount - 10) * 1000;\n }\n\n const totalPoints = basePoints * multiplier;\n log.debug(\n `Monster kill #${this.monsterKillCount}: ${basePoints} × ${multiplier} = ${totalPoints} points`\n );\n\n return totalPoints;\n }\n\n // Calculate current P-coin color based on time elapsed\n getPcoinColorForTime(spawnTime: number): {\n color: string;\n points: number;\n name: string;\n index: number;\n duration: number;\n } {\n const now = Date.now();\n const elapsed = now - spawnTime;\n const colorChangeInterval = 1000; // Change color every 1 second\n const colorIndex =\n Math.floor(elapsed / colorChangeInterval) % P_COIN_COLORS.length;\n const colorData = P_COIN_COLORS[colorIndex];\n return { ...colorData, index: colorIndex };\n }\n\n // Get current P-coin color and points (legacy method)\n getCurrentPcoinColor(): { color: string; points: number; name: string } {\n const colorData = P_COIN_COLORS[this.pCoinColorIndex];\n return colorData;\n }\n\n // Get current color for a specific P-coin\n getPcoinCurrentColor(coin: Coin): string {\n if (coin.type === CoinType.POWER && coin.spawnTime !== undefined) {\n const colorData = this.getPcoinColorForTime(coin.spawnTime);\n return colorData.color;\n }\n return P_COIN_COLORS[0].color; // Default to blue\n }\n\n // Advance P-coin color to next in sequence (legacy method)\n advancePcoinColor(): void {\n this.pCoinColorIndex = (this.pCoinColorIndex + 1) % P_COIN_COLORS.length;\n const newColor = this.getCurrentPcoinColor();\n log.debug(\n `P-coin color advanced to: ${newColor.name} (${newColor.points} points)`\n );\n }\n\n // Reset monster kill count when power mode starts\n resetMonsterKillCount(): void {\n this.monsterKillCount = 0;\n log.debug(\"Monster kill count reset for new power mode session\");\n }\n\n\n\n isPowerModeActive(): boolean {\n // Check if POWER_MODE effect is active\n const powerModeEffect = this.activeEffects.get(\"POWER_MODE\");\n if (powerModeEffect) {\n const isActive = Date.now() < powerModeEffect.endTime;\n if (!isActive) {\n // Effect has expired, remove it\n this.activeEffects.delete(\"POWER_MODE\");\n this.powerModeActive = false;\n }\n return isActive;\n }\n return this.powerModeActive; // Fallback to legacy property\n }\n\n getCoins(): Coin[] {\n return this.coins.filter((coin) => !coin.isCollected);\n }\n\n getAllCoins(): Coin[] {\n return [...this.coins];\n }\n\n getFirebombCount(): number {\n return this.firebombCount;\n }\n\n getBombAndMonsterPoints(): number {\n return this.bombAndMonsterPoints;\n }\n\n updateMonsters(monsters: Monster[]): void {\n // Check both new effect system and legacy system\n const isPowerModeActive = this.isPowerModeActive() || this.powerModeActive;\n \n if (isPowerModeActive) {\n // Calculate remaining time from either system\n let timeLeft = 0;\n \n // Check new effect system first\n const powerModeEffect = this.activeEffects.get(\"POWER_MODE\");\n if (powerModeEffect) {\n timeLeft = powerModeEffect.endTime - Date.now();\n } else {\n // Fall back to legacy system\n timeLeft = this.powerModeEndTime - Date.now();\n }\n \n const shouldBlink = timeLeft <= 2000 && timeLeft > 0; // Blink when 2 seconds or less remaining\n \n monsters.forEach((monster) => {\n monster.isFrozen = true;\n monster.isBlinking = shouldBlink;\n });\n } else {\n monsters.forEach((monster) => {\n monster.isFrozen = false;\n monster.isBlinking = false;\n });\n }\n }\n\n unfreezeAllMonsters(monsters: Monster[]): void {\n monsters.forEach((monster) => {\n monster.isFrozen = false;\n monster.isBlinking = false;\n });\n }\n\n resetEffects(): void {\n this.powerModeActive = false;\n this.powerModeEndTime = 0;\n this.firebombCount = 0;\n this.coins = [];\n this.activeEffects.clear();\n this.bombAndMonsterPoints = 0;\n this.monsterKillCount = 0;\n log.debug(\"Coin effects reset\");\n }\n\n // New method to get coin configuration\n getCoinConfig(type: string): CoinTypeConfig | undefined {\n return COIN_TYPES[type];\n }\n\n // New method to check if an effect is active\n isEffectActive(effectType: string): boolean {\n return this.activeEffects.has(effectType);\n }\n\n // Get power mode end time\n getPowerModeEndTime(): number {\n const powerModeEffect = this.activeEffects.get(\"POWER_MODE\");\n return powerModeEffect ? powerModeEffect.endTime : 0;\n }\n\n // Legacy method with dynamic duration\n private activatePowerMode(): void {\n this.powerModeActive = true;\n \n // Get duration based on current P-coin color (if we have a recent P-coin)\n let duration = GAME_CONFIG.POWER_COIN_DURATION; // Default fallback\n \n // Find the most recent P-coin to get its color\n const recentPcoin = this.coins.find(coin => coin.type === CoinType.POWER && coin.spawnTime);\n if (recentPcoin && recentPcoin.spawnTime) {\n const colorData = this.getPcoinColorForTime(recentPcoin.spawnTime);\n duration = colorData.duration;\n }\n \n this.powerModeEndTime = Date.now() + duration;\n this.resetMonsterKillCount();\n \n // Also add to activeEffects Map so checkEffectsEnd can handle it properly\n this.activeEffects.set(\"POWER_MODE\", {\n endTime: this.powerModeEndTime,\n effect: COIN_EFFECTS.POWER_MODE\n });\n \n log.debug(`Power mode timing - duration: ${duration}ms, endTime: ${this.powerModeEndTime}, currentTime: ${Date.now()}`);\n \n // Pause difficulty scaling during power mode\n try {\n const scalingManager = ScalingManager.getInstance();\n scalingManager.pauseForPowerMode();\n log.debug(\"Difficulty scaling paused (power mode active)\");\n } catch (error) {\n log.debug(\"Could not pause difficulty scaling (ScalingManager not available)\");\n }\n \n log.debug(`Power mode activated for ${duration}ms (${duration/1000}s)`);\n }\n}\n","import { create } from 'zustand';\nimport { PlayerSlice, createPlayerSlice } from './slices/playerSlice';\nimport { GameStateSlice, createGameStateSlice } from './slices/gameStateSlice';\nimport { BombSlice, createBombSlice } from './slices/bombSlice';\nimport { LevelSlice, createLevelSlice } from './slices/levelSlice';\nimport { LevelHistorySlice, createLevelHistorySlice } from './slices/levelHistorySlice';\nimport { MultiplierSlice, createMultiplierSlice } from './slices/multiplierSlice';\nimport { AudioSettingsSlice, createAudioSettingsSlice } from './slices/audioSettingsSlice';\nimport { CoinSlice, createCoinSlice } from './slices/coinSlice';\nimport { FloatingTextSlice, createFloatingTextSlice } from './slices/floatingTextSlice';\nimport { MapDefinition } from '../types/interfaces';\nimport { CoinManager } from '../managers/coinManager';\n\ninterface GameStore extends PlayerSlice, GameStateSlice, BombSlice, LevelSlice, LevelHistorySlice, MultiplierSlice, AudioSettingsSlice, CoinSlice, FloatingTextSlice {\n resetGame: () => void;\n initializeLevel: (mapData: MapDefinition) => { bombManager: any; firstBomb: any };\n getLevelHistory: () => any[];\n getGameStartTime: () => number;\n getSessionId: () => string;\n}\n\nexport const useGameStore = create<GameStore>((set, get, api) => {\n // Create all slices first\n const playerSlice = createPlayerSlice(set, get, api);\n const gameStateSlice = createGameStateSlice(set, get, api);\n const bombSlice = createBombSlice(set, get, api);\n const levelSlice = createLevelSlice(set, get, api);\n const levelHistorySlice = createLevelHistorySlice(set, get, api);\n const multiplierSlice = createMultiplierSlice(set, get, api);\n const audioSettingsSlice = createAudioSettingsSlice(set, get, api);\n const coinSlice = createCoinSlice(set, get, api);\n const floatingTextSlice = createFloatingTextSlice(set, get, api);\n\n return {\n ...playerSlice,\n ...gameStateSlice,\n ...bombSlice,\n ...levelSlice,\n ...levelHistorySlice,\n ...multiplierSlice,\n ...audioSettingsSlice,\n ...coinSlice,\n ...floatingTextSlice,\n \n resetGame: () => {\n get().resetGameState();\n get().resetPlayer();\n get().resetBombState();\n get().resetLevelState();\n get().resetLevelHistory();\n get().resetMultiplier();\n get().resetAudioSettings();\n get().resetCoinState();\n get().resetEffects();\n get().clearAllFloatingTexts();\n },\n \n // Override initializeLevel to handle the full game initialization\n initializeLevel: (mapData: MapDefinition) => {\n // Get the level slice's initializeLevel method\n const { bombManager, firstBomb } = levelSlice.initializeLevel(mapData);\n \n // Set up bombs without initial blinking (blinking will start after first bomb is collected)\n const bombsWithState = mapData.bombs.map(bomb => ({\n ...bomb,\n isBlinking: false, // No initial blinking - will be set after first bomb collection\n isCollected: false,\n isCorrect: false\n }));\n \n // Update bomb state\n get().setBombs(bombsWithState);\n get().setBombManager(bombManager);\n \n // Initialize coin manager\n const coinManager = new CoinManager(mapData.coinSpawnPoints || []);\n get().setCoinManager(coinManager);\n \n // Reset bomb collection state\n set({\n collectedBombs: [],\n correctOrderCount: 0,\n nextBombOrder: 1\n });\n \n // Set player position\n get().setPlayerPosition(mapData.playerStart.x, mapData.playerStart.y);\n \n return { bombManager, firstBomb };\n },\n\n // Add convenience methods for accessing level history data\n getLevelHistory: () => {\n return levelHistorySlice.getLevelResults();\n },\n\n getGameStartTime: () => {\n return levelHistorySlice.getGameStartTime();\n },\n\n getSessionId: () => {\n return levelHistorySlice.getSessionId();\n }\n };\n});","export class InputManager {\n private keys: Set<string> = new Set();\n private keyPressTimes: Map<string, number> = new Map();\n private touchControls = {\n left: false,\n right: false,\n up: false,\n float: false\n };\n \n // Store bound event handlers for proper cleanup\n private boundKeyDownHandler: (event: KeyboardEvent) => void;\n private boundKeyUpHandler: (event: KeyboardEvent) => void;\n private boundPreventDefaultHandler: (event: KeyboardEvent) => void;\n \n constructor() {\n // Bind event handlers once and store them\n this.boundKeyDownHandler = this.handleKeyDown.bind(this);\n this.boundKeyUpHandler = this.handleKeyUp.bind(this);\n this.boundPreventDefaultHandler = (e: KeyboardEvent) => {\n if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'Space', ' ', 'p', 'P'].includes(e.key)) {\n e.preventDefault();\n }\n };\n \n this.bindEvents();\n }\n \n private bindEvents() {\n document.addEventListener('keydown', this.boundKeyDownHandler);\n document.addEventListener('keyup', this.boundKeyUpHandler);\n document.addEventListener('keydown', this.boundPreventDefaultHandler);\n }\n \n isKeyPressed(key: string): boolean {\n return this.keys.has(key) || this.getTouchControl(key);\n }\n \n isShiftPressed(): boolean {\n return this.keys.has('Shift');\n }\n \n getKeyPressDuration(key: string): number {\n const startTime = this.keyPressTimes.get(key);\n if (startTime && this.keys.has(key)) {\n return Date.now() - startTime;\n }\n return 0;\n }\n \n private getTouchControl(key: string): boolean {\n switch (key) {\n case 'ArrowLeft':\n return this.touchControls.left;\n case 'ArrowRight':\n return this.touchControls.right;\n case 'ArrowUp':\n return this.touchControls.up;\n case ' ':\n case 'Space':\n return this.touchControls.float;\n default:\n return false;\n }\n }\n \n private handleKeyDown(event: KeyboardEvent): void {\n if (!this.keys.has(event.key)) {\n this.keyPressTimes.set(event.key, Date.now());\n }\n this.keys.add(event.key);\n }\n \n private handleKeyUp(event: KeyboardEvent): void {\n this.keys.delete(event.key);\n this.keyPressTimes.delete(event.key);\n }\n \n // Touch controls for mobile\n setTouchControl(control: keyof typeof this.touchControls, pressed: boolean): void {\n this.touchControls[control] = pressed;\n }\n \n cleanup(): void {\n document.removeEventListener('keydown', this.boundKeyDownHandler);\n document.removeEventListener('keyup', this.boundKeyUpHandler);\n document.removeEventListener('keydown', this.boundPreventDefaultHandler);\n }\n }","import { Player, Monster, Bomb, Platform, Ground, CollisionResult, Coin } from '../types/interfaces';\n\nexport class CollisionManager {\n checkPlayerPlatformCollision(player: Player, platforms: Platform[]): CollisionResult {\n for (const platform of platforms) {\n const collision = this.checkFullCollision(player, platform);\n if (collision.hasCollision) {\n return collision;\n }\n }\n return { hasCollision: false };\n }\n\n checkPlayerGroundCollision(player: Player, ground: Ground): CollisionResult {\n const collision = this.checkFullCollision(player, ground);\n return collision;\n }\n\n checkMonsterGroundCollision(monster: Monster, ground: Ground): CollisionResult {\n const collision = this.checkFullCollision(monster, ground);\n return collision;\n }\n\n checkPlayerCoinCollision(player: Player, coins: Coin[]): Coin | null {\n for (const coin of coins) {\n if (!coin.isCollected && this.isColliding(player, coin)) {\n return coin;\n }\n }\n return null;\n }\n\n private checkFullCollision(entity: { x: number; y: number; width: number; height: number; velocityX?: number; velocityY?: number }, surface: { x: number; y: number; width: number; height: number }): CollisionResult {\n // Calculate entity's next position\n const nextX = entity.x + (entity.velocityX || 0);\n const nextY = entity.y + (entity.velocityY || 0);\n \n // Check if there would be a collision at the next position\n if (this.wouldCollide(nextX, nextY, entity.width, entity.height, surface)) {\n // Determine which side of the collision is happening\n const entityCenterX = entity.x + entity.width / 2;\n const entityCenterY = entity.y + entity.height / 2;\n const surfaceCenterX = surface.x + surface.width / 2;\n const surfaceCenterY = surface.y + surface.height / 2;\n \n const deltaX = entityCenterX - surfaceCenterX;\n const deltaY = entityCenterY - surfaceCenterY;\n \n // Calculate overlap on each axis\n const overlapX = (entity.width + surface.width) / 2 - Math.abs(deltaX);\n const overlapY = (entity.height + surface.height) / 2 - Math.abs(deltaY);\n \n // Resolve collision based on smallest overlap\n if (overlapX < overlapY) {\n // Horizontal collision\n if (deltaX > 0) {\n // Player hitting from the right\n return {\n hasCollision: true,\n normal: { x: 1, y: 0 },\n penetration: overlapX\n };\n } else {\n // Player hitting from the left\n return {\n hasCollision: true,\n normal: { x: -1, y: 0 },\n penetration: overlapX\n };\n }\n } else {\n // Vertical collision\n if (deltaY > 0) {\n // Player hitting from below\n return {\n hasCollision: true,\n normal: { x: 0, y: 1 },\n penetration: overlapY\n };\n } else {\n // Player hitting from above (landing on platform)\n return {\n hasCollision: true,\n normal: { x: 0, y: -1 },\n penetration: overlapY\n };\n }\n }\n }\n \n return { hasCollision: false };\n }\n\n private wouldCollide(x: number, y: number, width: number, height: number, surface: { x: number; y: number; width: number; height: number }): boolean {\n return (\n x < surface.x + surface.width &&\n x + width > surface.x &&\n y < surface.y + surface.height &&\n y + height > surface.y\n );\n }\n\n checkPlayerBombCollision(player: Player, bombs: Bomb[]): Bomb | null {\n for (const bomb of bombs) {\n if (!bomb.isCollected && this.isColliding(player, bomb)) {\n return bomb;\n }\n }\n return null;\n }\n\n checkPlayerMonsterCollision(player: Player, monsters: Monster[]): Monster | null {\n for (const monster of monsters) {\n if (monster.isActive && this.isColliding(player, monster)) {\n return monster;\n }\n }\n return null;\n }\n\n checkBoundaryCollision(entity: { x: number; y: number; width: number; height: number }, bounds: { width: number; height: number }): CollisionResult {\n const nextX = entity.x;\n const nextY = entity.y;\n \n // Check each boundary\n if (nextX < 0) {\n // Left boundary collision\n return {\n hasCollision: true,\n normal: { x: 1, y: 0 },\n penetration: Math.abs(nextX)\n };\n }\n \n if (nextX + entity.width > bounds.width) {\n // Right boundary collision\n return {\n hasCollision: true,\n normal: { x: -1, y: 0 },\n penetration: nextX + entity.width - bounds.width\n };\n }\n \n if (nextY < 0) {\n // Top boundary collision\n return {\n hasCollision: true,\n normal: { x: 0, y: 1 },\n penetration: Math.abs(nextY)\n };\n }\n \n if (nextY + entity.height > bounds.height) {\n // Bottom boundary collision\n return {\n hasCollision: true,\n normal: { x: 0, y: -1 },\n penetration: nextY + entity.height - bounds.height\n };\n }\n \n return { hasCollision: false };\n }\n\n resolveBoundaryCollision(player: Player, bounds: { width: number; height: number }): { player: Player; fellOffScreen: boolean } {\n const boundaryCollision = this.checkBoundaryCollision(player, bounds);\n \n if (!boundaryCollision.hasCollision || !boundaryCollision.normal || !boundaryCollision.penetration) {\n return { player, fellOffScreen: false };\n }\n \n const updatedPlayer = { ...player };\n const { normal, penetration } = boundaryCollision;\n \n // Resolve collision based on normal direction\n if (normal.x === 1) {\n // Left boundary - move player to x = 0\n updatedPlayer.x = 0;\n updatedPlayer.velocityX = 0;\n } else if (normal.x === -1) {\n // Right boundary - move player to right edge\n updatedPlayer.x = bounds.width - player.width;\n updatedPlayer.velocityX = 0;\n } else if (normal.y === 1) {\n // Top boundary - move player to y = 0 and stop upward velocity\n updatedPlayer.y = 0;\n updatedPlayer.velocityY = 0;\n } else if (normal.y === -1) {\n // Bottom boundary - player fell off screen\n return { player: updatedPlayer, fellOffScreen: true };\n }\n \n return { player: updatedPlayer, fellOffScreen: false };\n }\n\n private isColliding(rect1: { x: number; y: number; width: number; height: number }, rect2: { x: number; y: number; width: number; height: number }): boolean {\n return (\n rect1.x < rect2.x + rect2.width &&\n rect1.x + rect1.width > rect2.x &&\n rect1.y < rect2.y + rect2.height &&\n rect1.y + rect1.height > rect2.y\n );\n }\n}","import { GAME_CONFIG } from \"../types/constants\";\ntype Animation = {\n name: string;\n frames: HTMLImageElement[];\n frameDuration: number; // ms per frame\n loop: boolean;\n};\n\nexport class SpriteInstance {\n animations: Record<string, Animation>;\n currentAnimation: Animation;\n currentFrameIndex: number = 0;\n frameTimer: number = 0;\n\n constructor(animations: Animation[], initial: string) {\n this.animations = Object.fromEntries(animations.map((a) => [a.name, a]));\n this.currentAnimation = this.animations[initial];\n }\n\n setAnimation(name: string) {\n if (this.currentAnimation.name !== name) {\n this.currentAnimation = this.animations[name];\n this.currentFrameIndex = 0;\n this.frameTimer = 0;\n }\n }\n\n setAnimationPreserveFrame(name: string) {\n if (this.currentAnimation.name !== name) {\n const newAnimation = this.animations[name];\n if (newAnimation) {\n // Preserve the current frame position, but clamp to new animation's frame count\n const preservedFrame = Math.min(this.currentFrameIndex, newAnimation.frames.length - 1);\n this.currentAnimation = newAnimation;\n this.currentFrameIndex = preservedFrame;\n // Keep the same frame timer to maintain timing\n }\n }\n }\n\n update(dt: number) {\n this.frameTimer += dt;\n if (this.frameTimer > this.currentAnimation.frameDuration) {\n this.frameTimer = 0;\n this.currentFrameIndex++;\n if (this.currentFrameIndex >= this.currentAnimation.frames.length) {\n this.currentFrameIndex = this.currentAnimation.loop\n ? 0\n : this.currentAnimation.frames.length - 1;\n }\n }\n }\n\n draw(ctx: CanvasRenderingContext2D, x: number, y: number, scale: number = 1) {\n const img = this.currentAnimation.frames[this.currentFrameIndex];\n if (img.complete) {\n const drawWidth = GAME_CONFIG.PLAYER_WIDTH * 2.5; // Make sprite 1.7x wider\n const drawHeight = GAME_CONFIG.PLAYER_HEIGHT * scale;\n \n // Center the sprite horizontally\n const spriteX = x - (drawWidth - GAME_CONFIG.PLAYER_WIDTH) / 2.3;\n \n // Check if this is a left-facing animation\n const isLeftFacing = this.currentAnimation.name.includes('-left');\n \n if (isLeftFacing) {\n // For left-facing sprites, flip around the sprite's center\n ctx.save();\n ctx.scale(-1, 1);\n // Calculate the center point of the sprite for proper flipping\n const centerX = spriteX + drawWidth / 2.14;\n ctx.translate(-centerX * 2, 0);\n ctx.drawImage(img, spriteX, y, drawWidth, drawHeight);\n ctx.restore();\n } else {\n // For right-facing sprites, draw normally\n ctx.drawImage(img, spriteX, y, drawWidth, drawHeight);\n }\n \n // Draw hitbox border that matches the actual collision box (narrower)\n ctx.save();\n // ctx.strokeStyle = \"red\";\n // ctx.lineWidth = 2;\n // ctx.strokeRect(x, y, GAME_CONFIG.PLAYER_WIDTH, drawHeight);\n ctx.restore();\n }\n }\n}\n","// Detect if we're in the game's own development environment\n// import.meta.env.DEV is true when running the game directly with npm run dev\nconst isDev = import.meta.env.DEV;\n\nexport const ASSET_PATHS = {\n audio: isDev ? \"/audio\" : \"/dist/audio\",\n images: isDev ? \"/assets\" : \"/dist/assets\",\n};\n\n// Helper function to get background image path using the new maps-bg-images folder\nexport const getBackgroundImagePath = (theme: string): string => {\n return `${ASSET_PATHS.images}/maps-bg-images/${theme}.png`;\n};\n","import { SpriteInstance } from \"../lib/SpriteInstance\";\nimport { ASSET_PATHS } from \"../config/assets\";\n\n// Helper function to load images from public folder\nconst loadImage = (path: string): HTMLImageElement => {\n const img = new Image();\n img.src = `${ASSET_PATHS.images}/${path}`;\n return img;\n};\n\nconst sigurdIdleFrames = [\n loadImage(\"sigurd-idle/sigurd-idle1.png\"),\n loadImage(\"sigurd-idle/sigurd-idle2.png\"),\n loadImage(\"sigurd-idle/sigurd-idle3.png\"),\n loadImage(\"sigurd-idle/sigurd-idle4.png\"),\n];\n\nconst runningFrames = [\n loadImage(\"running/run1.png\"),\n loadImage(\"running/run2.png\"),\n loadImage(\"running/run3.png\"),\n];\n\nconst jumpFrames = [\n loadImage(\"jumping/jump1.png\"),\n loadImage(\"jumping/jump2.png\"),\n loadImage(\"jumping/jump3.png\"),\n];\n\n\n\nconst completeFrames = [\n loadImage(\"complete/complete1.png\"),\n loadImage(\"complete/complete2.png\"),\n loadImage(\"complete/complete3.png\"),\n loadImage(\"complete/complete4.png\"),\n loadImage(\"complete/complete5.png\"),\n];\n\nconst floatStationaryFrames = [loadImage(\"float/float1.png\")];\n\nconst floatDirectionalFrames = [loadImage(\"float-dir/float-dir1.png\")];\n\nconst landingFrames = [loadImage(\"landing/landing1.png\")];\n\nconst playerAnimations = [\n {\n name: \"walk-right\",\n frames: runningFrames,\n frameDuration: 100,\n loop: true,\n },\n {\n name: \"walk-left\",\n frames: runningFrames,\n frameDuration: 100,\n loop: true,\n },\n {\n name: \"idle-right\",\n frames: sigurdIdleFrames,\n frameDuration: 1000,\n loop: true,\n },\n {\n name: \"idle-left\",\n frames: sigurdIdleFrames,\n frameDuration: 1000,\n loop: true,\n },\n { name: \"jump-right\", frames: jumpFrames, frameDuration: 100, loop: false },\n { name: \"jump-left\", frames: jumpFrames, frameDuration: 100, loop: false },\n {\n name: \"land-right\",\n frames: landingFrames,\n frameDuration: 500,\n loop: false,\n },\n { name: \"land-left\", frames: landingFrames, frameDuration: 500, loop: false },\n {\n name: \"float-stationary\",\n frames: floatStationaryFrames,\n frameDuration: 100,\n loop: true,\n },\n {\n name: \"float-right\",\n frames: floatDirectionalFrames,\n frameDuration: 100,\n loop: false,\n },\n {\n name: \"float-left\",\n frames: floatDirectionalFrames,\n frameDuration: 100,\n loop: true,\n },\n {\n name: \"ghost-complete\",\n frames: completeFrames,\n frameDuration: 100,\n loop: false,\n },\n // Add more animations as needed\n];\n\nexport const playerSprite = new SpriteInstance(playerAnimations, \"idle-left\");\n","import { SpriteInstance } from \"../lib/SpriteInstance\";\nimport { ASSET_PATHS } from \"../config/assets\";\nimport { GAME_CONFIG } from \"../types/constants\";\n\n// Helper function to load images from public folder\nconst loadImage = (path: string): HTMLImageElement => {\n const img = new Image();\n img.src = `${ASSET_PATHS.images}/${path}`;\n return img;\n};\n\nconst unlitBombFrame2 = [loadImage(\"bomb/bomb1.png\")];\n\nconst litBombFrame2 = [\n loadImage(\"bomb/bomb1.png\"),\n loadImage(\"bomb/bomb2.png\"),\n];\n\nconst bombAnimations = [\n {\n name: \"unlit\",\n frames: unlitBombFrame2,\n frameDuration: 100,\n loop: false,\n },\n {\n name: \"lit\",\n frames: litBombFrame2,\n frameDuration: 100, // Faster blinking for more noticeable effect\n loop: true,\n },\n\n // Add more animations as needed\n];\n\n// Create a custom bomb sprite instance with proper drawing\nexport class BombSpriteInstance extends SpriteInstance {\n draw(ctx: CanvasRenderingContext2D, x: number, y: number, scale: number = 1) {\n const img = this.currentAnimation.frames[this.currentFrameIndex];\n if (img.complete) {\n const drawWidth = GAME_CONFIG.BOMB_SIZE * scale;\n const drawHeight = GAME_CONFIG.BOMB_SIZE * scale;\n\n // Draw the bomb sprite centered on the bomb's position\n ctx.drawImage(img, x, y, drawWidth, drawHeight);\n }\n }\n}\n\nexport const bombSprite = new BombSpriteInstance(bombAnimations, \"unlit\");\n","import { GAME_CONFIG } from '../types/constants';\nimport { ASSET_PATHS } from '../config/assets';\nimport { logger } from '../lib/logger';\n\ninterface BackgroundImage {\n image: HTMLImageElement;\n isLoaded: boolean;\n}\n\n// Map human-readable map names to custom background image files\nconst MAP_NAME_TO_BACKGROUND_MAP: Record<string, string> = {\n \n 'startup lab': 'startup-lab.png',\n 'nav': 'nav.png',\n 'skatteetaten': 'skatteetaten.png',\n 'innovasjon norge': 'innovasjon-norge.png',\n 'kommunehuset': 'kommunehuset.png',\n 'alltinn norge': 'alltinn-norge.png',\n 'silicone vally': 'silicone-vally.png',\n 'default': 'startup-lab.png',\n};\n\nexport class BackgroundManager {\n private currentBackground: BackgroundImage | null = null;\n private isLoading: boolean = false;\n private canvasWidth: number;\n private canvasHeight: number;\n private currentMapName: string = '';\n\n constructor(canvasWidth: number, canvasHeight: number) {\n this.canvasWidth = canvasWidth;\n this.canvasHeight = canvasHeight;\n }\n\n // Load background based on map name\n loadMapBackground(mapName: string): void {\n if (this.isLoading) return; // Prevent multiple simultaneous loads\n \n this.currentMapName = mapName;\n this.isLoading = true;\n \n // Clear existing background\n if (this.currentBackground) {\n this.currentBackground.image.src = '';\n this.currentBackground = null;\n }\n\n // Start loading in background - doesn't block game loop\n this.loadBackgroundAsync(mapName).catch(error => {\n console.error('BackgroundManager: Failed to load background:', error);\n this.isLoading = false;\n });\n }\n\n private async loadBackgroundAsync(mapName: string): Promise<void> {\n try {\n const imageFileName = MAP_NAME_TO_BACKGROUND_MAP[mapName] || MAP_NAME_TO_BACKGROUND_MAP['default'];\n \n if (!imageFileName) {\n console.warn(`BackgroundManager: No background image found for map: ${mapName}, using fallback`);\n this.isLoading = false;\n return;\n }\n\n const image = await this.loadImage(`${ASSET_PATHS.images}/maps-bg-images/${imageFileName}`);\n \n this.currentBackground = {\n image: image,\n isLoaded: true\n };\n \n this.isLoading = false;\n logger.flow(`Background loaded: ${mapName}`);\n } catch (error) {\n console.error('BackgroundManager: Failed to load background image:', error);\n this.isLoading = false;\n }\n }\n\n private loadImage(src: string): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => resolve(img);\n img.onerror = () => reject(new Error(`Failed to load image: ${src}`));\n img.src = src;\n });\n }\n\n update(playerX: number, playerY: number): void {\n // No parallax movement needed for static backgrounds\n // This method is kept for compatibility but doesn't do anything\n }\n\n render(ctx: CanvasRenderingContext2D): void {\n if (!this.currentBackground || !this.currentBackground.isLoaded) {\n // Show loading state\n if (this.isLoading) {\n this.renderLoading(ctx);\n } else {\n // Fallback: render a simple gradient background\n this.renderFallback(ctx);\n }\n return;\n }\n\n const image = this.currentBackground.image;\n \n // Calculate scale to fit the canvas exactly (crop if necessary)\n const scaleX = this.canvasWidth / image.width;\n const scaleY = this.canvasHeight / image.height;\n const scale = Math.max(scaleX, scaleY); // Use max to ensure full coverage\n \n const scaledWidth = image.width * scale;\n const scaledHeight = image.height * scale;\n \n // Calculate offset to center the image if it's larger than canvas\n const offsetX = (scaledWidth - this.canvasWidth) / 2;\n const offsetY = (scaledHeight - this.canvasHeight) / 2;\n \n // Draw the image cropped to canvas dimensions\n ctx.drawImage(\n image,\n -offsetX, -offsetY, scaledWidth, scaledHeight\n );\n }\n\n private renderLoading(ctx: CanvasRenderingContext2D): void {\n // Create a loading background that matches the game's theme\n const gradient = ctx.createLinearGradient(0, 0, 0, this.canvasHeight);\n gradient.addColorStop(0, '#262521'); // Dark background\n gradient.addColorStop(1, '#484744'); // Slightly lighter\n \n ctx.fillStyle = gradient;\n ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);\n \n // Add loading text\n ctx.fillStyle = '#ffffff';\n ctx.font = '16px Arial';\n ctx.textAlign = 'center';\n ctx.fillText('Loading background...', this.canvasWidth / 2, this.canvasHeight / 2);\n }\n\n private renderFallback(ctx: CanvasRenderingContext2D): void {\n // Create a simple gradient background as fallback\n const gradient = ctx.createLinearGradient(0, 0, 0, this.canvasHeight);\n gradient.addColorStop(0, '#87CEEB'); // Sky blue\n gradient.addColorStop(1, '#4682B4'); // Steel blue\n \n ctx.fillStyle = gradient;\n ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);\n }\n\n isReady(): boolean {\n return this.currentBackground?.isLoaded || false;\n }\n\n isCurrentlyLoading(): boolean {\n return this.isLoading;\n }\n\n getCurrentTheme(): string {\n return this.currentMapName;\n }\n\n // Get the current map name\n getCurrentMapName(): string {\n return this.currentMapName;\n }\n\n // Get list of available background images\n static getAvailableBackgrounds(): string[] {\n return Object.values(MAP_NAME_TO_BACKGROUND_MAP);\n }\n\n // Get the map name mapping for debugging\n static getMapNameMapping(): Record<string, string> {\n return { ...MAP_NAME_TO_BACKGROUND_MAP };\n }\n\n // Preload all background images to prevent flashing\n static async preloadAllBackgrounds(): Promise<void> {\n logger.flow('Starting background preloading...');\n const backgrounds = Object.values(MAP_NAME_TO_BACKGROUND_MAP);\n let loadedCount = 0;\n \n const preloadPromises = backgrounds.map(async (background) => {\n try {\n const img = new Image();\n await new Promise((resolve, reject) => {\n img.onload = resolve;\n img.onerror = reject;\n img.src = `${ASSET_PATHS.images}/maps-bg-images/${background}`;\n });\n loadedCount++;\n // Only log every 2nd background to reduce spam\n if (loadedCount % 2 === 0 || loadedCount === backgrounds.length) {\n logger.flow(`Preloaded ${loadedCount}/${backgrounds.length} backgrounds`);\n }\n } catch (error) {\n logger.warn(`Failed to preload background: ${background}`);\n }\n });\n \n await Promise.all(preloadPromises);\n logger.flow(`Background preloading complete! Loaded ${loadedCount}/${backgrounds.length} backgrounds.`);\n }\n} ","import { Monster } from \"../types/interfaces\";\nimport { logger } from \"../lib/logger\";\nimport { ScalingManager } from \"./ScalingManager\";\n\nexport interface RespawnConfig {\n ambusher: number;\n chaser: number;\n floater: number;\n patrol: number;\n}\n\ninterface DeadMonster {\n monster: Monster;\n respawnTime: number;\n}\n\nexport class OptimizedRespawnManager {\n private static instance: OptimizedRespawnManager;\n private deadMonsters: DeadMonster[] = [];\n private respawnConfig: RespawnConfig;\n private scalingManager: ScalingManager;\n private lastUpdateTime: number = 0;\n private updateInterval: number = 500; // Update every 500ms instead of every frame\n private paused: boolean = false;\n\n private constructor() {\n this.respawnConfig = this.getDefaultRespawnConfig();\n this.scalingManager = ScalingManager.getInstance();\n logger.debug(\"Respawn manager initialized\");\n }\n\n public static getInstance(): OptimizedRespawnManager {\n if (!OptimizedRespawnManager.instance) {\n OptimizedRespawnManager.instance = new OptimizedRespawnManager();\n }\n return OptimizedRespawnManager.instance;\n }\n\n // ===== CONFIGURATION =====\n private getDefaultRespawnConfig(): RespawnConfig {\n return {\n ambusher: 10000, // 10 seconds\n chaser: 7000, // 7 seconds\n floater: 15000, // 15 seconds\n patrol: 8000, // 8 seconds\n };\n }\n\n public updateRespawnConfig(newConfig: Partial<RespawnConfig>): void {\n this.respawnConfig = { ...this.respawnConfig, ...newConfig };\n logger.debug(\n \"OptimizedRespawnManager: Updated respawn configuration\",\n this.respawnConfig\n );\n }\n\n public getRespawnConfig(): RespawnConfig {\n return { ...this.respawnConfig };\n }\n\n // ===== MONSTER MANAGEMENT =====\n public killMonster(monster: Monster): void {\n if (monster.isDead) {\n logger.debug(`Monster already dead, skipping kill: ${monster.type}`);\n return;\n }\n\n // Store original spawn position if not already set\n if (!monster.originalSpawnPoint) {\n monster.originalSpawnPoint = { x: monster.x, y: monster.y };\n }\n\n // Mark monster as dead\n monster.isDead = true;\n monster.isActive = false;\n monster.deathTime = Date.now();\n monster.respawnTime =\n monster.deathTime + this.getRespawnDelay(monster.type);\n\n // Add to dead monsters list (sorted by respawn time for efficient processing)\n const deadMonster: DeadMonster = {\n monster,\n respawnTime: monster.respawnTime,\n };\n this.insertSorted(deadMonster);\n\n logger.monster(\n `${monster.type} killed - respawning in ${\n this.getRespawnDelay(monster.type) / 1000\n }s`\n );\n }\n\n private insertSorted(deadMonster: DeadMonster): void {\n // Binary search to find insertion point for optimal performance\n let left = 0;\n let right = this.deadMonsters.length;\n\n while (left < right) {\n const mid = Math.floor((left + right) / 2);\n if (this.deadMonsters[mid].respawnTime <= deadMonster.respawnTime) {\n left = mid + 1;\n } else {\n right = mid;\n }\n }\n\n this.deadMonsters.splice(left, 0, deadMonster);\n }\n\n // ===== UPDATE LOOP =====\n public update(): Monster[] {\n const currentTime = Date.now();\n\n // Throttle updates for better performance\n if (currentTime - this.lastUpdateTime < this.updateInterval) {\n return [];\n }\n this.lastUpdateTime = currentTime;\n\n // Don't update if paused\n if (this.paused) {\n return [];\n }\n\n const monstersToRespawn: Monster[] = [];\n\n // Process respawns (since array is sorted, we can process from the beginning)\n while (\n this.deadMonsters.length > 0 &&\n this.deadMonsters[0].respawnTime <= currentTime\n ) {\n const deadMonster = this.deadMonsters.shift()!;\n const respawnedMonster = this.respawnMonster(deadMonster.monster);\n monstersToRespawn.push(respawnedMonster);\n }\n\n if (monstersToRespawn.length > 0) {\n logger.monster(\n `Respawning ${monstersToRespawn.length} monsters: ${monstersToRespawn\n .map((m) => m.type)\n .join(\", \")}`\n );\n }\n\n return monstersToRespawn;\n }\n\n // ===== PAUSE MANAGEMENT =====\n public pause(): void {\n this.paused = true;\n logger.pause(\"Respawn system paused\");\n }\n\n public resume(): void {\n this.paused = false;\n logger.pause(\"Respawn system resumed\");\n }\n\n public isPaused(): boolean {\n return this.paused;\n }\n\n private respawnMonster(monster: Monster): Monster {\n const spawnPoint = monster.originalSpawnPoint!;\n\n // Reset monster state\n this.resetMonsterState(monster, spawnPoint);\n\n // Reset individual scaling for this monster\n this.scalingManager.resetMonsterScaling(monster);\n\n logger.monster(`${monster.type} respawned`);\n\n return monster;\n }\n\n private resetMonsterState(\n monster: Monster,\n spawnPoint: { x: number; y: number }\n ): void {\n // Reset basic state\n monster.isDead = false;\n monster.isActive = true;\n monster.x = spawnPoint.x;\n monster.y = spawnPoint.y;\n monster.isFrozen = false;\n monster.isBlinking = false;\n\n // Reset movement properties\n monster.velocityX = 0;\n monster.velocityY = 0;\n monster.isGrounded = false;\n monster.isFalling = false;\n monster.currentPlatform = null;\n\n // Reset behavior state\n monster.behaviorState = undefined;\n monster.lastDirectionChange = undefined;\n\n // Clear respawn properties\n monster.deathTime = undefined;\n monster.respawnTime = undefined;\n }\n\n private getRespawnDelay(monsterType: string): number {\n switch (monsterType) {\n case \"AMBUSHER\":\n return this.respawnConfig.ambusher;\n case \"CHASER\":\n return this.respawnConfig.chaser;\n case \"FLOATER\":\n return this.respawnConfig.floater;\n case \"HORIZONTAL_PATROL\":\n case \"VERTICAL_PATROL\":\n return this.respawnConfig.patrol;\n default:\n logger.warn(\n `Unknown monster type for respawn delay: ${monsterType}, using default`\n );\n return this.respawnConfig.patrol;\n }\n }\n\n // ===== UTILITY METHODS =====\n public getDeadMonsterCount(): number {\n return this.deadMonsters.length;\n }\n\n public getDeadMonsters(): Monster[] {\n return this.deadMonsters.map((dm) => dm.monster);\n }\n\n public getRespawnTimeRemaining(monster: Monster): number {\n if (!monster.isDead || !monster.respawnTime) {\n return 0;\n }\n return Math.max(0, monster.respawnTime - Date.now());\n }\n\n public getNextRespawnTime(): number | null {\n return this.deadMonsters.length > 0\n ? this.deadMonsters[0].respawnTime\n : null;\n }\n\n public reset(): void {\n this.deadMonsters = [];\n this.lastUpdateTime = 0;\n logger.debug(\"OptimizedRespawnManager: Reset - cleared all dead monsters\");\n }\n\n public setUpdateInterval(intervalMs: number): void {\n this.updateInterval = intervalMs;\n logger.debug(\n `OptimizedRespawnManager: Update interval set to ${intervalMs}ms`\n );\n }\n\n public cleanup(): void {\n this.deadMonsters = [];\n this.lastUpdateTime = 0;\n }\n}\n","import {\n Player,\n Monster,\n Bomb,\n Platform,\n Ground,\n Coin,\n FloatingText,\n} from \"../types/interfaces\";\nimport { COLORS } from \"../types/constants\";\nimport { playerSprite } from \"../entities/Player\";\nimport { bombSprite, BombSpriteInstance } from \"../entities/Bomb\";\nimport { SpriteInstance } from \"../lib/SpriteInstance\";\nimport { GAME_CONFIG } from \"../types/constants\";\nimport { COIN_TYPES, P_COIN_COLORS } from \"../config/coinTypes\";\nimport { log } from \"../lib/logger\";\nimport { BackgroundManager } from \"./BackgroundManager\";\nimport { OptimizedRespawnManager } from \"./OptimizedRespawnManager\";\n\ninterface CoinManagerInterface {\n getPcoinCurrentColor: (coin: Coin) => string;\n}\n\nexport class RenderManager {\n private canvas: HTMLCanvasElement;\n private ctx: CanvasRenderingContext2D;\n private lastTime: number = 0;\n private backgroundManager: BackgroundManager;\n private bombSprites: Map<number, SpriteInstance> = new Map(); // Individual sprites for each bomb\n private currentSpawnManager: any = null;\n private currentGameState: any = null;\n\n constructor(canvas: HTMLCanvasElement) {\n this.canvas = canvas;\n this.ctx = canvas.getContext(\"2d\")!;\n this.backgroundManager = new BackgroundManager(canvas.width, canvas.height);\n log.debug(\"RenderManager initialized with canvas\");\n }\n\n render(\n player: Player,\n platforms: Platform[],\n bombs: Bomb[],\n monsters: Monster[],\n ground: Ground | null,\n coins: Coin[] = [],\n floatingTexts: FloatingText[] = [],\n coinManager?: CoinManagerInterface,\n spawnManager?: any,\n currentMap?: any,\n gameState?: any\n ): void {\n // Store spawn manager and game state for use in indicator rendering\n this.currentSpawnManager = spawnManager;\n this.currentGameState = gameState;\n const currentTime = Date.now();\n const deltaTime = currentTime - this.lastTime;\n this.lastTime = currentTime;\n\n // Update background based on player position\n this.backgroundManager.update(player.x, player.y);\n\n // Render background first\n this.renderBackground();\n\n // Render game elements on top\n if (ground) {\n this.renderGround(ground);\n }\n this.renderPlatforms(platforms);\n this.renderBombs(bombs);\n this.renderCoins(coins, coinManager);\n this.renderMonsters(monsters);\n this.renderPlayer(player);\n this.renderFloatingTexts(floatingTexts, deltaTime);\n }\n\n private clearCanvas(): void {\n this.ctx.fillStyle = COLORS.BACKGROUND;\n this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);\n }\n\n private renderBackground(): void {\n if (GAME_CONFIG.USE_SPRITES && GAME_CONFIG.PARALLAX_ENABLED) {\n // Use background when sprites and parallax are enabled\n this.backgroundManager.render(this.ctx);\n } else {\n // Fallback to solid background when sprites or parallax are disabled\n this.clearCanvas();\n }\n }\n\n private renderGround(ground: Ground): void {\n this.ctx.fillStyle = ground.color;\n this.ctx.fillRect(ground.x, ground.y, ground.width, ground.height);\n }\n\n private renderPlayer(player: Player): void {\n if (playerSprite && GAME_CONFIG.USE_SPRITES) {\n // Calculate scale to match player's collision dimensions\n const scale = player.height / GAME_CONFIG.PLAYER_HEIGHT;\n playerSprite.draw(this.ctx, player.x, player.y, scale);\n } else {\n this.ctx.fillStyle = player.color;\n this.ctx.fillRect(player.x, player.y, player.width, player.height);\n }\n }\n\n private renderPlatforms(platforms: Platform[]): void {\n platforms.forEach((platform) => {\n this.ctx.fillStyle = platform.color;\n this.ctx.strokeStyle = platform.borderColor;\n\n // Draw rounded rectangle\n const radius = 4; // Corner radius\n const x = platform.x;\n const y = platform.y;\n const width = platform.width;\n const height = platform.height;\n\n this.ctx.beginPath();\n this.ctx.moveTo(x + radius, y);\n this.ctx.lineTo(x + width - radius, y);\n this.ctx.quadraticCurveTo(x + width, y, x + width, y + radius);\n this.ctx.lineTo(x + width, y + height - radius);\n this.ctx.quadraticCurveTo(\n x + width,\n y + height,\n x + width - radius,\n y + height\n );\n this.ctx.lineTo(x + radius, y + height);\n this.ctx.quadraticCurveTo(x, y + height, x, y + height - radius);\n this.ctx.lineTo(x, y + radius);\n this.ctx.quadraticCurveTo(x, y, x + radius, y);\n this.ctx.closePath();\n this.ctx.lineWidth = 3;\n this.ctx.stroke();\n this.ctx.fill();\n });\n }\n\n private renderBombs(bombs: Bomb[]): void {\n bombs.forEach((bomb) => {\n // Don't render collected bombs\n if (bomb.isCollected) {\n return;\n }\n\n if (bombSprite && GAME_CONFIG.USE_SPRITES) {\n // Get or create individual sprite for this bomb\n let individualSprite = this.bombSprites.get(bomb.order);\n if (!individualSprite) {\n // Create new sprite instance for this bomb\n const bombAnimations = [\n {\n name: \"unlit\",\n frames: bombSprite.animations.unlit.frames,\n frameDuration: 50,\n loop: false,\n },\n {\n name: \"lit\",\n frames: bombSprite.animations.lit.frames,\n frameDuration: 100,\n loop: true,\n },\n ];\n individualSprite = new BombSpriteInstance(bombAnimations, \"unlit\");\n this.bombSprites.set(bomb.order, individualSprite);\n }\n\n // Set animation based on this bomb's state\n const animationName = bomb.isBlinking ? \"lit\" : \"unlit\";\n individualSprite.setAnimation(animationName);\n individualSprite.update(16);\n\n // Calculate scale to match bomb's collision dimensions\n const scale = bomb.width / GAME_CONFIG.BOMB_SIZE;\n individualSprite.draw(this.ctx, bomb.x, bomb.y, scale);\n } else {\n // Fallback to colored rectangles\n this.ctx.fillStyle = bomb.isBlinking ? COLORS.BOMB_NEXT : COLORS.BOMB;\n this.ctx.fillRect(bomb.x, bomb.y, bomb.width, bomb.height);\n\n // Draw bomb number\n this.ctx.fillStyle = \"#000000\";\n this.ctx.font = \"12px Arial\";\n this.ctx.textAlign = \"center\";\n this.ctx.fillText(\n bomb.order.toString(),\n bomb.x + bomb.width / 2,\n bomb.y + bomb.height / 2 + 4\n );\n }\n });\n }\n\n private renderCoins(coins: Coin[], coinManager?: CoinManagerInterface): void {\n coins.forEach((coin) => {\n if (coin.isCollected) {\n return; // Don't render collected coins\n }\n\n const coinConfig = COIN_TYPES[coin.type];\n let color = coinConfig?.color || \"#FFD700\"; // Default gold color\n\n // Special handling for P-coins (power coins)\n if (coin.type === \"POWER\" && coinManager) {\n color = coinManager.getPcoinCurrentColor(coin);\n }\n\n // Draw coin as circle\n this.ctx.fillStyle = color;\n this.ctx.beginPath();\n this.ctx.arc(\n coin.x + coin.width / 2,\n coin.y + coin.height / 2,\n coin.width / 2,\n 0,\n 2 * Math.PI\n );\n this.ctx.fill();\n\n // Add coin type indicator\n this.ctx.fillStyle = \"#fff\";\n this.ctx.font = \"14px Arial\";\n this.ctx.textAlign = \"center\";\n this.ctx.textBaseline = \"middle\";\n\n let coinSymbol = \"C\";\n if (coin.type === \"POWER\") {\n coinSymbol = \"P\";\n this.ctx.fillStyle = \"#000\";\n } else if (coin.type === \"BONUS_MULTIPLIER\") {\n coinSymbol = \"B\";\n this.ctx.fillStyle = \"#fff\";\n } else if (coin.type === \"EXTRA_LIFE\") {\n coinSymbol = \"M\";\n this.ctx.fillStyle = \"#fff\";\n }\n\n this.ctx.fillText(\n coinSymbol,\n coin.x + coin.width / 2,\n coin.y + coin.height / 2 + 2\n );\n });\n }\n\n private renderMonsters(monsters: Monster[]): void {\n // log.debug(`Rendering ${monsters.length} monsters`);\n\n monsters.forEach((monster, index) => {\n if (!monster.isActive) {\n log.debug(`Monster ${index} is not active, skipping`);\n return; // Don't render inactive monsters\n }\n\n // log.debug(`Rendering monster ${index}:`, {\n // type: monster.type,\n // x: monster.x,\n // y: monster.y,\n // color: monster.color,\n // isActive: monster.isActive,\n // isFrozen: monster.isFrozen,\n // isBlinking: monster.isBlinking,\n // });\n\n // Handle blinking effect for monsters about to unfreeze\n let monsterColor = monster.color;\n if (monster.isBlinking) {\n const time = Date.now();\n if (Math.floor(time / 300) % 2 === 0) {\n monsterColor = COLORS.MONSTER_FROZEN; // Blink to frozen color\n } else {\n monsterColor = monster.color; // Normal color\n }\n } else if (monster.isFrozen) {\n monsterColor = COLORS.MONSTER_FROZEN;\n }\n\n this.ctx.fillStyle = monsterColor;\n this.ctx.fillRect(monster.x, monster.y, monster.width, monster.height);\n\n // Draw monster eyes\n this.ctx.fillStyle = \"#000\";\n this.ctx.fillRect(monster.x + 2, monster.y + 2, 2, 2);\n this.ctx.fillRect(monster.x + monster.width - 4, monster.y + 2, 2, 2);\n });\n\n // Render respawn indicators for dead monsters\n this.renderRespawnIndicators(monsters);\n\n // Render spawn indicators for pending dynamic spawns\n this.renderSpawnIndicators(this.currentSpawnManager);\n }\n\n private renderRespawnIndicators(monsters: Monster[]): void {\n const respawnManager = OptimizedRespawnManager.getInstance();\n\n monsters.forEach((monster) => {\n if (monster.isDead && monster.originalSpawnPoint) {\n const timeRemaining = respawnManager.getRespawnTimeRemaining(monster);\n const secondsRemaining = Math.ceil(timeRemaining / 1000);\n if (timeRemaining > 0 && secondsRemaining <= 3) {\n // Only show in final 3 seconds\n // Draw respawn indicator at original spawn point\n const spawnPoint = monster.originalSpawnPoint;\n\n // Use monster's actual color with pulsating effect\n const pulseIntensity = Math.sin(Date.now() / 200) * 0.3 + 0.7; // Pulsing effect\n const monsterColor = monster.color || \"#ffffff\";\n\n // Draw a pulsating filled rectangle using monster's color\n this.ctx.fillStyle = `${monsterColor}${Math.floor(\n pulseIntensity * 1 * 255\n )\n .toString(16)\n .padStart(2, \"0\")}`;\n this.ctx.fillRect(\n spawnPoint.x,\n spawnPoint.y,\n monster.width,\n monster.height\n );\n\n // Draw respawn timer inside the rectangle\n const text = `${secondsRemaining}`;\n const textX = spawnPoint.x + monster.width / 2;\n const textY = spawnPoint.y + monster.height / 2 + 4;\n\n // Draw text using monster's color\n this.ctx.fillStyle = \"#ffffff\"; // White text for contrast\n this.ctx.font = \"16px Arial\";\n this.ctx.textAlign = \"center\";\n this.ctx.textBaseline = \"middle\";\n this.ctx.fillText(text, textX, textY);\n }\n }\n });\n }\n\n private renderSpawnIndicators(spawnManager?: any): void {\n if (!spawnManager) {\n return;\n }\n \n // Only show spawn indicators when game is in PLAYING state\n if (!this.currentGameState || this.currentGameState.currentState !== \"PLAYING\") {\n return;\n }\n \n try {\n const pendingSpawns = spawnManager.getPendingSpawns();\n \n pendingSpawns.forEach((spawn: any) => {\n const timeRemaining = spawnManager.getSpawnTimeRemaining(spawn);\n const secondsRemaining = Math.ceil(timeRemaining / 1000);\n if (timeRemaining > 0 && secondsRemaining <= 3) {\n // Only show in final 3 seconds\n // Create a temporary monster to get its dimensions and color\n const tempMonster = spawn.spawnPoint.createMonster();\n \n // Use monster's actual color with pulsating effect\n const pulseIntensity = Math.sin(Date.now() / 200) * 0.3 + 0.7; // Pulsing effect\n const monsterColor = tempMonster.color || \"#ffffff\";\n \n // Draw a pulsating filled rectangle using monster's color\n this.ctx.fillStyle = `${monsterColor}${Math.floor(\n pulseIntensity * 1 * 255\n )\n .toString(16)\n .padStart(2, \"0\")}`;\n this.ctx.fillRect(\n tempMonster.x,\n tempMonster.y,\n tempMonster.width,\n tempMonster.height\n );\n \n // Draw spawn timer inside the rectangle\n const text = `${secondsRemaining}`;\n const textX = tempMonster.x + tempMonster.width / 2;\n const textY = tempMonster.y + tempMonster.height / 2;\n \n // Draw text using white for contrast\n this.ctx.fillStyle = \"#ffffff\"; // White text for contrast\n this.ctx.font = \"16px Arial\";\n this.ctx.textAlign = \"center\";\n this.ctx.textBaseline = \"middle\";\n this.ctx.fillText(text, textX, textY);\n }\n });\n } catch (error) {\n // Silently fail if spawn manager is not available\n // This prevents errors when the game is not fully initialized\n }\n }\n\n private renderFloatingTexts(\n floatingTexts: FloatingText[],\n deltaTime: number\n ): void {\n floatingTexts.forEach((text) => {\n // Calculate animation progress\n const elapsed = Date.now() - text.startTime;\n const progress = Math.min(elapsed / text.duration, 1);\n\n // Animate position (float upward)\n const floatDistance = 50; // How far the text floats up\n const animatedY = text.y - floatDistance * progress;\n\n // Animate opacity (fade out)\n const opacity = 1 - progress;\n\n // Apply opacity\n this.ctx.globalAlpha = opacity;\n\n this.ctx.fillStyle = text.color;\n this.ctx.font = `${text.fontSize}px Arial`;\n this.ctx.textAlign = \"center\";\n this.ctx.textBaseline = \"middle\";\n this.ctx.fillText(text.text, text.x, animatedY);\n\n // Reset opacity\n this.ctx.globalAlpha = 1;\n });\n }\n\n // Public method to load a city theme\n loadCityTheme(cityName: string): void {\n this.backgroundManager.loadMapBackground(cityName);\n }\n\n // Public method to load a background by map name\n loadMapBackground(mapName: string): void {\n this.backgroundManager.loadMapBackground(mapName);\n }\n\n // Check if background is ready\n isParallaxReady(): boolean {\n return this.backgroundManager.isReady();\n }\n\n // Check if background is currently loading\n isParallaxLoading(): boolean {\n return this.backgroundManager.isCurrentlyLoading();\n }\n\n // Get current map name\n getCurrentMapName(): string {\n return this.backgroundManager.getCurrentMapName();\n }\n\n // Clear bomb sprites (call when bombs are reset)\n clearBombSprites(): void {\n this.bombSprites.clear();\n }\n}\n","export interface Player {\n x: number;\n y: number;\n width: number;\n height: number;\n color: string;\n velocityX: number;\n velocityY: number;\n isGrounded: boolean;\n isFloating: boolean;\n isJumping: boolean;\n jumpStartTime: number;\n moveSpeed: number;\n jumpPower: number;\n gravity: number;\n floatGravity: number;\n}\n\n// Base monster properties that all monsters share\ninterface BaseMonster {\n x: number;\n y: number;\n width: number;\n height: number;\n color?: string;\n speed: number;\n direction: number;\n isActive: boolean;\n isFrozen?: boolean;\n isBlinking?: boolean; // For power mode warning\n spawnTime?: number; // When this monster was spawned\n lastDirectionChange?: number; // For behavior timing\n behaviorState?: string; // Current behavior state\n spawnDelay?: number; // When this monster should spawn (in milliseconds)\n // New properties for gravity-based movement\n velocityX?: number;\n velocityY?: number;\n isGrounded?: boolean;\n gravity?: number;\n isFalling?: boolean; // Whether the monster is currently falling\n currentPlatform?: Platform | null; // Current platform the monster is on\n spawnSide?: 'left' | 'right'; // Which side of the platform it spawned on\n walkLengths?: number; // How many times to walk across the platform before falling\n currentWalkCount?: number; // Current walk count\n originalSpawnX?: number; // Original spawn position for fall detection\n // Respawn system properties\n isDead?: boolean; // Whether the monster is currently dead\n deathTime?: number; // When the monster was killed\n respawnTime?: number; // When the monster should respawn\n originalSpawnPoint?: { x: number; y: number }; // Original spawn position for respawning\n \n // Individual scaling properties\n individualSpawnTime?: number; // When this specific monster was spawned (for individual scaling)\n individualScalingPaused?: boolean; // Whether this monster's scaling is paused\n}\n\n// Patrol monster (horizontal and vertical)\ninterface PatrolMonster extends BaseMonster {\n type: \"HORIZONTAL_PATROL\" | \"VERTICAL_PATROL\";\n patrolStartX: number;\n patrolEndX: number;\n patrolStartY?: number; // For vertical patrol\n patrolEndY?: number; // For vertical patrol\n patrolSide?: \"left\" | \"right\"; // Which side of platform to patrol on (for vertical patrol)\n targetPlatformX?: number; // Target platform X position for vertical patrol monsters\n}\n\n// Chaser monster\ninterface ChaserMonster extends BaseMonster {\n type: \"CHASER\";\n patrolStartX: number;\n patrolEndX: number;\n patrolStartY?: number;\n patrolEndY?: number;\n directness?: number; // How direct they track the player (0.0-1.0)\n chaseTargetX?: number; // Current chase target\n chaseTargetY?: number; // Current chase target\n chaseUpdateInterval?: number; // How often to update target (ms)\n}\n\n// Ambusher monster\ninterface AmbusherMonster extends BaseMonster {\n type: \"AMBUSHER\";\n targetX?: number; // For wandering behavior\n targetY?: number; // For wandering behavior\n ambushCooldown?: number; // Time until next ambush\n ambushTargetX?: number; // Stored target position\n ambushTargetY?: number; // Stored target position\n}\n\n// Floater monster\ninterface FloaterMonster extends BaseMonster {\n type: \"FLOATER\";\n patrolStartX: number;\n patrolEndX: number;\n patrolStartY?: number;\n patrolEndY?: number;\n startAngle?: number; // Starting angle in degrees for straight-line movement\n}\n\n// Union type for all monster types\nexport type Monster =\n | PatrolMonster\n | ChaserMonster\n | AmbusherMonster\n | FloaterMonster;\n\n// Type guards for monster types\nexport const isPatrolMonster = (monster: Monster): monster is PatrolMonster =>\n monster.type === \"HORIZONTAL_PATROL\" || monster.type === \"VERTICAL_PATROL\";\n\nexport const isChaserMonster = (monster: Monster): monster is ChaserMonster =>\n monster.type === \"CHASER\";\n\nexport const isAmbusherMonster = (\n monster: Monster\n): monster is AmbusherMonster => monster.type === \"AMBUSHER\";\n\nexport const isFloaterMonster = (monster: Monster): monster is FloaterMonster =>\n monster.type === \"FLOATER\";\n\nexport interface Bomb {\n x: number;\n y: number;\n width: number;\n height: number;\n order: number;\n group: number;\n isCollected: boolean;\n isBlinking: boolean;\n isCorrect?: boolean;\n}\n\nexport interface Coin {\n x: number;\n y: number;\n width: number;\n height: number;\n type: string;\n isCollected: boolean;\n velocityX: number;\n velocityY: number;\n spawnX: number;\n spawnY: number;\n effectDuration?: number;\n colorIndex?: number; // For P-coins to track current color\n spawnTime?: number; // For P-coins to track when they spawned\n platformDirection?: number | null; // For platform movement\n groundDirection?: number | null; // For ground movement\n}\n\nexport interface CoinSpawnPoint {\n x: number;\n y: number;\n type: string;\n spawnAngle?: number;\n}\n\nexport interface MonsterSpawnPoint {\n spawnDelay: number; // When this monster should spawn (in milliseconds)\n createMonster: () => Monster; // Function that creates the monster using MonsterFactory\n color?: string; // Optional custom color override for the monster\n}\n\nexport interface Platform {\n x: number;\n y: number;\n width: number;\n height: number;\n color: string;\n borderColor?: string;\n isVertical?: boolean; // Indicates if this is a vertical platform (wall)\n}\n\nexport interface Ground {\n x: number;\n y: number;\n width: number;\n height: number;\n color: string;\n}\n\nexport interface MapDefinition {\n id: string;\n name: string;\n width: number;\n height: number;\n playerStart: {\n x: number;\n y: number;\n };\n platforms: Platform[];\n ground: Ground;\n bombs: Bomb[];\n monsters: Monster[];\n coinSpawnPoints?: CoinSpawnPoint[];\n monsterSpawnPoints?: MonsterSpawnPoint[];\n background?: string;\n spawnIndicatorColor?: string; // Color for spawn/respawn indicators\n\n groupSequence: number[];\n timeLimit?: number;\n \n}\n\nexport interface CollisionResult {\n hasCollision: boolean;\n normal?: { x: number; y: number };\n penetration?: number;\n}\n\nexport interface BombCollectionState {\n collectedBombs: Set<string>;\n correctBombs: Set<string>;\n activeGroup: number | null;\n nextBombOrder: number | null;\n gameStarted: boolean;\n}\n\nexport interface centerPoint {\n offsetHeight: number,\n offsetWidth: number,\n}\n\nexport interface CoinState {\n coins: Coin[];\n activeEffects: {\n powerMode: boolean;\n powerModeEndTime: number;\n };\n firebombCount: number;\n}\n\n// Comprehensive GameState interface for type safety\nexport interface GameStateInterface {\n // Player state\n player: Player;\n\n // Game state\n currentState: string;\n currentLevel: number;\n score: number;\n lives: number;\n multiplier: number;\n multiplierScore: number;\n\n // Collections\n monsters: Monster[];\n bombs: Bomb[];\n coins: Coin[];\n platforms: Platform[];\n ground: Ground;\n\n // Effects\n activeEffects: {\n powerMode: boolean;\n powerModeEndTime: number;\n };\n\n // Counters\n firebombCount: number;\n totalCoinsCollected: number;\n totalPowerCoinsCollected: number;\n totalBonusMultiplierCoinsCollected: number;\n\n // Managers\n coinManager?: {\n resetMonsterKillCount: () => void;\n getPcoinColorForTime?: (spawnTime: number) => {\n color: string;\n points: number;\n name: string;\n index: number;\n duration?: number;\n };\n getPowerModeEndTime?: () => number;\n };\n difficultyManager?: {\n pause: () => void;\n resume: () => void;\n };\n\n // Methods\n addScore: (points: number) => void;\n setMultiplier: (multiplier: number, score: number) => void;\n}\n\n// New interfaces for scalable coin system\nexport interface CoinEffect {\n type: string;\n duration?: number;\n points?: number;\n apply: (gameState: GameStateInterface, coin?: any) => void;\n remove?: (gameState: GameStateInterface) => void;\n}\n\nexport interface CoinPhysicsConfig {\n hasGravity: boolean;\n bounces: boolean;\n reflects: boolean;\n customUpdate?: (coin: Coin, platforms: Platform[], ground: Ground) => void;\n}\n\nexport interface CoinTypeConfig {\n type: string;\n color: string;\n points: number;\n physics: CoinPhysicsConfig;\n effects: CoinEffect[];\n spawnCondition?: (gameState: GameStateInterface) => boolean;\n maxActive?: number;\n}\n\nexport interface FloatingText {\n id: string;\n text: string;\n x: number;\n y: number;\n startTime: number;\n duration: number;\n color: string;\n fontSize: number;\n}\n\n// New interface for monster spawn configurations\nexport interface MonsterSpawnConfig {\n type: string;\n spawnInterval: number; // Base spawn interval in milliseconds\n maxActive: number; // Maximum number of this type active at once\n spawnPoints: Array<{\n x: number;\n y: number;\n patrolStartX?: number;\n patrolEndX?: number;\n patrolStartY?: number;\n patrolEndY?: number;\n }>;\n speedRange: { min: number; max: number };\n difficultyMultiplier: number; // How much this type scales with difficulty\n}\n\n// Interface for dynamic spawning system\nexport interface DynamicSpawnSystem {\n levelStartTime: number;\n currentDifficulty: number;\n spawnConfigs: MonsterSpawnConfig[];\n activeMonsters: Monster[];\n lastSpawnTimes: Map<string, number>;\n difficultyScaling: {\n timeBased: boolean;\n scoreBased: boolean;\n bombBased: boolean;\n };\n}\n","import { Monster, Platform, Ground } from \"../../types/interfaces\";\nimport { GAME_CONFIG } from \"../../types/constants\";\n\nexport class MovementUtils {\n public static checkMonsterPlatformCollision(\n monster: Monster,\n platform: any\n ): boolean {\n return (\n monster.x < platform.x + platform.width &&\n monster.x + monster.width > platform.x &&\n monster.y < platform.y + platform.height &&\n monster.y + monster.height > platform.y\n );\n }\n\n /**\n * Check if monster is standing on top of a platform\n */\n public static isMonsterOnPlatform(monster: Monster, platform: Platform): boolean {\n const tolerance = 2; // Small tolerance for platform detection\n return (\n monster.x < platform.x + platform.width &&\n monster.x + monster.width > platform.x &&\n Math.abs(monster.y + monster.height - platform.y) <= tolerance\n );\n }\n\n /**\n * Find the platform the monster is currently standing on\n */\n public static findCurrentPlatform(monster: Monster, platforms: Platform[]): Platform | null {\n for (const platform of platforms) {\n if (this.isMonsterOnPlatform(monster, platform)) {\n return platform;\n }\n }\n return null;\n }\n\n /**\n * Check if monster is on the ground\n */\n public static isMonsterOnGround(monster: Monster, ground: Ground): boolean {\n const tolerance = 2;\n return Math.abs(monster.y + monster.height - ground.y) <= tolerance;\n }\n\n /**\n * Apply gravity to monster\n */\n public static applyGravity(monster: Monster): void {\n if (!monster.velocityY) monster.velocityY = 0;\n if (!monster.gravity) monster.gravity = GAME_CONFIG.GRAVITY;\n \n monster.velocityY += monster.gravity;\n monster.y += monster.velocityY;\n }\n\n /**\n * Check if monster has reached the edge of a platform\n */\n public static isAtPlatformEdge(monster: Monster, platform: Platform, direction: number): boolean {\n const edgeTolerance = 5;\n \n if (direction > 0) {\n // Moving right, check right edge\n return monster.x + monster.width >= platform.x + platform.width - edgeTolerance;\n } else {\n // Moving left, check left edge\n return monster.x <= platform.x + edgeTolerance;\n }\n }\n\n /**\n * Check if monster has fallen off the platform\n */\n public static hasFallenOffPlatform(monster: Monster, platform: Platform): boolean {\n return (\n monster.x + monster.width < platform.x || // Fell off left edge\n monster.x > platform.x + platform.width // Fell off right edge\n );\n }\n\n /**\n * Determine which side of a platform a monster spawned on\n */\n public static determineSpawnSide(monster: Monster, platform: Platform): 'left' | 'right' {\n const platformCenter = platform.x + platform.width / 2;\n return monster.x < platformCenter ? 'left' : 'right';\n }\n\n /**\n * Check if monster should fall based on walk count and position\n */\n public static shouldFall(\n monster: Monster, \n platform: Platform, \n originalSpawnX: number, \n currentWalkCount: number, \n walkLengths: number\n ): boolean {\n // Check if we've completed the required number of walks\n if (currentWalkCount >= walkLengths) {\n // Check if we're back at the original spawn position (with some tolerance)\n const tolerance = 10;\n const isAtSpawnPosition = Math.abs(monster.x - originalSpawnX) <= tolerance;\n \n if (isAtSpawnPosition) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Check if monster would be outside map boundaries at the given position\n */\n public static isOutsideBoundaries(\n monster: Monster,\n newX: number,\n newY: number\n ): boolean {\n return (\n newX <= 0 ||\n newX + monster.width >= GAME_CONFIG.CANVAS_WIDTH ||\n newY <= 0 ||\n newY + monster.height >= GAME_CONFIG.CANVAS_HEIGHT\n );\n }\n\n /**\n * Clamp monster position to map boundaries\n */\n public static clampToBoundaries(monster: Monster): void {\n monster.x = Math.max(0, Math.min(monster.x, GAME_CONFIG.CANVAS_WIDTH - monster.width));\n monster.y = Math.max(0, Math.min(monster.y, GAME_CONFIG.CANVAS_HEIGHT - monster.height));\n }\n\n /**\n * Check if movement to new position is safe (no platform collisions and within boundaries)\n */\n public static isMovementSafe(\n monster: Monster,\n newX: number,\n newY: number,\n platforms: any[]\n ): boolean {\n // Check boundary collisions\n if (this.isOutsideBoundaries(monster, newX, newY)) {\n return false;\n }\n\n // Check platform collisions\n for (const platform of platforms) {\n if (this.checkMonsterPlatformCollision({ ...monster, x: newX, y: newY }, platform)) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Check if movement to new position is safe (including ground collision)\n */\n public static isMovementSafeWithGround(\n monster: Monster,\n newX: number,\n newY: number,\n platforms: any[],\n ground: any\n ): boolean {\n // Check boundary collisions\n if (this.isOutsideBoundaries(monster, newX, newY)) {\n return false;\n }\n\n // Check platform collisions\n for (const platform of platforms) {\n if (this.checkMonsterPlatformCollision({ ...monster, x: newX, y: newY }, platform)) {\n return false;\n }\n }\n\n // Check ground collision\n if (ground) {\n if (this.checkMonsterPlatformCollision({ ...monster, x: newX, y: newY }, ground)) {\n return false;\n }\n }\n\n return true;\n }\n} ","import { Monster, isPatrolMonster } from \"../../types/interfaces\";\nimport { GAME_CONFIG } from \"../../types/constants\";\nimport { useGameStore } from \"../../stores/gameStore\";\nimport { MovementUtils } from \"./MovementUtils\";\nimport { ScalingManager } from \"../ScalingManager\";\nimport { logger } from \"../../lib/logger\";\n\nexport class PatrolMovement {\n public update(monster: Monster, currentTime: number, gameState?: any, deltaTime?: number): void {\n // Check if game is paused\n if (gameState && gameState.currentState !== 'PLAYING') {\n return;\n }\n\n // Determine if this is horizontal or vertical patrol based on monster type\n const isHorizontal = monster.type === \"HORIZONTAL_PATROL\";\n \n if (isHorizontal) {\n this.updateHorizontalPatrol(monster, currentTime, deltaTime);\n } else {\n this.updateVerticalPatrol(monster, currentTime, deltaTime);\n }\n }\n\n private updateHorizontalPatrol(monster: Monster, currentTime: number, deltaTime?: number): void {\n // Type guard to ensure this is a patrol monster\n if (!isPatrolMonster(monster)) return;\n \n // Get individual scaling values for this monster\n const scalingManager = ScalingManager.getInstance();\n const valuesToUse = scalingManager.getMonsterScaledValues(monster);\n const baseValues = scalingManager.getBaseValues();\n const monsterAge = scalingManager.getMonsterAge(monster);\n const speed = valuesToUse.patrol.speed;\n \n // Log scaling info for debugging (only in debug mode)\n if (monsterAge < 2) {\n logger.debug(`Patrol scaling - Age: ${monsterAge.toFixed(1)}s, Speed: ${speed.toFixed(2)}`);\n }\n\n // Simple back and forth movement on the platform (frame-rate independent)\n const frameSpeed = deltaTime ? speed * (deltaTime / 16.67) : speed; // 16.67ms = 60fps\n const newX = monster.x + frameSpeed * monster.direction;\n\n // Check if we would walk off the platform\n if (\n newX < monster.patrolStartX ||\n newX + monster.width > monster.patrolEndX\n ) {\n // Turn around\n monster.direction *= -1;\n monster.lastDirectionChange = currentTime;\n } else {\n // Safe to move\n monster.x = newX;\n }\n\n // Keep monster on platform\n const gameState = useGameStore.getState();\n const platforms = gameState.platforms || [];\n const currentPlatform = MovementUtils.findCurrentPlatform(monster, platforms);\n \n if (currentPlatform) {\n monster.y = currentPlatform.y - monster.height;\n monster.velocityY = 0;\n monster.isGrounded = true;\n } else {\n // Check ground collision if not on platform\n this.handleGroundCollision(monster, gameState.ground);\n }\n }\n\n private updateVerticalPatrol(monster: Monster, currentTime: number, deltaTime?: number): void {\n // Type guard to ensure this is a patrol monster\n if (!isPatrolMonster(monster)) return;\n \n // Get individual scaling values for this monster\n const scalingManager = ScalingManager.getInstance();\n const valuesToUse = scalingManager.getMonsterScaledValues(monster);\n const baseValues = scalingManager.getBaseValues();\n const monsterAge = scalingManager.getMonsterAge(monster);\n const speed = valuesToUse.patrol.speed;\n \n // Initialize target X position only once\n if (!monster.originalSpawnX) {\n const gameState = useGameStore.getState();\n const platforms = gameState.platforms || [];\n const patrolSide = (monster as any).patrolSide || \"left\";\n const targetPlatformX = (monster as any).targetPlatformX;\n \n // Find the target vertical platform using the stored targetPlatformX\n const targetPlatform = platforms.find(platform => \n platform.isVertical && \n Math.abs(platform.x - targetPlatformX) < 1 // Use exact match with small tolerance\n );\n \n if (targetPlatform) {\n const spacing = 8; // Equal spacing from platform edge\n monster.originalSpawnX = patrolSide === \"left\" \n ? targetPlatform.x - monster.width - spacing // Left side of wall\n : targetPlatform.x + spacing + targetPlatform.width; // Right side of wall\n monster.x = monster.originalSpawnX; // Set initial position\n }\n }\n \n // Simple up and down movement within patrol bounds using appropriate speed (frame-rate independent)\n const frameSpeed = deltaTime ? speed * (deltaTime / 16.67) : speed; // 16.67ms = 60fps\n const newY = monster.y + frameSpeed * monster.direction;\n\n // Check if we would walk off the patrol area\n if (\n newY < monster.patrolStartY ||\n newY + monster.height > monster.patrolEndY\n ) {\n // Turn around\n monster.direction *= -1;\n monster.lastDirectionChange = currentTime;\n } else {\n // Safe to move\n monster.y = newY;\n }\n\n // Keep monster at fixed X position (no repositioning every frame)\n if (monster.originalSpawnX !== undefined) {\n monster.x = monster.originalSpawnX; // Always return to exact position\n monster.velocityX = 0;\n monster.velocityY = 0;\n monster.isGrounded = false;\n } else {\n // Keep monster at fixed X position if no vertical platform found\n monster.velocityX = 0;\n monster.velocityY = 0;\n monster.isGrounded = false;\n }\n }\n\n private handleGroundCollision(monster: Monster, ground: any): void {\n if (!ground) return;\n\n // Check if monster is colliding with ground\n const isColliding = (\n monster.x < ground.x + ground.width &&\n monster.x + monster.width > ground.x &&\n monster.y < ground.y + ground.height &&\n monster.y + monster.height > ground.y\n );\n \n if (isColliding) {\n // Monster is colliding with ground - place it on top\n monster.y = ground.y - monster.height;\n monster.velocityY = 0;\n monster.isGrounded = true;\n }\n }\n} ","import { Monster, isChaserMonster } from \"../../types/interfaces\";\nimport { useGameStore } from \"../../stores/gameStore\";\nimport { logger } from \"../../lib/logger\";\nimport { MovementUtils } from \"./MovementUtils\";\nimport { ScalingManager } from \"../ScalingManager\";\n\nexport class ChaserMovement {\n public update(monster: Monster, currentTime: number, gameState: any, deltaTime?: number): void {\n // Type guard to ensure this is a chaser monster\n if (!isChaserMonster(monster)) return;\n\n // Check if game is paused\n if (gameState.currentState !== 'PLAYING') {\n return;\n }\n \n // Get player position\n const player = gameState.player;\n if (!player) return;\n\n // Get individual scaling values for this monster\n const scalingManager = ScalingManager.getInstance();\n const valuesToUse = scalingManager.getMonsterScaledValues(monster);\n const baseValues = scalingManager.getBaseValues();\n const monsterAge = scalingManager.getMonsterAge(monster);\n \n // Log scaling info for debugging (only in debug mode)\n if (monsterAge < 2) {\n logger.debug(`Chaser scaling - Age: ${monsterAge.toFixed(1)}s, Speed: ${valuesToUse.chaser.speed.toFixed(2)}`);\n }\n\n // Initialize chaser state if not set\n if (!monster.behaviorState) {\n monster.behaviorState = 'chasing';\n monster.lastDirectionChange = currentTime;\n monster.chaseTargetX = player.x;\n monster.chaseTargetY = player.y;\n \n // Store randomization multipliers (not absolute values) to preserve difficulty scaling\n (monster as any).updateIntervalMultiplier = 0.8 + Math.random() * 0.4; // 0.8 to 1.2\n (monster as any).directnessMultiplier = 0.85 + Math.random() * 0.3; // 0.85 to 1.15\n (monster as any).speedMultiplier = 0.9 + Math.random() * 0.2; // 0.9 to 1.1\n \n // Add random offset to initial target to prevent immediate convergence\n const targetOffsetX = (Math.random() - 0.5) * 50; // ±25 pixels\n const targetOffsetY = (Math.random() - 0.5) * 50; // ±25 pixels\n monster.chaseTargetX = player.x + targetOffsetX;\n monster.chaseTargetY = player.y + targetOffsetY;\n \n // Add random delay to prevent all chasers from updating at the same time\n monster.lastDirectionChange = currentTime + Math.random() * valuesToUse.chaser.updateInterval;\n }\n\n const platforms = gameState.platforms || [];\n // Apply individual multipliers to values to preserve difficulty scaling\n const directness = valuesToUse.chaser.directness * ((monster as any).directnessMultiplier || 1);\n const updateInterval = valuesToUse.chaser.updateInterval * ((monster as any).updateIntervalMultiplier || 1);\n\n // Update chase target periodically (creates \"drifting\" effect)\n const timeSinceLastUpdate = currentTime - (monster.lastDirectionChange || currentTime);\n if (timeSinceLastUpdate > updateInterval) {\n // Blend current target with new player position based on directness\n const currentTargetX = monster.chaseTargetX || monster.x;\n const currentTargetY = monster.chaseTargetY || monster.y;\n \n // Only add random offset occasionally (not every update) to reduce jittering\n const shouldAddOffset = Math.random() < 0.3; // 30% chance\n const randomOffsetX = shouldAddOffset ? (Math.random() - 0.5) * 15 : 0; // ±7.5 pixels, or 0\n const randomOffsetY = shouldAddOffset ? (Math.random() - 0.5) * 15 : 0; // ±7.5 pixels, or 0\n \n monster.chaseTargetX = currentTargetX + (player.x + randomOffsetX - currentTargetX) * directness;\n monster.chaseTargetY = currentTargetY + (player.y + randomOffsetY - currentTargetY) * directness;\n \n monster.lastDirectionChange = currentTime;\n \n // logger.debug(`Chaser updated target: (${monster.chaseTargetX}, ${monster.chaseTargetY}) from player (${player.x}, ${player.y}) with directness ${directness}`);\n }\n\n // Calculate direction to current target\n const targetX = monster.chaseTargetX || monster.x;\n const targetY = monster.chaseTargetY || monster.y;\n const dx = targetX - monster.x;\n const dy = targetY - monster.y;\n\n // Calculate distance to target\n const distance = Math.sqrt(dx * dx + dy * dy);\n \n // Debug logging\n // logger.debug(`Chaser at (${monster.x}, ${monster.y}), target at (${targetX}, ${targetY}), dx=${dx}, dy=${dy}, distance=${distance}`);\n \n // Only move if we're not too close to the target (prevents jittering)\n // Increased threshold to reduce micro-movements\n if (distance > 20) {\n // Simple direct movement - move towards target using speed with individual multiplier (frame-rate independent)\n const individualSpeed = valuesToUse.chaser.speed * ((monster as any).speedMultiplier || 1);\n const frameSpeed = deltaTime ? individualSpeed * (deltaTime / 16.67) : individualSpeed; // 16.67ms = 60fps\n const moveX = Math.sign(dx) * frameSpeed;\n const moveY = Math.sign(dy) * frameSpeed;\n \n this.applyMovement(monster, moveX, moveY, targetX, targetY, platforms, gameState.ground);\n } else if (distance > 5) {\n // When close to target, use slower, smoother movement to prevent jittering\n const individualSpeed = valuesToUse.chaser.speed * ((monster as any).speedMultiplier || 1) * 0.5; // Half speed when close\n const frameSpeed = deltaTime ? individualSpeed * (deltaTime / 16.67) : individualSpeed; // 16.67ms = 60fps\n const moveX = Math.sign(dx) * frameSpeed;\n const moveY = Math.sign(dy) * frameSpeed;\n \n this.applyMovement(monster, moveX, moveY, targetX, targetY, platforms, gameState.ground);\n }\n // If distance <= 5, don't move at all to prevent jittering\n }\n \n private applyMovement(monster: Monster, moveX: number, moveY: number, targetX: number, targetY: number, platforms: any[], ground: any): void {\n const newX = monster.x + moveX;\n const newY = monster.y + moveY;\n \n // logger.debug(`Chaser movement: (${moveX}, ${moveY}), new position: (${newX}, ${newY})`);\n \n // Check if X movement is safe (platforms and boundaries)\n const canMoveX = MovementUtils.isMovementSafe(monster, newX, monster.y, platforms);\n \n // Check if Y movement is safe (platforms and boundaries)\n const canMoveY = MovementUtils.isMovementSafe(monster, monster.x, newY, platforms);\n \n // Apply movement if possible\n if (canMoveX) {\n monster.x = newX;\n }\n \n if (canMoveY) {\n monster.y = newY;\n }\n \n // Handle ground collision\n this.handleGroundCollision(monster, ground);\n \n // If we can't move in either direction, try to find an alternative path\n if (!canMoveX && !canMoveY) {\n this.findAlternativePath(monster, targetX, targetY, platforms);\n }\n }\n \n private findAlternativePath(monster: Monster, targetX: number, targetY: number, platforms: any[]): void {\n const dx = targetX - monster.x;\n const dy = targetY - monster.y;\n \n // When blocked, try to move around the platform by going perpendicular to the target direction\n // This creates a more natural \"go around\" behavior\n \n // Determine which direction to try first based on target position\n // Add some randomization to prevent all chasers from choosing the same path\n const randomFactor = Math.random();\n const targetDirection = Math.abs(dx) > Math.abs(dy) \n ? (randomFactor > 0.7 ? 'vertical' : 'horizontal') // 30% chance to choose vertical even if horizontal is closer\n : (randomFactor > 0.7 ? 'horizontal' : 'vertical'); // 30% chance to choose horizontal even if vertical is closer\n \n if (targetDirection === 'horizontal') {\n // Target is more horizontally distant - try moving vertically to go around\n // Randomize direction order to prevent all chasers from choosing the same path\n const verticalDirections = Math.random() > 0.5 ? [1, -1] : [-1, 1]; // Randomize up/down order\n \n for (const verticalDir of verticalDirections) {\n const newY = monster.y + verticalDir * monster.speed;\n let canMoveY = true;\n \n for (const platform of platforms) {\n if (MovementUtils.checkMonsterPlatformCollision({ ...monster, y: newY }, platform)) {\n canMoveY = false;\n break;\n }\n }\n \n if (canMoveY) {\n monster.y = newY;\n // logger.debug(`Chaser found alternative path: moving vertically ${verticalDir > 0 ? 'down' : 'up'}`);\n return;\n }\n }\n \n // If vertical movement failed, try horizontal movement in the opposite direction\n const horizontalDir = Math.sign(dx) * -1; // Move away from target to go around\n const newX = monster.x + horizontalDir * monster.speed;\n let canMoveX = true;\n \n for (const platform of platforms) {\n if (MovementUtils.checkMonsterPlatformCollision({ ...monster, x: newX }, platform)) {\n canMoveX = false;\n break;\n }\n }\n \n if (canMoveX) {\n monster.x = newX;\n // logger.debug(`Chaser found alternative path: moving horizontally away from target`);\n return;\n }\n } else {\n // Target is more vertically distant - try moving horizontally to go around\n // Randomize direction order to prevent all chasers from choosing the same path\n const horizontalDirections = Math.random() > 0.5 ? [1, -1] : [-1, 1]; // Randomize left/right order\n \n for (const horizontalDir of horizontalDirections) {\n const newX = monster.x + horizontalDir * monster.speed;\n let canMoveX = true;\n \n for (const platform of platforms) {\n if (MovementUtils.checkMonsterPlatformCollision({ ...monster, x: newX }, platform)) {\n canMoveX = false;\n break;\n }\n }\n \n if (canMoveX) {\n monster.x = newX;\n // logger.debug(`Chaser found alternative path: moving horizontally ${horizontalDir > 0 ? 'right' : 'left'}`);\n return;\n }\n }\n \n // If horizontal movement failed, try vertical movement in the opposite direction\n const verticalDir = Math.sign(dy) * -1; // Move away from target to go around\n const newY = monster.y + verticalDir * monster.speed;\n let canMoveY = true;\n \n for (const platform of platforms) {\n if (MovementUtils.checkMonsterPlatformCollision({ ...monster, y: newY }, platform)) {\n canMoveY = false;\n break;\n }\n }\n \n if (canMoveY) {\n monster.y = newY;\n // logger.debug(`Chaser found alternative path: moving vertically away from target`);\n return;\n }\n }\n \n // If all alternative paths failed, try random movement to get unstuck\n this.tryRandomMovement(monster, platforms);\n }\n \n private handleGroundCollision(monster: Monster, ground: any): void {\n if (!ground) return;\n \n // Check if monster is colliding with ground\n const isColliding = (\n monster.x < ground.x + ground.width &&\n monster.x + monster.width > ground.x &&\n monster.y < ground.y + ground.height &&\n monster.y + monster.height > ground.y\n );\n \n if (isColliding) {\n // Monster is colliding with ground - place it on top\n monster.y = ground.y - monster.height;\n monster.velocityY = 0;\n monster.isGrounded = true;\n }\n }\n \n private tryRandomMovement(monster: Monster, platforms: any[]): void {\n // Try moving in random directions to get unstuck\n const directions = [\n { x: 1, y: 0 }, // Right\n { x: -1, y: 0 }, // Left\n { x: 0, y: 1 }, // Down\n { x: 0, y: -1 }, // Up\n { x: 1, y: 1 }, // Down-right\n { x: -1, y: 1 }, // Down-left\n { x: 1, y: -1 }, // Up-right\n { x: -1, y: -1 } // Up-left\n ];\n \n // Shuffle directions to try them in random order\n for (let i = directions.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [directions[i], directions[j]] = [directions[j], directions[i]];\n }\n \n for (const dir of directions) {\n const newX = monster.x + dir.x * monster.speed;\n const newY = monster.y + dir.y * monster.speed;\n \n let canMove = true;\n for (const platform of platforms) {\n if (MovementUtils.checkMonsterPlatformCollision({ ...monster, x: newX, y: newY }, platform)) {\n canMove = false;\n break;\n }\n }\n \n if (canMove) {\n monster.x = newX;\n monster.y = newY;\n // logger.debug(`Chaser unstuck with random movement: (${dir.x}, ${dir.y})`);\n return;\n }\n }\n \n // If we still can't move, the monster is completely stuck\n // logger.debug('Chaser is completely stuck and cannot move');\n }\n} ","import { Monster, isAmbusherMonster } from \"../../types/interfaces\";\nimport { GAME_CONFIG } from \"../../types/constants\";\nimport { logger } from \"../../lib/logger\";\nimport { MovementUtils } from \"./MovementUtils\";\nimport { ScalingManager } from \"../ScalingManager\";\n\nexport class AmbusherMovement {\n public update(monster: Monster, currentTime: number, gameState: any, deltaTime?: number): void {\n // Type guard to ensure this is an ambusher monster\n if (!isAmbusherMonster(monster)) return;\n\n // Check if game is paused\n if (gameState.currentState !== 'PLAYING') {\n return;\n }\n\n const player = gameState.player;\n if (!player) return;\n\n // Get individual scaling values for this monster\n const scalingManager = ScalingManager.getInstance();\n const valuesToUse = scalingManager.getMonsterScaledValues(monster);\n const baseValues = scalingManager.getBaseValues();\n const monsterAge = scalingManager.getMonsterAge(monster);\n\n // Log scaling info for debugging (only in debug mode)\n if (monsterAge < 2) {\n logger.debug(`Ambusher scaling - Age: ${monsterAge.toFixed(1)}s, Speed: ${valuesToUse.ambusher.speed.toFixed(2)}`);\n }\n\n // Initialize ambusher state if not set\n if (!monster.behaviorState) {\n monster.behaviorState = \"wandering\";\n monster.lastDirectionChange = currentTime;\n monster.ambushCooldown = 2000; // Start with 2 second delay\n }\n\n const platforms = gameState.platforms || [];\n\n if (monster.behaviorState === \"wandering\") {\n // Initialize current wandering direction if not set\n if (!(monster as any).targetX || !(monster as any).targetY) {\n this.chooseNewWanderingDirection(monster, currentTime);\n }\n\n const timeSinceDirectionChange =\n currentTime - (monster.lastDirectionChange || currentTime);\n\n // Change direction every 2-4 seconds\n if (timeSinceDirectionChange > 2000 + Math.random() * 2000) {\n this.chooseNewWanderingDirection(monster, currentTime);\n }\n\n // Move toward current wandering target\n const moveSpeed = valuesToUse.ambusher.speed * 0.5; // Use appropriate speed\n const frameSpeed = deltaTime ? moveSpeed * (deltaTime / 16.67) : moveSpeed; // 16.67ms = 60fps\n const targetX = (monster as any).targetX || monster.x;\n const targetY = (monster as any).targetY || monster.y;\n\n // Calculate direction to target\n const dx = targetX - monster.x;\n const dy = targetY - monster.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n if (distance > 5) {\n // Normalize direction\n const normX = dx / distance;\n const normY = dy / distance;\n\n // Try to move toward target (frame-rate independent)\n const newX = monster.x + frameSpeed * normX;\n const newY = monster.y + frameSpeed * normY;\n\n // Check if new position is safe (platforms, boundaries, and ground)\n if (MovementUtils.isMovementSafeWithGround(monster, newX, newY, platforms, gameState.ground)) {\n monster.x = newX;\n monster.y = newY;\n } else {\n // If blocked, choose new direction\n this.chooseNewWanderingDirection(monster, currentTime);\n }\n } else {\n // Reached target, choose new direction\n this.chooseNewWanderingDirection(monster, currentTime);\n }\n\n // Check if it's time to ambush using appropriate interval (frame-rate independent)\n monster.ambushCooldown += deltaTime || 16;\n if (monster.ambushCooldown >= valuesToUse.ambusher.ambushInterval) {\n monster.behaviorState = \"ambushing\";\n monster.lastDirectionChange = currentTime;\n monster.ambushCooldown = 0; // Reset cooldown\n monster.ambushTargetX = player.x;\n monster.ambushTargetY = player.y;\n logger.debug(\n `Ambusher switching to ambush mode, targeting player at (${monster.ambushTargetX}, ${monster.ambushTargetY})`\n );\n }\n } else if (monster.behaviorState === \"ambushing\") {\n // Simple ambush: move toward player position\n const ambushSpeed = valuesToUse.ambusher.speed * 3.0; // Use appropriate speed\n const frameSpeed = deltaTime ? ambushSpeed * (deltaTime / 16.67) : ambushSpeed; // 16.67ms = 60fps\n const targetX = monster.ambushTargetX || monster.x;\n const targetY = monster.ambushTargetY || monster.y;\n const distance = Math.sqrt(\n (targetX - monster.x) ** 2 + (targetY - monster.y) ** 2\n );\n\n if (distance > 5) {\n // Calculate direction to target\n const dx = targetX - monster.x;\n const dy = targetY - monster.y;\n const normX = dx / distance;\n const normY = dy / distance;\n\n // Try to move toward target (frame-rate independent)\n const newX = monster.x + frameSpeed * normX;\n const newY = monster.y + frameSpeed * normY;\n\n // Check if movement is safe (platforms, boundaries, and ground)\n if (MovementUtils.isMovementSafeWithGround(monster, newX, newY, platforms, gameState.ground)) {\n monster.x = newX;\n monster.y = newY;\n } else {\n // If blocked, end ambush\n monster.behaviorState = \"wandering\";\n monster.lastDirectionChange = currentTime;\n logger.debug(\"Ambusher blocked, returning to wandering\");\n }\n } else {\n // Reached target, return to wandering\n monster.behaviorState = \"wandering\";\n monster.lastDirectionChange = currentTime;\n logger.debug(\"Ambusher reached target, returning to wandering\");\n }\n }\n }\n\n private chooseNewWanderingDirection(\n monster: Monster,\n currentTime: number\n ): void {\n // Choose a random direction (up, down, left, right, or diagonal)\n const directions = [\n { x: 1, y: 0 }, // Right\n { x: -1, y: 0 }, // Left\n { x: 0, y: 1 }, // Down\n { x: 0, y: -1 }, // Up\n { x: 1, y: 1 }, // Down-Right\n { x: -1, y: 1 }, // Down-Left\n { x: 1, y: -1 }, // Up-Right\n { x: -1, y: -1 }, // Up-Left\n ];\n\n const randomDirection =\n directions[Math.floor(Math.random() * directions.length)];\n\n // Set a target point in that direction (within map bounds)\n const targetDistance = 50 + Math.random() * 100; // Random distance between 50-150 pixels\n const newTargetX = Math.max(\n 0,\n Math.min(\n monster.x + randomDirection.x * targetDistance,\n GAME_CONFIG.CANVAS_WIDTH - monster.width\n )\n );\n const newTargetY = Math.max(\n 0,\n Math.min(\n monster.y + randomDirection.y * targetDistance,\n GAME_CONFIG.CANVAS_HEIGHT - monster.height\n )\n );\n\n (monster as any).targetX = newTargetX;\n (monster as any).targetY = newTargetY;\n monster.lastDirectionChange = currentTime;\n }\n}\n","import { Monster } from \"../../types/interfaces\";\nimport { GAME_CONFIG } from \"../../types/constants\";\nimport { useGameStore } from \"../../stores/gameStore\";\nimport { MovementUtils } from \"./MovementUtils\";\nimport { ScalingManager } from \"../ScalingManager\";\nimport { logger } from \"../../lib/logger\";\n\nexport class FloaterMovement {\n public update(monster: Monster, currentTime: number, gameStateParam?: any, deltaTime?: number): void {\n // Check if game is paused\n if (gameStateParam && gameStateParam.currentState !== 'PLAYING') {\n return;\n }\n\n // Get individual scaling values for this monster\n const scalingManager = ScalingManager.getInstance();\n const valuesToUse = scalingManager.getMonsterScaledValues(monster);\n const baseValues = scalingManager.getBaseValues();\n const monsterAge = scalingManager.getMonsterAge(monster);\n \n // Log scaling info for debugging (only in debug mode)\n if (monsterAge < 2) {\n logger.debug(`Floater scaling - Age: ${monsterAge.toFixed(1)}s, Speed: ${valuesToUse.floater.speed.toFixed(2)}`);\n }\n\n // Initialize velocity if not set (convert angle to velocity)\n if (!monster.velocityX && !monster.velocityY) {\n this.initializeVelocity(monster, valuesToUse.floater.speed);\n }\n\n // Update velocity magnitude with current scaled speed (but preserve direction)\n const currentSpeed = Math.sqrt(monster.velocityX * monster.velocityX + monster.velocityY * monster.velocityY);\n if (currentSpeed > 0) {\n const speedRatio = valuesToUse.floater.speed / currentSpeed;\n monster.velocityX *= speedRatio;\n monster.velocityY *= speedRatio;\n }\n\n // Move in straight line based on velocity (frame-rate independent)\n const frameMultiplier = deltaTime ? deltaTime / 16.67 : 1; // 16.67ms = 60fps\n const newX = monster.x + monster.velocityX * frameMultiplier;\n const newY = monster.y + monster.velocityY * frameMultiplier;\n\n // Check for collisions with platforms\n const gameState = useGameStore.getState();\n const platforms = gameState.platforms || [];\n let canMove = true;\n let collisionNormal = { x: 0, y: 0 };\n\n // Check platform collisions\n for (const platform of platforms) {\n if (MovementUtils.checkMonsterPlatformCollision({ ...monster, x: newX, y: newY }, platform)) {\n canMove = false;\n collisionNormal = this.calculateCollisionNormal(monster, platform);\n break;\n }\n }\n\n // Check boundary collisions\n if (newX <= 0 || newX + monster.width >= GAME_CONFIG.CANVAS_WIDTH ||\n newY <= 0 || newY + monster.height >= GAME_CONFIG.CANVAS_HEIGHT) {\n canMove = false;\n collisionNormal = this.calculateBoundaryCollisionNormal(monster, newX, newY);\n }\n \n // Check ground collision\n if (gameState.ground) {\n if (MovementUtils.checkMonsterPlatformCollision({ ...monster, x: newX, y: newY }, gameState.ground)) {\n canMove = false;\n collisionNormal = this.calculateCollisionNormal(monster, gameState.ground);\n }\n }\n\n if (canMove) {\n // Safe to move\n monster.x = newX;\n monster.y = newY;\n } else {\n // Bounce off the collision using appropriate bounce angle\n this.bounceOffCollision(monster, collisionNormal, valuesToUse.floater.bounceAngle);\n }\n }\n\n private initializeVelocity(monster: Monster, scaledSpeed: number): void {\n // Type guard to ensure this is a floater monster\n if (monster.type !== \"FLOATER\") return;\n \n const angle = monster.startAngle || 45; // Default to 45 degrees if not specified\n \n // Convert angle from degrees to radians\n const angleRad = (angle * Math.PI) / 180;\n \n monster.velocityX = Math.cos(angleRad) * scaledSpeed;\n monster.velocityY = Math.sin(angleRad) * scaledSpeed;\n }\n\n private calculateCollisionNormal(monster: Monster, platform: any): { x: number; y: number } {\n const monsterCenterX = monster.x + monster.width / 2;\n const monsterCenterY = monster.y + monster.height / 2;\n \n // Find the closest point on the platform to the monster center\n const closestX = Math.max(platform.x, Math.min(monsterCenterX, platform.x + platform.width));\n const closestY = Math.max(platform.y, Math.min(monsterCenterY, platform.y + platform.height));\n \n // Calculate the normal vector from the closest point to the monster center\n const normalX = monsterCenterX - closestX;\n const normalY = monsterCenterY - closestY;\n \n // Normalize the normal vector\n const length = Math.sqrt(normalX * normalX + normalY * normalY);\n \n if (length > 0.1) {\n return { x: normalX / length, y: normalY / length };\n } else {\n // Monster is very close to the platform - determine which side\n const distToLeft = Math.abs(monster.x + monster.width - platform.x);\n const distToRight = Math.abs(monster.x - (platform.x + platform.width));\n const distToTop = Math.abs(monster.y + monster.height - platform.y);\n const distToBottom = Math.abs(monster.y - (platform.y + platform.height));\n \n const minDist = Math.min(distToLeft, distToRight, distToTop, distToBottom);\n \n if (minDist === distToLeft) return { x: -1, y: 0 };\n if (minDist === distToRight) return { x: 1, y: 0 };\n if (minDist === distToTop) return { x: 0, y: -1 };\n return { x: 0, y: 1 };\n }\n }\n\n private calculateBoundaryCollisionNormal(monster: Monster, newX: number, newY: number): { x: number; y: number } {\n if (newX <= 0) return { x: 1, y: 0 }; // Left boundary\n if (newX + monster.width >= GAME_CONFIG.CANVAS_WIDTH) return { x: -1, y: 0 }; // Right boundary\n if (newY <= 0) return { x: 0, y: 1 }; // Top boundary\n return { x: 0, y: -1 }; // Bottom boundary\n }\n\n private bounceOffCollision(monster: Monster, normal: { x: number; y: number }, bounceAngle: number): void {\n // Calculate the dot product of velocity and normal\n const dotProduct = monster.velocityX * normal.x + monster.velocityY * normal.y;\n \n // Reflect the velocity vector\n monster.velocityX = monster.velocityX - 2 * dotProduct * normal.x;\n monster.velocityY = monster.velocityY - 2 * dotProduct * normal.y;\n \n // Add some randomness to the bounce based on bounceAngle\n const randomAngle = (Math.random() - 0.5) * bounceAngle;\n const speed = Math.sqrt(monster.velocityX * monster.velocityX + monster.velocityY * monster.velocityY);\n \n // Apply random angle change\n const currentAngle = Math.atan2(monster.velocityY, monster.velocityX);\n const newAngle = currentAngle + randomAngle;\n \n monster.velocityX = Math.cos(newAngle) * speed;\n monster.velocityY = Math.sin(newAngle) * speed;\n }\n} ","import { Monster } from \"../types/interfaces\";\nimport { MonsterType } from \"../types/enums\";\nimport { \n PatrolMovement,\n ChaserMovement,\n AmbusherMovement,\n FloaterMovement\n} from \"./monster-movements\";\nimport { MovementUtils } from \"./monster-movements/MovementUtils\";\n\nexport class MonsterBehaviorManager {\n private patrolMovement: PatrolMovement;\n private chaserMovement: ChaserMovement;\n private ambusherMovement: AmbusherMovement;\n private floaterMovement: FloaterMovement;\n\n constructor() {\n this.patrolMovement = new PatrolMovement();\n this.chaserMovement = new ChaserMovement();\n this.ambusherMovement = new AmbusherMovement();\n this.floaterMovement = new FloaterMovement();\n }\n\n public updateMonsterBehaviors(currentTime: number, gameState: any, deltaTime?: number): void {\n if (!gameState.monsters) return;\n\n gameState.monsters.forEach((monster: Monster) => {\n if (!monster.isActive || monster.isFrozen) return;\n\n switch (monster.type) {\n case MonsterType.HORIZONTAL_PATROL:\n case MonsterType.VERTICAL_PATROL:\n this.patrolMovement.update(monster, currentTime, gameState, deltaTime);\n break;\n case MonsterType.CHASER:\n this.chaserMovement.update(monster, currentTime, gameState, deltaTime);\n break;\n case MonsterType.AMBUSHER:\n this.ambusherMovement.update(monster, currentTime, gameState, deltaTime);\n break;\n case MonsterType.FLOATER:\n this.floaterMovement.update(monster, currentTime, gameState, deltaTime);\n break;\n }\n\n // Safety check: clamp monster to boundaries if it somehow got outside\n MovementUtils.clampToBoundaries(monster);\n });\n }\n}\n","import { Monster, MonsterSpawnPoint } from \"../types/interfaces\";\nimport { logger } from \"../lib/logger\";\nimport { useGameStore } from \"../stores/gameStore\";\nimport { MonsterBehaviorManager } from \"./MonsterBehaviorManager\";\n\ninterface ScheduledSpawn {\n id: string;\n spawnPoint: MonsterSpawnPoint;\n scheduledTime: number;\n executed: boolean;\n}\n\ninterface PauseState {\n isPaused: boolean;\n pauseStartTime: number;\n totalPausedTime: number;\n pauseReasons: Set<string>;\n}\n\nexport class OptimizedSpawnManager {\n private levelStartTime: number = 0;\n private scheduledSpawns: ScheduledSpawn[] = [];\n private behaviorManager: MonsterBehaviorManager;\n private pauseState: PauseState;\n private lastUpdateTime: number = 0;\n private updateInterval: number = 16; // Update every 16ms (60fps) for smooth movement\n\n constructor() {\n this.behaviorManager = new MonsterBehaviorManager();\n this.pauseState = this.createPauseState();\n }\n\n // ===== INITIALIZATION =====\n public initializeLevel(spawnPoints: MonsterSpawnPoint[]): void {\n this.levelStartTime = Date.now();\n this.scheduledSpawns = this.createScheduledSpawns(spawnPoints);\n this.resetPauseState();\n \n logger.flow(`Level initialized with ${spawnPoints.length} spawn points`);\n \n // Debug: Log scheduled spawns\n this.scheduledSpawns.forEach((spawn, index) => {\n const delaySeconds = (spawn.scheduledTime - this.levelStartTime) / 1000;\n try {\n const monster = spawn.spawnPoint.createMonster();\n logger.debug(`Scheduled spawn ${index}: ${monster.type} at ${delaySeconds.toFixed(1)}s`);\n } catch (error) {\n logger.error(`Failed to create monster for spawn ${index}: ${error}`);\n }\n });\n }\n\n private createScheduledSpawns(spawnPoints: MonsterSpawnPoint[]): ScheduledSpawn[] {\n return spawnPoints.map((spawnPoint, index) => ({\n id: `spawn-${index}`,\n spawnPoint,\n scheduledTime: this.levelStartTime + spawnPoint.spawnDelay,\n executed: false,\n }));\n }\n\n private resetPauseState(): void {\n this.pauseState = this.createPauseState();\n }\n\n private createPauseState(): PauseState {\n return {\n isPaused: false,\n pauseStartTime: 0,\n totalPausedTime: 0,\n pauseReasons: new Set(),\n };\n }\n\n // ===== UPDATE LOOP =====\n public update(currentTime: number, deltaTime?: number): void {\n // Don't update if paused\n if (this.pauseState.isPaused) {\n return;\n }\n\n const gameState = useGameStore.getState();\n const adjustedTime = this.getAdjustedTime();\n \n // Debug: Log that update is being called (every 5 seconds)\n if (Math.floor(adjustedTime / 5000) !== Math.floor((adjustedTime - 16) / 5000)) {\n logger.debug(`SpawnManager.update() called at ${(adjustedTime / 1000).toFixed(1)}s, paused: ${this.pauseState.isPaused}, spawns: ${this.scheduledSpawns.length}`);\n }\n \n // Process spawns every frame (no throttling for spawn timing)\n this.processSpawns(currentTime, gameState);\n \n // Update behaviors every frame for smooth movement (only if there are active monsters)\n if (gameState.monsters.some(m => m.isActive)) {\n this.behaviorManager.updateMonsterBehaviors(currentTime, gameState, deltaTime);\n }\n }\n\n private processSpawns(currentTime: number, gameState: any): void {\n const adjustedTime = this.getAdjustedTime();\n const adjustedAbsoluteTime = this.getAdjustedAbsoluteTime();\n const spawnsToExecute: ScheduledSpawn[] = [];\n\n // Debug: Log spawn processing (every 5 seconds)\n if (Math.floor(adjustedTime / 5000) !== Math.floor((adjustedTime - 16) / 5000)) {\n const pendingSpawns = this.scheduledSpawns.filter(s => !s.executed);\n logger.info(`Spawn check at ${(adjustedTime / 1000).toFixed(1)}s: ${pendingSpawns.length} pending spawns`);\n pendingSpawns.forEach(spawn => {\n const timeUntilSpawn = (spawn.scheduledTime - adjustedAbsoluteTime) / 1000;\n try {\n const monster = spawn.spawnPoint.createMonster();\n logger.info(` - ${monster.type} in ${timeUntilSpawn.toFixed(1)}s (scheduled: ${spawn.scheduledTime}, current: ${adjustedAbsoluteTime})`);\n } catch (error) {\n logger.error(` - Failed to create monster: ${error}`);\n }\n });\n }\n\n // Find spawns that should execute now\n for (const spawn of this.scheduledSpawns) {\n if (!spawn.executed && adjustedAbsoluteTime >= spawn.scheduledTime) {\n spawnsToExecute.push(spawn);\n logger.info(`Spawn ready to execute: ${spawn.spawnPoint.createMonster().type} (scheduled at ${(spawn.scheduledTime / 1000).toFixed(1)}s, current time ${(adjustedTime / 1000).toFixed(1)}s)`);\n }\n }\n\n // Execute spawns in batch\n if (spawnsToExecute.length > 0) {\n logger.info(`Executing ${spawnsToExecute.length} spawns at ${(adjustedTime / 1000).toFixed(1)}s`);\n this.executeSpawns(spawnsToExecute, currentTime, gameState);\n }\n }\n\n private executeSpawns(spawns: ScheduledSpawn[], currentTime: number, gameState: any): void {\n const spawnedMonsters: Monster[] = [];\n\n for (const spawn of spawns) {\n try {\n const monster = this.createMonster(spawn.spawnPoint);\n spawnedMonsters.push(monster);\n spawn.executed = true;\n \n logger.monster(`Spawned ${monster.type} at (${monster.x}, ${monster.y})`);\n } catch (error) {\n logger.error(`Failed to spawn monster: ${error}`);\n }\n }\n\n // Batch update game state\n if (spawnedMonsters.length > 0) {\n this.addMonstersToGameState(spawnedMonsters, gameState);\n logger.debug(`Added ${spawnedMonsters.length} monsters to game state`);\n }\n }\n\n private createMonster(spawnPoint: MonsterSpawnPoint): Monster {\n const monster = spawnPoint.createMonster();\n \n if (spawnPoint.color) {\n monster.color = spawnPoint.color;\n }\n\n // Set original spawn point for respawn system\n if (!monster.originalSpawnPoint) {\n monster.originalSpawnPoint = { x: monster.x, y: monster.y };\n }\n\n return monster;\n }\n\n private addMonstersToGameState(monsters: Monster[], gameState: any): void {\n if (gameState.updateMonsters) {\n const currentMonsters = gameState.monsters || [];\n const updatedMonsters = [...currentMonsters, ...monsters];\n gameState.updateMonsters(updatedMonsters);\n } else {\n logger.warn(\"Game state updateMonsters method is not available\");\n }\n }\n\n // ===== PAUSE MANAGEMENT =====\n public pause(reason: string = \"default\"): void {\n if (!this.pauseState.isPaused) {\n this.pauseState.isPaused = true;\n this.pauseState.pauseStartTime = Date.now();\n }\n this.pauseState.pauseReasons.add(reason);\n logger.pause(`Spawning paused (${reason})`);\n logger.debug(`SpawnManager pause state: ${this.pauseState.isPaused}, reasons: ${Array.from(this.pauseState.pauseReasons).join(', ')}`);\n }\n\n public resume(reason: string = \"default\"): void {\n this.pauseState.pauseReasons.delete(reason);\n \n if (this.pauseState.pauseReasons.size === 0 && this.pauseState.isPaused) {\n const pauseDuration = Date.now() - this.pauseState.pauseStartTime;\n this.pauseState.totalPausedTime += pauseDuration;\n this.pauseState.isPaused = false;\n logger.pause(`Spawning resumed (paused for ${(pauseDuration / 1000).toFixed(1)}s)`);\n }\n logger.debug(`SpawnManager pause state: ${this.pauseState.isPaused}, reasons: ${Array.from(this.pauseState.pauseReasons).join(', ')}`);\n }\n\n public isPaused(): boolean {\n return this.pauseState.isPaused;\n }\n\n public getPauseStatus(): any {\n return {\n isPaused: this.pauseState.isPaused,\n pauseReasons: Array.from(this.pauseState.pauseReasons),\n totalPausedTime: this.pauseState.totalPausedTime,\n };\n }\n\n private getAdjustedTime(): number {\n const currentTime = Date.now();\n const actualElapsed = currentTime - this.levelStartTime;\n return actualElapsed - this.pauseState.totalPausedTime;\n }\n\n private getAdjustedAbsoluteTime(): number {\n return this.levelStartTime + this.getAdjustedTime();\n }\n\n // ===== MONSTER MANAGEMENT =====\n public removeMonster(monster: Monster): void {\n monster.isActive = false;\n\n const gameState = useGameStore.getState();\n if (gameState.updateMonsters) {\n const currentMonsters = gameState.monsters || [];\n const updatedMonsters = currentMonsters.filter((m) => m !== monster);\n gameState.updateMonsters(updatedMonsters);\n }\n }\n\n // ===== UTILITY METHODS =====\n public reset(): void {\n this.levelStartTime = Date.now();\n this.scheduledSpawns.forEach(spawn => spawn.executed = false);\n this.resetPauseState();\n this.lastUpdateTime = 0;\n }\n\n public getSpawnStatus(): any {\n const executedCount = this.scheduledSpawns.filter(s => s.executed).length;\n const pendingCount = this.scheduledSpawns.filter(s => !s.executed).length;\n const adjustedTime = this.getAdjustedTime();\n \n return {\n totalSpawnPoints: this.scheduledSpawns.length,\n executedCount,\n pendingCount,\n isPaused: this.pauseState.isPaused,\n pauseReasons: Array.from(this.pauseState.pauseReasons),\n adjustedTime: adjustedTime / 1000,\n levelStartTime: this.levelStartTime,\n totalPausedTime: this.pauseState.totalPausedTime,\n };\n }\n\n public getSpawnTimeRemaining(spawn: ScheduledSpawn): number {\n if (spawn.executed) {\n return 0;\n }\n const adjustedAbsoluteTime = this.getAdjustedAbsoluteTime();\n return Math.max(0, spawn.scheduledTime - adjustedAbsoluteTime);\n }\n\n public getPendingSpawns(): ScheduledSpawn[] {\n return this.scheduledSpawns.filter(s => !s.executed);\n }\n\n public setUpdateInterval(intervalMs: number): void {\n this.updateInterval = intervalMs;\n logger.debug(`OptimizedSpawnManager: Update interval set to ${intervalMs}ms`);\n }\n\n public cleanup(): void {\n this.scheduledSpawns = [];\n this.resetPauseState();\n this.lastUpdateTime = 0;\n }\n} ","import { AudioEvent, GameState } from \"../types/enums\";\nimport { ASSET_PATHS } from \"../config/assets\";\nimport { useGameStore } from \"../stores/gameStore\";\nimport { log } from \"../lib/logger\";\n\n// Type definition for webkit AudioContext\ninterface WebkitWindow extends Window {\n webkitAudioContext?: typeof AudioContext;\n}\n\nexport class AudioManager {\n private audioContext: AudioContext | null = null;\n private backgroundMusicGain: GainNode | null = null;\n private isBackgroundMusicPlaying = false;\n private backgroundMusicBuffer: AudioBuffer | null = null;\n private backgroundMusicSource: AudioBufferSourceNode | null = null;\n\n constructor() {\n this.initializeAudioContext();\n this.loadBackgroundMusic();\n }\n\n private initializeAudioContext(): void {\n try {\n this.audioContext = new (window.AudioContext ||\n (window as WebkitWindow).webkitAudioContext)();\n this.backgroundMusicGain = this.audioContext.createGain();\n this.backgroundMusicGain.connect(this.audioContext.destination);\n this.updateAudioVolumes(); // Set initial volume based on settings\n } catch (error) {\n log.warn(\"Web Audio API not supported:\", error);\n }\n }\n\n private async loadBackgroundMusic(): Promise<void> {\n if (!this.audioContext) return;\n\n try {\n const response = await fetch(`${ASSET_PATHS.audio}/background-music.wav`);\n const arrayBuffer = await response.arrayBuffer();\n this.backgroundMusicBuffer = await this.audioContext.decodeAudioData(\n arrayBuffer\n );\n \n } catch (error) {\n log.warn(\"Failed to load background music:\", error);\n }\n }\n\n private ensureAudioContext(): void {\n if (this.audioContext?.state === \"suspended\") {\n this.audioContext.resume();\n }\n }\n\n playSound(event: AudioEvent, gameState?: GameState): void {\n this.ensureAudioContext();\n\n switch (event) {\n case AudioEvent.BOMB_COLLECT:\n this.playBombCollectSound();\n break;\n case AudioEvent.MONSTER_HIT:\n this.playMonsterHitSound();\n break;\n case AudioEvent.MAP_CLEARED:\n this.playMapClearedSound();\n break;\n case AudioEvent.BONUS_SCREEN:\n log.audio(\"Bonus sound\");\n this.playBonusSound();\n break;\n case AudioEvent.COIN_COLLECT:\n this.playCoinCollectSound();\n break;\n case AudioEvent.POWER_COIN_ACTIVATE:\n this.playPowerCoinActivateSound();\n break;\n case AudioEvent.BACKGROUND_MUSIC:\n // Only start background music if game state is PLAYING\n if (gameState === GameState.PLAYING) {\n this.startBackgroundMusic();\n }\n break;\n default:\n log.debug(`Audio event ${event} not implemented yet`);\n }\n }\n\n stopBackgroundMusic(): void {\n \n this.isBackgroundMusicPlaying = false;\n\n // Stop the current audio source if playing\n if (this.backgroundMusicSource) {\n try {\n this.backgroundMusicSource.stop();\n } catch (error) {\n // Source might already be stopped, ignore error\n }\n this.backgroundMusicSource = null;\n }\n }\n\n private playBombCollectSound(): void {\n if (!this.audioContext) return;\n\n const oscillator = this.audioContext.createOscillator();\n const gainNode = this.audioContext.createGain();\n\n oscillator.connect(gainNode);\n gainNode.connect(this.audioContext.destination);\n\n oscillator.type = \"square\";\n oscillator.frequency.setValueAtTime(800, this.audioContext.currentTime);\n oscillator.frequency.exponentialRampToValueAtTime(\n 1200,\n this.audioContext.currentTime + 0.1\n );\n\n const sfxVolume = this.getSFXVolume();\n gainNode.gain.setValueAtTime(0.3 * sfxVolume, this.audioContext.currentTime);\n gainNode.gain.exponentialRampToValueAtTime(\n 0.01,\n this.audioContext.currentTime + 0.2\n );\n\n oscillator.start();\n oscillator.stop(this.audioContext.currentTime + 0.2);\n }\n\n private playMonsterHitSound(): void {\n if (!this.audioContext) return;\n\n const oscillator = this.audioContext.createOscillator();\n const gainNode = this.audioContext.createGain();\n\n oscillator.connect(gainNode);\n gainNode.connect(this.audioContext.destination);\n\n oscillator.type = \"sawtooth\";\n oscillator.frequency.setValueAtTime(200, this.audioContext.currentTime);\n oscillator.frequency.exponentialRampToValueAtTime(\n 50,\n this.audioContext.currentTime + 0.3\n );\n\n const sfxVolume = this.getSFXVolume();\n gainNode.gain.setValueAtTime(0.4 * sfxVolume, this.audioContext.currentTime);\n gainNode.gain.exponentialRampToValueAtTime(\n 0.01,\n this.audioContext.currentTime + 0.3\n );\n\n oscillator.start();\n oscillator.stop(this.audioContext.currentTime + 0.3);\n }\n\n private playMapClearedSound(): void {\n if (!this.audioContext) return;\n\n // Play a ascending melody\n const notes = [523.25, 587.33, 659.25, 698.46, 783.99]; // C5, D5, E5, F5, G5\n let time = this.audioContext.currentTime;\n const sfxVolume = this.getSFXVolume();\n\n notes.forEach((frequency, index) => {\n const oscillator = this.audioContext!.createOscillator();\n const gainNode = this.audioContext!.createGain();\n\n oscillator.connect(gainNode);\n gainNode.connect(this.audioContext!.destination);\n\n oscillator.type = \"triangle\";\n oscillator.frequency.setValueAtTime(frequency, time);\n\n gainNode.gain.setValueAtTime(0.3 * sfxVolume, time);\n gainNode.gain.exponentialRampToValueAtTime(0.01, time + 0.3);\n\n oscillator.start(time);\n oscillator.stop(time + 0.3);\n\n time += 0.15;\n });\n }\n\n private playBonusSound(): void {\n if (!this.audioContext) return;\n\n // Play a short celebratory melody\n const melody = [659.25, 783.99, 1046.5, 783.99, 1046.5]; // E5, G5, C6, G5, C6\n let time = this.audioContext.currentTime;\n const sfxVolume = this.getSFXVolume();\n\n melody.forEach((frequency, index) => {\n const oscillator = this.audioContext!.createOscillator();\n const gainNode = this.audioContext!.createGain();\n\n oscillator.connect(gainNode);\n gainNode.connect(this.audioContext!.destination);\n\n oscillator.type = \"sine\";\n oscillator.frequency.setValueAtTime(frequency, time);\n\n gainNode.gain.setValueAtTime(0.2 * sfxVolume, time);\n gainNode.gain.exponentialRampToValueAtTime(0.01, time + 0.4);\n\n oscillator.start(time);\n oscillator.stop(time + 0.4);\n\n time += 0.2;\n });\n }\n\n private playCoinCollectSound(): void {\n if (!this.audioContext) return;\n\n const oscillator = this.audioContext.createOscillator();\n const gainNode = this.audioContext.createGain();\n\n oscillator.connect(gainNode);\n gainNode.connect(this.audioContext.destination);\n\n oscillator.type = \"sine\";\n oscillator.frequency.setValueAtTime(1000, this.audioContext.currentTime);\n oscillator.frequency.exponentialRampToValueAtTime(\n 1500,\n this.audioContext.currentTime + 0.1\n );\n\n const sfxVolume = this.getSFXVolume();\n gainNode.gain.setValueAtTime(0.3 * sfxVolume, this.audioContext.currentTime);\n gainNode.gain.exponentialRampToValueAtTime(\n 0.01,\n this.audioContext.currentTime + 0.15\n );\n\n oscillator.start();\n oscillator.stop(this.audioContext.currentTime + 0.15);\n }\n\n private playPowerCoinActivateSound(): void {\n if (!this.audioContext) return;\n\n // Play a power-up sound with multiple oscillators\n const time = this.audioContext.currentTime;\n const sfxVolume = this.getSFXVolume();\n\n // Main power sound\n const mainOsc = this.audioContext.createOscillator();\n const mainGain = this.audioContext.createGain();\n mainOsc.connect(mainGain);\n mainGain.connect(this.audioContext.destination);\n\n mainOsc.type = \"square\";\n mainOsc.frequency.setValueAtTime(200, time);\n mainOsc.frequency.exponentialRampToValueAtTime(400, time + 0.3);\n\n mainGain.gain.setValueAtTime(0.2 * sfxVolume, time);\n mainGain.gain.exponentialRampToValueAtTime(0.01, time + 0.5);\n\n mainOsc.start(time);\n mainOsc.stop(time + 0.5);\n\n // High frequency overlay\n const highOsc = this.audioContext.createOscillator();\n const highGain = this.audioContext.createGain();\n highOsc.connect(highGain);\n highGain.connect(this.audioContext.destination);\n\n highOsc.type = \"sine\";\n highOsc.frequency.setValueAtTime(800, time);\n highOsc.frequency.exponentialRampToValueAtTime(1200, time + 0.2);\n\n highGain.gain.setValueAtTime(0.15 * sfxVolume, time);\n highGain.gain.exponentialRampToValueAtTime(0.01, time + 0.3);\n\n highOsc.start(time);\n highOsc.stop(time + 0.3);\n }\n\n private startBackgroundMusic(): void {\n if (\n !this.audioContext ||\n this.isBackgroundMusicPlaying ||\n !this.backgroundMusicBuffer\n )\n return;\n\n \n this.isBackgroundMusicPlaying = true;\n this.playBackgroundMusicFile();\n }\n\n private playBackgroundMusicFile(): void {\n if (\n !this.audioContext ||\n !this.backgroundMusicGain ||\n !this.backgroundMusicBuffer ||\n !this.isBackgroundMusicPlaying\n )\n return;\n\n try {\n this.backgroundMusicSource = this.audioContext.createBufferSource();\n this.backgroundMusicSource.buffer = this.backgroundMusicBuffer;\n this.backgroundMusicSource.connect(this.backgroundMusicGain);\n\n // Set up looping\n this.backgroundMusicSource.loop = true;\n\n // Handle when the audio ends (for non-looping or if loop is disabled)\n this.backgroundMusicSource.onended = () => {\n if (this.isBackgroundMusicPlaying) {\n // Restart the music if it should still be playing\n setTimeout(() => {\n if (this.isBackgroundMusicPlaying) {\n this.playBackgroundMusicFile();\n }\n }, 100);\n }\n };\n\n this.backgroundMusicSource.start();\n \n } catch (error) {\n log.warn(\"Failed to play background music file:\", error);\n }\n }\n\n cleanup(): void {\n this.stopBackgroundMusic();\n if (this.audioContext) {\n this.audioContext.close();\n }\n }\n \n private updateAudioVolumes(): void {\n const audioSettings = useGameStore.getState().audioSettings;\n if (this.backgroundMusicGain) {\n const musicVolume = audioSettings.masterMuted || audioSettings.musicMuted \n ? 0 \n : (audioSettings.masterVolume / 100) * (audioSettings.musicVolume / 100);\n this.backgroundMusicGain.gain.value = musicVolume;\n }\n }\n \n private getSFXVolume(): number {\n const audioSettings = useGameStore.getState().audioSettings;\n return audioSettings.masterMuted || audioSettings.sfxMuted \n ? 0 \n : (audioSettings.masterVolume / 100) * (audioSettings.sfxVolume / 100);\n }\n\n // Public method to update audio volumes when settings change\n public updateVolumes(): void {\n this.updateAudioVolumes();\n }\n}\n","import { SpriteInstance } from \"./SpriteInstance\";\n\nexport type AnimationState = {\n isGrounded: boolean;\n isMoving: boolean;\n isFloating: boolean;\n gameState: string;\n moveDirection: \"left\" | \"right\" | \"none\";\n lastDirection: \"left\" | \"right\";\n};\n\nexport class AnimationController {\n private sprite: SpriteInstance;\n private currentState: AnimationState;\n private wasInAir: boolean = false; // Track previous air state for landing detection\n private isLanding: boolean = false; // Track if currently playing landing animation\n private isMapCleared: boolean = false; // Track if map is cleared and player should fall\n private mapClearedFallComplete: boolean = false; // Track if falling is complete\n\n constructor(sprite: SpriteInstance) {\n this.sprite = sprite;\n this.currentState = {\n isGrounded: true,\n isMoving: false,\n isFloating: false,\n gameState: \"\",\n moveDirection: \"none\",\n lastDirection: \"right\",\n };\n }\n\n update(\n isGrounded: boolean,\n moveX: number,\n isFloating: boolean = false,\n gameState: string = \"\"\n ): void {\n const newState: AnimationState = {\n isGrounded,\n isMoving: moveX !== 0,\n isFloating,\n gameState,\n moveDirection: moveX > 0 ? \"right\" : moveX < 0 ? \"left\" : \"none\",\n lastDirection: this.getLastDirection(),\n };\n\n // Check for MAP_CLEARED state transition\n if (gameState === \"MAP_CLEARED\" && !this.isMapCleared) {\n this.isMapCleared = true;\n this.mapClearedFallComplete = false;\n\n // If player is already grounded when map is cleared, immediately complete\n if (isGrounded) {\n this.mapClearedFallComplete = true;\n }\n }\n\n // Check if landing animation finished\n if (this.isLanding) {\n const currentAnim = this.sprite.currentAnimation.name;\n if (\n currentAnim.includes(\"land\") &&\n this.sprite.currentFrameIndex >=\n this.sprite.currentAnimation.frames.length - 1\n ) {\n this.isLanding = false;\n\n // If this was the map cleared landing, mark fall as complete\n if (this.isMapCleared) {\n this.mapClearedFallComplete = true;\n }\n }\n }\n\n // Check for landing transition\n const justLanded = this.wasInAir && isGrounded;\n\n this.currentState = newState;\n this.wasInAir = !isGrounded;\n\n if (justLanded && !this.isLanding && this.isMapCleared) {\n // Map cleared landing - play landing animation\n\n this.setLandingAnimation();\n } else if (justLanded && !this.isLanding) {\n // Normal landing - play landing animation\n\n this.setLandingAnimation();\n } else if (!this.isLanding) {\n // Normal animation update (only if not currently landing)\n this.updateAnimation();\n }\n }\n\n private getLastDirection(): \"left\" | \"right\" {\n const currentAnim = this.sprite.currentAnimation.name;\n return currentAnim.includes(\"right\") ? \"right\" : \"left\";\n }\n\n private updateAnimation(): void {\n const {\n isGrounded,\n isMoving,\n isFloating,\n gameState,\n moveDirection,\n lastDirection,\n } = this.currentState;\n\n if (this.isMapCleared) {\n if (this.mapClearedFallComplete) {\n // Fall complete - play completion animation\n\n this.sprite.setAnimation(\"ghost-complete\");\n } else if (!isGrounded) {\n // Still falling - use jump animation\n\n this.handleAirAnimations(moveDirection, lastDirection);\n } else {\n // Player is on ground - they just landed from falling\n\n this.mapClearedFallComplete = true;\n this.sprite.setAnimation(\"ghost-complete\");\n }\n } else if (gameState === \"MAP_CLEARED\") {\n this.isMapCleared = true;\n this.mapClearedFallComplete = false;\n // Start falling immediately\n this.handleAirAnimations(moveDirection, lastDirection);\n } else if (isFloating) {\n // Floating - check direction for float animation\n this.handleFloatAnimations(moveDirection, lastDirection);\n } else if (!isGrounded) {\n // In air - jump animations\n this.handleAirAnimations(moveDirection, lastDirection);\n } else if (isMoving) {\n // On ground and moving - walk animations\n this.handleWalkAnimations(moveDirection);\n } else {\n // On ground and not moving - idle animations\n this.handleIdleAnimations(lastDirection);\n }\n }\n\n private handleAirAnimations(\n moveDirection: \"left\" | \"right\" | \"none\",\n lastDirection: \"left\" | \"right\"\n ): void {\n if (moveDirection === \"right\") {\n this.sprite.setAnimationPreserveFrame(\"jump-right\");\n } else if (moveDirection === \"left\") {\n this.sprite.setAnimationPreserveFrame(\"jump-left\");\n } else {\n // No movement in air - maintain last direction\n const animation = lastDirection === \"right\" ? \"jump-right\" : \"jump-left\";\n this.sprite.setAnimationPreserveFrame(animation);\n }\n }\n\n private handleFloatAnimations(\n moveDirection: \"left\" | \"right\" | \"none\",\n lastDirection: \"left\" | \"right\"\n ): void {\n if (moveDirection === \"right\") {\n this.sprite.setAnimation(\"float-right\");\n } else if (moveDirection === \"left\") {\n this.sprite.setAnimation(\"float-left\");\n } else {\n // No movement while floating - use stationary float animation\n this.sprite.setAnimation(\"float-stationary\");\n }\n }\n\n private handleWalkAnimations(moveDirection: \"left\" | \"right\" | \"none\"): void {\n if (moveDirection === \"right\") {\n this.sprite.setAnimation(\"walk-right\");\n } else if (moveDirection === \"left\") {\n this.sprite.setAnimation(\"walk-left\");\n }\n }\n\n private handleIdleAnimations(lastDirection: \"left\" | \"right\"): void {\n const animation = lastDirection === \"right\" ? \"idle-right\" : \"idle-left\";\n this.sprite.setAnimation(animation);\n }\n\n // Optional: Add landing animation support\n setLandingAnimation(): void {\n const { lastDirection } = this.currentState;\n const animation = lastDirection === \"right\" ? \"land-right\" : \"land-left\";\n\n this.sprite.setAnimation(animation);\n this.isLanding = true;\n }\n\n // Debug method\n getCurrentState(): AnimationState {\n return { ...this.currentState };\n }\n\n // Reset method for game state changes\n reset(): void {\n this.isMapCleared = false;\n this.mapClearedFallComplete = false;\n this.isLanding = false;\n this.wasInAir = false;\n }\n}\n","import { InputManager } from \"./InputManager\";\nimport { CollisionManager } from \"./CollisionManager\";\nimport { RenderManager } from \"./RenderManager\";\nimport { OptimizedSpawnManager } from \"./OptimizedSpawnManager\";\nimport { ScalingManager } from \"./ScalingManager\";\nimport { OptimizedRespawnManager } from \"./OptimizedRespawnManager\";\nimport { useGameStore } from \"../stores/gameStore\";\nimport { GameState, MenuType } from \"../types/enums\";\nimport { Monster } from \"../types/interfaces\";\nimport { GAME_CONFIG, DEV_CONFIG } from \"../types/constants\";\nimport { mapDefinitions } from \"../maps/mapDefinitions\";\nimport { AudioManager } from \"./AudioManager\";\nimport { AudioEvent } from \"../types/enums\";\nimport { playerSprite } from \"../entities/Player\";\nimport { AnimationController } from \"../lib/AnimationController\";\nimport {\n sendGameReady,\n sendGameStateUpdate,\n sendMapCompletionData,\n} from \"../lib/communicationUtils\";\nimport { log } from \"../lib/logger\";\n\nexport class GameManager {\n private inputManager: InputManager;\n private collisionManager: CollisionManager;\n private renderManager: RenderManager;\n private monsterSpawnManager: OptimizedSpawnManager;\n private audioManager: AudioManager;\n private animationController: AnimationController;\n private scalingManager: ScalingManager;\n private monsterRespawnManager: OptimizedRespawnManager;\n private animationFrameId: number | null = null;\n private lastTime = 0;\n private isBackgroundMusicPlaying = false;\n private previousGameState: GameState | null = null;\n private devModeInitialized = false;\n private boundGameLoop: (currentTime: number) => void;\n private wasGroundedWhenMapCleared: boolean = false;\n private mapStartTime: number = 0;\n\n constructor(canvas: HTMLCanvasElement) {\n this.inputManager = new InputManager();\n this.collisionManager = new CollisionManager();\n this.renderManager = new RenderManager(canvas);\n this.audioManager = new AudioManager();\n this.animationController = new AnimationController(playerSprite);\n this.scalingManager = ScalingManager.getInstance();\n this.monsterRespawnManager = OptimizedRespawnManager.getInstance();\n\n // Initialize monster spawn manager with empty array initially\n this.monsterSpawnManager = new OptimizedSpawnManager();\n\n // Bind the game loop once to prevent multiple instances\n this.boundGameLoop = this.gameLoop.bind(this);\n\n // Set AudioManager reference in store for settings updates\n const gameState = useGameStore.getState();\n if (\"setAudioManager\" in gameState) {\n gameState.setAudioManager(this.audioManager);\n }\n }\n\n start(): void {\n // Check if DEV_MODE is enabled\n if (DEV_CONFIG.ENABLED) {\n log.dev(\"DEV_MODE is ENABLED\");\n log.dev(`Target state: ${DEV_CONFIG.TARGET_STATE}`);\n this.initializeDevMode();\n } else {\n // Reset game state to ensure fresh start\n const gameState = useGameStore.getState();\n gameState.resetGame();\n \n // Set game start time when game actually starts\n if (\"setGameStartTime\" in gameState) {\n (gameState as any).setGameStartTime(Date.now());\n }\n\n // Initialize first level normally\n this.loadCurrentLevel();\n }\n\n // Send game ready signal to host\n sendGameReady();\n\n this.gameLoop(0);\n }\n\n private initializeDevMode(): void {\n const gameState = useGameStore.getState();\n\n // Reset game state first\n gameState.resetGameState();\n\n // Apply mock data AFTER reset\n gameState.addScore(DEV_CONFIG.MOCK_DATA.score);\n\n // Set lives (need to calculate difference)\n const currentLives = gameState.lives;\n const targetLives = DEV_CONFIG.MOCK_DATA.lives;\n if (targetLives < currentLives) {\n for (let i = 0; i < currentLives - targetLives; i++) {\n gameState.loseLife();\n }\n // Reset state after losing lives since loseLife might change it\n if (targetLives > 0) {\n gameState.setState(GameState.MENU);\n }\n }\n\n // Set level to target level in dev mode\n const targetLevel = DEV_CONFIG.TARGET_LEVEL;\n if (targetLevel > 1) {\n // Reset to level 1 first, then advance to target level\n gameState.resetLevelState();\n for (let i = 1; i < targetLevel; i++) {\n gameState.nextLevel();\n }\n }\n // Always load the current level data\n this.loadCurrentLevel();\n\n // Set the target state\n switch (DEV_CONFIG.TARGET_STATE) {\n case \"START_MENU\":\n gameState.setState(GameState.MENU);\n gameState.setMenuType(MenuType.START);\n break;\n case \"COUNTDOWN\":\n gameState.setState(GameState.COUNTDOWN);\n gameState.setMenuType(MenuType.COUNTDOWN);\n break;\n case \"PLAYING\":\n gameState.setState(GameState.PLAYING);\n gameState.setMenuType(MenuType.IN_GAME);\n break;\n case \"PAUSED\":\n gameState.setState(GameState.PAUSED);\n gameState.setMenuType(MenuType.PAUSE);\n break;\n case \"SETTINGS\":\n gameState.setState(GameState.MENU);\n gameState.setMenuType(MenuType.SETTINGS);\n break;\n case \"BONUS\":\n // Set collected bombs count for bonus screen\n gameState.setState(GameState.BONUS);\n gameState.setMenuType(MenuType.BONUS);\n // Mock the correct order count\n gameState.resetBombState();\n for (let i = 0; i < DEV_CONFIG.MOCK_DATA.correctOrderCount; i++) {\n gameState.collectBomb(i + 1);\n }\n break;\n case \"VICTORY\":\n gameState.setState(GameState.VICTORY);\n gameState.setMenuType(MenuType.VICTORY);\n break;\n case \"GAME_OVER\":\n gameState.setState(GameState.GAME_OVER);\n gameState.setMenuType(MenuType.GAME_OVER);\n break;\n default:\n log.warn(`Unknown DEV_MODE target state: ${DEV_CONFIG.TARGET_STATE}`);\n gameState.setState(GameState.MENU);\n gameState.setMenuType(MenuType.START);\n }\n\n // Set multiplier LAST to override any automatic calculations\n log.dev(\n `DEV_MODE: Setting multiplier to ${DEV_CONFIG.MOCK_DATA.multiplier}x with ${DEV_CONFIG.MOCK_DATA.multiplierScore} progress`\n );\n gameState.setMultiplier(\n DEV_CONFIG.MOCK_DATA.multiplier,\n DEV_CONFIG.MOCK_DATA.multiplierScore\n );\n\n log.dev(\n `DEV_MODE initialized with state: ${DEV_CONFIG.TARGET_STATE}, level: ${DEV_CONFIG.TARGET_LEVEL}`\n );\n this.devModeInitialized = true;\n }\n\n stop(): void {\n if (this.animationFrameId) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = null;\n }\n this.audioManager.stopBackgroundMusic();\n this.isBackgroundMusicPlaying = false;\n }\n\n private loadCurrentLevel(): void {\n const gameState = useGameStore.getState();\n const currentLevel = gameState.currentLevel;\n\n if (currentLevel <= mapDefinitions.length) {\n const mapDefinition = mapDefinitions[currentLevel - 1];\n gameState.initializeLevel(mapDefinition);\n\n // Clear floating texts when loading new level\n gameState.clearAllFloatingTexts();\n\n // Reset animation controller state when loading new level\n this.animationController.reset();\n\n // Start difficulty scaling for this map\n this.scalingManager.startMap();\n\n // Load parallax background for this level based on map name (non-blocking)\n this.renderManager.loadMapBackground(mapDefinition.name);\n\n // Initialize monster spawn manager with map-specific spawn points\n if (mapDefinition.monsterSpawnPoints) {\n log.info(\n `GameManager: Initializing MonsterSpawnManager with ${mapDefinition.monsterSpawnPoints.length} spawn points`\n );\n this.monsterSpawnManager.initializeLevel(\n mapDefinition.monsterSpawnPoints\n );\n } else {\n log.info(\n `GameManager: Initializing MonsterSpawnManager with no spawn points`\n );\n this.monsterSpawnManager.initializeLevel([]);\n }\n\n // Reset respawn manager for new level\n this.monsterRespawnManager.reset();\n\n // Set up original spawn points for static monsters from the map\n if (mapDefinition.monsters) {\n const monstersWithSpawnPoints = mapDefinition.monsters.map(\n (monster) => ({\n ...monster,\n originalSpawnPoint: { x: monster.x, y: monster.y },\n })\n );\n gameState.updateMonsters(monstersWithSpawnPoints);\n log.debug(\n `Set up original spawn points for ${monstersWithSpawnPoints.length} static monsters`\n );\n }\n\n // Ensure coins are cleared when loading new level\n gameState.resetCoinState();\n log.debug(\"Coins reset when loading new level\");\n\n // Record map start time for completion tracking\n this.mapStartTime = Date.now();\n }\n }\n\n private gameLoop(currentTime: number): void {\n const deltaTime = currentTime - this.lastTime;\n this.lastTime = currentTime;\n\n const gameState = useGameStore.getState();\n\n // Handle background music - only play during PLAYING state\n // This must be called before dev mode checks to ensure music stops when paused\n this.handleBackgroundMusic(gameState.currentState);\n\n // Handle difficulty manager pause/resume based on game state\n this.handleDifficultyPause(gameState.currentState);\n\n // DEV_MODE: Skip normal game logic if we're in dev mode and not in PLAYING state\n if (DEV_CONFIG.ENABLED && this.devModeInitialized) {\n // Only run normal game logic if we're in PLAYING state in dev mode\n if (gameState.currentState !== GameState.PLAYING) {\n this.render();\n this.animationFrameId = requestAnimationFrame(this.boundGameLoop);\n return;\n }\n }\n\n // Check if we need to reload the level after a reset\n if (gameState.currentState === GameState.MENU && !gameState.currentMap) {\n this.loadCurrentLevel();\n }\n\n // Check for bonus animation completion and auto-continue\n if (\n gameState.currentState === GameState.BONUS &&\n gameState.bonusAnimationComplete &&\n !DEV_CONFIG.ENABLED\n ) {\n // Animation is complete, proceed to next level after a brief delay\n setTimeout(() => {\n this.proceedToNextLevel();\n }, 2000); // 2 second delay after animation completes\n // Reset the flag to prevent multiple calls\n gameState.setBonusAnimationComplete(false);\n }\n\n if (gameState.currentState === GameState.PLAYING) {\n this.update(deltaTime);\n playerSprite.update(deltaTime);\n this.handleCollisions();\n this.checkWinCondition();\n } else if (gameState.currentState === GameState.MAP_CLEARED) {\n // Update sprite animation for map cleared state\n playerSprite.update(deltaTime);\n\n // Get current player state for falling\n const player = gameState.player;\n\n // Only apply gravity if player wasn't already grounded when map was cleared\n if (!this.wasGroundedWhenMapCleared) {\n // Apply gravity to make player fall\n const updatedPlayer = { ...player };\n updatedPlayer.velocityY += player.gravity;\n updatedPlayer.y += updatedPlayer.velocityY;\n\n // Check for ground collision during fall\n const ground = gameState.ground;\n if (ground) {\n const groundCollision =\n this.collisionManager.checkPlayerGroundCollision(\n updatedPlayer,\n ground\n );\n if (\n groundCollision.hasCollision &&\n groundCollision.normal &&\n groundCollision.penetration\n ) {\n if (groundCollision.normal.y === -1) {\n // Landing on ground\n updatedPlayer.y = updatedPlayer.y - groundCollision.penetration;\n updatedPlayer.velocityY = 0;\n updatedPlayer.isGrounded = true;\n }\n }\n }\n\n // Update player state\n gameState.updatePlayer(updatedPlayer);\n }\n\n // Update animation controller with actual player state\n this.animationController.update(\n player.isGrounded,\n 0,\n false,\n gameState.currentState\n );\n }\n\n this.render();\n this.animationFrameId = requestAnimationFrame(this.boundGameLoop);\n }\n\n private handleDifficultyPause(currentState: GameState): void {\n // Pause difficulty scaling and monster spawning when game is not in PLAYING state\n if (currentState === GameState.PLAYING) {\n // Only resume if not paused by power mode\n if (!this.scalingManager.isCurrentlyPausedByPowerMode()) {\n this.scalingManager.resume();\n }\n this.scalingManager.resumeAllMonsterScaling();\n this.monsterSpawnManager.resume();\n this.monsterRespawnManager.resume();\n } else {\n this.scalingManager.pause();\n this.scalingManager.pauseAllMonsterScaling();\n this.monsterSpawnManager.pause();\n this.monsterRespawnManager.pause();\n }\n }\n\n private handleBackgroundMusic(currentState: GameState): void {\n // Only play music during PLAYING state - stop in all other states\n const shouldPlayMusic = currentState === GameState.PLAYING;\n\n // Detect state changes\n const stateChanged = this.previousGameState !== currentState;\n\n if (stateChanged) {\n log.audio(\n `Game state changed: ${this.previousGameState} -> ${currentState}`\n );\n }\n\n // Start music if we should be playing and aren't already\n if (shouldPlayMusic && !this.isBackgroundMusicPlaying) {\n log.audio(\"Starting background music\");\n this.audioManager.playSound(AudioEvent.BACKGROUND_MUSIC, currentState);\n this.isBackgroundMusicPlaying = true;\n }\n\n // Stop music if we shouldn't be playing but are\n if (!shouldPlayMusic && this.isBackgroundMusicPlaying) {\n log.audio(\"Stopping background music\");\n this.audioManager.stopBackgroundMusic();\n this.isBackgroundMusicPlaying = false;\n }\n\n this.previousGameState = currentState;\n }\n\n private update(deltaTime: number): void {\n this.updatePlayer(deltaTime);\n this.updateMonsters(deltaTime);\n this.updateCoins(deltaTime);\n\n // Individual scaling is now handled by ScalingManager per monster\n }\n\n private updatePlayer(deltaTime: number): void {\n const gameState = useGameStore.getState();\n let player = { ...gameState.player };\n\n // Handle pause key\n if (\n this.inputManager.isKeyPressed(\"p\") ||\n this.inputManager.isKeyPressed(\"P\")\n ) {\n if (gameState.currentState === GameState.PLAYING) {\n gameState.setState(GameState.PAUSED);\n gameState.setMenuType(MenuType.PAUSE);\n }\n return; // Don't process other input while paused\n }\n\n // Handle input\n let moveX = 0;\n if (this.inputManager.isKeyPressed(\"ArrowLeft\")) {\n moveX = -player.moveSpeed;\n }\n if (this.inputManager.isKeyPressed(\"ArrowRight\")) {\n moveX = player.moveSpeed;\n }\n\n // Update animation state\n this.animationController.update(\n player.isGrounded,\n moveX,\n player.isFloating,\n gameState.currentState\n );\n\n // Variable height jumping mechanics\n const isUpPressed = this.inputManager.isKeyPressed(\"ArrowUp\");\n const isShiftPressed = this.inputManager.isShiftPressed();\n const isSpacePressed =\n this.inputManager.isKeyPressed(\" \") ||\n this.inputManager.isKeyPressed(\"Space\");\n\n if (isUpPressed && player.isGrounded && !player.isJumping) {\n // Start jump\n player.isJumping = true;\n player.jumpStartTime = Date.now();\n player.isGrounded = false;\n\n // Initial jump velocity (minimum jump)\n const baseJumpPower = isShiftPressed\n ? GAME_CONFIG.SUPER_JUMP_POWER\n : GAME_CONFIG.JUMP_POWER;\n player.velocityY = -baseJumpPower * 0.6; // Start with 60% of jump power\n }\n\n // Continue jump if key is held and we're still in jump phase\n if (isUpPressed && player.isJumping && player.velocityY < 0) {\n const jumpDuration = Date.now() - player.jumpStartTime;\n\n if (jumpDuration <= GAME_CONFIG.MAX_JUMP_DURATION) {\n // Calculate additional jump power based on hold duration\n const holdRatio = Math.min(\n jumpDuration / GAME_CONFIG.MAX_JUMP_DURATION,\n 1\n );\n const baseJumpPower = isShiftPressed\n ? GAME_CONFIG.SUPER_JUMP_POWER\n : GAME_CONFIG.JUMP_POWER;\n const targetVelocity = -baseJumpPower * (0.6 + 0.4 * holdRatio); // Scale from 60% to 100%\n\n // Gradually increase jump power\n if (player.velocityY > targetVelocity) {\n player.velocityY = targetVelocity;\n }\n }\n }\n\n // End jump when key is released or max duration reached\n if (\n (!isUpPressed ||\n Date.now() - player.jumpStartTime > GAME_CONFIG.MAX_JUMP_DURATION) &&\n player.isJumping\n ) {\n player.isJumping = false;\n }\n\n // Floating mechanism - works anytime the player is in the air\n if (isSpacePressed && !player.isGrounded) {\n // Only kill momentum if we're just starting to float (not already floating)\n if (!player.isFloating) {\n player.velocityY = 0;\n }\n // Set floating state for slower fall\n player.isFloating = true;\n } else {\n player.isFloating = false;\n }\n\n // Apply movement\n player.velocityX = moveX;\n player.x += player.velocityX;\n\n // Apply gravity - only use float gravity when floating and falling (velocityY >= 0)\n const gravity =\n player.isFloating && player.velocityY >= 0\n ? player.floatGravity\n : player.gravity;\n player.velocityY += gravity;\n player.y += player.velocityY;\n\n // Handle boundary collisions\n const bounds = {\n width: GAME_CONFIG.CANVAS_WIDTH,\n height: GAME_CONFIG.CANVAS_HEIGHT,\n };\n const boundaryResult = this.collisionManager.resolveBoundaryCollision(\n player,\n bounds\n );\n\n if (boundaryResult.fellOffScreen) {\n // Player fell off screen\n gameState.loseLife();\n return;\n }\n\n // Update player with boundary-resolved position\n player = boundaryResult.player;\n\n // Reset grounded state\n player.isGrounded = false;\n\n gameState.updatePlayer(player);\n }\n\n private updateMonsters(deltaTime: number): void {\n // Debug: Log that updateMonsters is being called (every 5 seconds)\n const currentTime = Date.now();\n const gameTime = (currentTime - this.mapStartTime) / 1000;\n\n if (\n Math.floor(gameTime / 5) !== Math.floor((gameTime - deltaTime / 1000) / 5)\n ) {\n log.debug(\n `GameManager.updateMonsters() called at ${gameTime.toFixed(1)}s`\n );\n }\n\n // Update monster spawn manager (handles spawning and behavior)\n this.monsterSpawnManager.update(currentTime, deltaTime);\n\n // Update respawn manager - get any monsters that should respawn\n const respawnedMonsters = this.monsterRespawnManager.update();\n\n // Get fresh game state after monster spawning\n const gameState = useGameStore.getState();\n\n // Add any respawned monsters back to the active monsters list\n let monsters = gameState.monsters;\n if (respawnedMonsters.length > 0) {\n monsters = [...monsters, ...respawnedMonsters];\n log.debug(\n `Added ${\n respawnedMonsters.length\n } respawned monsters to active list: ${respawnedMonsters\n .map((m) => m.type)\n .join(\", \")}`\n );\n }\n\n // Debug: Log respawn status\n const deadMonsterCount = this.monsterRespawnManager.getDeadMonsterCount();\n if (deadMonsterCount > 0) {\n log.debug(\n `Respawn system: ${deadMonsterCount} monsters waiting to respawn`\n );\n }\n\n // Update the game state with any new monsters\n gameState.updateMonsters(monsters);\n\n // All monster behavior (including scaling) is now handled by MonsterBehaviorManager\n // through the OptimizedSpawnManager.update() call above\n }\n\n private updateCoins(deltaTime: number): void {\n const gameState = useGameStore.getState();\n const platforms = gameState.currentMap?.platforms || [];\n const ground = gameState.currentMap?.ground;\n const coinManager = gameState.coinManager;\n\n if (ground && coinManager) {\n // Check spawn conditions for all coin types\n coinManager.checkSpawnConditions(\n gameState as unknown as Record<string, unknown>\n );\n\n // Let CoinManager handle all coin physics updates\n coinManager.update(platforms, ground, gameState);\n\n // Update the store with the latest coin state\n gameState.setCoins(coinManager.getCoins());\n\n // Update monster states based on power mode\n gameState.updateMonsterStates(gameState.monsters);\n }\n\n // Update floating texts (remove expired ones)\n gameState.updateFloatingTexts();\n }\n\n private handleCollisions(): void {\n const gameState = useGameStore.getState();\n const { player, platforms, bombs, monsters, ground, coins } = gameState;\n\n // Platform collisions - handle all directions\n const platformCollision =\n this.collisionManager.checkPlayerPlatformCollision(player, platforms);\n if (\n platformCollision.hasCollision &&\n platformCollision.normal &&\n platformCollision.penetration\n ) {\n const updatedPlayer = { ...player };\n\n if (platformCollision.normal.y === -1) {\n // Landing on top of platform\n updatedPlayer.y = updatedPlayer.y - platformCollision.penetration;\n updatedPlayer.velocityY = 0;\n updatedPlayer.isGrounded = true;\n } else if (platformCollision.normal.y === 1) {\n // Hitting platform from below\n updatedPlayer.y = updatedPlayer.y + platformCollision.penetration;\n updatedPlayer.velocityY = 0;\n } else if (platformCollision.normal.x === 1) {\n // Hitting platform from the right\n updatedPlayer.x = updatedPlayer.x + platformCollision.penetration;\n updatedPlayer.velocityX = 0;\n } else if (platformCollision.normal.x === -1) {\n // Hitting platform from the left\n updatedPlayer.x = updatedPlayer.x - platformCollision.penetration;\n updatedPlayer.velocityX = 0;\n }\n\n gameState.updatePlayer(updatedPlayer);\n }\n\n // Ground collision - handle all directions\n if (ground) {\n const groundCollision = this.collisionManager.checkPlayerGroundCollision(\n player,\n ground\n );\n if (\n groundCollision.hasCollision &&\n groundCollision.normal &&\n groundCollision.penetration\n ) {\n const updatedPlayer = { ...player };\n\n if (groundCollision.normal.y === -1) {\n // Landing on top of ground\n updatedPlayer.y = updatedPlayer.y - groundCollision.penetration;\n updatedPlayer.velocityY = 0;\n updatedPlayer.isGrounded = true;\n } else if (groundCollision.normal.y === 1) {\n // Hitting ground from below (shouldn't normally happen but just in case)\n updatedPlayer.y = updatedPlayer.y + groundCollision.penetration;\n updatedPlayer.velocityY = 0;\n } else if (groundCollision.normal.x === 1) {\n // Hitting ground from the right\n updatedPlayer.x = updatedPlayer.x + groundCollision.penetration;\n updatedPlayer.velocityX = 0;\n } else if (groundCollision.normal.x === -1) {\n // Hitting ground from the left\n updatedPlayer.x = updatedPlayer.x - groundCollision.penetration;\n updatedPlayer.velocityX = 0;\n }\n\n gameState.updatePlayer(updatedPlayer);\n }\n }\n\n // Bomb collisions\n const collectedBomb = this.collisionManager.checkPlayerBombCollision(\n player,\n bombs\n );\n if (collectedBomb) {\n this.audioManager.playSound(AudioEvent.BOMB_COLLECT);\n const result = gameState.collectBomb(collectedBomb.order);\n\n // Check if this was a firebomb (correct order) to trigger coin spawning\n if (result && result.isCorrect) {\n gameState.onFirebombCollected();\n }\n }\n\n // Coin collisions\n const collectedCoin = this.collisionManager.checkPlayerCoinCollision(\n player,\n coins\n );\n if (collectedCoin) {\n this.audioManager.playSound(AudioEvent.COIN_COLLECT);\n\n // Let the coin slice handle the collection (it will call coinManager.collectCoin internally)\n gameState.collectCoin(collectedCoin);\n\n // If it's a power coin, play special sound\n if (collectedCoin.type === \"POWER\") {\n this.audioManager.playSound(AudioEvent.POWER_COIN_ACTIVATE);\n }\n }\n\n // Monster collisions\n const hitMonster = this.collisionManager.checkPlayerMonsterCollision(\n player,\n monsters\n );\n if (hitMonster) {\n // Check if god mode is enabled in dev config\n if (DEV_CONFIG.GOD_MODE) {\n log.dev(\"God mode enabled - player is invincible to monsters\");\n return; // Ignore monster collision entirely\n }\n\n // Check if power mode is active - if so, kill the monster instead\n if (gameState.activeEffects.powerMode) {\n // Monster is killed during power mode - use progressive bonus system\n const points =\n gameState.coinManager?.calculateMonsterKillPoints(\n gameState.multiplier\n ) || GAME_CONFIG.MONSTER_KILL_POINTS * gameState.multiplier; // Fallback\n gameState.addScore(points);\n\n // Show floating text for monster kill points\n if (gameState.addFloatingText) {\n const text = points.toString();\n gameState.addFloatingText(\n text,\n hitMonster.x + hitMonster.width / 2,\n hitMonster.y + hitMonster.height / 2,\n 1000, // duration\n \"#fff\", // White color\n 15 // fontSize\n );\n }\n\n // Notify coin manager about points earned (not bonus)\n if (gameState.coinManager) {\n gameState.coinManager.onPointsEarned(points, false);\n }\n\n log.debug(`Monster killed during power mode: ${points} points`);\n\n // Play monster kill sound (same as coin collect sound)\n this.audioManager.playSound(AudioEvent.COIN_COLLECT);\n\n // Kill the monster and schedule it for respawn\n this.monsterRespawnManager.killMonster(hitMonster);\n } else {\n // Normal monster collision - player dies\n this.audioManager.playSound(AudioEvent.MONSTER_HIT);\n this.handlePlayerDeath();\n }\n }\n }\n\n private handlePlayerDeath(): void {\n const gameState = useGameStore.getState();\n\n // Check if this will be the last life before calling loseLife\n if (gameState.lives <= 1) {\n // This will be the last life - just call loseLife and let it handle game over\n gameState.loseLife();\n } else {\n // Player will still have lives after losing one\n gameState.loseLife();\n this.respawnPlayer();\n }\n }\n\n private respawnPlayer(): void {\n const gameState = useGameStore.getState();\n const currentMap = gameState.currentMap;\n\n if (currentMap) {\n // Clear floating texts when respawning\n gameState.clearAllFloatingTexts();\n\n // Reset difficulty to base values when player dies\n this.scalingManager.resetOnDeath();\n log.debug(\n \"ScalingManager: Reset difficulty to base values after player death\"\n );\n\n // Reset coins when player dies\n gameState.resetCoinState();\n log.debug(\"Coins reset after player death\");\n\n // Reset player position\n gameState.setPlayerPosition(\n currentMap.playerStart.x,\n currentMap.playerStart.y\n );\n\n // Reset monsters to starting positions\n const resetMonsters = currentMap.monsters.map((monster) => ({\n ...monster,\n x: (monster as any).patrolStartX || monster.x,\n direction: 1, // Reset to initial direction\n }));\n gameState.updateMonsters(resetMonsters);\n\n // Reset animation controller state\n this.animationController.reset();\n\n // Reload parallax background for the current level\n this.renderManager.loadMapBackground(currentMap.name);\n\n // Show countdown before resuming\n gameState.setMenuType(MenuType.COUNTDOWN);\n gameState.setState(GameState.COUNTDOWN);\n\n setTimeout(() => {\n gameState.setState(GameState.PLAYING);\n }, 3000);\n }\n }\n\n private checkWinCondition(): void {\n const gameState = useGameStore.getState();\n if (gameState.collectedBombs.length === GAME_CONFIG.TOTAL_BOMBS) {\n // Level completed - this will trigger a state change which will stop the music\n log.game(\"Level completed - proceeding to next phase\");\n\n // Record if player was grounded when map was cleared\n this.wasGroundedWhenMapCleared = gameState.player.isGrounded;\n\n // Play map cleared sound\n this.audioManager.playSound(AudioEvent.MAP_CLEARED);\n\n // Set game state to MAP_CLEARED to trigger the animation\n gameState.setState(GameState.MAP_CLEARED);\n\n // Pause the game briefly, then proceed\n setTimeout(() => {\n this.proceedAfterMapCleared();\n }, 3000); // Brief pause to hear the sound and see the animation\n }\n }\n\n private proceedAfterMapCleared(): void {\n const gameState = useGameStore.getState();\n const bonusPoints =\n GAME_CONFIG.BONUS_POINTS[\n gameState.correctOrderCount as keyof typeof GAME_CONFIG.BONUS_POINTS\n ] || 0;\n\n // Calculate completion time\n const completionTime = Date.now() - this.mapStartTime;\n\n // Capture coin collection data BEFORE resetting effects\n const coinStats = gameState.getCoinStats();\n const coinsCollected = coinStats.totalCoinsCollected;\n const powerModeActivations = coinStats.totalPowerCoinsCollected;\n\n // Clear floating texts when map is completed\n gameState.clearAllFloatingTexts();\n\n // Reset coin effects and state when map is completed\n gameState.resetEffects();\n gameState.resetCoinState();\n log.debug(\"Coins reset when map is cleared\");\n\n // Record the level result when level is completed\n if (gameState.currentMap) {\n const levelResult = {\n level: gameState.currentLevel,\n mapName: gameState.currentMap.name,\n correctOrderCount: gameState.correctOrderCount,\n totalBombs: GAME_CONFIG.TOTAL_BOMBS,\n score: gameState.score,\n bonus: bonusPoints,\n hasBonus: bonusPoints > 0,\n coinsCollected: coinsCollected,\n powerModeActivations: powerModeActivations,\n completionTime: completionTime,\n timestamp: Date.now(),\n lives: gameState.lives,\n multiplier: gameState.multiplier,\n };\n gameState.addLevelResult(levelResult);\n\n // Send comprehensive map completion data to external site\n const mapCompletionData = {\n mapName: gameState.currentMap.name,\n level: gameState.currentLevel,\n correctOrderCount: gameState.correctOrderCount,\n totalBombs: GAME_CONFIG.TOTAL_BOMBS,\n score: gameState.score,\n bonus: bonusPoints,\n hasBonus: bonusPoints > 0,\n timestamp: Date.now(),\n lives: gameState.lives,\n multiplier: gameState.multiplier,\n completionTime: completionTime,\n coinsCollected: coinsCollected,\n powerModeActivations: powerModeActivations,\n };\n\n sendMapCompletionData(mapCompletionData);\n }\n\n if (bonusPoints > 0) {\n // Show bonus screen\n gameState.setMenuType(MenuType.BONUS);\n gameState.setState(GameState.BONUS);\n this.audioManager.playSound(AudioEvent.BONUS_SCREEN);\n gameState.addScore(bonusPoints);\n\n // Notify coin manager about bonus points (these should not trigger B-coin spawning)\n if (gameState.coinManager) {\n gameState.coinManager.onPointsEarned(bonusPoints, true);\n }\n } else {\n // No bonus, go directly to next level\n this.proceedToNextLevel();\n }\n }\n\n private proceedToNextLevel(): void {\n const gameState = useGameStore.getState();\n const nextLevel = gameState.currentLevel + 1;\n\n if (nextLevel <= mapDefinitions.length) {\n // Reset coin effects and state before loading new level\n gameState.resetEffects();\n gameState.resetCoinState();\n log.debug(\"Coins reset when proceeding to next level\");\n\n gameState.nextLevel();\n this.loadCurrentLevel();\n // Always show countdown when transitioning to next level\n gameState.setMenuType(MenuType.COUNTDOWN);\n gameState.setState(GameState.COUNTDOWN);\n\n setTimeout(() => {\n gameState.setState(GameState.PLAYING);\n }, 3000);\n } else {\n // All levels completed - show victory screen\n gameState.setState(GameState.VICTORY);\n gameState.setMenuType(MenuType.VICTORY);\n }\n }\n\n // Method to be called from BonusScreen to continue to next level\n public continueToNextLevel(): void {\n this.proceedToNextLevel();\n }\n\n private calculateBonus(correctCount: number): number {\n return (\n GAME_CONFIG.BONUS_POINTS[\n correctCount as keyof typeof GAME_CONFIG.BONUS_POINTS\n ] || 0\n );\n }\n\n private render(): void {\n const gameState = useGameStore.getState();\n this.renderManager.render(\n gameState.player,\n gameState.platforms,\n gameState.bombs,\n gameState.monsters,\n gameState.ground,\n gameState.coins,\n gameState.floatingTexts,\n gameState.coinManager,\n this.monsterSpawnManager,\n gameState.currentMap,\n gameState\n );\n }\n\n cleanup(): void {\n this.stop();\n this.inputManager.cleanup();\n this.audioManager.cleanup();\n }\n\n // Debug method to check pause status of all managers\n public getPauseStatus(): any {\n return {\n gameState: useGameStore.getState().currentState,\n scalingManager: this.scalingManager.getPauseStatus(),\n spawnManager: this.monsterSpawnManager.getPauseStatus(),\n respawnManager: {\n isPaused: this.monsterRespawnManager.isPaused(),\n },\n };\n }\n\n // Debug method to check spawn status\n public getSpawnStatus(): any {\n return this.monsterSpawnManager.getSpawnStatus();\n }\n\n // Expose spawn manager for render manager\n public getSpawnManager(): OptimizedSpawnManager {\n return this.monsterSpawnManager;\n }\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport { log } from '../lib/logger';\n\n// Type definitions for browser-specific fullscreen APIs\ninterface WebkitDocument extends Document {\n webkitFullscreenEnabled?: boolean;\n webkitFullscreenElement?: Element | null;\n webkitExitFullscreen?: () => Promise<void>;\n}\n\ninterface WebkitElement extends HTMLElement {\n webkitRequestFullscreen?: () => Promise<void>;\n}\n\ninterface MozDocument extends Document {\n mozFullScreenEnabled?: boolean;\n mozFullScreenElement?: Element | null;\n mozCancelFullScreen?: () => Promise<void>;\n}\n\ninterface MozElement extends HTMLElement {\n mozRequestFullScreen?: () => Promise<void>;\n}\n\ninterface MsDocument extends Document {\n msFullscreenEnabled?: boolean;\n msFullscreenElement?: Element | null;\n msExitFullscreen?: () => Promise<void>;\n}\n\ninterface MsElement extends HTMLElement {\n msRequestFullscreen?: () => Promise<void>;\n}\n\nexport const useFullscreen = () => {\n const [isFullscreen, setIsFullscreen] = useState(false);\n\n // Dispatch custom fullscreen event\n const dispatchFullscreenEvent = useCallback((fullscreen: boolean) => {\n const event = new CustomEvent('sigurd-startup-fullscreen-change', {\n detail: {\n isFullscreen: fullscreen,\n timestamp: Date.now(),\n gameId: 'sigurd-startup-game'\n },\n bubbles: true,\n cancelable: true\n });\n \n // Dispatch on window for external sites to catch\n window.dispatchEvent(event);\n \n // Also dispatch on document for iframe scenarios\n document.dispatchEvent(event);\n \n log.debug(`Fullscreen event dispatched: ${fullscreen ? 'entered' : 'exited'}`);\n }, []);\n\n // Check if fullscreen is supported\n const isFullscreenSupported = () => {\n return !!(\n document.fullscreenEnabled ||\n (document as WebkitDocument).webkitFullscreenEnabled ||\n (document as MozDocument).mozFullScreenEnabled ||\n (document as MsDocument).msFullscreenEnabled\n );\n };\n\n // Get the fullscreen element\n const getFullscreenElement = () => {\n return (\n document.fullscreenElement ||\n (document as WebkitDocument).webkitFullscreenElement ||\n (document as MozDocument).mozFullScreenElement ||\n (document as MsDocument).msFullscreenElement\n );\n };\n\n // Enter fullscreen\n const enterFullscreen = useCallback(async (element?: HTMLElement) => {\n if (!isFullscreenSupported()) {\n console.warn('Fullscreen is not supported in this browser');\n return false;\n }\n\n const targetElement = element || document.documentElement;\n\n try {\n if (targetElement.requestFullscreen) {\n await targetElement.requestFullscreen();\n } else if ((targetElement as WebkitElement).webkitRequestFullscreen) {\n await (targetElement as WebkitElement).webkitRequestFullscreen();\n } else if ((targetElement as MozElement).mozRequestFullScreen) {\n await (targetElement as MozElement).mozRequestFullScreen();\n } else if ((targetElement as MsElement).msRequestFullscreen) {\n await (targetElement as MsElement).msRequestFullscreen();\n }\n return true;\n } catch (error) {\n console.error('Error entering fullscreen:', error);\n return false;\n }\n }, []);\n\n // Exit fullscreen\n const exitFullscreen = useCallback(async () => {\n try {\n if (document.exitFullscreen) {\n await document.exitFullscreen();\n } else if ((document as WebkitDocument).webkitExitFullscreen) {\n await (document as WebkitDocument).webkitExitFullscreen();\n } else if ((document as MozDocument).mozCancelFullScreen) {\n await (document as MozDocument).mozCancelFullScreen();\n } else if ((document as MsDocument).msExitFullscreen) {\n await (document as MsDocument).msExitFullscreen();\n }\n return true;\n } catch (error) {\n console.error('Error exiting fullscreen:', error);\n return false;\n }\n }, []);\n\n // Toggle fullscreen\n const toggleFullscreen = useCallback(async (element?: HTMLElement) => {\n if (isFullscreen) {\n const success = await exitFullscreen();\n if (success) {\n setIsFullscreen(false);\n dispatchFullscreenEvent(false);\n }\n } else {\n const success = await enterFullscreen(element);\n if (success) {\n setIsFullscreen(true);\n dispatchFullscreenEvent(true);\n }\n }\n }, [isFullscreen, enterFullscreen, exitFullscreen, dispatchFullscreenEvent]);\n\n // Listen for fullscreen changes\n useEffect(() => {\n const handleFullscreenChange = () => {\n const fullscreenElement = getFullscreenElement();\n const newFullscreenState = !!fullscreenElement;\n \n // Only dispatch event if state actually changed\n if (newFullscreenState !== isFullscreen) {\n setIsFullscreen(newFullscreenState);\n dispatchFullscreenEvent(newFullscreenState);\n }\n };\n\n // Add event listeners for different browsers\n document.addEventListener('fullscreenchange', handleFullscreenChange);\n document.addEventListener('webkitfullscreenchange', handleFullscreenChange);\n document.addEventListener('mozfullscreenchange', handleFullscreenChange);\n document.addEventListener('MSFullscreenChange', handleFullscreenChange);\n\n // Initial check\n handleFullscreenChange();\n\n return () => {\n document.removeEventListener('fullscreenchange', handleFullscreenChange);\n document.removeEventListener('webkitfullscreenchange', handleFullscreenChange);\n document.removeEventListener('mozfullscreenchange', handleFullscreenChange);\n document.removeEventListener('MSFullscreenChange', handleFullscreenChange);\n };\n }, [isFullscreen, dispatchFullscreenEvent]);\n\n return {\n isFullscreen,\n isFullscreenSupported: isFullscreenSupported(),\n enterFullscreen,\n exitFullscreen,\n toggleFullscreen,\n };\n}; ","import React, { useRef, useEffect, useState } from \"react\";\nimport { GameManager } from \"../managers/GameManager\";\nimport { GAME_CONFIG } from \"../types/constants\";\nimport { useFullscreen } from \"../hooks/useFullscreen\";\n\ninterface GameCanvasProps {\n className?: string;\n}\n\nconst GameCanvas: React.FC<GameCanvasProps> = ({ className = \"\" }) => {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const gameManagerRef = useRef<GameManager | null>(null);\n const { isFullscreen } = useFullscreen();\n const [canvasStyle, setCanvasStyle] = useState<React.CSSProperties>({});\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n // Set canvas size\n canvas.width = GAME_CONFIG.CANVAS_WIDTH;\n canvas.height = GAME_CONFIG.CANVAS_HEIGHT;\n\n\n\n // Initialize game manager\n gameManagerRef.current = new GameManager(canvas);\n gameManagerRef.current.start();\n\n return () => {\n if (gameManagerRef.current) {\n gameManagerRef.current.cleanup();\n }\n };\n }, []);\n\n // Handle responsive sizing for fullscreen\n useEffect(() => {\n const updateCanvasSize = () => {\n if (!isFullscreen) {\n setCanvasStyle({\n imageRendering: \"crisp-edges\",\n });\n return;\n }\n\n const aspectRatio = GAME_CONFIG.CANVAS_WIDTH / GAME_CONFIG.CANVAS_HEIGHT; // 4:3\n const windowWidth = window.innerWidth;\n const windowHeight = window.innerHeight;\n const windowAspectRatio = windowWidth / windowHeight;\n\n let width, height;\n\n if (windowAspectRatio > aspectRatio) {\n // Window is wider than game aspect ratio\n height = windowHeight * 0.9; // Use 90% of window height\n width = height * aspectRatio;\n } else {\n // Window is taller than game aspect ratio\n width = windowWidth * 0.9; // Use 90% of window width\n height = width / aspectRatio;\n }\n\n setCanvasStyle({\n width: `${width}px`,\n height: `${height}px`,\n imageRendering: \"crisp-edges\",\n });\n };\n\n updateCanvasSize();\n window.addEventListener(\"resize\", updateCanvasSize);\n\n return () => {\n window.removeEventListener(\"resize\", updateCanvasSize);\n };\n }, [isFullscreen]);\n\n return (\n <div className=\"relative\">\n <canvas\n ref={canvasRef}\n className={`shadow-black/10 shadow-lg rounded-lg ${className}`}\n style={canvasStyle}\n />\n </div>\n );\n};\n\nexport default GameCanvas;\n","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n outline:\n \"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-10 px-4 py-2\",\n sm: \"h-9 rounded-md px-3\",\n lg: \"h-11 rounded-md px-8\",\n icon: \"h-10 w-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\"\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n {...props}\n />\n )\n }\n)\nButton.displayName = \"Button\"\n\nexport { Button, buttonVariants }","import * as React from \"react\"\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst TooltipProvider = TooltipPrimitive.Provider\n\nconst Tooltip = TooltipPrimitive.Root\n\nconst TooltipTrigger = TooltipPrimitive.Trigger\n\nconst TooltipContent = React.forwardRef<\n React.ElementRef<typeof TooltipPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className\n )}\n {...props}\n />\n))\nTooltipContent.displayName = TooltipPrimitive.Content.displayName\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }\n","import React, { useRef } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { useGameStore } from \"../../../stores/gameStore\";\nimport { GameState, MenuType } from \"../../../types/enums\";\nimport { Maximize, Minimize, Play, Settings } from \"lucide-react\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { useFullscreen } from \"../../../hooks/useFullscreen\";\n\nconst StartMenu: React.FC = () => {\n const { setState, setMenuType } = useGameStore();\n const { isFullscreen, toggleFullscreen } = useFullscreen();\n const gameContainerRef = useRef<HTMLDivElement>(null);\n\n const startGame = () => {\n // First hide the start menu\n setMenuType(MenuType.COUNTDOWN);\n // Then set countdown state\n setState(GameState.COUNTDOWN);\n\n // After 3 seconds, start the game\n setTimeout(() => {\n setState(GameState.PLAYING);\n }, 3000);\n };\n\n const openSettings = () => {\n setMenuType(MenuType.SETTINGS);\n };\n\n const handleFullscreenToggle = () => {\n // Find the game container element (the shadow root host)\n const gameElement = gameContainerRef.current?.closest(\n \"sigurd-startup\"\n ) as HTMLElement;\n if (gameElement) {\n toggleFullscreen(gameElement);\n } else {\n // Fallback to document element if game element not found\n toggleFullscreen();\n }\n };\n\n return (\n <div className=\"flex flex-col items-center justify-center h-full rounded-lg\">\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n onClick={handleFullscreenToggle}\n variant=\"outline\"\n className=\"absolute top-4 right-4 bg-background-80 text-foreground backdrop-blur-sm border-none hover:bg-primary hover:text-black h-10 w-10\"\n >\n {isFullscreen ? (\n <Minimize\n className=\"text-foreground hover:text-primary\"\n size={24}\n />\n ) : (\n <Maximize\n className=\"text-foreground hover:text-primary\"\n size={24}\n />\n )}\n </Button>\n </TooltipTrigger>\n <TooltipContent>\n {isFullscreen\n ? \"Avslutt fullskjerm (F11 eller F)\"\n : \"Fullskjerm (F11 eller F)\"}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n <div className=\"text-center mb-8\">\n <h1 className=\"text-4xl font-bold text-white mb-2\">Sigurd Startup</h1>\n <p className=\"text-muted-foreground\">\n Samle så mye finansiering som mulig!\n </p>\n </div>\n\n <div className=\"space-y-4 w-[70%]\">\n <Button\n onClick={startGame}\n className=\"w-full bg-primary hover:bg-primary-80 text-white font-bold py-3 text-lg transition-all duration-200 uppercase flex items-center justify-center gap-2\"\n >\n <Play size={20} />\n Start\n </Button>\n\n <Button\n onClick={openSettings}\n variant=\"outline\"\n className=\"w-full border-secondary text-muted-foreground hover:bg-secondary hover:text-white font-bold py-3 text-lg transition-all duration-200 uppercase flex items-center justify-center gap-2\"\n >\n <Settings size={20} />\n Innstillinger\n </Button>\n </div>\n </div>\n );\n};\n\nexport default StartMenu;\n","import React, { useState, useEffect } from \"react\";\nimport { DEV_CONFIG } from \"../../../types/constants\";\nimport { useGameStore } from \"../../../stores/gameStore\";\n\nconst CountdownOverlay: React.FC = () => {\n const [count, setCount] = useState(3);\n const { currentMap } = useGameStore();\n useEffect(() => {\n // Only run countdown if not in DEV_MODE\n if (!DEV_CONFIG.ENABLED) {\n const interval = setInterval(() => {\n setCount((prev) => (prev > 1 ? prev - 1 : 0));\n }, 1000);\n\n return () => clearInterval(interval);\n }\n }, []);\n\n if (count === 0 && !DEV_CONFIG.ENABLED) return null;\n\n return (\n <div className=\"text-center\">\n <>\n <div className=\"text-8xl font-bold text-primary\">{count}</div>\n <div className=\"flex items-center justify-center gap-2\">\n <div className=\"w-2 h-2 bg-white rounded-full p-1 animate-pulse\" />\n <p className=\"text-2xl text-white uppercase italic\">\n {currentMap?.name}\n </p>\n <div className=\"w-2 h-2 bg-white rounded-full p-1 animate-pulse\" />\n </div>\n </>\n </div>\n );\n};\n\nexport default CountdownOverlay;\n","import React, { useRef } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { useGameStore } from \"../../../stores/gameStore\";\nimport { GameState, MenuType } from \"../../../types/enums\";\nimport {\n Play,\n Pause,\n Maximize,\n Minimize,\n Zap,\n CircleDollarSign,\n Map,\n Heart,\n} from \"lucide-react\";\nimport { calculateMultiplierProgress } from \"../../../lib/scoringUtils\";\nimport { useFullscreen } from \"../../../hooks/useFullscreen\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { TooltipProvider } from \"@radix-ui/react-tooltip\";\n\nconst InGameMenu: React.FC = () => {\n const {\n score,\n lives,\n currentLevel,\n setState,\n setMenuType,\n isPaused,\n multiplier,\n multiplierScore,\n } = useGameStore();\n const gameContainerRef = useRef<HTMLDivElement>(null);\n const { isFullscreen, toggleFullscreen } = useFullscreen();\n\n const togglePause = () => {\n if (isPaused) {\n setState(GameState.PLAYING);\n } else {\n setState(GameState.PAUSED);\n setMenuType(MenuType.PAUSE);\n }\n };\n\n const handleFullscreenToggle = () => {\n // Find the game container element (the shadow root host)\n const gameElement = gameContainerRef.current?.closest(\n \"sigurd-startup\"\n ) as HTMLElement;\n if (gameElement) {\n toggleFullscreen(gameElement);\n } else {\n // Fallback to document element if game element not found\n toggleFullscreen();\n }\n };\n\n // Calculate multiplier progress\n const progress = calculateMultiplierProgress(multiplierScore, multiplier);\n\n return (\n <div\n ref={gameContainerRef}\n className=\"flex justify-between items-center w-full h-full\"\n >\n {/* SCOREBOARD */}\n <div className=\"absolute top-4 left-1/2 transform -translate-x-1/2 z-10 bg-background-80 text-foreground px-4 py-2 rounded-lg backdrop-blur-sm pointer-events-auto\">\n <div className=\"flex items-center gap-4 text-sm font-mono\">\n <div className=\"text-center\">\n <div className=\"text-primary font-bold flex items-center gap-1\">\n <CircleDollarSign size={16} />\n {score.toLocaleString()}\n </div>\n {/* <div className=\"text-xs text-muted-foreground\">SCORE</div> */}\n </div>\n <div className=\"w-px h-8 bg-border\"></div>\n <div className=\"text-center\">\n <div className=\"text-primary font-bold flex items-center gap-1\">\n <Map size={16} />\n {currentLevel.toLocaleString()}\n </div>\n {/* <div className=\"text-xs text-muted-foreground\">LEVEL</div> */}\n </div>\n <div className=\"w-px h-8 bg-border\"></div>\n <div className=\"min-w-20 flex justify-center border border-primary p-1 rounded-lg relative overflow-hidden\">\n {/* Progress bar background */}\n <div\n className=\"absolute inset-0 bg-primary-20 transition-all duration-300 ease-out\"\n style={{ width: `${progress * 100}%` }}\n />\n <div className=\"text-primary text-center font-bold flex items-center gap-1 relative z-10\">\n <Zap size={16} />x{multiplier}\n </div>\n {/* <div className=\"text-xs text-muted-foreground\">MULTIPLIER</div> */}\n </div>\n </div>\n </div>\n\n {/* MENU BUTTONS */}\n <div className=\"flex items-center space-x-4 absolute right-4 top-4\">\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n onClick={togglePause}\n variant=\"outline\"\n className=\"bg-background-80 text-foreground backdrop-blur-sm border-none hover:bg-primary hover:text-black h-10 w-10\"\n >\n {isPaused ? (\n <Play className=\"text-white hover:text-primary\" size={24} />\n ) : (\n <Pause\n className=\"text-foreground hover:text-primary\"\n size={24}\n />\n )}\n </Button>\n </TooltipTrigger>\n <TooltipContent>{\"Pause Spill (P)\"}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n onClick={handleFullscreenToggle}\n variant=\"outline\"\n className=\"bg-background-80 text-foreground backdrop-blur-sm border-none hover:bg-primary hover:text-black h-10 w-10\"\n >\n {isFullscreen ? (\n <Minimize\n className=\"text-foreground hover:text-primary\"\n size={24}\n />\n ) : (\n <Maximize\n className=\"text-foreground hover:text-primary\"\n size={24}\n />\n )}\n </Button>\n </TooltipTrigger>\n <TooltipContent>\n {isFullscreen\n ? \"Avslutt fullskjerm (F11 eller F)\"\n : \"Fullskjerm (F11 eller F)\"}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n </div>\n\n {/* Lives */}\n <div\n className={`absolute left-3 bottom-2 ${\n isFullscreen ? \"bottom-4\" : \"bottom-2\"\n }`}\n >\n <div className=\"text-xl font-bold text-red-400 flex items-center gap-1\">\n {Array.from({ length: 3 }).map((_, index) => (\n <Heart\n color=\"#ff3143\"\n size={isFullscreen ? 25 : 20}\n key={index}\n fill={index < lives ? \"#ff3143\" : \"none\"}\n />\n ))}\n {lives > 3 ? <p>+ {lives - 3}</p> : \"\"}\n </div>\n </div>\n </div>\n );\n};\n\nexport default InGameMenu;\n","import React from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { useGameStore } from \"../../../stores/gameStore\";\nimport { GameState, MenuType } from \"../../../types/enums\";\nimport { Play, Settings, Home, RotateCcw } from \"lucide-react\";\n\n\nconst PauseMenu: React.FC = () => {\n const { setState, setMenuType, resetGame } = useGameStore();\n\n const resumeGame = () => {\n // Show countdown before resuming\n setMenuType(MenuType.COUNTDOWN);\n setState(GameState.COUNTDOWN);\n \n // After 3 seconds, start the game\n setTimeout(() => {\n setState(GameState.PLAYING);\n }, 3000);\n };\n\n const openSettings = () => {\n setMenuType(MenuType.SETTINGS);\n };\n\n const quitToMenu = () => {\n resetGame();\n setState(GameState.MENU);\n setMenuType(MenuType.START);\n };\n\n const restartGame = () => {\n // Don't call resetGame() as it clears everything\n // Instead, just reset the current level state and player position\n const { resetBombState, resetPlayer, resetEffects, clearAllFloatingTexts, currentMap } = useGameStore.getState();\n \n // Reset level-specific state\n resetBombState();\n resetPlayer();\n resetEffects();\n clearAllFloatingTexts();\n \n // Re-initialize the current level if we have a map\n if (currentMap) {\n const { initializeLevel } = useGameStore.getState();\n initializeLevel(currentMap);\n }\n\n // Set state to MENU with no current map to trigger level reload in GameManager\n setState(GameState.MENU);\n setMenuType(MenuType.COUNTDOWN);\n\n // Start countdown immediately, GameManager will handle the level reload\n setState(GameState.COUNTDOWN);\n \n // After 3 seconds, start the game\n setTimeout(() => {\n setState(GameState.PLAYING);\n }, 3000);\n };\n\n return (\n <div className=\"flex flex-col items-center justify-center h-full\">\n <div className=\"space-y-4\">\n <Button\n onClick={resumeGame}\n className=\"w-full bg-primary hover:bg-primary-80 text-white font-bold py-3 text-md transition-all duration-200 uppercase flex items-center justify-center gap-2\"\n >\n <Play size={20} />\n Fortsett\n </Button>\n\n <Button\n onClick={openSettings}\n variant=\"outline\"\n className=\"w-full border-secondary text-muted-foreground bg-secondary hover:text-white font-bold py-3 text-md transition-all duration-200 uppercase flex items-center justify-center gap-2\"\n >\n <Settings size={20} />\n Innstillinger\n </Button>\n\n <Button\n onClick={restartGame}\n variant=\"outline\"\n className=\"w-full border-secondary text-muted-foreground bg-secondary hover:text-white font-bold py-3 text-md transition-all duration-200 uppercase flex items-center justify-center gap-2\"\n >\n <RotateCcw size={20} />\n Start på nytt\n </Button>\n\n <Button\n onClick={quitToMenu}\n variant=\"default\"\n className=\"w-full bg-red-600 hover:bg-red-600/80 text-white font-bold py-3 text-md transition-all duration-200 uppercase flex items-center justify-center gap-2\"\n >\n <Home size={20} />\n hovedmeny\n </Button>\n </div>\n </div>\n );\n};\n\nexport default PauseMenu;\n","import React from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { useGameStore } from \"../../../stores/gameStore\";\nimport { MenuType } from \"../../../types/enums\";\nimport { ArrowLeft } from \"lucide-react\";\n\nconst SettingsMenu: React.FC = () => {\n const { setMenuType, previousMenu } = useGameStore();\n\n // Get audio settings from AudioManager\n const audioSettings = useGameStore((state) => state.audioSettings);\n const updateAudioSettings = useGameStore(\n (state) => state.updateAudioSettings\n );\n\n const {\n masterVolume,\n musicVolume,\n sfxVolume,\n masterMuted,\n musicMuted,\n sfxMuted,\n } = audioSettings || {\n masterVolume: 80,\n musicVolume: 70,\n sfxVolume: 90,\n masterMuted: false,\n musicMuted: false,\n sfxMuted: false,\n };\n\n const goBack = () => {\n // Go back to the previous menu that was stored when opening settings\n if (previousMenu) {\n setMenuType(previousMenu);\n } else {\n // Fallback to START menu if no previous menu is stored\n setMenuType(MenuType.START);\n }\n };\n\n return (\n <div className=\"flex flex-col items-center justify-center h-full w-full\">\n <div className=\"flex items-center mb-6 w-[70%] gap-2\">\n <Button\n onClick={goBack}\n variant=\"default\"\n className=\"bg-primary hover:bg-primary/80 text-white w-10 h-10\"\n >\n <ArrowLeft size={25} />\n </Button>\n <h2 className=\"text-2xl font-bold text-white uppercase\">\n Innstillinger\n </h2>\n </div>\n\n <div className=\"space-y-2 w-[70%]\">\n {/* Master Volume */}\n <div className=\"p-3 bg-card rounded-md\">\n <div className=\"flex justify-between items-center mb-2\">\n <span className=\"text-muted-foreground\">Master volum</span>\n <button\n onClick={() => updateAudioSettings({ masterMuted: !masterMuted })}\n className={`px-3 py-1 rounded text-sm font-mono ${\n masterMuted\n ? \"bg-red-600 text-white\"\n : \"bg-secondary text-white\"\n }`}\n >\n {masterMuted ? \"Muted\" : `${masterVolume}%`}\n </button>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n value={masterMuted ? 0 : masterVolume}\n onChange={(e) =>\n updateAudioSettings({ masterVolume: Number(e.target.value) })\n }\n className=\"w-full accent-primary\"\n disabled={masterMuted}\n />\n </div>\n\n {/* Music Volume */}\n <div className=\"p-3 bg-card rounded-md\">\n <div className=\"flex justify-between items-center mb-2\">\n <span className=\"text-muted-foreground\">Musikk volum</span>\n <button\n onClick={() => updateAudioSettings({ musicMuted: !musicMuted })}\n className={`px-3 py-1 rounded text-sm font-mono ${\n musicMuted ? \"bg-red-600 text-white\" : \"bg-secondary text-white\"\n }`}\n >\n {musicMuted ? \"Muted\" : `${musicVolume}%`}\n </button>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n value={musicMuted ? 0 : musicVolume}\n onChange={(e) =>\n updateAudioSettings({ musicVolume: Number(e.target.value) })\n }\n className=\"w-full accent-primary\"\n disabled={musicMuted}\n />\n </div>\n\n {/* SFX Volume */}\n <div className=\"p-3 bg-card rounded-md\">\n <div className=\"flex justify-between items-center mb-2\">\n <span className=\"text-muted-foreground\">Lyd effekter</span>\n <button\n onClick={() => updateAudioSettings({ sfxMuted: !sfxMuted })}\n className={`px-3 py-1 rounded text-sm font-mono ${\n sfxMuted ? \"bg-red-600 text-white\" : \"bg-secondary text-white\"\n }`}\n >\n {sfxMuted ? \"Muted\" : `${sfxVolume}%`}\n </button>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n value={sfxMuted ? 0 : sfxVolume}\n onChange={(e) =>\n updateAudioSettings({ sfxVolume: Number(e.target.value) })\n }\n className=\"w-full accent-primary\"\n disabled={sfxMuted}\n />\n </div>\n <div className=\"text-center text-sm text-gray-400\">\n <p>(Trykk på tallene for å mute lyd)</p>\n </div>\n </div>\n </div>\n );\n};\n\nexport default SettingsMenu;\n","import { useState, useEffect, useRef } from 'react';\n\ninterface UseAnimatedCounterOptions {\n duration?: number;\n steps?: number;\n easing?: 'linear' | 'ease-out' | 'ease-in' | 'ease-in-out' | 'gentle-ease-out';\n delay?: number;\n onComplete?: () => void;\n}\n\nexport const useAnimatedCounter = (\n targetValue: number,\n options: UseAnimatedCounterOptions = {}\n) => {\n const {\n duration = 3000,\n steps = 60,\n easing = 'ease-out',\n delay = 0,\n onComplete\n } = options;\n\n const [animatedValue, setAnimatedValue] = useState(0);\n const hasCompleted = useRef(false);\n const lastTargetValue = useRef(targetValue);\n\n useEffect(() => {\n if (targetValue === 0) {\n setAnimatedValue(0);\n hasCompleted.current = false;\n return;\n }\n\n // Reset if target value changed (new bonus screen)\n if (lastTargetValue.current !== targetValue) {\n hasCompleted.current = false;\n setAnimatedValue(0);\n lastTargetValue.current = targetValue;\n }\n\n // If animation already completed for this target value, just return the final value\n if (hasCompleted.current) {\n setAnimatedValue(targetValue);\n return;\n }\n\n // Add a small delay before starting animation\n const startTimer = setTimeout(() => {\n // Calculate step duration to ensure consistent animation time\n // regardless of target value - all animations will take exactly 'duration' milliseconds\n const stepDuration = duration / steps;\n let currentStep = 0;\n\n const timer = setInterval(() => {\n currentStep++;\n \n // Calculate progress (0 to 1) - this ensures consistent timing\n // regardless of whether target is 10,000 or 50,000\n const progress = currentStep / steps;\n \n // Apply easing function\n let easedProgress: number;\n switch (easing) {\n case 'linear':\n easedProgress = progress;\n break;\n case 'ease-out':\n // Use quadratic ease-out for gentler animation\n easedProgress = 1 - (1 - progress) * (1 - progress);\n break;\n case 'gentle-ease-out':\n // Custom easing: starts faster, ends slower but not as dramatic\n easedProgress = 1 - Math.pow(1 - progress, 1.5);\n break;\n case 'ease-in':\n easedProgress = progress * progress;\n break;\n case 'ease-in-out':\n easedProgress = progress < 0.5 \n ? 2 * progress * progress \n : 1 - Math.pow(-2 * progress + 2, 2) / 2;\n break;\n default:\n easedProgress = 1 - (1 - progress) * (1 - progress);\n }\n \n // Calculate smooth decimal value\n const smoothValue = targetValue * easedProgress;\n // Round to nearest integer for display\n const displayValue = Math.round(smoothValue);\n \n setAnimatedValue(displayValue);\n \n if (currentStep >= steps) {\n setAnimatedValue(targetValue);\n hasCompleted.current = true;\n clearInterval(timer);\n // Call onComplete callback when animation finishes\n if (onComplete) {\n onComplete();\n }\n }\n }, stepDuration);\n\n return () => clearInterval(timer);\n }, delay);\n\n return () => clearTimeout(startTimer);\n }, [targetValue, duration, steps, easing, delay, onComplete]);\n\n return animatedValue;\n}; ","import React from \"react\";\nimport { useGameStore } from \"../../../stores/gameStore\";\nimport { GameState, MenuType } from \"../../../types/enums\";\nimport { GAME_CONFIG, DEV_CONFIG } from \"../../../types/constants\";\nimport { mapDefinitions } from \"../../../maps/mapDefinitions\";\nimport { Button } from \"@/components/ui/button\";\nimport { useAnimatedCounter } from \"../../../hooks/useAnimatedCounter\";\nimport { sendGameCompletionData, calculateGameStats, GameCompletionData } from \"../../../lib/communicationUtils\";\n\nconst BonusScreen: React.FC = () => {\n const {\n correctOrderCount,\n currentMap,\n currentLevel,\n nextLevel,\n setState,\n setMenuType,\n initializeLevel,\n setBonusAnimationComplete,\n } = useGameStore();\n\n const bonusPoints =\n GAME_CONFIG.BONUS_POINTS[\n correctOrderCount as keyof typeof GAME_CONFIG.BONUS_POINTS\n ] || 50000;\n\n // Use the animated counter hook\n const animatedBonusPoints = useAnimatedCounter(bonusPoints, {\n duration: 6000, // 6 seconds for slower overall animation\n steps: 120, // More steps for smoother animation\n easing: 'gentle-ease-out', // Less dramatic at start, still slows down\n delay: 200, // Small delay to let the screen settle\n onComplete: () => setBonusAnimationComplete(true) // Notify game store when animation is done\n });\n\n const continueGame = () => {\n const nextLevelNum = currentLevel + 1;\n\n if (nextLevelNum <= mapDefinitions.length) {\n // More levels available\n nextLevel();\n\n // Load the next level's map data\n const nextMapIndex = nextLevelNum - 1;\n const nextMap = mapDefinitions[nextMapIndex];\n if (nextMap) {\n initializeLevel(nextMap);\n }\n\n setMenuType(MenuType.COUNTDOWN);\n setState(GameState.COUNTDOWN);\n\n setTimeout(() => {\n setState(GameState.PLAYING);\n }, 3000);\n } else {\n // All levels completed - send comprehensive victory completion data\n const gameStore = useGameStore.getState();\n const levelResults = gameStore.getLevelResults();\n const multiplier = gameStore.multiplier;\n const gameStartTime = gameStore.getGameStartTime();\n const sessionId = gameStore.getSessionId();\n \n // Calculate comprehensive game statistics\n const gameStats = calculateGameStats(levelResults, gameStore.score, gameStore.lives, multiplier, 'completed', gameStartTime, Date.now());\n \n const gameCompletionData: GameCompletionData = {\n finalScore: gameStore.score,\n totalLevels: mapDefinitions.length,\n completedLevels: levelResults.length,\n timestamp: Date.now(),\n lives: gameStore.lives,\n multiplier,\n levelHistory: levelResults,\n totalCoinsCollected: gameStats.totalCoinsCollected,\n totalPowerModeActivations: gameStats.totalPowerModeActivations,\n totalBombs: gameStats.totalBombs,\n totalCorrectOrders: gameStats.totalCorrectOrders,\n averageCompletionTime: gameStats.averageCompletionTime,\n gameEndReason: 'completed',\n sessionId,\n startTime: gameStartTime,\n endTime: Date.now()\n };\n \n sendGameCompletionData(gameCompletionData);\n \n setState(GameState.VICTORY);\n setMenuType(MenuType.VICTORY);\n }\n };\n\n return (\n <div className=\"text-center max-w-md\">\n <h1 className=\"text-4xl font-bold text-primary mb-4 uppercase\">\n {currentMap?.name} Fullført!\n </h1>\n\n <div className=\"text-white mb-6 space-y-4\">\n {bonusPoints > 0 && (\n <div className=\"flex flex-col items-center justify-center gap-5\">\n <div className=\"text-2xl\">\n Bra jobba! Du samlet{\" \"}\n <span className=\"font-bold text-primary animate-pulse\">\n {correctOrderCount}\n </span>{\" \"}\n av 23 finansiering og unngikk byrokratet!{\" \"}\n </div>\n <div className=\"text-4xl font-bold animate-pulse\">\n {animatedBonusPoints.toLocaleString()} kr\n </div>\n {!DEV_CONFIG.ENABLED && (\n <div className=\"text-sm text-gray-400 mt-2\">\n {mapDefinitions.length > currentLevel ? (\n `Fortsetter til ${mapDefinitions[currentLevel]?.name || 'Neste nivå'}...`\n ) : (\n ''\n )}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default BonusScreen;\n","import React from \"react\";\n\nimport { useGameStore } from \"../../../stores/gameStore\";\n\nimport { Home, RotateCcw, Trophy } from \"lucide-react\";\n\nconst VictoryMenu: React.FC = () => {\n const { score, resetGame } = useGameStore();\n\n const handleRestart = () => {\n resetGame();\n };\n\n return (\n <div className=\"text-center max-w-md flex flex-col items-center justify-center gap-4\">\n <h1 className=\"text-2xl font-bold uppercase\">slutt</h1>\n\n <div className=\"text-white mb-6 space-y-4\">\n <div className=\"text-2xl text-primary\">Du har klart det umulige!</div>\n <div className=\"text-lg\">\n Du hjalp Sigurd med å unngå byrokratiske hindringer og samle\n finansiering.\n </div>\n\n <div className=\"text-2xl flex flex-col items-center justify-center gap-2\">\n <div className=\"text-foreground\">Total finansiering samlet:</div>\n <div className=\"font-bold text-3xl text-primary\">\n {score.toLocaleString()}\n </div>\n </div>\n </div>\n\n <div className=\"flex items-center justify-center gap-2\">\n <button\n onClick={handleRestart}\n className=\"bg-primary text-white font-bold hover:bg-primary/80 rounded-lg py-1 px-3 text-lg transition-all duration-200 transform hover:scale-105 flex items-center justify-center gap-2\"\n >\n <Home className=\"w-7 h-7\" strokeWidth={2} />\n </button>\n {/* <button\n onClick={() => {}}\n className=\"bg-primary text-white font-bold hover:bg-primary/80 rounded-lg py-1 px-3 text-lg transition-all duration-200 transform hover:scale-105 flex items-center justify-center gap-2\"\n >\n <RotateCcw className=\"w-7 h-7\" strokeWidth={2} />\n </button>\n <button\n onClick={() => {}}\n className=\"bg-primary text-white font-bold hover:bg-primary/80 rounded-lg py-1 px-3 text-lg transition-all duration-200 transform hover:scale-105 flex items-center justify-center gap-2\"\n >\n <Trophy className=\"w-7 h-7\" strokeWidth={2} />\n </button> */}\n </div>\n </div>\n );\n};\n\nexport default VictoryMenu;\n","import React from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { useGameStore } from \"../../../stores/gameStore\";\n\nconst GameOverScreen: React.FC = () => {\n const { score, resetGame, levelHistory } = useGameStore();\n\n const handleRestart = () => {\n resetGame();\n };\n\n return (\n <div className=\"bg-gradient-to-b rounded-lg text-center max-w-md\">\n <h1 className=\"text-4xl font-bold text-red-400 mb-4 uppercase\">\n konkurs\n </h1>\n\n <div className=\"text-white mb-6 space-y-3\">\n <div className=\"text-2xl\">\n <span className=\"text-yellow-400\">\n Total finansiering:{\" \"}\n <span className=\"font-bold text-white\">\n {score.toLocaleString()} kr\n </span>\n </span>\n </div>\n\n {/* Level History */}\n {levelHistory.length > 0 && (\n <div className=\"mt-6 border-t border-gray-600 pt-4\">\n <div className=\"overflow-x-auto\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-gray-600\">\n <th className=\"text-left py-2 px-2 text-primary font-semibold\">\n Bane\n </th>\n <th className=\"text-left py-2 px-2 text-primary font-semibold\">\n Mynter\n </th>\n <th className=\"text-left py-2 px-2 text-primary font-semibold\">\n Finansiering\n </th>\n <th className=\"text-left py-2 px-2 text-primary font-semibold\">\n Bonus\n </th>\n </tr>\n </thead>\n <tbody>\n {levelHistory.map((level, index) => (\n <tr key={index} className=\"border-b border-gray-700/50\">\n <td className=\"py-2 px-2 text-gray-300\">\n {level.level} ({level.mapName})\n </td>\n <td className=\"py-2 px-2 text-gray-300\">\n {level.coinsCollected}\n </td>\n <td className=\"py-2 px-2 text-gray-300\">\n {level.score.toLocaleString()}\n </td>\n <td className=\"py-2 px-2\">\n {level.bonus > 0 ? (\n <span className=\"text-yellow-400 font-semibold\">\n {level.bonus.toLocaleString()} kr\n </span>\n ) : (\n <span className=\"text-gray-500\">-</span>\n )}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n )}\n </div>\n\n <Button\n onClick={handleRestart}\n className=\"bg-primary hover:bg-primary/80 text-white font-bold py-3 px-8 text-lg transition-all duration-200 transform hover:scale-105 uppercase\"\n >\n prøv igjen\n </Button>\n </div>\n );\n};\n\nexport default GameOverScreen;\n","import React from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { useGameStore } from \"../../../stores/gameStore\";\nimport { MenuType } from \"../../../types/enums\";\nimport { ArrowLeft } from \"lucide-react\";\n\nconst AudioSettingsMenu: React.FC = () => {\n const { setMenuType, previousMenu } = useGameStore();\n \n // Get audio settings from AudioManager\n const audioSettings = useGameStore((state) => state.audioSettings);\n const updateAudioSettings = useGameStore(\n (state) => state.updateAudioSettings\n );\n\n const {\n masterVolume,\n musicVolume,\n sfxVolume,\n masterMuted,\n musicMuted,\n sfxMuted,\n } = audioSettings || {\n masterVolume: 80,\n musicVolume: 70,\n sfxVolume: 90,\n masterMuted: false,\n musicMuted: false,\n sfxMuted: false,\n };\n\n const goBack = () => {\n // Go back to the previous menu that was stored when opening settings\n if (previousMenu) {\n setMenuType(previousMenu);\n } else {\n // Fallback to START menu if no previous menu is stored\n setMenuType(MenuType.START);\n }\n };\n\n return (\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"bg-card backdrop-blur-sm rounded-xl p-6 border border-secondary max-w-md w-full\">\n <div className=\"flex items-center mb-6 gap-2\">\n <Button\n onClick={goBack}\n variant=\"ghost\"\n className=\"text-muted-foreground hover:text-white p-1\"\n >\n <ArrowLeft size={20} />\n </Button>\n <h2 className=\"text-xl font-bold text-primary\">Lydinnstillinger</h2>\n </div>\n \n <div className=\"space-y-4\">\n {/* Master Volume */}\n <div>\n <div className=\"flex justify-between items-center mb-2\">\n <span className=\"text-muted-foreground\">Master Volume</span>\n <button\n onClick={() => updateAudioSettings({ masterMuted: !masterMuted })}\n className={`px-3 py-1 rounded text-sm font-mono ${\n masterMuted ? 'bg-red-600 text-white' : 'bg-secondary text-white'\n }`}\n >\n {masterMuted ? 'Muted' : `${masterVolume}%`}\n </button>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n value={masterMuted ? 0 : masterVolume}\n onChange={(e) =>\n updateAudioSettings({ masterVolume: Number(e.target.value) })\n }\n className=\"w-full accent-primary\"\n disabled={masterMuted}\n />\n </div>\n\n {/* Music Volume */}\n <div>\n <div className=\"flex justify-between items-center mb-2\">\n <span className=\"text-muted-foreground\">Music Volume</span>\n <button\n onClick={() => updateAudioSettings({ musicMuted: !musicMuted })}\n className={`px-3 py-1 rounded text-sm font-mono ${\n musicMuted ? 'bg-red-600 text-white' : 'bg-secondary text-white'\n }`}\n >\n {musicMuted ? 'Muted' : `${musicVolume}%`}\n </button>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n value={musicMuted ? 0 : musicVolume}\n onChange={(e) =>\n updateAudioSettings({ musicVolume: Number(e.target.value) })\n }\n className=\"w-full accent-primary\"\n disabled={musicMuted}\n />\n </div>\n\n {/* SFX Volume */}\n <div>\n <div className=\"flex justify-between items-center mb-2\">\n <span className=\"text-muted-foreground\">Sound Effects</span>\n <button\n onClick={() => updateAudioSettings({ sfxMuted: !sfxMuted })}\n className={`px-3 py-1 rounded text-sm font-mono ${\n sfxMuted ? 'bg-red-600 text-white' : 'bg-secondary text-white'\n }`}\n >\n {sfxMuted ? 'Muted' : `${sfxVolume}%`}\n </button>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n value={sfxMuted ? 0 : sfxVolume}\n onChange={(e) =>\n updateAudioSettings({ sfxVolume: Number(e.target.value) })\n }\n className=\"w-full accent-primary\"\n disabled={sfxMuted}\n />\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default AudioSettingsMenu; ","import React from \"react\";\n\nconst Menu = ({\n children,\n transparent,\n}: {\n children: React.ReactNode;\n transparent?: boolean;\n}) => {\n return (\n <div\n className={`absolute inset-0 flex items-center justify-center z-50 rounded-lg ${\n transparent ? \"bg-transparent\" : \"bg-menu backdrop-blur-sm\"\n }`}\n >\n {children}\n </div>\n );\n};\n\nexport default Menu;\n","import { useEffect } from \"react\";\nimport { useGameStore } from \"../stores/gameStore\";\nimport { GameState, MenuType } from \"../types/enums\";\n\n// Type definition for webkit fullscreen element\ninterface WebkitDocument extends Document {\n webkitFullscreenElement?: Element | null;\n}\n\nexport const useKeyboardShortcuts = (onFullscreenToggle?: () => void) => {\n const { currentState, setState, setMenuType, isPaused } = useGameStore();\n\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n // Prevent shortcuts when typing in input fields\n if (\n event.target instanceof HTMLInputElement ||\n event.target instanceof HTMLTextAreaElement\n ) {\n return;\n }\n\n switch (event.key) {\n case \"F11\":\n case \"f\":\n event.preventDefault();\n onFullscreenToggle?.();\n break;\n\n case \"Escape\":\n // Exit fullscreen if in fullscreen mode\n if (\n document.fullscreenElement ||\n (document as WebkitDocument).webkitFullscreenElement\n ) {\n event.preventDefault();\n onFullscreenToggle?.();\n }\n // Pause/unpause game if playing\n else if (currentState === GameState.PLAYING) {\n event.preventDefault();\n if (isPaused) {\n setState(GameState.PLAYING);\n } else {\n setState(GameState.PAUSED);\n setMenuType(MenuType.PAUSE);\n }\n }\n break;\n\n case \"p\":\n case \"P\":\n // Pause/unpause game if playing\n if (currentState === GameState.PLAYING) {\n event.preventDefault();\n if (isPaused) {\n setState(GameState.PLAYING);\n } else {\n setState(GameState.PAUSED);\n setMenuType(MenuType.PAUSE);\n }\n }\n break;\n\n case \" \":\n if (currentState === GameState.PAUSED) {\n event.preventDefault();\n // Show countdown before resuming\n setMenuType(MenuType.COUNTDOWN);\n setState(GameState.COUNTDOWN);\n \n // After 3 seconds, start the game\n setTimeout(() => {\n setState(GameState.PLAYING);\n }, 3000);\n }\n break;\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n\n return () => {\n document.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [currentState, isPaused, setState, setMenuType, onFullscreenToggle]);\n};\n","import { useState, useEffect } from 'react';\nimport { BackgroundManager } from '../managers/BackgroundManager';\nimport { logger } from '../lib/logger';\n\nexport const useBackgroundPreloading = () => {\n const [isPreloading, setIsPreloading] = useState(true);\n\n useEffect(() => {\n // Preload all background images to prevent flashing\n BackgroundManager.preloadAllBackgrounds().then(() => {\n logger.flow(\"All background images preloaded\");\n setIsPreloading(false);\n }).catch(error => {\n logger.warn(\"Failed to preload some background images\");\n setIsPreloading(false);\n });\n }, []);\n\n return { isPreloading };\n}; ","// Auto-generated version file\n// This file is updated during the build process\n\nexport const VERSION = {\n major: 2,\n minor: 2,\n patch: 2,\n build: 0,\n timestamp: 1754650011612,\n hash: '86ANDO',\n full: '2.2.2'\n};\n\n// Version string for easy access\nexport const VERSION_STRING = VERSION.full;\n\n// Version object for external sites\nexport const getVersion = () => ({\n version: VERSION_STRING,\n major: VERSION.major,\n minor: VERSION.minor,\n patch: VERSION.patch,\n build: VERSION.build,\n timestamp: VERSION.timestamp,\n hash: VERSION.hash\n});\n\n// Version info for console logging\nexport const logVersion = () => {\n console.log(`🎮 Sigurd Startup Game v${VERSION_STRING} (Build ${VERSION.build})`);\n console.log(`📦 Hash: ${VERSION.hash}`);\n console.log(`⏰ Built: ${new Date(VERSION.timestamp).toISOString()}`);\n};\n","import React, { useState } from \"react\";\nimport { useGameStore } from \"../stores/gameStore\";\nimport { GameState, MenuType } from \"../types/enums\";\nimport GameCanvas from \"./GameCanvas\";\nimport StartMenu from \"./menu/menus/StartMenu\";\nimport CountdownOverlay from \"./menu/menus/CountdownOverlay\";\nimport InGameMenu from \"./menu/menus/InGameMenu\";\nimport PauseMenu from \"./menu/menus/PauseMenu\";\nimport SettingsMenu from \"./menu/menus/SettingsMenu\";\nimport BonusScreen from \"./menu/menus/BonusScreen\";\nimport VictoryMenu from \"./menu/menus/VictoryMenu\";\nimport GameOverScreen from \"./menu/menus/GameOverScreen\";\nimport AudioSettingsMenu from \"./menu/menus/AudioSettingsMenu\";\nimport Menu from \"./menu/Menu\";\nimport { DEV_CONFIG } from \"@/types/constants\";\nimport { Circle } from \"lucide-react\";\nimport { useKeyboardShortcuts } from \"../hooks/useKeyboardShortcuts\";\nimport { useFullscreen } from \"../hooks/useFullscreen\";\nimport { useBackgroundPreloading } from \"../hooks/useBackgroundPreloading\";\nimport { VERSION_STRING, getVersion } from \"../version\";\n\nconst MainGame: React.FC = () => {\n const { currentState, showMenu } = useGameStore();\n const gameContainerRef = React.useRef<HTMLDivElement>(null);\n const { toggleFullscreen } = useFullscreen();\n const { isFullscreen } = useFullscreen();\n const { isPreloading } = useBackgroundPreloading();\n\n const handleFullscreenToggle = () => {\n const gameElement = gameContainerRef.current?.closest(\n \"sigurd-startup\"\n ) as HTMLElement;\n if (gameElement) {\n toggleFullscreen(gameElement);\n } else {\n toggleFullscreen();\n }\n };\n\n // Set up keyboard shortcuts\n useKeyboardShortcuts(handleFullscreenToggle);\n\n return (\n <div ref={gameContainerRef} className=\"relative rounded-lg\">\n <GameCanvas />\n\n {/* Loading overlay */}\n {isPreloading && (\n <Menu>\n <div className=\"text-white text-center\">\n <div className=\"text-lg font-bold mb-2\">Loading Backgrounds...</div>\n <div className=\"text-sm text-gray-300\">\n Please wait while we prepare your game\n </div>\n </div>\n </Menu>\n )}\n\n {DEV_CONFIG.ENABLED && (\n <div className=\"text-white text-2xl absolute top-1 left-1 bg-red-500 rounded-full p-1 flex items-center justify-center gap-1 z-50\">\n <span className=\"text-xs font-bold uppercase\">Dev</span>\n <Circle className=\"w-4 h-4\" fill=\"white\" />\n </div>\n )}\n\n {/* Version display */}\n <div\n className={`absolute bottom-3 right-3 ${\n isFullscreen ? \"text-md\" : \"text-xs\"\n } text-muted-foreground z-40 ${isFullscreen ? \"bottom-4\" : \"bottom-3\"}`}\n >\n v{VERSION_STRING} (Build {getVersion().build})\n </div>\n\n {/* Menu overlays positioned relative to the canvas */}\n {!isPreloading && (\n <>\n {showMenu === MenuType.START && (\n <Menu>\n <StartMenu />\n </Menu>\n )}\n {showMenu === MenuType.COUNTDOWN && (\n <Menu>\n <CountdownOverlay />\n </Menu>\n )}\n {showMenu === MenuType.PAUSE && (\n <Menu>\n <PauseMenu />\n </Menu>\n )}\n {showMenu === MenuType.SETTINGS && (\n <Menu>\n <SettingsMenu />\n </Menu>\n )}\n {currentState === GameState.PLAYING && (\n <Menu transparent={true}>\n <InGameMenu />\n </Menu>\n )}\n {showMenu === MenuType.BONUS && (\n <Menu>\n <BonusScreen />\n </Menu>\n )}\n {showMenu === MenuType.VICTORY && (\n <Menu>\n <VictoryMenu />\n </Menu>\n )}\n {showMenu === MenuType.GAME_OVER && (\n <Menu>\n <GameOverScreen />\n </Menu>\n )}\n {showMenu === MenuType.AUDIO_SETTINGS && (\n <Menu>\n <AudioSettingsMenu />\n </Menu>\n )}\n </>\n )}\n </div>\n );\n};\n\nexport default MainGame;\n","import ReactDOM from \"react-dom/client\";\nimport MainGame from \"./components/MainGame\"; // your root game component\nimport \"./index.css\";\nimport css from './index.css?inline';\nimport { getVersion, logVersion } from \"./version\";\n\ninterface GameElementInterface {\n getVersion: () => ReturnType<typeof getVersion>;\n isCompatible: (minVersion: string) => boolean;\n}\n\nclass GameElement extends HTMLElement implements GameElementInterface {\n private root: ReactDOM.Root | null = null;\n\n connectedCallback() {\n const shadow = this.attachShadow({ mode: \"open\" });\n const rootElement = document.createElement(\"div\");\n shadow.appendChild(rootElement);\n \n const style = document.createElement('style');\n style.textContent = css;\n shadow.appendChild(style);\n\n this.root = ReactDOM.createRoot(rootElement);\n this.root.render(<MainGame />);\n\n // Log version info\n logVersion();\n\n // Expose version to external sites\n this.setAttribute('data-version', getVersion().version);\n this.setAttribute('data-build', getVersion().build.toString());\n }\n\n disconnectedCallback() {\n if (this.root) {\n this.root.unmount();\n this.root = null;\n }\n }\n\n getVersion() {\n return getVersion();\n }\n\n isCompatible(minVersion: string) {\n const current = getVersion();\n const [major, minor, patch] = current.version.split('.').map(Number);\n const [minMajor, minMinor, minPatch] = minVersion.split('.').map(Number);\n \n if (major > minMajor) return true;\n if (major < minMajor) return false;\n if (minor > minMinor) return true;\n if (minor < minMinor) return false;\n return patch >= minPatch;\n }\n}\n\n// Define the custom element\ncustomElements.define(\"sigurd-startup\", GameElement);\n\n// Export version for direct import\nexport { getVersion, logVersion };\n","// Import to register the custom element first\nimport './game-wrapper';\n\n// Import non-React exports only\nimport { getVersion, logVersion } from './game-wrapper';\nimport { ASSET_PATHS, getBackgroundImagePath } from './config/assets';\n\n// Main library exports (non-React only)\nexport { getVersion, logVersion } from './game-wrapper';\nexport { ASSET_PATHS, getBackgroundImagePath } from './config/assets';\n\n// Re-export types for convenience\nexport type { GameState, MenuType } from './types/enums';\nexport type { \n GameStateInterface, \n CoinState, \n BombCollectionState,\n CoinPhysicsConfig,\n CoinTypeConfig,\n MonsterSpawnConfig\n} from './types/interfaces';\n\n// Default export for easy importing\nconst SigurdStartupGame = {\n getVersion,\n ASSET_PATHS,\n getBackgroundImagePath,\n};\n\nexport default SigurdStartupGame; "],"names":["f","require$$0","k","l","m","n","p","q","c","a","g","b","d","e","h","reactJsxRuntime_production_min","React","REACT_ELEMENT_TYPE","REACT_PORTAL_TYPE","REACT_FRAGMENT_TYPE","REACT_STRICT_MODE_TYPE","REACT_PROFILER_TYPE","REACT_PROVIDER_TYPE","REACT_CONTEXT_TYPE","REACT_FORWARD_REF_TYPE","REACT_SUSPENSE_TYPE","REACT_SUSPENSE_LIST_TYPE","REACT_MEMO_TYPE","REACT_LAZY_TYPE","REACT_OFFSCREEN_TYPE","MAYBE_ITERATOR_SYMBOL","FAUX_ITERATOR_SYMBOL","getIteratorFn","maybeIterable","maybeIterator","ReactSharedInternals","error","format","_len2","args","_key2","printWarning","level","ReactDebugCurrentFrame","stack","argsWithFormat","item","enableScopeAPI","enableCacheElement","enableTransitionTracing","enableLegacyHidden","enableDebugTracing","REACT_MODULE_REFERENCE","isValidElementType","type","getWrappedName","outerType","innerType","wrapperName","displayName","functionName","getContextName","getComponentNameFromType","context","provider","outerName","lazyComponent","payload","init","assign","disabledDepth","prevLog","prevInfo","prevWarn","prevError","prevGroup","prevGroupCollapsed","prevGroupEnd","disabledLog","disableLogs","props","reenableLogs","ReactCurrentDispatcher","prefix","describeBuiltInComponentFrame","name","source","ownerFn","x","match","reentry","componentFrameCache","PossiblyWeakMap","describeNativeComponentFrame","fn","construct","frame","control","previousPrepareStackTrace","previousDispatcher","Fake","sample","sampleLines","controlLines","s","_frame","syntheticFrame","describeFunctionComponentFrame","shouldConstruct","Component","prototype","describeUnknownElementTypeFrameInDEV","hasOwnProperty","loggedTypeFailures","setCurrentlyValidatingElement","element","owner","checkPropTypes","typeSpecs","values","location","componentName","has","typeSpecName","error$1","err","ex","isArrayImpl","isArray","typeName","value","hasToStringTag","willCoercionThrow","testStringCoercion","checkKeyStringCoercion","ReactCurrentOwner","RESERVED_PROPS","specialPropKeyWarningShown","specialPropRefWarningShown","hasValidRef","config","getter","hasValidKey","warnIfStringRefCannotBeAutoConverted","self","defineKeyPropWarningGetter","warnAboutAccessingKey","defineRefPropWarningGetter","warnAboutAccessingRef","ReactElement","key","ref","jsxDEV","maybeKey","propName","defaultProps","ReactCurrentOwner$1","ReactDebugCurrentFrame$1","setCurrentlyValidatingElement$1","propTypesMisspellWarningShown","isValidElement","object","getDeclarationErrorAddendum","getSourceInfoErrorAddendum","ownerHasKeyUseWarning","getCurrentComponentErrorInfo","parentType","info","parentName","validateExplicitKey","currentComponentErrorInfo","childOwner","validateChildKeys","node","i","child","iteratorFn","iterator","step","validatePropTypes","propTypes","_name","validateFragmentProps","fragment","keys","didWarnAboutKeySpread","jsxWithValidation","isStaticChildren","validType","sourceInfo","typeString","children","beforeExample","afterExample","jsxWithValidationStatic","jsxWithValidationDynamic","jsx","jsxs","reactJsxRuntime_development","jsxRuntimeModule","require$$1","client","o","GAME_CONFIG","DEFAULT_AUDIO_SETTINGS","DEV_CONFIG","COLORS","createInitialPlayer","createPlayerSlice","set","get","playerUpdate","y","GameState","MenuType","MonsterType","CoinType","AudioEvent","Logger","__publicField","throttleMs","now","lastTime","message","logger","log","sendScoreToHost","score","map","lives","multiplier","scoreData","scoreEvent","detailedScoreEvent","sendGameReady","event","sendGameStateUpdate","state","sendMapCompletionData","data","sendGameCompletionData","calculateGameStats","levelHistory","finalScore","gameEndReason","startTime","endTime","totalBombs","sum","totalCorrectOrders","totalCoinsCollected","totalPowerModeActivations","totalPlayTime","averageCompletionTime","getMonsterColor","createBaseMonster","speed","spawnDelay","createHorizontalPatrolMonster","platformX","platformY","platformWidth","spawnSide","walkLengths","direction","initialDirection","createVerticalPatrolMonster","startY","patrolHeight","side","createFloaterMonster","startX","startAngle","createChaserMonster","directness","updateInterval","createAmbusherMonster","ambushInterval","createBomb","order","group","createPlatform","dimensions","color","borderColor","createVerticalPlatform","height","centerX","offsetWidth","centerY","offsetHeight","centerPoint","level1Map","level2Map","level3Map","level4Map","level5Map","level7Map","mapDefinitions","createGameStateSlice","api","currentMap","menuType","currentState","complete","newLives","levelResults","gameStartTime","sessionId","gameStats","gameCompletionData","currentLevel","points","levelScore","newScore","calculateBombScore","isFirebomb","basePoints","actualPoints","formatScoreLog","calculation","calculateMultiplierProgress","multiplierScore","currentMultiplier","MULTIPLIER_THRESHOLDS","MAX_MULTIPLIER","currentThreshold","nextThreshold","progress","createBombSlice","bombOrder","bombs","bombManager","bomb","result","scoreCalculation","text","updatedBombs","nextGroup","nextOrder","isNextBomb","id","BombManager","bombId","isCorrectOrder","isCorrect","allGroups","uncollectedBombs","createLevelSlice","mapData","firstBomb","monstersWithColors","monster","monsters","levelStartTime","completionTime","completionData","createLevelHistorySlice","createMultiplierSlice","calculateMultiplier","newMultiplierScore","newMultiplier","multiplierIncreased","createAudioSettingsSlice","newSettings","audioManager","createCoinSlice","coins","manager","coin","coinManager","updatedCoins","powerModeEndTime","colorData","activeEffects","newTotalCoinsCollected","newTotalPowerCoinsCollected","newTotalBonusMultiplierCoinsCollected","newTotalExtraLifeCoinsCollected","pointsNeeded","wasPowerModeActive","isPowerModeActive","createFloatingTextSlice","duration","fontSize","floatingText","currentTime","_ScalingManager","newConfig","reason","pauseDuration","cacheKey","cached","oldValues","baseValues","initialInfo","actualElapsed","pauseTimeAfterSpawn","adjustedElapsed","age","position","newValues","intervals","changes","timeElapsed","baseValue","scalingFactor","maxValue","scaledValue","ScalingManager","COIN_EFFECTS","gameState","COIN_PHYSICS","platforms","ground","landedOnPlatform","currentPlatform","platform","coinBottom","platformTop","isOnTop","isHorizontallyAligned","P_COIN_COLORS","COIN_TYPES","bonusCount","CoinPhysics","physicsConfig","coinCenterX","coinCenterY","platformCenterX","platformCenterY","deltaX","deltaY","collisionNormal","dotProduct","spawnAngle","angleRad","closestX","closestY","normalX","normalY","length","coinLeft","coinRight","coinTop","objectLeft","objectRight","objectTop","objectBottom","distToLeft","distToRight","distToTop","distToBottom","minDist","normal","oldVX","oldVY","oldSpeed","newSpeed","speedRatio","penetrationX","penetrationY","CoinManager","spawnPoints","coinConfig","initialVelocity","isBonus","lastThreshold","spawnKey","point","spawnPoint","combinedState","spawnX","spawnY","threshold","pointsEarned","spawnTime","effect","gameStateWithManager","effectsToRemove","effectData","effectType","totalPoints","elapsed","colorIndex","newColor","powerModeEffect","isActive","timeLeft","shouldBlink","recentPcoin","useGameStore","create","playerSlice","gameStateSlice","bombSlice","levelSlice","levelHistorySlice","multiplierSlice","audioSettingsSlice","coinSlice","floatingTextSlice","bombsWithState","InputManager","pressed","CollisionManager","player","collision","entity","surface","nextX","nextY","entityCenterX","entityCenterY","surfaceCenterX","surfaceCenterY","overlapX","overlapY","width","bounds","boundaryCollision","updatedPlayer","penetration","rect1","rect2","SpriteInstance","animations","initial","newAnimation","preservedFrame","dt","ctx","scale","img","drawWidth","drawHeight","spriteX","ASSET_PATHS","getBackgroundImagePath","theme","loadImage","path","sigurdIdleFrames","runningFrames","jumpFrames","completeFrames","floatStationaryFrames","floatDirectionalFrames","landingFrames","playerAnimations","playerSprite","unlitBombFrame2","litBombFrame2","bombAnimations","BombSpriteInstance","bombSprite","MAP_NAME_TO_BACKGROUND_MAP","BackgroundManager","canvasWidth","canvasHeight","mapName","imageFileName","image","src","resolve","reject","playerX","playerY","scaleX","scaleY","scaledWidth","scaledHeight","offsetX","offsetY","gradient","backgrounds","loadedCount","preloadPromises","background","_OptimizedRespawnManager","deadMonster","left","right","mid","monstersToRespawn","respawnedMonster","monsterType","dm","intervalMs","OptimizedRespawnManager","RenderManager","canvas","floatingTexts","spawnManager","deltaTime","radius","individualSprite","animationName","coinSymbol","index","monsterColor","time","respawnManager","timeRemaining","secondsRemaining","pulseIntensity","textX","textY","spawn","tempMonster","animatedY","opacity","cityName","isPatrolMonster","isChaserMonster","isAmbusherMonster","MovementUtils","platformCenter","originalSpawnX","currentWalkCount","newX","newY","PatrolMovement","scalingManager","valuesToUse","monsterAge","frameSpeed","patrolSide","targetPlatformX","targetPlatform","ChaserMovement","targetOffsetX","targetOffsetY","currentTargetX","currentTargetY","shouldAddOffset","randomOffsetX","randomOffsetY","targetX","targetY","dx","dy","distance","individualSpeed","moveX","moveY","canMoveX","canMoveY","randomFactor","verticalDirections","verticalDir","horizontalDir","horizontalDirections","directions","j","dir","canMove","AmbusherMovement","moveSpeed","normX","normY","ambushSpeed","randomDirection","targetDistance","newTargetX","newTargetY","FloaterMovement","gameStateParam","currentSpeed","frameMultiplier","scaledSpeed","monsterCenterX","monsterCenterY","bounceAngle","randomAngle","newAngle","MonsterBehaviorManager","OptimizedSpawnManager","delaySeconds","adjustedTime","adjustedAbsoluteTime","spawnsToExecute","pendingSpawns","timeUntilSpawn","spawns","spawnedMonsters","updatedMonsters","executedCount","pendingCount","AudioManager","arrayBuffer","oscillator","gainNode","sfxVolume","notes","frequency","melody","mainOsc","mainGain","highOsc","highGain","audioSettings","musicVolume","AnimationController","sprite","isGrounded","isFloating","newState","justLanded","isMoving","moveDirection","lastDirection","animation","GameManager","currentLives","targetLives","targetLevel","mapDefinition","monstersWithSpawnPoints","groundCollision","shouldPlayMusic","isUpPressed","isShiftPressed","isSpacePressed","baseJumpPower","jumpDuration","holdRatio","targetVelocity","gravity","boundaryResult","gameTime","respawnedMonsters","deadMonsterCount","platformCollision","collectedBomb","collectedCoin","hitMonster","resetMonsters","bonusPoints","coinStats","coinsCollected","powerModeActivations","levelResult","mapCompletionData","correctCount","useFullscreen","isFullscreen","setIsFullscreen","useState","dispatchFullscreenEvent","useCallback","fullscreen","isFullscreenSupported","getFullscreenElement","enterFullscreen","targetElement","exitFullscreen","toggleFullscreen","useEffect","handleFullscreenChange","newFullscreenState","GameCanvas","className","canvasRef","useRef","gameManagerRef","canvasStyle","setCanvasStyle","updateCanvasSize","aspectRatio","windowWidth","windowHeight","windowAspectRatio","cn","inputs","twMerge","clsx","buttonVariants","cva","Button","variant","size","asChild","Comp","Slot","TooltipProvider","TooltipPrimitive","Tooltip","TooltipTrigger","TooltipContent","sideOffset","StartMenu","setState","setMenuType","gameContainerRef","startGame","openSettings","handleFullscreenToggle","gameElement","Minimize","Maximize","Play","Settings","CountdownOverlay","count","setCount","interval","prev","Fragment","InGameMenu","isPaused","togglePause","CircleDollarSign","Map","Zap","Pause","_","Heart","PauseMenu","resetGame","resumeGame","quitToMenu","restartGame","resetBombState","resetPlayer","resetEffects","clearAllFloatingTexts","initializeLevel","RotateCcw","Home","SettingsMenu","previousMenu","updateAudioSettings","masterVolume","masterMuted","musicMuted","sfxMuted","goBack","ArrowLeft","useAnimatedCounter","targetValue","options","steps","easing","delay","onComplete","animatedValue","setAnimatedValue","hasCompleted","lastTargetValue","startTimer","stepDuration","currentStep","timer","easedProgress","smoothValue","displayValue","BonusScreen","correctOrderCount","nextLevel","setBonusAnimationComplete","animatedBonusPoints","VictoryMenu","handleRestart","GameOverScreen","AudioSettingsMenu","Menu","transparent","useKeyboardShortcuts","onFullscreenToggle","handleKeyDown","useBackgroundPreloading","isPreloading","setIsPreloading","VERSION","VERSION_STRING","getVersion","logVersion","MainGame","showMenu","GameElement","shadow","rootElement","style","css","ReactDOM","minVersion","current","major","minor","patch","minMajor","minMinor","minPatch","SigurdStartupGame"],"mappings":"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","x_google_ignoreList":[0,1,2,3]}