User prompt
# Cosmic Cat Tree Game Implementation Plan ## 1. Core Game Logic & Mechanics - Implement Bird movement patterns and spawning system - Complete Cat and Kitten charm mechanics with cooldowns - Add UFO collection behavior and automation - Create sparkle generation and collection system - Implement idle progression mechanics - Add tap interaction for tree sparkle burst
User prompt
# Cosmic Cat Tree Game Implementation Plan ## 1. Core Game Logic & Mechanics - Implement Bird movement patterns and spawning system - Complete Cat and Kitten charm mechanics with cooldowns - Add UFO collection behavior and automation - Create sparkle generation and collection system - Implement idle progression mechanics - Add tap interaction for tree sparkle burst ## 2. Animation System ### Particle Effects - Sparkle Dust generation and floating - Collection beam effects for UFOs - Charm effect particles - Tree tap burst effect - Sleeping cat Zzz particles ### Character Animations - Cat/Kitten idle animations (tail swish, ear twitch) - Bird flight and perching animations - UFO hovering and collection movements - Tree leaf shimmer effect ## 3. Game Object Methods ### Cat & Kitten - tryCharmBird(): Check nearby birds and attempt to charm them - getCharmRadius(): Define interaction range - handleCharmCooldown(): Manage charm timing - playIdleAnimation(): Handle random idle animations ### Bird - setRandomPosition(): Set starting position and target - update(): Handle movement towards tree - handleCharmed(): Manage charmed state and rewards - playFlightAnimation(): Control flight animations ### UFO - findNearestSparkle(): Locate closest collectible sparkle - moveToSparkle(): Navigate to target sparkle - collectSparkle(): Handle collection and rewards - playBeamEffect(): Show collection beam ### Sparkle - update(): Handle floating animation - handleCollection(): Manage collection state ## 4. Game Class Methods - spawnBirds(): Manage bird population - updateSparkles(): Handle sparkle lifecycle - createSparkle(): Generate new sparkles - handlePurchases(): Manage resource spending - updateUI(): Keep display current - saveGameState(): Store progress to localStorage - loadGameState(): Restore saved progress - initializeSoundSystem(): Set up audio management ## 5. Asset Management ### Visual Assets - Tree background with branch positions - Cat and kitten sprites with animation frames - Bird variants with flight animations - UFO design with beam effects - Sparkle and particle effect sprites - UI elements and upgrade icons ### Audio Assets - Background music - Bird chirp sounds - UFO hover and collection sounds - Sparkle collection effects - UI interaction sounds - Cat purring and meowing ## 6. Implementation Order 1. Set up basic game structure and asset loading 2. Implement core movement and positioning 3. Add basic animations and particle system 4. Implement charm mechanics and sparkle generation 5. Add UFO collection system 6. Integrate purchase and upgrade system 7. Implement save/load functionality 8. Add sound effects and background music 9. Polish animations and visual feedback 10. Balance gameplay mechanics and economy 11. Optimize performance and memory usage 12. Final testing and bug fixes
User prompt
Please fix the bug: 'Uncaught SecurityError: Failed to read the 'localStorage' property from 'Window': The document is sandboxed and lacks the 'allow-same-origin' flag.' in or related to this line: 'return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {' Line Number: 158 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
improve the ui
User prompt
continue
User prompt
refactor
User prompt
continue
User prompt
fill in any missing code.
User prompt
create classes for all assets that do not have one
Code edit (3 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Maximum call stack size exceeded' in or related to this line: 'return false;' Line Number: 50
User prompt
Please fix the bug: 'Maximum call stack size exceeded' in or related to this line: 'return isLocalStorageAccessible() ? false : undefined;' Line Number: 50
User prompt
Please fix the bug: 'Uncaught SecurityError: Failed to read the 'localStorage' property from 'Window': The document is sandboxed and lacks the 'allow-same-origin' flag.' in or related to this line: 'return false;' Line Number: 50
User prompt
Please fix the bug: 'Uncaught SecurityError: Failed to read the 'localStorage' property from 'Window': The document is sandboxed and lacks the 'allow-same-origin' flag.' in or related to this line: 'return false;' Line Number: 50
User prompt
Please fix the bug: 'Uncaught SecurityError: Failed to read the 'localStorage' property from 'Window': The document is sandboxed and lacks the 'allow-same-origin' flag.' in or related to this line: 'return typeof o;' Line Number: 135
User prompt
Please fix the bug: 'Uncaught SecurityError: Failed to read the 'localStorage' property from 'Window': The document is sandboxed and lacks the 'allow-same-origin' flag.' in or related to this line: 'return typeof o;' Line Number: 131
User prompt
Please fix the bug: 'Uncaught SecurityError: Failed to read the 'localStorage' property from 'Window': The document is sandboxed and lacks the 'allow-same-origin' flag.' in or related to this line: 'return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;' Line Number: 128
User prompt
Please fix the bug: 'Uncaught SecurityError: Failed to read the 'localStorage' property from 'Window': The document is sandboxed and lacks the 'allow-same-origin' flag.' in or related to this line: 'return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;' Line Number: 118
User prompt
ensure all shapes are initialized and used correctly.
User prompt
improve the ui layout
Code edit (1 edits merged)
Please save this source code
User prompt
improve the code
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'height')' in or related to this line: 'createPlaceholderAsset(TREE_ASSET_ID, 0x8b4513, 5, LK.canvas.height * 0.6); // Brown Tree Trunk (adjust height as needed);' Line Number: 847
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'height')' in or related to this line: 'createPlaceholderAsset(TREE_ASSET_ID, 0x8b4513, 5, LK.canvas.height * 0.6); // Brown Tree Trunk (adjust height as needed);' Line Number: 845
/**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ var TREE_ASSET_ID = 'tree_graphic'; // and destroyed in the global scope of `gamecode.js`. (Guideline 1) // Ensure that important variables, instances, arrays, and variables are created // --- Global Scope Variables --- /** * gamecode.js * * This file contains the core game logic for the Cosmic Cat Tree game. * It defines the game objects, their behaviors, and manages the overall game state * according to the provided plan and guidelines. */ if (!LK.Assets) { LK.Assets = {}; } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) { return _arrayLikeToArray(r, a); } var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) { return Array.from(r); } } function _arrayWithoutHoles(r) { if (Array.isArray(r)) { return _arrayLikeToArray(r); } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) { n[e] = r[e]; } return n; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) { return e; } if (void 0 !== e) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(t); } function _assertThisInitialized(e) { if (void 0 === e) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return e; } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } function _inherits(t, e) { if ("function" != typeof e && null !== e) { throw new TypeError("Super expression must either be null or a function"); } t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _classCallCheck(a, n) { if (!(a instanceof n)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) { return t; } var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) { return i; } throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } var cats = []; var kittens = []; var birds = []; var ufos = []; var sparkles = []; // Game State Variables var sparkleCount = 0; var maxBirds = 10; // Maximum number of birds allowed on screen var birdSpawnTimer = 0; var birdSpawnInterval = 1.5; // Seconds between bird spawns var treePosition = { x: 0, y: 0 }; // Center of the tree (set in Initialize Game) // UI Elements var sparkleCountText = null; var addKittenButton = null; // Add more UI elements for upgrades if needed // Constants var CAT_CHARM_RADIUS = 100; var CAT_CHARM_COOLDOWN = 2.0; // seconds var KITTEN_CHARM_RADIUS = 60; var KITTEN_CHARM_COOLDOWN = 3.0; // seconds var BIRD_SPEED = 50; // pixels per second var UFO_SPEED = 150; // pixels per second var SPARKLE_VALUE = 1; var KITTEN_COST = 10; // --- Asset IDs (Ensure these match the assets uploaded in the LK editor) --- var CAT_ASSET_ID = 'cat_graphic'; var KITTEN_ASSET_ID = 'kitten_graphic'; var BIRD_ASSET_ID = 'bird_graphic'; var UFO_ASSET_ID = 'ufo_graphic'; var SPARKLE_ASSET_ID = 'sparkle_graphic'; // Optional tree graphic // const TREE_ASSET_ID = 'tree_graphic'; // --- Utility Functions --- function distance(x1, y1, x2, y2) { var dx = x1 - x2; var dy = y1 - y2; return Math.sqrt(dx * dx + dy * dy); } // --- Game Object Classes --- (Guideline 2) /** * Base class for charming entities (Cats and Kittens) */ var Charmer = /*#__PURE__*/function () { function Charmer(assetId, x, y, charmRadius, charmCooldown) { _classCallCheck(this, Charmer); // Asset Retrieval & Positioning (Guideline 3, 13) this.sprite = LK.getAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); this.sprite.x = x; this.sprite.y = y; LK.add(this.sprite); this.charmRadius = charmRadius; this.charmCooldownTime = charmCooldown; this.charmTimer = 0; // Ready to charm immediately this.isCharmer = true; // Property to identify charmers } // Define interaction range (Plan 2) return _createClass(Charmer, [{ key: "getCharmRadius", value: function getCharmRadius() { return this.charmRadius; } // Manage charm timing (Plan 2) }, { key: "handleCharmCooldown", value: function handleCharmCooldown(deltaTime) { if (this.charmTimer > 0) { this.charmTimer -= deltaTime; } } // Check nearby birds and attempt to charm them (Plan 2) }, { key: "tryCharmBird", value: function tryCharmBird() { if (this.charmTimer > 0) { return false; // Still on cooldown } for (var i = birds.length - 1; i >= 0; i--) { var bird = birds[i]; if (!bird.isCharmed) { var dist = distance(this.sprite.x, this.sprite.y, bird.sprite.x, bird.sprite.y); if (dist <= this.getCharmRadius()) { bird.handleCharmed(); // Bird handles its state change and reward (sparkle) this.charmTimer = this.charmCooldownTime; // Reset cooldown // Optionally add visual feedback here (e.g., particle effect if available) return true; // Charmed a bird } } } return false; // No bird charmed } }, { key: "update", value: function update(deltaTime) { this.handleCharmCooldown(deltaTime); this.tryCharmBird(); // Attempt to charm every frame if cooldown is ready } }, { key: "destroy", value: function destroy() { LK.remove(this.sprite); } }]); }(); /** * Cat Class */ var Cat = /*#__PURE__*/function (_Charmer) { function Cat(x, y) { _classCallCheck(this, Cat); return _callSuper(this, Cat, [CAT_ASSET_ID, x, y, CAT_CHARM_RADIUS, CAT_CHARM_COOLDOWN]); // Cat-specific properties can be added here } // Cat-specific methods can be added here _inherits(Cat, _Charmer); return _createClass(Cat); }(Charmer); /** * Kitten Class */ var Kitten = /*#__PURE__*/function (_Charmer2) { function Kitten(x, y) { _classCallCheck(this, Kitten); return _callSuper(this, Kitten, [KITTEN_ASSET_ID, x, y, KITTEN_CHARM_RADIUS, KITTEN_CHARM_COOLDOWN]); // Kitten-specific properties can be added here } // Kitten-specific methods can be added here _inherits(Kitten, _Charmer2); return _createClass(Kitten); }(Charmer); /** * Bird Class */ var Bird = /*#__PURE__*/function () { function Bird() { _classCallCheck(this, Bird); // Asset Retrieval (Guideline 3) this.sprite = LK.getAsset(BIRD_ASSET_ID, { anchorX: 0.5, anchorY: 0.5 }); this.setRandomPosition(); // Set starting position and target (Plan 2) LK.add(this.sprite); this.speed = BIRD_SPEED + (Math.random() * 20 - 10); // Add slight speed variation this.isCharmed = false; this.targetX = treePosition.x; this.targetY = treePosition.y; this.toBeRemoved = false; } // Set starting position and target (Plan 2) return _createClass(Bird, [{ key: "setRandomPosition", value: function setRandomPosition() { var side = Math.floor(Math.random() * 4); var edgeBuffer = 50; // Spawn slightly off-screen switch (side) { case 0: // Top this.sprite.x = Math.random() * LK.canvas.width; this.sprite.y = -edgeBuffer; break; case 1: // Right this.sprite.x = LK.canvas.width + edgeBuffer; this.sprite.y = Math.random() * LK.canvas.height; break; case 2: // Bottom this.sprite.x = Math.random() * LK.canvas.width; this.sprite.y = LK.canvas.height + edgeBuffer; break; case 3: // Left this.sprite.x = -edgeBuffer; this.sprite.y = Math.random() * LK.canvas.height; break; } } // Handle movement towards tree (Plan 2) }, { key: "update", value: function update(deltaTime) { if (this.isCharmed || this.toBeRemoved) { // Potentially add a "falling" or "poof" animation here if possible // For now, charmed birds are handled instantly return; } var dx = this.targetX - this.sprite.x; var dy = this.targetY - this.sprite.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 5) { // Reached the tree (or close enough) this.toBeRemoved = true; // Mark for removal without reward } else { var moveX = dx / dist * this.speed * deltaTime; var moveY = dy / dist * this.speed * deltaTime; this.sprite.x += moveX; this.sprite.y += moveY; // Flip sprite based on direction this.sprite.scale.x = dx > 0 ? 1 : -1; } } // Manage charmed state and rewards (Plan 2) }, { key: "handleCharmed", value: function handleCharmed() { if (this.isCharmed) { return; } // Already charmed this.isCharmed = true; // Trigger sparkle generation (Plan 1) Game.Instance.createSparkle(this.sprite.x, this.sprite.y, SPARKLE_VALUE); this.toBeRemoved = true; // Mark for removal after being charmed } }, { key: "destroy", value: function destroy() { LK.remove(this.sprite); } }]); }(); /** * UFO Class */ var UFO = /*#__PURE__*/function () { function UFO(x, y) { _classCallCheck(this, UFO); // Asset Retrieval (Guideline 3, 13) this.sprite = LK.getAsset(UFO_ASSET_ID, { anchorX: 0.5, anchorY: 0.5 }); this.sprite.x = x; this.sprite.y = y; LK.add(this.sprite); this.speed = UFO_SPEED; this.targetSparkle = null; this.isCollecting = false; // State flag } // Locate closest collectible sparkle (Plan 2) return _createClass(UFO, [{ key: "findNearestSparkle", value: function findNearestSparkle() { var closestDist = Infinity; var nearest = null; for (var _i = 0, _sparkles = sparkles; _i < _sparkles.length; _i++) { var sparkle = _sparkles[_i]; if (!sparkle.isBeingCollected && !sparkle.isCollected) { var dist = distance(this.sprite.x, this.sprite.y, sparkle.sprite.x, sparkle.sprite.y); if (dist < closestDist) { closestDist = dist; nearest = sparkle; } } } if (nearest) { this.targetSparkle = nearest; this.targetSparkle.isBeingCollected = true; // Mark sparkle so other UFOs ignore it this.isCollecting = true; } else { this.targetSparkle = null; this.isCollecting = false; } } // Navigate to target sparkle (Plan 2) }, { key: "moveToSparkle", value: function moveToSparkle(deltaTime) { if (!this.targetSparkle || this.targetSparkle.isCollected) { this.isCollecting = false; this.targetSparkle = null; return; } var targetX = this.targetSparkle.sprite.x; var targetY = this.targetSparkle.sprite.y; var dx = targetX - this.sprite.x; var dy = targetY - this.sprite.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 10) { // Close enough to collect this.collectSparkle(); } else { var moveX = dx / dist * this.speed * deltaTime; var moveY = dy / dist * this.speed * deltaTime; this.sprite.x += moveX; this.sprite.y += moveY; // Optional: Point UFO towards sparkle // this.sprite.rotation = Math.atan2(dy, dx); } } // Handle collection and rewards (Plan 2) }, { key: "collectSparkle", value: function collectSparkle() { if (this.targetSparkle && !this.targetSparkle.isCollected) { var value = this.targetSparkle.handleCollection(); // Sparkle handles its removal Game.Instance.addSparkles(value); // Add to global count via Game method this.targetSparkle = null; this.isCollecting = false; // Optionally add visual feedback for collection } } }, { key: "update", value: function update(deltaTime) { if (!this.isCollecting) { this.findNearestSparkle(); // Look for a new target if not currently collecting } if (this.targetSparkle) { this.moveToSparkle(deltaTime); // Move towards target if one exists } else { // Optional: Add idle behavior (e.g., slow drift or patrol) // this.sprite.x += Math.sin(LK.Time.now * 0.5) * 0.5 * deltaTime * 60; } } }, { key: "destroy", value: function destroy() { LK.remove(this.sprite); } }]); }(); /** * Sparkle Class */ var Sparkle = /*#__PURE__*/function () { function Sparkle(x, y, value) { _classCallCheck(this, Sparkle); // Asset Retrieval (Guideline 3, 13) this.sprite = LK.getAsset(SPARKLE_ASSET_ID, { anchorX: 0.5, anchorY: 0.5 }); this.sprite.x = x; this.sprite.y = y; LK.add(this.sprite); this.value = value; this.isCollected = false; this.isBeingCollected = false; // Flag to prevent multiple UFOs targeting same sparkle this.lifeTimer = 0; // Used for animation this.floatAmplitude = 3; this.floatSpeed = 2; } // Handle floating animation (Plan 2) return _createClass(Sparkle, [{ key: "update", value: function update(deltaTime) { if (this.isCollected) { return; } this.lifeTimer += deltaTime; // Simple vertical float this.sprite.y += Math.sin(this.lifeTimer * this.floatSpeed) * this.floatAmplitude * deltaTime; // Optional: Add slight drift, fade-out over time, etc. } // Manage collection state (Plan 2) }, { key: "handleCollection", value: function handleCollection() { if (this.isCollected) { return 0; } // Already collected this.isCollected = true; // Mark for removal in the main game loop this.destroy(); // Remove sprite immediately return this.value; } }, { key: "destroy", value: function destroy() { LK.remove(this.sprite); } }]); }(); // --- Game Class --- var Game = /*#__PURE__*/function () { function Game() { _classCallCheck(this, Game); Game.Instance = this; // Set static instance // Game initialization logic } /** * Initialize Game * Called once when the game starts or resets. * Only set background color here directly. (Guideline 7) * Initialize global state, arrays, and create initial objects. */ return _createClass(Game, [{ key: 'Initialize Game', value: function Initialize_Game() { console.log("Initializing Cosmic Cat Tree Game..."); LK.backgroundColor = 0x1a1a2e; // Dark space blue // Reset Global State sparkleCount = 0; birdSpawnTimer = 0; treePosition = { x: LK.canvas.width / 2, y: LK.canvas.height / 2 }; // Create placeholder asset for the tree trunk after canvas dimensions are available createPlaceholderAsset(TREE_ASSET_ID, 0x8b4513, 5, LK.canvas.height * 0.6); // Brown Tree Trunk (adjust height as needed) // Clear existing objects from previous sessions (if any) - Belt and suspenders this.clearAllObjects(); // Initialize Arrays cats = []; kittens = []; birds = []; ufos = []; sparkles = []; // --- Create Initial Game Objects --- // Optional: Add a visual representation for the tree // try { // const treeSprite = LK.getAsset(TREE_ASSET_ID, 'The Cat Tree', 0.5, 1.0); // Anchor bottom-center // treeSprite.x = treePosition.x; // treeSprite.y = LK.canvas.height; // Place at bottom center // LK.add(treeSprite); // // Note: Tree isn't added to an array as it's static background element // } catch (e) { // console.warn("Tree asset not found or failed to load:", e); // } // Create the initial Cat (adjust position as needed) var initialCat = new Cat(treePosition.x, treePosition.y); cats.push(initialCat); // Create the initial UFO var initialUFO = new UFO(treePosition.x, treePosition.y - 150); // Start near the tree ufos.push(initialUFO); // --- Initialize UI --- this.setupUI(); console.log("Game Initialized"); console.log("Canvas dimensions:", LK.canvas.width, LK.canvas.height); console.log("Tree Position:", treePosition.x, treePosition.y); } /** * Setup UI Elements * Creates text displays and buttons. */ }, { key: "setupUI", value: function setupUI() { // Sparkle Counter Display sparkleCountText = LK.CreateText({ text: "Sparkles: ".concat(sparkleCount), x: 10, y: 10, style: { fill: 0xFFFFFF, fontSize: 20 }, anchor: { x: 0, y: 0 } // Anchor top-left }); LK.add(sparkleCountText); // --- Purchase Button Example --- (Plan 3: handlePurchases) addKittenButton = LK.CreateButton({ text: "Add Kitten (".concat(KITTEN_COST, ")"), x: LK.canvas.width - 10, y: 10, width: 150, height: 40, backgroundColor: 0x33aa33, textColor: 0xffffff, pointerup: this.handlePurchaseKitten, // Reference the handler method scope: this, // Ensure 'this' inside the handler refers to the Game instance anchor: { x: 1, y: 0 } // Anchor top-right }); LK.add(addKittenButton); } // Manage resource spending (Plan 3) // Event handler for the Add Kitten button (Guideline 8) }, { key: "handlePurchaseKitten", value: function handlePurchaseKitten(obj) { // 'this' refers to the Game instance because scope was set // 'obj' contains event data if needed, but not used here console.log("Attempting to purchase kitten..."); if (sparkleCount >= KITTEN_COST) { sparkleCount -= KITTEN_COST; this.updateUI(); // Update display immediately // Add a new kitten at a randomish position near the tree var angle = Math.random() * Math.PI * 2; var radius = 50 + Math.random() * 50; // Place 50-100 pixels from center var kx = treePosition.x + Math.cos(angle) * radius; var ky = treePosition.y + Math.sin(angle) * radius; var newKitten = new Kitten(kx, ky); kittens.push(newKitten); console.log("Kitten purchased!"); } else { console.log("Not enough sparkles to purchase kitten."); // Optional: Add feedback like button changing color briefly } } /** * Update Game * Called every frame by the LK engine. * @param {number} deltaTime - Time elapsed since the last frame in seconds. */ }, { key: 'Update Game', value: function Update_Game(deltaTime) { // --- Update Game Logic --- // 1. Spawn Birds (Plan 3) this.spawnBirds(deltaTime); // 2. Update Cats & Kittens for (var _i2 = 0, _cats = cats; _i2 < _cats.length; _i2++) { var cat = _cats[_i2]; cat.update(deltaTime); } for (var _i3 = 0, _kittens = kittens; _i3 < _kittens.length; _i3++) { var kitten = _kittens[_i3]; kitten.update(deltaTime); } // 3. Update Birds (and handle removal) for (var i = birds.length - 1; i >= 0; i--) { var bird = birds[i]; bird.update(deltaTime); if (bird.toBeRemoved) { bird.destroy(); birds.splice(i, 1); } } // 4. Update UFOs for (var _i4 = 0, _ufos = ufos; _i4 < _ufos.length; _i4++) { var ufo = _ufos[_i4]; ufo.update(deltaTime); } // 5. Update Sparkles (and handle removal) (Plan 3: updateSparkles) // Although individual sparkles update, we check for collected ones here for (var i = sparkles.length - 1; i >= 0; i--) { var sparkle = sparkles[i]; if (sparkle.isCollected) { // Sparkle.destroy() already called LK.remove sparkles.splice(i, 1); } else { sparkle.update(deltaTime); // Handle animation } } // 6. Update UI (Plan 3) - Done periodically or when values change // This is called frequently, consider optimizing if performance issues arise // this.updateUI(); // Called when sparkleCount changes instead for efficiency } /** * Cleans up all game objects. Called before Initialize Game on reset. */ }, { key: "clearAllObjects", value: function clearAllObjects() { console.log("Clearing objects..."); [].concat(_toConsumableArray(cats), _toConsumableArray(kittens), _toConsumableArray(birds), _toConsumableArray(ufos), _toConsumableArray(sparkles)).forEach(function (obj) { return obj.destroy(); }); cats = []; kittens = []; birds = []; ufos = []; sparkles = []; // Remove UI elements explicitly if they exist if (sparkleCountText) { LK.remove(sparkleCountText); } if (addKittenButton) { LK.remove(addKittenButton); } sparkleCountText = null; addKittenButton = null; console.log("Objects cleared."); } // --- Game Class Helper Methods --- // Manage bird population (Plan 3) }, { key: "spawnBirds", value: function spawnBirds(deltaTime) { birdSpawnTimer += deltaTime; if (birdSpawnTimer >= birdSpawnInterval && birds.length < maxBirds) { birdSpawnTimer = 0; // Reset timer var newBird = new Bird(); birds.push(newBird); } } // Generate new sparkles (Plan 3) - Called by Bird.handleCharmed }, { key: "createSparkle", value: function createSparkle(x, y, value) { var newSparkle = new Sparkle(x, y, value); sparkles.push(newSparkle); } // Method to add sparkles to the global count (called by UFO) }, { key: "addSparkles", value: function addSparkles(amount) { sparkleCount += amount; this.updateUI(); // Update UI when count changes } // Keep display current (Plan 3) }, { key: "updateUI", value: function updateUI() { if (sparkleCountText) { sparkleCountText.text = "Sparkles: ".concat(sparkleCount); } if (addKittenButton) { // Update button text/state if needed (e.g., disable if too poor) addKittenButton.setText("Add Kitten (".concat(KITTEN_COST, ")")); addKittenButton.button.disabled = sparkleCount < KITTEN_COST; // Example of disabling addKittenButton.button.backgroundColor = sparkleCount < KITTEN_COST ? 0x888888 : 0x33aa33; } // Update other UI elements as needed } /** * Draw Foreground * Called after Update Game. Used for drawing elements on top of sprites. * Not typically used if UI elements cover needs. */ // 'Draw Foreground'() { // } /** * Draw Background * Called before Update Game. Used for background elements. * Avoid adding backgrounds unless specifically requested (Guideline 4). */ // 'Draw Background'() { // } }]); }(); // Attach the Game class to the global LK context // Static instance holder _defineProperty(Game, "Instance", null); LK.Game = Game; // --- Asset Definitions --- // IMPORTANT: Make sure these IDs match the assets uploaded in the LK Editor // and the constants defined at the top of the file. (Guideline 4) // Example Asset Definitions (Replace with actual asset details) // LK.Assets['assets/cat.png'] = { id: CAT_ASSET_ID, frameWidth: 64, frameHeight: 64, frameTags: {} }; // LK.Assets['assets/kitten.png'] = { id: KITTEN_ASSET_ID, frameWidth: 48, frameHeight: 48, frameTags: {} }; // LK.Assets['assets/bird.png'] = { id: BIRD_ASSET_ID, frameWidth: 32, frameHeight: 32, frameTags: {} }; // LK.Assets['assets/ufo.png'] = { id: UFO_ASSET_ID, frameWidth: 80, frameHeight: 40, frameTags: {} }; // LK.Assets['assets/sparkle.png'] = { id: SPARKLE_ASSET_ID, frameWidth: 16, frameHeight: 16, frameTags: {} }; // LK.Assets['assets/tree.png'] = { id: TREE_ASSET_ID, frameWidth: 200, frameHeight: 400, frameTags: {} }; // Placeholder assets if actual graphics aren't available - REMOVE IF USING REAL ASSETS // Using simple squares as placeholders if real assets aren't loaded function createPlaceholderAsset(id, color, width, height) { if (!LK.Assets[id]) { // Only create if not already defined (e.g., by uploaded assets) var shape; var shape; var tex = LK.getAsset(id, { width: width, height: height, color: color, shape: 'box' }); // Generate texture for LK LK.Assets[id] = { id: id, texture: tex, frameWidth: width, frameHeight: height, frameTags: {} }; console.log("Created placeholder asset for ".concat(id)); } } createPlaceholderAsset(CAT_ASSET_ID, 0xffccaa, 50, 50); // Beige Cat createPlaceholderAsset(KITTEN_ASSET_ID, 0xffebcc, 35, 35); // Lighter Beige Kitten createPlaceholderAsset(BIRD_ASSET_ID, 0xadd8e6, 25, 20); // Light Blue Bird createPlaceholderAsset(UFO_ASSET_ID, 0xcccccc, 60, 30); // Grey UFO createPlaceholderAsset(SPARKLE_ASSET_ID, 0xffff00, 10, 10); // Yellow Sparkle createPlaceholderAsset(TREE_ASSET_ID, 0x8b4513, 5, 300); // Brown Tree Trunk (simple line) createPlaceholderAsset(SPARKLE_ASSET_ID, 0xffff00, 10, 10); // Yellow Sparkle createPlaceholderAsset(TREE_ASSET_ID, 0x8b4513, 5, LK.canvas.height * 0.6); // Brown Tree Trunk (adjust height as needed);
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
var TREE_ASSET_ID = 'tree_graphic';
// and destroyed in the global scope of `gamecode.js`. (Guideline 1)
// Ensure that important variables, instances, arrays, and variables are created
// --- Global Scope Variables ---
/**
* gamecode.js
*
* This file contains the core game logic for the Cosmic Cat Tree game.
* It defines the game objects, their behaviors, and manages the overall game state
* according to the provided plan and guidelines.
*/
if (!LK.Assets) {
LK.Assets = {};
}
function _toConsumableArray(r) {
return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _unsupportedIterableToArray(r, a) {
if (r) {
if ("string" == typeof r) {
return _arrayLikeToArray(r, a);
}
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
}
}
function _iterableToArray(r) {
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) {
return Array.from(r);
}
}
function _arrayWithoutHoles(r) {
if (Array.isArray(r)) {
return _arrayLikeToArray(r);
}
}
function _arrayLikeToArray(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) {
n[e] = r[e];
}
return n;
}
function _defineProperty(e, r, t) {
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
value: t,
enumerable: !0,
configurable: !0,
writable: !0
}) : e[r] = t, e;
}
function _callSuper(t, o, e) {
return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
}
function _possibleConstructorReturn(t, e) {
if (e && ("object" == _typeof(e) || "function" == typeof e)) {
return e;
}
if (void 0 !== e) {
throw new TypeError("Derived constructors may only return object or undefined");
}
return _assertThisInitialized(t);
}
function _assertThisInitialized(e) {
if (void 0 === e) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return e;
}
function _isNativeReflectConstruct() {
try {
var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
} catch (t) {}
return (_isNativeReflectConstruct = function _isNativeReflectConstruct() {
return !!t;
})();
}
function _getPrototypeOf(t) {
return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) {
return t.__proto__ || Object.getPrototypeOf(t);
}, _getPrototypeOf(t);
}
function _inherits(t, e) {
if ("function" != typeof e && null !== e) {
throw new TypeError("Super expression must either be null or a function");
}
t.prototype = Object.create(e && e.prototype, {
constructor: {
value: t,
writable: !0,
configurable: !0
}
}), Object.defineProperty(t, "prototype", {
writable: !1
}), e && _setPrototypeOf(t, e);
}
function _setPrototypeOf(t, e) {
return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {
return t.__proto__ = e, t;
}, _setPrototypeOf(t, e);
}
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
function _classCallCheck(a, n) {
if (!(a instanceof n)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(e, r) {
for (var t = 0; t < r.length; t++) {
var o = r[t];
o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o);
}
}
function _createClass(e, r, t) {
return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
writable: !1
}), e;
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == _typeof(i) ? i : i + "";
}
function _toPrimitive(t, r) {
if ("object" != _typeof(t) || !t) {
return t;
}
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != _typeof(i)) {
return i;
}
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
var cats = [];
var kittens = [];
var birds = [];
var ufos = [];
var sparkles = [];
// Game State Variables
var sparkleCount = 0;
var maxBirds = 10; // Maximum number of birds allowed on screen
var birdSpawnTimer = 0;
var birdSpawnInterval = 1.5; // Seconds between bird spawns
var treePosition = {
x: 0,
y: 0
}; // Center of the tree (set in Initialize Game)
// UI Elements
var sparkleCountText = null;
var addKittenButton = null;
// Add more UI elements for upgrades if needed
// Constants
var CAT_CHARM_RADIUS = 100;
var CAT_CHARM_COOLDOWN = 2.0; // seconds
var KITTEN_CHARM_RADIUS = 60;
var KITTEN_CHARM_COOLDOWN = 3.0; // seconds
var BIRD_SPEED = 50; // pixels per second
var UFO_SPEED = 150; // pixels per second
var SPARKLE_VALUE = 1;
var KITTEN_COST = 10;
// --- Asset IDs (Ensure these match the assets uploaded in the LK editor) ---
var CAT_ASSET_ID = 'cat_graphic';
var KITTEN_ASSET_ID = 'kitten_graphic';
var BIRD_ASSET_ID = 'bird_graphic';
var UFO_ASSET_ID = 'ufo_graphic';
var SPARKLE_ASSET_ID = 'sparkle_graphic';
// Optional tree graphic
// const TREE_ASSET_ID = 'tree_graphic';
// --- Utility Functions ---
function distance(x1, y1, x2, y2) {
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}
// --- Game Object Classes --- (Guideline 2)
/**
* Base class for charming entities (Cats and Kittens)
*/
var Charmer = /*#__PURE__*/function () {
function Charmer(assetId, x, y, charmRadius, charmCooldown) {
_classCallCheck(this, Charmer);
// Asset Retrieval & Positioning (Guideline 3, 13)
this.sprite = LK.getAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
this.sprite.x = x;
this.sprite.y = y;
LK.add(this.sprite);
this.charmRadius = charmRadius;
this.charmCooldownTime = charmCooldown;
this.charmTimer = 0; // Ready to charm immediately
this.isCharmer = true; // Property to identify charmers
}
// Define interaction range (Plan 2)
return _createClass(Charmer, [{
key: "getCharmRadius",
value: function getCharmRadius() {
return this.charmRadius;
}
// Manage charm timing (Plan 2)
}, {
key: "handleCharmCooldown",
value: function handleCharmCooldown(deltaTime) {
if (this.charmTimer > 0) {
this.charmTimer -= deltaTime;
}
}
// Check nearby birds and attempt to charm them (Plan 2)
}, {
key: "tryCharmBird",
value: function tryCharmBird() {
if (this.charmTimer > 0) {
return false; // Still on cooldown
}
for (var i = birds.length - 1; i >= 0; i--) {
var bird = birds[i];
if (!bird.isCharmed) {
var dist = distance(this.sprite.x, this.sprite.y, bird.sprite.x, bird.sprite.y);
if (dist <= this.getCharmRadius()) {
bird.handleCharmed(); // Bird handles its state change and reward (sparkle)
this.charmTimer = this.charmCooldownTime; // Reset cooldown
// Optionally add visual feedback here (e.g., particle effect if available)
return true; // Charmed a bird
}
}
}
return false; // No bird charmed
}
}, {
key: "update",
value: function update(deltaTime) {
this.handleCharmCooldown(deltaTime);
this.tryCharmBird(); // Attempt to charm every frame if cooldown is ready
}
}, {
key: "destroy",
value: function destroy() {
LK.remove(this.sprite);
}
}]);
}();
/**
* Cat Class
*/
var Cat = /*#__PURE__*/function (_Charmer) {
function Cat(x, y) {
_classCallCheck(this, Cat);
return _callSuper(this, Cat, [CAT_ASSET_ID, x, y, CAT_CHARM_RADIUS, CAT_CHARM_COOLDOWN]); // Cat-specific properties can be added here
}
// Cat-specific methods can be added here
_inherits(Cat, _Charmer);
return _createClass(Cat);
}(Charmer);
/**
* Kitten Class
*/
var Kitten = /*#__PURE__*/function (_Charmer2) {
function Kitten(x, y) {
_classCallCheck(this, Kitten);
return _callSuper(this, Kitten, [KITTEN_ASSET_ID, x, y, KITTEN_CHARM_RADIUS, KITTEN_CHARM_COOLDOWN]); // Kitten-specific properties can be added here
}
// Kitten-specific methods can be added here
_inherits(Kitten, _Charmer2);
return _createClass(Kitten);
}(Charmer);
/**
* Bird Class
*/
var Bird = /*#__PURE__*/function () {
function Bird() {
_classCallCheck(this, Bird);
// Asset Retrieval (Guideline 3)
this.sprite = LK.getAsset(BIRD_ASSET_ID, {
anchorX: 0.5,
anchorY: 0.5
});
this.setRandomPosition(); // Set starting position and target (Plan 2)
LK.add(this.sprite);
this.speed = BIRD_SPEED + (Math.random() * 20 - 10); // Add slight speed variation
this.isCharmed = false;
this.targetX = treePosition.x;
this.targetY = treePosition.y;
this.toBeRemoved = false;
}
// Set starting position and target (Plan 2)
return _createClass(Bird, [{
key: "setRandomPosition",
value: function setRandomPosition() {
var side = Math.floor(Math.random() * 4);
var edgeBuffer = 50; // Spawn slightly off-screen
switch (side) {
case 0:
// Top
this.sprite.x = Math.random() * LK.canvas.width;
this.sprite.y = -edgeBuffer;
break;
case 1:
// Right
this.sprite.x = LK.canvas.width + edgeBuffer;
this.sprite.y = Math.random() * LK.canvas.height;
break;
case 2:
// Bottom
this.sprite.x = Math.random() * LK.canvas.width;
this.sprite.y = LK.canvas.height + edgeBuffer;
break;
case 3:
// Left
this.sprite.x = -edgeBuffer;
this.sprite.y = Math.random() * LK.canvas.height;
break;
}
}
// Handle movement towards tree (Plan 2)
}, {
key: "update",
value: function update(deltaTime) {
if (this.isCharmed || this.toBeRemoved) {
// Potentially add a "falling" or "poof" animation here if possible
// For now, charmed birds are handled instantly
return;
}
var dx = this.targetX - this.sprite.x;
var dy = this.targetY - this.sprite.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 5) {
// Reached the tree (or close enough)
this.toBeRemoved = true; // Mark for removal without reward
} else {
var moveX = dx / dist * this.speed * deltaTime;
var moveY = dy / dist * this.speed * deltaTime;
this.sprite.x += moveX;
this.sprite.y += moveY;
// Flip sprite based on direction
this.sprite.scale.x = dx > 0 ? 1 : -1;
}
}
// Manage charmed state and rewards (Plan 2)
}, {
key: "handleCharmed",
value: function handleCharmed() {
if (this.isCharmed) {
return;
} // Already charmed
this.isCharmed = true;
// Trigger sparkle generation (Plan 1)
Game.Instance.createSparkle(this.sprite.x, this.sprite.y, SPARKLE_VALUE);
this.toBeRemoved = true; // Mark for removal after being charmed
}
}, {
key: "destroy",
value: function destroy() {
LK.remove(this.sprite);
}
}]);
}();
/**
* UFO Class
*/
var UFO = /*#__PURE__*/function () {
function UFO(x, y) {
_classCallCheck(this, UFO);
// Asset Retrieval (Guideline 3, 13)
this.sprite = LK.getAsset(UFO_ASSET_ID, {
anchorX: 0.5,
anchorY: 0.5
});
this.sprite.x = x;
this.sprite.y = y;
LK.add(this.sprite);
this.speed = UFO_SPEED;
this.targetSparkle = null;
this.isCollecting = false; // State flag
}
// Locate closest collectible sparkle (Plan 2)
return _createClass(UFO, [{
key: "findNearestSparkle",
value: function findNearestSparkle() {
var closestDist = Infinity;
var nearest = null;
for (var _i = 0, _sparkles = sparkles; _i < _sparkles.length; _i++) {
var sparkle = _sparkles[_i];
if (!sparkle.isBeingCollected && !sparkle.isCollected) {
var dist = distance(this.sprite.x, this.sprite.y, sparkle.sprite.x, sparkle.sprite.y);
if (dist < closestDist) {
closestDist = dist;
nearest = sparkle;
}
}
}
if (nearest) {
this.targetSparkle = nearest;
this.targetSparkle.isBeingCollected = true; // Mark sparkle so other UFOs ignore it
this.isCollecting = true;
} else {
this.targetSparkle = null;
this.isCollecting = false;
}
}
// Navigate to target sparkle (Plan 2)
}, {
key: "moveToSparkle",
value: function moveToSparkle(deltaTime) {
if (!this.targetSparkle || this.targetSparkle.isCollected) {
this.isCollecting = false;
this.targetSparkle = null;
return;
}
var targetX = this.targetSparkle.sprite.x;
var targetY = this.targetSparkle.sprite.y;
var dx = targetX - this.sprite.x;
var dy = targetY - this.sprite.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 10) {
// Close enough to collect
this.collectSparkle();
} else {
var moveX = dx / dist * this.speed * deltaTime;
var moveY = dy / dist * this.speed * deltaTime;
this.sprite.x += moveX;
this.sprite.y += moveY;
// Optional: Point UFO towards sparkle
// this.sprite.rotation = Math.atan2(dy, dx);
}
}
// Handle collection and rewards (Plan 2)
}, {
key: "collectSparkle",
value: function collectSparkle() {
if (this.targetSparkle && !this.targetSparkle.isCollected) {
var value = this.targetSparkle.handleCollection(); // Sparkle handles its removal
Game.Instance.addSparkles(value); // Add to global count via Game method
this.targetSparkle = null;
this.isCollecting = false;
// Optionally add visual feedback for collection
}
}
}, {
key: "update",
value: function update(deltaTime) {
if (!this.isCollecting) {
this.findNearestSparkle(); // Look for a new target if not currently collecting
}
if (this.targetSparkle) {
this.moveToSparkle(deltaTime); // Move towards target if one exists
} else {
// Optional: Add idle behavior (e.g., slow drift or patrol)
// this.sprite.x += Math.sin(LK.Time.now * 0.5) * 0.5 * deltaTime * 60;
}
}
}, {
key: "destroy",
value: function destroy() {
LK.remove(this.sprite);
}
}]);
}();
/**
* Sparkle Class
*/
var Sparkle = /*#__PURE__*/function () {
function Sparkle(x, y, value) {
_classCallCheck(this, Sparkle);
// Asset Retrieval (Guideline 3, 13)
this.sprite = LK.getAsset(SPARKLE_ASSET_ID, {
anchorX: 0.5,
anchorY: 0.5
});
this.sprite.x = x;
this.sprite.y = y;
LK.add(this.sprite);
this.value = value;
this.isCollected = false;
this.isBeingCollected = false; // Flag to prevent multiple UFOs targeting same sparkle
this.lifeTimer = 0; // Used for animation
this.floatAmplitude = 3;
this.floatSpeed = 2;
}
// Handle floating animation (Plan 2)
return _createClass(Sparkle, [{
key: "update",
value: function update(deltaTime) {
if (this.isCollected) {
return;
}
this.lifeTimer += deltaTime;
// Simple vertical float
this.sprite.y += Math.sin(this.lifeTimer * this.floatSpeed) * this.floatAmplitude * deltaTime;
// Optional: Add slight drift, fade-out over time, etc.
}
// Manage collection state (Plan 2)
}, {
key: "handleCollection",
value: function handleCollection() {
if (this.isCollected) {
return 0;
} // Already collected
this.isCollected = true;
// Mark for removal in the main game loop
this.destroy(); // Remove sprite immediately
return this.value;
}
}, {
key: "destroy",
value: function destroy() {
LK.remove(this.sprite);
}
}]);
}(); // --- Game Class ---
var Game = /*#__PURE__*/function () {
function Game() {
_classCallCheck(this, Game);
Game.Instance = this; // Set static instance
// Game initialization logic
}
/**
* Initialize Game
* Called once when the game starts or resets.
* Only set background color here directly. (Guideline 7)
* Initialize global state, arrays, and create initial objects.
*/
return _createClass(Game, [{
key: 'Initialize Game',
value: function Initialize_Game() {
console.log("Initializing Cosmic Cat Tree Game...");
LK.backgroundColor = 0x1a1a2e; // Dark space blue
// Reset Global State
sparkleCount = 0;
birdSpawnTimer = 0;
treePosition = {
x: LK.canvas.width / 2,
y: LK.canvas.height / 2
};
// Create placeholder asset for the tree trunk after canvas dimensions are available
createPlaceholderAsset(TREE_ASSET_ID, 0x8b4513, 5, LK.canvas.height * 0.6); // Brown Tree Trunk (adjust height as needed)
// Clear existing objects from previous sessions (if any) - Belt and suspenders
this.clearAllObjects();
// Initialize Arrays
cats = [];
kittens = [];
birds = [];
ufos = [];
sparkles = [];
// --- Create Initial Game Objects ---
// Optional: Add a visual representation for the tree
// try {
// const treeSprite = LK.getAsset(TREE_ASSET_ID, 'The Cat Tree', 0.5, 1.0); // Anchor bottom-center
// treeSprite.x = treePosition.x;
// treeSprite.y = LK.canvas.height; // Place at bottom center
// LK.add(treeSprite);
// // Note: Tree isn't added to an array as it's static background element
// } catch (e) {
// console.warn("Tree asset not found or failed to load:", e);
// }
// Create the initial Cat (adjust position as needed)
var initialCat = new Cat(treePosition.x, treePosition.y);
cats.push(initialCat);
// Create the initial UFO
var initialUFO = new UFO(treePosition.x, treePosition.y - 150); // Start near the tree
ufos.push(initialUFO);
// --- Initialize UI ---
this.setupUI();
console.log("Game Initialized");
console.log("Canvas dimensions:", LK.canvas.width, LK.canvas.height);
console.log("Tree Position:", treePosition.x, treePosition.y);
}
/**
* Setup UI Elements
* Creates text displays and buttons.
*/
}, {
key: "setupUI",
value: function setupUI() {
// Sparkle Counter Display
sparkleCountText = LK.CreateText({
text: "Sparkles: ".concat(sparkleCount),
x: 10,
y: 10,
style: {
fill: 0xFFFFFF,
fontSize: 20
},
anchor: {
x: 0,
y: 0
} // Anchor top-left
});
LK.add(sparkleCountText);
// --- Purchase Button Example --- (Plan 3: handlePurchases)
addKittenButton = LK.CreateButton({
text: "Add Kitten (".concat(KITTEN_COST, ")"),
x: LK.canvas.width - 10,
y: 10,
width: 150,
height: 40,
backgroundColor: 0x33aa33,
textColor: 0xffffff,
pointerup: this.handlePurchaseKitten,
// Reference the handler method
scope: this,
// Ensure 'this' inside the handler refers to the Game instance
anchor: {
x: 1,
y: 0
} // Anchor top-right
});
LK.add(addKittenButton);
}
// Manage resource spending (Plan 3)
// Event handler for the Add Kitten button (Guideline 8)
}, {
key: "handlePurchaseKitten",
value: function handlePurchaseKitten(obj) {
// 'this' refers to the Game instance because scope was set
// 'obj' contains event data if needed, but not used here
console.log("Attempting to purchase kitten...");
if (sparkleCount >= KITTEN_COST) {
sparkleCount -= KITTEN_COST;
this.updateUI(); // Update display immediately
// Add a new kitten at a randomish position near the tree
var angle = Math.random() * Math.PI * 2;
var radius = 50 + Math.random() * 50; // Place 50-100 pixels from center
var kx = treePosition.x + Math.cos(angle) * radius;
var ky = treePosition.y + Math.sin(angle) * radius;
var newKitten = new Kitten(kx, ky);
kittens.push(newKitten);
console.log("Kitten purchased!");
} else {
console.log("Not enough sparkles to purchase kitten.");
// Optional: Add feedback like button changing color briefly
}
}
/**
* Update Game
* Called every frame by the LK engine.
* @param {number} deltaTime - Time elapsed since the last frame in seconds.
*/
}, {
key: 'Update Game',
value: function Update_Game(deltaTime) {
// --- Update Game Logic ---
// 1. Spawn Birds (Plan 3)
this.spawnBirds(deltaTime);
// 2. Update Cats & Kittens
for (var _i2 = 0, _cats = cats; _i2 < _cats.length; _i2++) {
var cat = _cats[_i2];
cat.update(deltaTime);
}
for (var _i3 = 0, _kittens = kittens; _i3 < _kittens.length; _i3++) {
var kitten = _kittens[_i3];
kitten.update(deltaTime);
}
// 3. Update Birds (and handle removal)
for (var i = birds.length - 1; i >= 0; i--) {
var bird = birds[i];
bird.update(deltaTime);
if (bird.toBeRemoved) {
bird.destroy();
birds.splice(i, 1);
}
}
// 4. Update UFOs
for (var _i4 = 0, _ufos = ufos; _i4 < _ufos.length; _i4++) {
var ufo = _ufos[_i4];
ufo.update(deltaTime);
}
// 5. Update Sparkles (and handle removal) (Plan 3: updateSparkles)
// Although individual sparkles update, we check for collected ones here
for (var i = sparkles.length - 1; i >= 0; i--) {
var sparkle = sparkles[i];
if (sparkle.isCollected) {
// Sparkle.destroy() already called LK.remove
sparkles.splice(i, 1);
} else {
sparkle.update(deltaTime); // Handle animation
}
}
// 6. Update UI (Plan 3) - Done periodically or when values change
// This is called frequently, consider optimizing if performance issues arise
// this.updateUI(); // Called when sparkleCount changes instead for efficiency
}
/**
* Cleans up all game objects. Called before Initialize Game on reset.
*/
}, {
key: "clearAllObjects",
value: function clearAllObjects() {
console.log("Clearing objects...");
[].concat(_toConsumableArray(cats), _toConsumableArray(kittens), _toConsumableArray(birds), _toConsumableArray(ufos), _toConsumableArray(sparkles)).forEach(function (obj) {
return obj.destroy();
});
cats = [];
kittens = [];
birds = [];
ufos = [];
sparkles = [];
// Remove UI elements explicitly if they exist
if (sparkleCountText) {
LK.remove(sparkleCountText);
}
if (addKittenButton) {
LK.remove(addKittenButton);
}
sparkleCountText = null;
addKittenButton = null;
console.log("Objects cleared.");
}
// --- Game Class Helper Methods ---
// Manage bird population (Plan 3)
}, {
key: "spawnBirds",
value: function spawnBirds(deltaTime) {
birdSpawnTimer += deltaTime;
if (birdSpawnTimer >= birdSpawnInterval && birds.length < maxBirds) {
birdSpawnTimer = 0; // Reset timer
var newBird = new Bird();
birds.push(newBird);
}
}
// Generate new sparkles (Plan 3) - Called by Bird.handleCharmed
}, {
key: "createSparkle",
value: function createSparkle(x, y, value) {
var newSparkle = new Sparkle(x, y, value);
sparkles.push(newSparkle);
}
// Method to add sparkles to the global count (called by UFO)
}, {
key: "addSparkles",
value: function addSparkles(amount) {
sparkleCount += amount;
this.updateUI(); // Update UI when count changes
}
// Keep display current (Plan 3)
}, {
key: "updateUI",
value: function updateUI() {
if (sparkleCountText) {
sparkleCountText.text = "Sparkles: ".concat(sparkleCount);
}
if (addKittenButton) {
// Update button text/state if needed (e.g., disable if too poor)
addKittenButton.setText("Add Kitten (".concat(KITTEN_COST, ")"));
addKittenButton.button.disabled = sparkleCount < KITTEN_COST; // Example of disabling
addKittenButton.button.backgroundColor = sparkleCount < KITTEN_COST ? 0x888888 : 0x33aa33;
}
// Update other UI elements as needed
}
/**
* Draw Foreground
* Called after Update Game. Used for drawing elements on top of sprites.
* Not typically used if UI elements cover needs.
*/
// 'Draw Foreground'() {
// }
/**
* Draw Background
* Called before Update Game. Used for background elements.
* Avoid adding backgrounds unless specifically requested (Guideline 4).
*/
// 'Draw Background'() {
// }
}]);
}(); // Attach the Game class to the global LK context
// Static instance holder
_defineProperty(Game, "Instance", null);
LK.Game = Game;
// --- Asset Definitions ---
// IMPORTANT: Make sure these IDs match the assets uploaded in the LK Editor
// and the constants defined at the top of the file. (Guideline 4)
// Example Asset Definitions (Replace with actual asset details)
// LK.Assets['assets/cat.png'] = { id: CAT_ASSET_ID, frameWidth: 64, frameHeight: 64, frameTags: {} };
// LK.Assets['assets/kitten.png'] = { id: KITTEN_ASSET_ID, frameWidth: 48, frameHeight: 48, frameTags: {} };
// LK.Assets['assets/bird.png'] = { id: BIRD_ASSET_ID, frameWidth: 32, frameHeight: 32, frameTags: {} };
// LK.Assets['assets/ufo.png'] = { id: UFO_ASSET_ID, frameWidth: 80, frameHeight: 40, frameTags: {} };
// LK.Assets['assets/sparkle.png'] = { id: SPARKLE_ASSET_ID, frameWidth: 16, frameHeight: 16, frameTags: {} };
// LK.Assets['assets/tree.png'] = { id: TREE_ASSET_ID, frameWidth: 200, frameHeight: 400, frameTags: {} };
// Placeholder assets if actual graphics aren't available - REMOVE IF USING REAL ASSETS
// Using simple squares as placeholders if real assets aren't loaded
function createPlaceholderAsset(id, color, width, height) {
if (!LK.Assets[id]) {
// Only create if not already defined (e.g., by uploaded assets)
var shape;
var shape;
var tex = LK.getAsset(id, {
width: width,
height: height,
color: color,
shape: 'box'
}); // Generate texture for LK
LK.Assets[id] = {
id: id,
texture: tex,
frameWidth: width,
frameHeight: height,
frameTags: {}
};
console.log("Created placeholder asset for ".concat(id));
}
}
createPlaceholderAsset(CAT_ASSET_ID, 0xffccaa, 50, 50); // Beige Cat
createPlaceholderAsset(KITTEN_ASSET_ID, 0xffebcc, 35, 35); // Lighter Beige Kitten
createPlaceholderAsset(BIRD_ASSET_ID, 0xadd8e6, 25, 20); // Light Blue Bird
createPlaceholderAsset(UFO_ASSET_ID, 0xcccccc, 60, 30); // Grey UFO
createPlaceholderAsset(SPARKLE_ASSET_ID, 0xffff00, 10, 10); // Yellow Sparkle
createPlaceholderAsset(TREE_ASSET_ID, 0x8b4513, 5, 300); // Brown Tree Trunk (simple line)
createPlaceholderAsset(SPARKLE_ASSET_ID, 0xffff00, 10, 10); // Yellow Sparkle
createPlaceholderAsset(TREE_ASSET_ID, 0x8b4513, 5, LK.canvas.height * 0.6); // Brown Tree Trunk (adjust height as needed);
an orange and white cat facing away from the camera. the cat is sitting straight up and looking up, ready to pounce. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
remove black box
fluffy translucent cloud. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
bright sun with wincing cartoon face and a black eye. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
a goofy ufo. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
red gaming reticle. Minimal. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
sunny day, hilly landscape. there is an alien invasion taking place in the distance. cities burning.
large AUTUMN SHADES tree with sparse bunches of leaves. branches are exposed, but the tree is tough and old.. true-color, realistic, Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
glowing orange sphere. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
sideway view of a fighter jet. . . In-Game 2d asset. transparent background. horizontal. No shadows.
shiny purple and black attack ufo.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows