User prompt
Create a rhythm-based game experience using the following audio assets with synchronized timing: bgtrack: Simple Happy Life – this is the main background music that defines the rhythm, tempo, and beat structure. hit (greenOrb): Phonk Chime Bell – this sound is soft and percussive. It should play exactly on-beat with the background track whenever the player hits a green orb. hitr (redOrb): Wind Chime from Sample Focus – this should sound clean and magical, triggered precisely when the player hits a red orb. It must also align on the beat of the bgtrack to feel musical. 🎵 Requirements: Synchronize the spawning of red and green orbs based on the beat timing of the bgtrack, using BPM-based intervals (e.g. 60000 / BPM = spawn interval). Both hit and hitr should play exactly on beat, triggered by the player’s action. Never allow sounds to play slightly off the rhythm. Increase BPM and orb falling speed based on combo count (e.g., every 10 combo = +5 BPM). Update both spawning logic and movement accordingly to stay in sync with the music. Use beat subdivisions like quarter or eighth notes to space out orb spawns, ensuring they do not overlap unnaturally. Ensure the different hit sounds (bell and wind chime) feel like natural extensions of the bgtrack and do not clash with its melody. Make sure all audio loops seamlessly, even as the BPM dynamically changes. 🎯 Final goal: Achieve a harmonic, beat-matched gameplay where every orb, sound, and combo effect feels like part of the song. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Use two different sound effects for orb hits: - Use 'hit' when hitting a greenOrb. - Use 'hitr' when hitting a redOrb. In the handleOrbHit() and autoHitOrbWithClone() functions, replace LK.getSound('hit').play() with a conditional that plays 'hit' for greenOrb and 'hitr' for redOrb.
User prompt
Make orbs spawn in sync with the background music's BPM (beats per minute). For example, at 120 BPM, spawn a new orb every 500ms. Ensure the spawn timing matches the beat rhythm to give players a strong sense of music synchronization. Adjust spawnInterval dynamically based on BPM.
User prompt
Add a mechanic where the speed of all falling orbs (red, green, black) increases gradually based on the player's combo count. For every 10 combo streak, increase orb fall speed slightly to make the game more challenging. This should dynamically update during gameplay and reset back to base speed when the combo breaks.
Code edit (2 edits merged)
Please save this source code
User prompt
swordmasterın yetenek aktiflik süresini 2 sn ye düşür ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
swordmasterın yeteneğinin aktiflik süresini 4 sn ye çıkar
Code edit (1 edits merged)
Please save this source code
User prompt
Update the ability of the character "swordmaster" so that when his ability is used, he spawns a temporary clone inside the targetZone. The clone should be controlled by basic AI logic: - It should automatically move toward the nearest redOrb or greenOrb within the targetZone. - It should avoid blackBomb orbs entirely (do not target or move toward them). - It should not move outside the boundaries of the targetZone. - The clone should move at a speed of 8 and only exist for 1 second. - While the clone is active, every 100ms it should check for a redOrb or greenOrb in range (distance < 100) and auto-hit it. - If it hits an orb, play the "hit" sound, increase the score, and animate it fading out. - After 1 second, the clone should fade out and be destroyed. Add the clone movement behavior using AI and integrate it into the main game update loop. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Create a rhythm game where: The player drags the selected character (ninja, wizard, or swordmaster) inside a fixed target zone. The goal is to touch and destroy red and green orbs using the character. If the player misses 5 red/green orbs (they fall past the zone), the game ends. If the player touches 5 black orbs, the game also ends. Ninja Ability: When the player taps on the ninja character, it activates a 3-second phase mode: During this time, the ninja can pass through black orbs without penalty. Show a visual effect (e.g. glow) while active. After 3 seconds, the ability ends. Add variables: missedCount → increases when red/green orb falls. blackTouchCount → increases when touching black orb. Call gameOver() when either reaches 5. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
I am building a rhythm-based mobile game using Upit Engine. I want to implement a new control mechanic where the player character (ninja, wizard, or swordmaster) can be dragged around inside the targetZone and used to destroy orbs by touching them. Please implement or fix the following mechanics: 🔹 1. Character Movement (Drag & Drop): The player should be able to tap and drag the selected character only within the targetZone area. The character follows the finger as long as it remains in the zone. Movement should feel smooth and responsive. 🔹 2. Orb Collision and Hit Logic: When the character sprite touches a red or green orb, that orb is destroyed and the score increases based on combo logic. If the character touches a black orb, nothing happens on the first hit — but on the second hit (same orb or another black one), the game ends (game over). 🔹 3. Ability Activation Logic: To use a character’s ability, the player must release the drag and directly tap the character itself (i.e. no dragging). This triggers the character’s special ability (freeze, auto combo, clone, etc.). 🔹 4. Target Zone Visual & Mechanics: The targetZone should be a visually clear area at the bottom (alpha ~0.5 or visible color like dark blue). Character dragging and orb collision can only happen inside this zone. Notes: The rest of the rhythm logic (orb spawning from top, combo tracking, music syncing) is already implemented. Clone ability of swordmaster should continue to auto-destroy orbs while the original character is being dragged. Please provide a revised code implementation for these mechanics. Thank you! ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
I'm working on a mobile rhythm game made with JavaScript and Upit Engine. The game has red, green, and black orbs that fall vertically from the top. At the bottom of the screen, there’s a targetZone where players must tap the orbs to score. There’s also a character (ninja, wizard, or swordmaster) with a special ability. Please help fix and improve the following issues in my current code: Orbs are not clickable in the target zone. 👉 Fix: Orbs should only be tappable when they are within the targetZone rectangle. Make sure the click detection is constrained to that area (X and Y bounds). Character ability is triggering when tapping the target zone. 👉 Fix: Ability should only activate when tapping directly on the character sprite, not when tapping the targetZone or screen. Swordmaster’s clone ability is not working. 👉 Fix: The clone spawns correctly, but it does not auto-hit orbs. Make the clone auto-hit the nearest orb inside the targetZone every 100ms for 1 second. TargetZone visibility is too low. 👉 Fix: Increase the visibility (e.g., set alpha to 0.5) and optionally give it a clearer color like dark blue for better UX. Additional Notes: Orbs fall straight down (this part is already correct). The game runs at ~60 FPS. The code is written in Upit’s framework with Container, LK.init.shape, and LK.getAsset. Please fix these problems and give me a corrected code block that I can directly paste into Upit Studio. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please update the game logic for a more intuitive tap-timing rhythm style: 1. Modify the orb movement: - All orbs should fall straight down from top to bottom (no target-based vector movement). - Remove all references to orb.targetX and orb.targetY. - Instead, orbs just increase their y position by `orb.speed` each frame. 2. Modify the target zone: - Make the targetZone much taller (e.g., height: 300) and stretch it across the full bottom of the screen. - Place the targetZone at the bottom of the screen (e.g., y: 2300 or 2400 depending on canvas size). 3. Modify the hit detection: - Players can only successfully hit orbs if they are within the targetZone bounds. - Tapping anywhere outside the zone does nothing. - Taps must be on orbs that are inside the vertical range of the targetZone (collision check). 4. Update swordmaster's clone AI: - The clone should only auto-hit orbs when they are inside the targetZone. - The clone should behave like a player: look for orbs inside the zone and auto-hit one every 100ms. 5. Bonus: Make orb speed slightly slower (e.g., speed: 4). This turns the game into a clearer rhythm-timing challenge like Friday Night Funkin' or Piano Tiles. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
In this Upit rhythm game code, please change the swordmaster character's ability. Instead of "dual strike", make it so that when the swordmaster uses their ability, it spawns a temporary clone of themselves. This clone should appear next to the original swordmaster, automatically hit orbs for 1 second (as if it perfectly taps the correct ones), and then disappear. The clone should visually look like the swordmaster and help the player for 1 second. Update only the related parts (the ability and orb interaction logic), and do not affect other characters. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
In this Upit game code, the character selection screen shows the characters (ninja, wizard, swordmaster), but tapping on them doesn’t trigger the selection function. Please fix the input detection so that tapping on the characters correctly selects them using selectCharacter(type) as intended. Do not change unrelated parts of the game.
User prompt
Redesign the gameplay to be more like Beat Saber. - Orbs should move toward the player from the top (not lanes) - Spawning should match BPM of the background music - Tapping or swiping should break orbs (use color to determine side or action) - Add simple feedback effects like screen shake or color flash - Allow player to use abilities like time-slow or auto-hit You can refactor the orb system and remove lane dependency if needed. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Scene 1 – Character Selection Screen: The player starts in a mystical dojo-like space with soft ambient music playing. On screen are 3 animated character avatars. Player must tap on one to begin the rhythm game. Character Options (Selectable): 🔹 Blue Mage • Appearance: Tall figure wearing a glowing blue robe, wide wizard hat, and holding a crystal staff. Mystical blue eyes, long white beard. • Animation: Calm idle floating motion, magic particles flowing around • Ability: Can cast “Ice Freeze” every 10 seconds to slow down incoming beat orbs for 3 seconds • Difficulty: Medium • Tagline: “Slow the rhythm, control the chaos.” 🔴 Dual Blade Swordmaster • Appearance: White torn martial arts outfit, red belt, bandaged arms, wild hair, two glowing swords • Animation: Breathing heavily, does quick sword swings while idle • Ability: Can slash both left and right lanes at the same time (multi-touch bonus), 2x combo window • Difficulty: Hard • Tagline: “Two blades. One rhythm.” ⚫ Shadow Ninja • Appearance: Full black suit, masked face, glowing dagger in hand, red eyes • Animation: Quick shadow dashes, fades in/out • Ability: Increased tap/slash speed; auto-slice chain combo when timing is perfect • Difficulty: Easy to pick, hard to master • Tagline: “Strike with silence. Dance with speed.” Gameplay Transition: Once the player selects a character, fade-in transition with music rising leads into rhythm gameplay arena (Scene 2). The player’s class ability is activated and UI adapts accordingly.
User prompt
Scene 1 – Character Selection Screen: The player starts in a mystical dojo-like space with soft ambient music playing. On screen are 3 animated character avatars. Player must tap on one to begin the rhythm game. Character Options (Selectable): 🔹 Blue Mage • Appearance: Tall figure wearing a glowing blue robe, wide wizard hat, and holding a crystal staff. Mystical blue eyes, long white beard. • Animation: Calm idle floating motion, magic particles flowing around • Ability: Can cast “Ice Freeze” every 10 seconds to slow down incoming beat orbs for 3 seconds • Difficulty: Medium • Tagline: “Slow the rhythm, control the chaos.” 🔴 Dual Blade Swordmaster • Appearance: White torn martial arts outfit, red belt, bandaged arms, wild hair, two glowing swords • Animation: Breathing heavily, does quick sword swings while idle • Ability: Can slash both left and right lanes at the same time (multi-touch bonus), 2x combo window • Difficulty: Hard • Tagline: “Two blades. One rhythm.” ⚫ Shadow Ninja • Appearance: Full black suit, masked face, glowing dagger in hand, red eyes • Animation: Quick shadow dashes, fades in/out • Ability: Increased tap/slash speed; auto-slice chain combo when timing is perfect • Difficulty: Easy to pick, hard to master • Tagline: “Strike with silence. Dance with speed.” Gameplay Transition: Once the player selects a character, fade-in transition with music rising leads into rhythm gameplay arena (Scene 2). The player’s class ability is activated and UI adapts accordingly. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Scene 1 – Character Selection Screen: The player starts in a mystical dojo-like space with soft ambient music playing. On screen are 3 animated character avatars. Player must tap on one to begin the rhythm game. Character Options (Selectable): 🔹 Blue Mage • Appearance: Tall figure wearing a glowing blue robe, wide wizard hat, and holding a crystal staff. Mystical blue eyes, long white beard. • Animation: Calm idle floating motion, magic particles flowing around • Ability: Can cast “Ice Freeze” every 10 seconds to slow down incoming beat orbs for 3 seconds • Difficulty: Medium • Tagline: “Slow the rhythm, control the chaos.” 🔴 Dual Blade Swordmaster • Appearance: White torn martial arts outfit, red belt, bandaged arms, wild hair, two glowing swords • Animation: Breathing heavily, does quick sword swings while idle • Ability: Can slash both left and right lanes at the same time (multi-touch bonus), 2x combo window • Difficulty: Hard • Tagline: “Two blades. One rhythm.” ⚫ Shadow Ninja • Appearance: Full black suit, masked face, glowing dagger in hand, red eyes • Animation: Quick shadow dashes, fades in/out • Ability: Increased tap/slash speed; auto-slice chain combo when timing is perfect • Difficulty: Easy to pick, hard to master • Tagline: “Strike with silence. Dance with speed.” Gameplay Transition: Once the player selects a character, fade-in transition with music rising leads into rhythm gameplay arena (Scene 2). The player’s class ability is activated and UI adapts accordingly.
User prompt
Scene 1 – Character Selection Screen: The player starts in a mystical dojo-like space with soft ambient music playing. On screen are 3 animated character avatars. Player must tap on one to begin the rhythm game. Character Options (Selectable): 🔹 Blue Mage • Appearance: Tall figure wearing a glowing blue robe, wide wizard hat, and holding a crystal staff. Mystical blue eyes, long white beard. • Animation: Calm idle floating motion, magic particles flowing around • Ability: Can cast “Ice Freeze” every 10 seconds to slow down incoming beat orbs for 3 seconds • Difficulty: Medium • Tagline: “Slow the rhythm, control the chaos.” 🔴 Dual Blade Swordmaster • Appearance: White torn martial arts outfit, red belt, bandaged arms, wild hair, two glowing swords • Animation: Breathing heavily, does quick sword swings while idle • Ability: Can slash both left and right lanes at the same time (multi-touch bonus), 2x combo window • Difficulty: Hard • Tagline: “Two blades. One rhythm.” ⚫ Shadow Ninja • Appearance: Full black suit, masked face, glowing dagger in hand, red eyes • Animation: Quick shadow dashes, fades in/out • Ability: Increased tap/slash speed; auto-slice chain combo when timing is perfect • Difficulty: Easy to pick, hard to master • Tagline: “Strike with silence. Dance with speed.” Gameplay Transition: Once the player selects a character, fade-in transition with music rising leads into rhythm gameplay arena (Scene 2). The player’s class ability is activated and UI adapts accordingly. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Rhythm Warriors: Beat Battle Arena
Initial prompt
Game Type: Music rhythm-based action game with fantasy RPG elements Visual Style: 3D stylized / vibrant / slightly cartoonish Theme: Players choose one of 3 classes — Ninja, Wizard, or Swordmaster — and enter a rhythm battle arena where colorful beat orbs come toward the player in sync with popular music tracks. Mechanics: • Notes come at the player in 3 lanes, color-coded: • 🔴 Red = hit left side • 🟢 Green = hit right side • ⚫ Black = bomb — must be dodged or ignored (touch = instant fail) • Orbs move faster as music progresses • Player interacts by tapping or slashing based on character’s ability Classes & Abilities: • Ninja: Fast dashes, quicker tap/slash speed, special move: “Shadow Slice” (auto-hits a fast series of beats) • Wizard: Normal speed, casts freeze spell every 10 seconds to slow incoming beats for 3 seconds • Swordmaster: Dual-wielding – can tap both left and right lanes at once (multi-touch), higher combo multiplier Game Objective: • Survive the full duration of the song without hitting bombs • Score is based on accuracy, combo, and class skill use • Unlock skins and new songs after each win Popular Track Suggestions: • “Blinding Lights” by The Weeknd • “Levitating” by Dua Lipa • “Believer” by Imagine Dragons • “Bad Guy” by Billie Eilish Interface Notes: • Color-coded lanes with beatballs moving toward player • Touch screen input or FaceKit interaction (head tilt to dodge bombs?) • Energy bar depletes if notes missed • Flashy effects for class abilities, visual feedback on perfect/good/miss
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var BeatOrb = Container.expand(function (orbType, lane) { var self = Container.call(this); self.orbType = orbType; self.lane = lane; self.speed = 4; self.hit = false; var orbGraphics = self.attachAsset(orbType, { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { var speedMultiplier = 1; if (selectedCharacter && selectedCharacter.freezeActive) { speedMultiplier = 0.3; } self.y += self.speed * speedMultiplier; }; return self; }); var Character = Container.expand(function (characterType) { var self = Container.call(this); self.type = characterType; self.abilityReady = true; self.abilityCooldown = 0; self.freezeActive = false; self.freezeTime = 0; self.baseY = 0; self.floatOffset = 0; self.animSpeed = 0.05 + Math.random() * 0.03; var characterGraphics = self.attachAsset(characterType, { anchorX: 0.5, anchorY: 0.5 }); self.useAbility = function () { if (!self.abilityReady) return false; LK.getSound('ability').play(); if (self.type === 'ninja') { // Shadow Slice: Auto-hit next 3 orbs comboMode = 3; LK.effects.flashObject(self, 0x9932cc, 500); } else if (self.type === 'wizard') { // Time Freeze: Slow orbs for 3 seconds self.freezeActive = true; self.freezeTime = 3000; LK.effects.flashObject(self, 0x00ffff, 3000); } else if (self.type === 'swordmaster') { // Dual Strike: Next hit scores double dualStrikeActive = true; LK.effects.flashObject(self, 0xffd700, 1000); } self.abilityReady = false; self.abilityCooldown = 10000; // 10 second cooldown return true; }; self.update = function () { if (!self.abilityReady) { self.abilityCooldown -= 16; // ~60fps if (self.abilityCooldown <= 0) { self.abilityReady = true; } } if (self.freezeActive) { self.freezeTime -= 16; if (self.freezeTime <= 0) { self.freezeActive = false; } } // Floating animation for character selection if (gameState === 'classSelection') { self.floatOffset += self.animSpeed; self.y = self.baseY + Math.sin(self.floatOffset) * 20; // Add mystical particle effect for wizard if (self.type === 'wizard' && LK.ticks % 20 === 0) { LK.effects.flashObject(self, 0x4169e1, 400); } // Add shadow dash effect for ninja if (self.type === 'ninja' && LK.ticks % 30 === 0) { LK.effects.flashObject(self, 0x9932cc, 300); } // Add sword gleam for swordmaster if (self.type === 'swordmaster' && LK.ticks % 25 === 0) { LK.effects.flashObject(self, 0xffd700, 350); } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a2e }); /**** * Game Code ****/ // Game state var gameState = 'classSelection'; // 'classSelection', 'playing', 'gameOver' var selectedCharacter = null; var score = 0; var combo = 0; var maxCombo = 0; var lives = 3; var comboMode = 0; // Ninja ability counter var dualStrikeActive = false; // Swordmaster ability var songProgress = 0; var songDuration = 120000; // 2 minutes // Game objects var orbs = []; var lanes = []; var characters = {}; var targetZone = null; // UI elements var scoreText = null; var comboText = null; var livesText = null; var abilityText = null; var instructionText = null; var ninjaDescText = null; var wizardDescText = null; var swordmasterDescText = null; var titleText = null; // Lane positions var lanePositions = [2048 * 0.25, 2048 * 0.5, 2048 * 0.75]; var targetY = 2200; // Start ambient music for character selection LK.playMusic('ambient', { volume: 0.6 }); // Initialize lanes for (var i = 0; i < 3; i++) { var lane = game.addChild(LK.getAsset('lane', { anchorX: 0.5, anchorY: 0, x: lanePositions[i], y: 200 })); lanes.push(lane); } // Target zone targetZone = game.addChild(LK.getAsset('targetZone', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: targetY, alpha: 0.3 })); // Create character selection characters.ninja = game.addChild(new Character('ninja')); characters.ninja.x = 2048 * 0.25; characters.ninja.y = 1000; characters.ninja.baseY = 1000; characters.wizard = game.addChild(new Character('wizard')); characters.wizard.x = 2048 * 0.5; characters.wizard.y = 1000; characters.wizard.baseY = 1000; characters.swordmaster = game.addChild(new Character('swordmaster')); characters.swordmaster.x = 2048 * 0.75; characters.swordmaster.y = 1000; characters.swordmaster.baseY = 1000; // UI Setup scoreText = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); LK.gui.topLeft.addChild(scoreText); scoreText.x = 120; scoreText.y = 20; comboText = new Text2('Combo: 0', { size: 50, fill: 0xFFFF00 }); comboText.anchor.set(0.5, 0); LK.gui.top.addChild(comboText); comboText.y = 80; livesText = new Text2('Lives: 3', { size: 50, fill: 0xFF4444 }); livesText.anchor.set(1, 0); LK.gui.topRight.addChild(livesText); livesText.x = -20; livesText.y = 20; abilityText = new Text2('Ability Ready!', { size: 40, fill: 0x00FF00 }); abilityText.anchor.set(0.5, 1); LK.gui.bottom.addChild(abilityText); abilityText.y = -100; // Title text titleText = new Text2('RHYTHM WARRIORS\nBeat Battle Arena', { size: 80, fill: 0xFFD700 }); titleText.anchor.set(0.5, 0); LK.gui.top.addChild(titleText); titleText.y = 200; // Character descriptions ninjaDescText = new Text2('⚫ SHADOW NINJA\n"Strike with silence. Dance with speed."\nAbility: Shadow Slice auto-combo\nDifficulty: Easy to pick, hard to master', { size: 35, fill: 0x9932cc }); ninjaDescText.anchor.set(0.5, 0); game.addChild(ninjaDescText); ninjaDescText.x = 2048 * 0.25; ninjaDescText.y = 1200; wizardDescText = new Text2('🔵 BLUE MAGE\n"Slow the rhythm, control the chaos."\nAbility: Ice Freeze slows orbs\nDifficulty: Medium', { size: 35, fill: 0x4169e1 }); wizardDescText.anchor.set(0.5, 0); game.addChild(wizardDescText); wizardDescText.x = 2048 * 0.5; wizardDescText.y = 1200; swordmasterDescText = new Text2('⚔️ DUAL BLADE SWORDMASTER\n"Two blades. One rhythm."\nAbility: Multi-touch dual strike\nDifficulty: Hard', { size: 35, fill: 0x8b4513 }); swordmasterDescText.anchor.set(0.5, 0); game.addChild(swordmasterDescText); swordmasterDescText.x = 2048 * 0.75; swordmasterDescText.y = 1200; instructionText = new Text2('TAP A CHARACTER TO BEGIN', { size: 50, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 1); LK.gui.bottom.addChild(instructionText); instructionText.y = -50; // Input handling game.down = function (x, y, obj) { if (gameState === 'classSelection') { // Check character selection if (characters.ninja.intersects({ x: x, y: y, width: 1, height: 1 })) { selectCharacter('ninja'); } else if (characters.wizard.intersects({ x: x, y: y, width: 1, height: 1 })) { selectCharacter('wizard'); } else if (characters.swordmaster.intersects({ x: x, y: y, width: 1, height: 1 })) { selectCharacter('swordmaster'); } } else if (gameState === 'playing') { // Handle orb hits and abilities if (y > 2000) { // Ability zone if (selectedCharacter && selectedCharacter.abilityReady) { selectedCharacter.useAbility(); updateAbilityText(); } } else { // Determine which lane was tapped var tapLane = -1; if (x < 2048 * 0.375) tapLane = 0; // Left lane else if (x < 2048 * 0.625) tapLane = 1; // Middle lane else tapLane = 2; // Right lane handleOrbHit(tapLane, x < 2048 * 0.5 ? 'red' : 'green'); } } }; function selectCharacter(type) { selectedCharacter = characters[type]; gameState = 'playing'; // Hide character descriptions and selection UI titleText.visible = false; ninjaDescText.visible = false; wizardDescText.visible = false; swordmasterDescText.visible = false; instructionText.visible = false; // Hide unselected characters for (var charType in characters) { if (charType !== type) { characters[charType].visible = false; } } // Position selected character selectedCharacter.x = 2048 / 2; selectedCharacter.y = 2400; // Character-specific selection effects if (type === 'ninja') { LK.effects.flashScreen(0x9932cc, 800); } else if (type === 'wizard') { LK.effects.flashScreen(0x4169e1, 800); } else if (type === 'swordmaster') { LK.effects.flashScreen(0xffd700, 800); } // Start music and orb spawning LK.playMusic('bgtrack'); } function handleOrbHit(lane, expectedType) { var hitOrb = null; var bestDistance = Infinity; // Find closest orb in target zone for this lane for (var i = 0; i < orbs.length; i++) { var orb = orbs[i]; if (orb.lane === lane && !orb.hit) { var distance = Math.abs(orb.y - targetY); if (distance < 150 && distance < bestDistance) { hitOrb = orb; bestDistance = distance; } } } if (hitOrb) { if (hitOrb.orbType === 'blackBomb') { // Hit a bomb - lose life lives--; combo = 0; LK.getSound('bomb').play(); LK.effects.flashScreen(0xff0000, 300); hitOrb.hit = true; if (lives <= 0) { endGame(); return; } } else if (hitOrb.orbType === 'redOrb' && expectedType === 'red' || hitOrb.orbType === 'greenOrb' && expectedType === 'green' || comboMode > 0) { // Successful hit var points = 100; if (comboMode > 0) { comboMode--; points *= 2; // Ninja bonus } if (dualStrikeActive) { points *= 2; // Swordmaster bonus dualStrikeActive = false; } combo++; if (combo > maxCombo) maxCombo = combo; // Combo multiplier points *= Math.min(combo, 10); score += points; LK.getSound('hit').play(); LK.effects.flashObject(hitOrb, 0xffffff, 200); hitOrb.hit = true; } else { // Wrong color hit combo = 0; LK.getSound('miss').play(); } } else { // Missed - no orb in range combo = 0; LK.getSound('miss').play(); } updateUI(); } function spawnOrb() { var lane = Math.floor(Math.random() * 3); var orbTypes = ['redOrb', 'greenOrb', 'blackBomb']; var weights = [0.4, 0.4, 0.2]; // 40% red, 40% green, 20% bomb var rand = Math.random(); var orbType = 'redOrb'; if (rand < weights[0]) orbType = 'redOrb';else if (rand < weights[0] + weights[1]) orbType = 'greenOrb';else orbType = 'blackBomb'; var orb = new BeatOrb(orbType, lane); orb.x = lanePositions[lane]; orb.y = 100; orbs.push(orb); game.addChild(orb); } function updateUI() { scoreText.setText('Score: ' + score); comboText.setText('Combo: ' + combo); livesText.setText('Lives: ' + lives); LK.setScore(score); } function updateAbilityText() { if (!selectedCharacter) return; if (selectedCharacter.abilityReady) { abilityText.setText('Ability Ready!'); abilityText.tint = 0x00ff00; } else { var cooldownSeconds = Math.ceil(selectedCharacter.abilityCooldown / 1000); abilityText.setText('Ability: ' + cooldownSeconds + 's'); abilityText.tint = 0xff4444; } } function endGame() { gameState = 'gameOver'; // Save high score var highScore = storage.highScore || 0; if (score > highScore) { storage.highScore = score; } // Save stats storage.gamesPlayed = (storage.gamesPlayed || 0) + 1; if (maxCombo > (storage.maxCombo || 0)) { storage.maxCombo = maxCombo; } LK.showGameOver(); } function checkWinCondition() { if (songProgress >= songDuration) { // Survived the full song! var bonusScore = lives * 1000 + maxCombo * 100; score += bonusScore; LK.setScore(score); // Save completion storage.songsCompleted = (storage.songsCompleted || 0) + 1; LK.showYouWin(); } } // Main game update loop game.update = function () { if (gameState !== 'playing') return; songProgress += 16; // ~60fps // Update character abilities if (selectedCharacter) { selectedCharacter.update(); updateAbilityText(); } // Spawn orbs based on music tempo if (LK.ticks % 40 === 0) { // Spawn every ~0.67 seconds spawnOrb(); } // Update orbs for (var i = orbs.length - 1; i >= 0; i--) { var orb = orbs[i]; // Remove hit orbs after animation if (orb.hit) { orb.alpha -= 0.1; if (orb.alpha <= 0) { orb.destroy(); orbs.splice(i, 1); } continue; } // Check if orb passed target zone (miss) if (orb.y > targetY + 200) { if (orb.orbType !== 'blackBomb') { // Missed a good orb combo = 0; updateUI(); } orb.destroy(); orbs.splice(i, 1); continue; } // Check bomb collision with target zone if (orb.orbType === 'blackBomb' && orb.y >= targetY - 50 && orb.y <= targetY + 50) { // Bomb reached target zone without being avoided lives--; combo = 0; LK.getSound('bomb').play(); LK.effects.flashScreen(0xff0000, 300); orb.destroy(); orbs.splice(i, 1); if (lives <= 0) { endGame(); return; } updateUI(); } } // Check win condition checkWinCondition(); };
===================================================================
--- original.js
+++ change.js
@@ -32,8 +32,11 @@
self.abilityReady = true;
self.abilityCooldown = 0;
self.freezeActive = false;
self.freezeTime = 0;
+ self.baseY = 0;
+ self.floatOffset = 0;
+ self.animSpeed = 0.05 + Math.random() * 0.03;
var characterGraphics = self.attachAsset(characterType, {
anchorX: 0.5,
anchorY: 0.5
});
@@ -70,53 +73,24 @@
if (self.freezeTime <= 0) {
self.freezeActive = false;
}
}
- // Character selection animations
+ // Floating animation for character selection
if (gameState === 'classSelection') {
- if (self.type === 'wizard') {
- // Floating motion for wizard
- self.y += Math.sin(LK.ticks * 0.05) * 0.5;
- // Add mystical particles effect with tint cycling
- self.tint = 0x4169e1 + Math.floor(Math.sin(LK.ticks * 0.1) * 50) * 0x010101;
- } else if (self.type === 'ninja') {
- // Shadow dash effect - quick position shifts
- if (LK.ticks % 180 === 0) {
- tween(self, {
- alpha: 0.3
- }, {
- duration: 200,
- easing: tween.easeOut
- });
- tween(self, {
- alpha: 1.0
- }, {
- duration: 200,
- easing: tween.easeIn
- });
- }
- // Red eye glow effect
- self.tint = 0x4a4a4a + Math.floor(Math.sin(LK.ticks * 0.15) * 100) * 0x010000;
- } else if (self.type === 'swordmaster') {
- // Breathing and sword swing motions
- self.scaleX = 1.5 + Math.sin(LK.ticks * 0.08) * 0.05;
- self.rotation = Math.sin(LK.ticks * 0.12) * 0.1;
- if (LK.ticks % 120 === 0) {
- // Quick sword swing animation
- tween(self, {
- rotation: 0.3
- }, {
- duration: 100,
- easing: tween.easeOut
- });
- tween(self, {
- rotation: 0
- }, {
- duration: 100,
- easing: tween.easeIn
- });
- }
+ self.floatOffset += self.animSpeed;
+ self.y = self.baseY + Math.sin(self.floatOffset) * 20;
+ // Add mystical particle effect for wizard
+ if (self.type === 'wizard' && LK.ticks % 20 === 0) {
+ LK.effects.flashObject(self, 0x4169e1, 400);
}
+ // Add shadow dash effect for ninja
+ if (self.type === 'ninja' && LK.ticks % 30 === 0) {
+ LK.effects.flashObject(self, 0x9932cc, 300);
+ }
+ // Add sword gleam for swordmaster
+ if (self.type === 'swordmaster' && LK.ticks % 25 === 0) {
+ LK.effects.flashObject(self, 0xffd700, 350);
+ }
}
};
return self;
});
@@ -152,11 +126,19 @@
var comboText = null;
var livesText = null;
var abilityText = null;
var instructionText = null;
+var ninjaDescText = null;
+var wizardDescText = null;
+var swordmasterDescText = null;
+var titleText = null;
// Lane positions
var lanePositions = [2048 * 0.25, 2048 * 0.5, 2048 * 0.75];
var targetY = 2200;
+// Start ambient music for character selection
+LK.playMusic('ambient', {
+ volume: 0.6
+});
// Initialize lanes
for (var i = 0; i < 3; i++) {
var lane = game.addChild(LK.getAsset('lane', {
anchorX: 0.5,
@@ -173,65 +155,21 @@
x: 2048 / 2,
y: targetY,
alpha: 0.3
}));
-// Create mystical background effect for character selection
-var selectionBackground = game.addChild(LK.getAsset('targetZone', {
- anchorX: 0.5,
- anchorY: 0.5,
- x: 2048 / 2,
- y: 2732 / 2,
- scaleX: 4,
- scaleY: 8,
- alpha: 0.1,
- tint: 0x4a148c
-}));
-// Create character selection with enhanced positioning
+// Create character selection
characters.ninja = game.addChild(new Character('ninja'));
-characters.ninja.x = 2048 * 0.2;
-characters.ninja.y = 1300;
-characters.ninja.scaleX = 1.5;
-characters.ninja.scaleY = 1.5;
+characters.ninja.x = 2048 * 0.25;
+characters.ninja.y = 1000;
+characters.ninja.baseY = 1000;
characters.wizard = game.addChild(new Character('wizard'));
characters.wizard.x = 2048 * 0.5;
-characters.wizard.y = 1300;
-characters.wizard.scaleX = 1.5;
-characters.wizard.scaleY = 1.5;
+characters.wizard.y = 1000;
+characters.wizard.baseY = 1000;
characters.swordmaster = game.addChild(new Character('swordmaster'));
-characters.swordmaster.x = 2048 * 0.8;
-characters.swordmaster.y = 1300;
-characters.swordmaster.scaleX = 1.5;
-characters.swordmaster.scaleY = 1.5;
-// Character description texts
-var ninjaDesc = new Text2('Shadow Ninja\n"Strike with silence.\nDance with speed."\n\nDifficulty: Easy to pick,\nhard to master\n\nAbility: Auto-slice chain\ncombo on perfect timing', {
- size: 35,
- fill: 0xffffff
-});
-ninjaDesc.anchor.set(0.5, 0);
-ninjaDesc.x = 2048 * 0.2;
-ninjaDesc.y = 1450;
-game.addChild(ninjaDesc);
-var wizardDesc = new Text2('Blue Mage\n"Slow the rhythm,\ncontrol the chaos."\n\nDifficulty: Medium\n\nAbility: Ice Freeze\nSlows orbs for 3 seconds\nevery 10 seconds', {
- size: 35,
- fill: 0xffffff
-});
-wizardDesc.anchor.set(0.5, 0);
-wizardDesc.x = 2048 * 0.5;
-wizardDesc.y = 1450;
-game.addChild(wizardDesc);
-var swordmasterDesc = new Text2('Dual Blade Swordmaster\n"Two blades.\nOne rhythm."\n\nDifficulty: Hard\n\nAbility: Multi-touch bonus\nSlash both lanes\nat the same time', {
- size: 35,
- fill: 0xffffff
-});
-swordmasterDesc.anchor.set(0.5, 0);
-swordmasterDesc.x = 2048 * 0.8;
-swordmasterDesc.y = 1450;
-game.addChild(swordmasterDesc);
-// Store character descriptions for later hiding
-characters.ninjaDesc = ninjaDesc;
-characters.wizardDesc = wizardDesc;
-characters.swordmasterDesc = swordmasterDesc;
-characters.selectionBackground = selectionBackground;
+characters.swordmaster.x = 2048 * 0.75;
+characters.swordmaster.y = 1000;
+characters.swordmaster.baseY = 1000;
// UI Setup
scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
@@ -261,26 +199,72 @@
});
abilityText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(abilityText);
abilityText.y = -100;
-instructionText = new Text2('Welcome to the Mystical Dojo\n\nChoose Your Warrior Class\nTap on a character to begin your rhythm battle!', {
- size: 60,
- fill: 0xffd700
+// Title text
+titleText = new Text2('RHYTHM WARRIORS\nBeat Battle Arena', {
+ size: 80,
+ fill: 0xFFD700
});
-instructionText.anchor.set(0.5, 0);
-instructionText.x = 2048 / 2;
-instructionText.y = 800;
-game.addChild(instructionText);
+titleText.anchor.set(0.5, 0);
+LK.gui.top.addChild(titleText);
+titleText.y = 200;
+// Character descriptions
+ninjaDescText = new Text2('⚫ SHADOW NINJA\n"Strike with silence. Dance with speed."\nAbility: Shadow Slice auto-combo\nDifficulty: Easy to pick, hard to master', {
+ size: 35,
+ fill: 0x9932cc
+});
+ninjaDescText.anchor.set(0.5, 0);
+game.addChild(ninjaDescText);
+ninjaDescText.x = 2048 * 0.25;
+ninjaDescText.y = 1200;
+wizardDescText = new Text2('🔵 BLUE MAGE\n"Slow the rhythm, control the chaos."\nAbility: Ice Freeze slows orbs\nDifficulty: Medium', {
+ size: 35,
+ fill: 0x4169e1
+});
+wizardDescText.anchor.set(0.5, 0);
+game.addChild(wizardDescText);
+wizardDescText.x = 2048 * 0.5;
+wizardDescText.y = 1200;
+swordmasterDescText = new Text2('⚔️ DUAL BLADE SWORDMASTER\n"Two blades. One rhythm."\nAbility: Multi-touch dual strike\nDifficulty: Hard', {
+ size: 35,
+ fill: 0x8b4513
+});
+swordmasterDescText.anchor.set(0.5, 0);
+game.addChild(swordmasterDescText);
+swordmasterDescText.x = 2048 * 0.75;
+swordmasterDescText.y = 1200;
+instructionText = new Text2('TAP A CHARACTER TO BEGIN', {
+ size: 50,
+ fill: 0xFFFFFF
+});
+instructionText.anchor.set(0.5, 1);
+LK.gui.bottom.addChild(instructionText);
+instructionText.y = -50;
// Input handling
game.down = function (x, y, obj) {
if (gameState === 'classSelection') {
- // Check character selection with proper hit areas
- var hitRadius = 150;
- if (Math.abs(x - characters.ninja.x) < hitRadius && Math.abs(y - characters.ninja.y) < hitRadius) {
+ // Check character selection
+ if (characters.ninja.intersects({
+ x: x,
+ y: y,
+ width: 1,
+ height: 1
+ })) {
selectCharacter('ninja');
- } else if (Math.abs(x - characters.wizard.x) < hitRadius && Math.abs(y - characters.wizard.y) < hitRadius) {
+ } else if (characters.wizard.intersects({
+ x: x,
+ y: y,
+ width: 1,
+ height: 1
+ })) {
selectCharacter('wizard');
- } else if (Math.abs(x - characters.swordmaster.x) < hitRadius && Math.abs(y - characters.swordmaster.y) < hitRadius) {
+ } else if (characters.swordmaster.intersects({
+ x: x,
+ y: y,
+ width: 1,
+ height: 1
+ })) {
selectCharacter('swordmaster');
}
} else if (gameState === 'playing') {
// Handle orb hits and abilities
@@ -301,99 +285,34 @@
}
};
function selectCharacter(type) {
selectedCharacter = characters[type];
- // Dramatic selection effect
- LK.effects.flashObject(selectedCharacter, 0xffffff, 800);
- tween(selectedCharacter, {
- scaleX: 2.0,
- scaleY: 2.0
- }, {
- duration: 500,
- easing: tween.easeOut
- });
- // Fade out unselected characters and descriptions
+ gameState = 'playing';
+ // Hide character descriptions and selection UI
+ titleText.visible = false;
+ ninjaDescText.visible = false;
+ wizardDescText.visible = false;
+ swordmasterDescText.visible = false;
+ instructionText.visible = false;
+ // Hide unselected characters
for (var charType in characters) {
if (charType !== type) {
- if (characters[charType].update) {
- // It's a character
- tween(characters[charType], {
- alpha: 0
- }, {
- duration: 800,
- easing: tween.easeOut
- });
- }
+ characters[charType].visible = false;
}
}
- // Fade out character descriptions
- tween(characters.ninjaDesc, {
- alpha: 0
- }, {
- duration: 600,
- easing: tween.easeOut
- });
- tween(characters.wizardDesc, {
- alpha: 0
- }, {
- duration: 600,
- easing: tween.easeOut
- });
- tween(characters.swordmasterDesc, {
- alpha: 0
- }, {
- duration: 600,
- easing: tween.easeOut
- });
- tween(characters.selectionBackground, {
- alpha: 0
- }, {
- duration: 800,
- easing: tween.easeOut
- });
- // Hide instruction text with fade
- tween(instructionText, {
- alpha: 0
- }, {
- duration: 500,
- easing: tween.easeOut
- });
- // Transition to game after animation
- LK.setTimeout(function () {
- gameState = 'playing';
- // Hide unselected characters completely
- for (var charType in characters) {
- if (charType !== type && characters[charType].update) {
- characters[charType].visible = false;
- }
- }
- // Position selected character for gameplay
- tween(selectedCharacter, {
- x: 2048 / 2,
- y: 2400,
- scaleX: 1.0,
- scaleY: 1.0
- }, {
- duration: 1000,
- easing: tween.easeInOut
- });
- // Hide instruction text completely
- instructionText.visible = false;
- characters.ninjaDesc.visible = false;
- characters.wizardDesc.visible = false;
- characters.swordmasterDesc.visible = false;
- characters.selectionBackground.visible = false;
- // Start music with fade-in
- LK.playMusic('bgtrack', {
- fade: {
- start: 0,
- end: 1,
- duration: 1000
- }
- });
- // Flash screen to indicate game start
- LK.effects.flashScreen(0x00ff00, 500);
- }, 1000);
+ // Position selected character
+ selectedCharacter.x = 2048 / 2;
+ selectedCharacter.y = 2400;
+ // Character-specific selection effects
+ if (type === 'ninja') {
+ LK.effects.flashScreen(0x9932cc, 800);
+ } else if (type === 'wizard') {
+ LK.effects.flashScreen(0x4169e1, 800);
+ } else if (type === 'swordmaster') {
+ LK.effects.flashScreen(0xffd700, 800);
+ }
+ // Start music and orb spawning
+ LK.playMusic('bgtrack');
}
function handleOrbHit(lane, expectedType) {
var hitOrb = null;
var bestDistance = Infinity;
A ninja wearing tight black clothes, purple scarf, masked face, white skin, glowing purple eyes, slim and agile body, simple background, front-facing character with no background, standing pose, 2D game character. In-Game asset. 2d. High contrast. No shadows
A white-clothed male samurai with torn clothes, long gray hair tied back, pale skin, red belt on his waist, holding two swords, standing confidently, simple pose, no background, front-facing, 2D game character. In-Game asset. 2d. High contrast. No shadows
A female mage with pale skin, long white hair, wearing a long blue robe and a pointed blue hat, holding a glowing icy staff with a blue crystal, snowflake patterns on robe, cold expression, simple background, front-facing, no background, 2D game character. In-Game asset. 2d. High contrast. No shadows
Green goblin without backround. In-Game asset. 2d. High contrast. No shadows
Red wild monster. In-Game asset. 2d. High contrast. No shadows
Black monster , white eyes looks like bomb. In-Game asset. 2d. High contrast. No shadows