/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Character = Container.expand(function (characterData) { var self = Container.call(this); self.characterData = characterData; self.isOnBoard = false; self.originalPosition = { x: 0, y: 0 }; self.boardSlot = null; self.soundInstance = null; self.soundTimer = null; var characterGraphics = self.attachAsset(characterData.assetId, { anchorX: 0.5, anchorY: 0.5 }); // Make character interactive self.interactive = true; // Add character name text var nameText = new Text2(characterData.name, { size: 45, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0.5); nameText.y = 90; self.addChild(nameText); self.playSound = function () { if (self.soundInstance) { self.soundInstance.stop(); } // Clear any existing sound timer if (self.soundTimer) { LK.clearInterval(self.soundTimer); } // Function to play sound once function playSoundOnce() { self.soundInstance = LK.getSound(characterData.soundId); self.soundInstance.play({ loop: false }); // Play without looping } // Play sound immediately playSoundOnce(); // Set up timer to play sound every 1.3 seconds self.soundTimer = LK.setInterval(function () { playSoundOnce(); }, 1300); // Visual feedback - bounce animation tween(characterGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(characterGraphics, { scaleX: 1.0, scaleY: 1.0 }, { duration: 200, easing: tween.easeIn }); } }); // Continuous singing animation self.singAnimation = LK.setInterval(function () { // Wobble effect tween(characterGraphics, { rotation: 0.1 }, { duration: 300, easing: tween.easeInOut, onFinish: function onFinish() { tween(characterGraphics, { rotation: -0.1 }, { duration: 300, easing: tween.easeInOut, onFinish: function onFinish() { tween(characterGraphics, { rotation: 0 }, { duration: 300, easing: tween.easeInOut }); } }); } }); // Pulsing effect based on sound type if (characterData.type === 'beat') { tween(characterGraphics, { scaleX: 1.1, scaleY: 1.1 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(characterGraphics, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeIn }); } }); } else if (characterData.type === 'voice') { // Smooth scaling for voice tween(characterGraphics, { scaleY: 1.15 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { tween(characterGraphics, { scaleY: 1.0 }, { duration: 400, easing: tween.easeInOut }); } }); } }, 600); }; self.stopSound = function () { if (self.soundInstance) { self.soundInstance.stop(); self.soundInstance = null; } // Clear sound timer if (self.soundTimer) { LK.clearInterval(self.soundTimer); self.soundTimer = null; } // Stop singing animation if (self.singAnimation) { LK.clearInterval(self.singAnimation); self.singAnimation = null; } // Reset rotation tween(characterGraphics, { rotation: 0 }, { duration: 200, easing: tween.easeOut }); }; self.returnToOriginalPosition = function () { tween(self, { x: self.originalPosition.x, y: self.originalPosition.y }, { duration: 300, easing: tween.easeOut }); }; return self; }); var MixingSlot = Container.expand(function (slotIndex) { var self = Container.call(this); self.slotIndex = slotIndex; self.character = null; self.isEmpty = true; var slotGraphics = self.attachAsset('mixing_slot', { anchorX: 0.5, anchorY: 0.5 }); self.addCharacter = function (character) { if (self.character) { self.removeCharacter(); } self.character = character; self.isEmpty = false; character.isOnBoard = true; character.boardSlot = self; // Store the character's parent container var characterParent = character.parent; // Check if character is a horror character (but not Horror Inky) var isHorrorCharacter = character.characterData.name.indexOf("Horror") !== -1 && character.characterData.name !== "Horror Inky"; if (isHorrorCharacter) { // Replace slot graphics with horror version self.removeChild(slotGraphics); slotGraphics = self.attachAsset('mixing_slot_active_horror', { anchorX: 0.5, anchorY: 0.5 }); } else { // Use regular active slot self.removeChild(slotGraphics); slotGraphics = self.attachAsset('mixing_slot_active', { anchorX: 0.5, anchorY: 0.5 }); } // Visual feedback - glow effect tween(slotGraphics, { tint: 0x888888, scaleX: 1.05, scaleY: 1.05 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(slotGraphics, { tint: 0xFFFFFF, scaleX: 1.0, scaleY: 1.0 }, { duration: 200, easing: tween.easeIn }); } }); // Position character directly to slot position (both are in game coordinates) tween(character, { x: self.x, y: self.y - 50 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(character, { y: self.y }, { duration: 200, easing: tween.bounceOut, onFinish: function onFinish() { character.playSound(); } }); } }); }; self.removeCharacter = function () { if (self.character) { var characterToRemove = self.character; self.character.stopSound(); self.character.isOnBoard = false; self.character.boardSlot = null; // Animate character up before returning tween(characterToRemove, { y: characterToRemove.y - 100, scaleX: 0.8, scaleY: 0.8 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { characterToRemove.returnToOriginalPosition(); // Reset scale after returning tween(characterToRemove, { scaleX: 1.0, scaleY: 1.0 }, { duration: 200, easing: tween.easeOut }); } }); self.character = null; } self.isEmpty = true; // Reset slot graphics to default mixing slot self.removeChild(slotGraphics); slotGraphics = self.attachAsset('mixing_slot', { anchorX: 0.5, anchorY: 0.5 }); // Fade slot back to normal tween(slotGraphics, { tint: 0xFFFFFF, scaleX: 0.95, scaleY: 0.95 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(slotGraphics, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeIn }); } }); }; self.containsPoint = function (x, y) { // Use fixed size for slot hit detection var halfWidth = 90; // Half of slot width var halfHeight = 90; // Half of slot height return x >= self.x - halfWidth && x <= self.x + halfWidth && y >= self.y - halfHeight && y <= self.y + halfHeight; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a2e }); /**** * Game Code ****/ // Add background image var bgImage = game.attachAsset('Bg', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.4, scaleY: 0.27 }); bgImage.x = 2048 / 2; bgImage.y = 2732 / 2; // Sound assets for each character // Character data // Characters // Mixing board slots // Sounds var characterData = [{ name: "Oren", assetId: "oren", soundId: "oren_beat", type: "beat" }, { name: "Horror Oren", assetId: "horror_oren", soundId: "horror_oren_beat", type: "beat" }, { name: "Raddy", assetId: "raddy", soundId: "raddy_beat", type: "beat" }, { name: "Horror Raddy", assetId: "horror_raddy", soundId: "horror_raddy_effect", type: "effect" }, { name: "Wenda", assetId: "wenda", soundId: "wenda_voice", type: "voice" }, { name: "Horror Wenda", assetId: "horror_wenda", soundId: "horror_wenda_voice", type: "voice" }, { name: "Alt Horror Wenda", assetId: "alt_horror_wenda", soundId: "alt_horror_wenda_effect", type: "effect" }, { name: "Jevin", assetId: "jevin", soundId: "jevin_voice", type: "voice" }, { name: "Horror Jevin", assetId: "horror_jevin", soundId: "horror_jevin_voice", type: "voice" }, { name: "Inky", assetId: "inky", soundId: "inky_effect", type: "effect" }, { name: "Horror Inky", assetId: "horror_inky", soundId: "horror_inky_effect", type: "effect" }, { //{3r_new} name: "Alt Horror Jevin", assetId: "alt_horror_jevin", soundId: "alt_horror_jevin_voice", type: "voice" //{3s_new} }, { name: "Cool Guy", assetId: "Cool_Guy", soundId: "Cool_Guy_voice", type: "voice" }, { name: "Horror Cool Guy", assetId: "horror_cool_guy", soundId: "horror_cool_guy_voice", type: "voice" }]; // Game elements var characters = []; var mixingSlots = []; var draggedCharacter = null; var dragOffset = { x: 0, //{3t_new} y: 0 //{3u_new} }; //{3v_new} // Title var titleText = new Text2("Sprunki Beat Mixer", { size: 120, fill: 0xFFFFFF //{3w_new} }); //{3x_new} titleText.anchor.set(0.5, 0); titleText.x = 2048 / 2; titleText.y = 100; game.addChild(titleText); // Title dance animation LK.setInterval(function () { // Bounce effect tween(titleText, { scaleX: 1.1, scaleY: 1.1, y: 80 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { tween(titleText, { scaleX: 1.0, scaleY: 1.0, y: 100 }, { duration: 400, easing: tween.bounceOut }); } }); // Color pulse effect tween(titleText, { tint: 0x00ff88 }, { duration: 200, easing: tween.easeInOut, onFinish: function onFinish() { tween(titleText, { tint: 0xffffff }, { duration: 600, easing: tween.easeInOut }); } }); }, 1200); // Subtle rotation wobble LK.setInterval(function () { tween(titleText, { rotation: 0.05 }, { duration: 300, easing: tween.easeInOut, onFinish: function onFinish() { tween(titleText, { rotation: -0.05 }, { duration: 300, easing: tween.easeInOut, onFinish: function onFinish() { tween(titleText, { rotation: 0 }, { duration: 300, easing: tween.easeInOut }); } }); } }); }, 1800); // Create mixing board slots var slotStartX = 2048 / 2 - 5 * 300 / 2; var slotY = 800; for (var i = 0; i < 5; i++) { var slot = new MixingSlot(i); slot.x = slotStartX + i * 300; slot.y = slotY; mixingSlots.push(slot); game.addChild(slot); } //{3y_new} // Create characters var charactersPerRow = 5; var characterStartX = 2048 / 2 - charactersPerRow * 300 / 2; var characterStartY = 1800; for (var i = 0; i < characterData.length; i++) { var character = new Character(characterData[i]); var row = Math.floor(i / charactersPerRow); var col = i % charactersPerRow; character.x = characterStartX + col * 300; character.y = characterStartY + row * 300; character.originalPosition.x = character.x; character.originalPosition.y = character.y; characters.push(character); game.addChild(character); } //{3z_new} // Instructions var instructionText = new Text2("Drag characters to mixing slots to create beats!", { size: 60, fill: 0xFFFFFF //{3A_new} }); //{3B_new} instructionText.anchor.set(0.5, 0); instructionText.x = 2048 / 2; instructionText.y = 1200; game.addChild(instructionText); // Helper functions function getCharacterAt(x, y) { for (var i = characters.length - 1; i >= 0; i--) { var character = characters[i]; // Use character position and asset dimensions for hit detection var characterAsset = character.children[0]; // The attached asset if (characterAsset) { var halfWidth = characterAsset.width / 2; var halfHeight = characterAsset.height / 2; if (x >= character.x - halfWidth && x <= character.x + halfWidth && y >= character.y - halfHeight && y <= character.y + halfHeight) { return character; } } } return null; } function getMixingSlotAt(x, y) { for (var i = 0; i < mixingSlots.length; i++) { if (mixingSlots[i].containsPoint(x, y)) { return mixingSlots[i]; } } return null; } // Event handlers game.down = function (x, y, obj) { // Check if we're tapping on a character first (prioritize character interaction) var character = getCharacterAt(x, y); if (character) { // If character is on board, check if this is a quick tap to remove or start dragging if (character.isOnBoard && character.boardSlot) { // For now, start dragging - removal will happen in up event if no movement occurred draggedCharacter = character; dragOffset.x = x - character.x; dragOffset.y = y - character.y; character.dragStartTime = Date.now(); character.dragStartX = x; character.dragStartY = y; // Bring to front var parentContainer = character.parent; parentContainer.removeChild(character); parentContainer.addChild(character); // Visual feedback tween(character, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, easing: tween.easeOut }); return; } // If character is not on board, start dragging if (!character.isOnBoard) { draggedCharacter = character; dragOffset.x = x - character.x; dragOffset.y = y - character.y; // Bring to front - store parent reference before removing var parentContainer = character.parent; parentContainer.removeChild(character); parentContainer.addChild(character); // Visual feedback tween(character, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, easing: tween.easeOut }); return; } } // If no character found, check if we're tapping on a slot with a character var slot = getMixingSlotAt(x, y); if (slot && !slot.isEmpty) { // Remove character from slot with a single tap slot.removeCharacter(); return; } }; game.move = function (x, y, obj) { if (draggedCharacter && draggedCharacter.parent) { // Ensure the dragged character follows the cursor smoothly draggedCharacter.x = x - dragOffset.x; draggedCharacter.y = y - dragOffset.y; // Highlight slot when hovering var hoverSlot = getMixingSlotAt(x, y); for (var i = 0; i < mixingSlots.length; i++) { var slot = mixingSlots[i]; if (slot === hoverSlot && slot.isEmpty) { tween(slot, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, easing: tween.easeOut }); } else { tween(slot, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, easing: tween.easeOut }); } } } else if (!draggedCharacter) { // Hover effect for characters only when not dragging var hoverCharacter = getCharacterAt(x, y); for (var i = 0; i < characters.length; i++) { var character = characters[i]; if (character === hoverCharacter && !character.isOnBoard) { tween(character, { scaleX: 1.05, scaleY: 1.05 }, { duration: 100, easing: tween.easeOut }); } else if (!character.isOnBoard) { tween(character, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, easing: tween.easeOut }); } } } }; game.up = function (x, y, obj) { if (draggedCharacter) { // Check if this was a quick tap (< 300ms and < 20px movement) vs a drag var timeDiff = Date.now() - (draggedCharacter.dragStartTime || 0); var distanceMoved = Math.sqrt(Math.pow(x - (draggedCharacter.dragStartX || x), 2) + Math.pow(y - (draggedCharacter.dragStartY || y), 2)); var isQuickTap = timeDiff < 300 && distanceMoved < 20; if (isQuickTap && draggedCharacter.isOnBoard && draggedCharacter.boardSlot) { // Quick tap on character in slot - remove it var slotToRemoveFrom = draggedCharacter.boardSlot; slotToRemoveFrom.removeCharacter(); // Reset scale tween(draggedCharacter, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, easing: tween.easeIn }); draggedCharacter = null; return; } var slot = getMixingSlotAt(x, y); // Check if we're dropping on an empty slot if (slot && slot.isEmpty) { // If character was already on board, remove from previous slot if (draggedCharacter.isOnBoard && draggedCharacter.boardSlot) { draggedCharacter.boardSlot.removeCharacter(); } slot.addCharacter(draggedCharacter); } else if (slot && !slot.isEmpty && draggedCharacter.isOnBoard) { // Handle swapping characters between slots var oldSlot = draggedCharacter.boardSlot; var swapCharacter = slot.character; // Remove both characters if (oldSlot) oldSlot.removeCharacter(); slot.removeCharacter(); // Add them to swapped positions slot.addCharacter(draggedCharacter); if (oldSlot && swapCharacter) oldSlot.addCharacter(swapCharacter); } else { // Return to original position if not dropped on a valid slot draggedCharacter.returnToOriginalPosition(); } // Reset scale tween(draggedCharacter, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, easing: tween.easeIn }); draggedCharacter = null; } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Character = Container.expand(function (characterData) {
var self = Container.call(this);
self.characterData = characterData;
self.isOnBoard = false;
self.originalPosition = {
x: 0,
y: 0
};
self.boardSlot = null;
self.soundInstance = null;
self.soundTimer = null;
var characterGraphics = self.attachAsset(characterData.assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Make character interactive
self.interactive = true;
// Add character name text
var nameText = new Text2(characterData.name, {
size: 45,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = 90;
self.addChild(nameText);
self.playSound = function () {
if (self.soundInstance) {
self.soundInstance.stop();
}
// Clear any existing sound timer
if (self.soundTimer) {
LK.clearInterval(self.soundTimer);
}
// Function to play sound once
function playSoundOnce() {
self.soundInstance = LK.getSound(characterData.soundId);
self.soundInstance.play({
loop: false
}); // Play without looping
}
// Play sound immediately
playSoundOnce();
// Set up timer to play sound every 1.3 seconds
self.soundTimer = LK.setInterval(function () {
playSoundOnce();
}, 1300);
// Visual feedback - bounce animation
tween(characterGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(characterGraphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeIn
});
}
});
// Continuous singing animation
self.singAnimation = LK.setInterval(function () {
// Wobble effect
tween(characterGraphics, {
rotation: 0.1
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(characterGraphics, {
rotation: -0.1
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(characterGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
});
// Pulsing effect based on sound type
if (characterData.type === 'beat') {
tween(characterGraphics, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(characterGraphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeIn
});
}
});
} else if (characterData.type === 'voice') {
// Smooth scaling for voice
tween(characterGraphics, {
scaleY: 1.15
}, {
duration: 400,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(characterGraphics, {
scaleY: 1.0
}, {
duration: 400,
easing: tween.easeInOut
});
}
});
}
}, 600);
};
self.stopSound = function () {
if (self.soundInstance) {
self.soundInstance.stop();
self.soundInstance = null;
}
// Clear sound timer
if (self.soundTimer) {
LK.clearInterval(self.soundTimer);
self.soundTimer = null;
}
// Stop singing animation
if (self.singAnimation) {
LK.clearInterval(self.singAnimation);
self.singAnimation = null;
}
// Reset rotation
tween(characterGraphics, {
rotation: 0
}, {
duration: 200,
easing: tween.easeOut
});
};
self.returnToOriginalPosition = function () {
tween(self, {
x: self.originalPosition.x,
y: self.originalPosition.y
}, {
duration: 300,
easing: tween.easeOut
});
};
return self;
});
var MixingSlot = Container.expand(function (slotIndex) {
var self = Container.call(this);
self.slotIndex = slotIndex;
self.character = null;
self.isEmpty = true;
var slotGraphics = self.attachAsset('mixing_slot', {
anchorX: 0.5,
anchorY: 0.5
});
self.addCharacter = function (character) {
if (self.character) {
self.removeCharacter();
}
self.character = character;
self.isEmpty = false;
character.isOnBoard = true;
character.boardSlot = self;
// Store the character's parent container
var characterParent = character.parent;
// Check if character is a horror character (but not Horror Inky)
var isHorrorCharacter = character.characterData.name.indexOf("Horror") !== -1 && character.characterData.name !== "Horror Inky";
if (isHorrorCharacter) {
// Replace slot graphics with horror version
self.removeChild(slotGraphics);
slotGraphics = self.attachAsset('mixing_slot_active_horror', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
// Use regular active slot
self.removeChild(slotGraphics);
slotGraphics = self.attachAsset('mixing_slot_active', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Visual feedback - glow effect
tween(slotGraphics, {
tint: 0x888888,
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(slotGraphics, {
tint: 0xFFFFFF,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeIn
});
}
});
// Position character directly to slot position (both are in game coordinates)
tween(character, {
x: self.x,
y: self.y - 50
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(character, {
y: self.y
}, {
duration: 200,
easing: tween.bounceOut,
onFinish: function onFinish() {
character.playSound();
}
});
}
});
};
self.removeCharacter = function () {
if (self.character) {
var characterToRemove = self.character;
self.character.stopSound();
self.character.isOnBoard = false;
self.character.boardSlot = null;
// Animate character up before returning
tween(characterToRemove, {
y: characterToRemove.y - 100,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
characterToRemove.returnToOriginalPosition();
// Reset scale after returning
tween(characterToRemove, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut
});
}
});
self.character = null;
}
self.isEmpty = true;
// Reset slot graphics to default mixing slot
self.removeChild(slotGraphics);
slotGraphics = self.attachAsset('mixing_slot', {
anchorX: 0.5,
anchorY: 0.5
});
// Fade slot back to normal
tween(slotGraphics, {
tint: 0xFFFFFF,
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(slotGraphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeIn
});
}
});
};
self.containsPoint = function (x, y) {
// Use fixed size for slot hit detection
var halfWidth = 90; // Half of slot width
var halfHeight = 90; // Half of slot height
return x >= self.x - halfWidth && x <= self.x + halfWidth && y >= self.y - halfHeight && y <= self.y + halfHeight;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Add background image
var bgImage = game.attachAsset('Bg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.27
});
bgImage.x = 2048 / 2;
bgImage.y = 2732 / 2;
// Sound assets for each character
// Character data
// Characters
// Mixing board slots
// Sounds
var characterData = [{
name: "Oren",
assetId: "oren",
soundId: "oren_beat",
type: "beat"
}, {
name: "Horror Oren",
assetId: "horror_oren",
soundId: "horror_oren_beat",
type: "beat"
}, {
name: "Raddy",
assetId: "raddy",
soundId: "raddy_beat",
type: "beat"
}, {
name: "Horror Raddy",
assetId: "horror_raddy",
soundId: "horror_raddy_effect",
type: "effect"
}, {
name: "Wenda",
assetId: "wenda",
soundId: "wenda_voice",
type: "voice"
}, {
name: "Horror Wenda",
assetId: "horror_wenda",
soundId: "horror_wenda_voice",
type: "voice"
}, {
name: "Alt Horror Wenda",
assetId: "alt_horror_wenda",
soundId: "alt_horror_wenda_effect",
type: "effect"
}, {
name: "Jevin",
assetId: "jevin",
soundId: "jevin_voice",
type: "voice"
}, {
name: "Horror Jevin",
assetId: "horror_jevin",
soundId: "horror_jevin_voice",
type: "voice"
}, {
name: "Inky",
assetId: "inky",
soundId: "inky_effect",
type: "effect"
}, {
name: "Horror Inky",
assetId: "horror_inky",
soundId: "horror_inky_effect",
type: "effect"
}, {
//{3r_new}
name: "Alt Horror Jevin",
assetId: "alt_horror_jevin",
soundId: "alt_horror_jevin_voice",
type: "voice" //{3s_new}
}, {
name: "Cool Guy",
assetId: "Cool_Guy",
soundId: "Cool_Guy_voice",
type: "voice"
}, {
name: "Horror Cool Guy",
assetId: "horror_cool_guy",
soundId: "horror_cool_guy_voice",
type: "voice"
}];
// Game elements
var characters = [];
var mixingSlots = [];
var draggedCharacter = null;
var dragOffset = {
x: 0,
//{3t_new}
y: 0 //{3u_new}
}; //{3v_new}
// Title
var titleText = new Text2("Sprunki Beat Mixer", {
size: 120,
fill: 0xFFFFFF //{3w_new}
}); //{3x_new}
titleText.anchor.set(0.5, 0);
titleText.x = 2048 / 2;
titleText.y = 100;
game.addChild(titleText);
// Title dance animation
LK.setInterval(function () {
// Bounce effect
tween(titleText, {
scaleX: 1.1,
scaleY: 1.1,
y: 80
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(titleText, {
scaleX: 1.0,
scaleY: 1.0,
y: 100
}, {
duration: 400,
easing: tween.bounceOut
});
}
});
// Color pulse effect
tween(titleText, {
tint: 0x00ff88
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleText, {
tint: 0xffffff
}, {
duration: 600,
easing: tween.easeInOut
});
}
});
}, 1200);
// Subtle rotation wobble
LK.setInterval(function () {
tween(titleText, {
rotation: 0.05
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleText, {
rotation: -0.05
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleText, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
});
}, 1800);
// Create mixing board slots
var slotStartX = 2048 / 2 - 5 * 300 / 2;
var slotY = 800;
for (var i = 0; i < 5; i++) {
var slot = new MixingSlot(i);
slot.x = slotStartX + i * 300;
slot.y = slotY;
mixingSlots.push(slot);
game.addChild(slot);
} //{3y_new}
// Create characters
var charactersPerRow = 5;
var characterStartX = 2048 / 2 - charactersPerRow * 300 / 2;
var characterStartY = 1800;
for (var i = 0; i < characterData.length; i++) {
var character = new Character(characterData[i]);
var row = Math.floor(i / charactersPerRow);
var col = i % charactersPerRow;
character.x = characterStartX + col * 300;
character.y = characterStartY + row * 300;
character.originalPosition.x = character.x;
character.originalPosition.y = character.y;
characters.push(character);
game.addChild(character);
} //{3z_new}
// Instructions
var instructionText = new Text2("Drag characters to mixing slots to create beats!", {
size: 60,
fill: 0xFFFFFF //{3A_new}
}); //{3B_new}
instructionText.anchor.set(0.5, 0);
instructionText.x = 2048 / 2;
instructionText.y = 1200;
game.addChild(instructionText);
// Helper functions
function getCharacterAt(x, y) {
for (var i = characters.length - 1; i >= 0; i--) {
var character = characters[i];
// Use character position and asset dimensions for hit detection
var characterAsset = character.children[0]; // The attached asset
if (characterAsset) {
var halfWidth = characterAsset.width / 2;
var halfHeight = characterAsset.height / 2;
if (x >= character.x - halfWidth && x <= character.x + halfWidth && y >= character.y - halfHeight && y <= character.y + halfHeight) {
return character;
}
}
}
return null;
}
function getMixingSlotAt(x, y) {
for (var i = 0; i < mixingSlots.length; i++) {
if (mixingSlots[i].containsPoint(x, y)) {
return mixingSlots[i];
}
}
return null;
}
// Event handlers
game.down = function (x, y, obj) {
// Check if we're tapping on a character first (prioritize character interaction)
var character = getCharacterAt(x, y);
if (character) {
// If character is on board, check if this is a quick tap to remove or start dragging
if (character.isOnBoard && character.boardSlot) {
// For now, start dragging - removal will happen in up event if no movement occurred
draggedCharacter = character;
dragOffset.x = x - character.x;
dragOffset.y = y - character.y;
character.dragStartTime = Date.now();
character.dragStartX = x;
character.dragStartY = y;
// Bring to front
var parentContainer = character.parent;
parentContainer.removeChild(character);
parentContainer.addChild(character);
// Visual feedback
tween(character, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
easing: tween.easeOut
});
return;
}
// If character is not on board, start dragging
if (!character.isOnBoard) {
draggedCharacter = character;
dragOffset.x = x - character.x;
dragOffset.y = y - character.y;
// Bring to front - store parent reference before removing
var parentContainer = character.parent;
parentContainer.removeChild(character);
parentContainer.addChild(character);
// Visual feedback
tween(character, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
easing: tween.easeOut
});
return;
}
}
// If no character found, check if we're tapping on a slot with a character
var slot = getMixingSlotAt(x, y);
if (slot && !slot.isEmpty) {
// Remove character from slot with a single tap
slot.removeCharacter();
return;
}
};
game.move = function (x, y, obj) {
if (draggedCharacter && draggedCharacter.parent) {
// Ensure the dragged character follows the cursor smoothly
draggedCharacter.x = x - dragOffset.x;
draggedCharacter.y = y - dragOffset.y;
// Highlight slot when hovering
var hoverSlot = getMixingSlotAt(x, y);
for (var i = 0; i < mixingSlots.length; i++) {
var slot = mixingSlots[i];
if (slot === hoverSlot && slot.isEmpty) {
tween(slot, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
easing: tween.easeOut
});
} else {
tween(slot, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeOut
});
}
}
} else if (!draggedCharacter) {
// Hover effect for characters only when not dragging
var hoverCharacter = getCharacterAt(x, y);
for (var i = 0; i < characters.length; i++) {
var character = characters[i];
if (character === hoverCharacter && !character.isOnBoard) {
tween(character, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 100,
easing: tween.easeOut
});
} else if (!character.isOnBoard) {
tween(character, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeOut
});
}
}
}
};
game.up = function (x, y, obj) {
if (draggedCharacter) {
// Check if this was a quick tap (< 300ms and < 20px movement) vs a drag
var timeDiff = Date.now() - (draggedCharacter.dragStartTime || 0);
var distanceMoved = Math.sqrt(Math.pow(x - (draggedCharacter.dragStartX || x), 2) + Math.pow(y - (draggedCharacter.dragStartY || y), 2));
var isQuickTap = timeDiff < 300 && distanceMoved < 20;
if (isQuickTap && draggedCharacter.isOnBoard && draggedCharacter.boardSlot) {
// Quick tap on character in slot - remove it
var slotToRemoveFrom = draggedCharacter.boardSlot;
slotToRemoveFrom.removeCharacter();
// Reset scale
tween(draggedCharacter, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeIn
});
draggedCharacter = null;
return;
}
var slot = getMixingSlotAt(x, y);
// Check if we're dropping on an empty slot
if (slot && slot.isEmpty) {
// If character was already on board, remove from previous slot
if (draggedCharacter.isOnBoard && draggedCharacter.boardSlot) {
draggedCharacter.boardSlot.removeCharacter();
}
slot.addCharacter(draggedCharacter);
} else if (slot && !slot.isEmpty && draggedCharacter.isOnBoard) {
// Handle swapping characters between slots
var oldSlot = draggedCharacter.boardSlot;
var swapCharacter = slot.character;
// Remove both characters
if (oldSlot) oldSlot.removeCharacter();
slot.removeCharacter();
// Add them to swapped positions
slot.addCharacter(draggedCharacter);
if (oldSlot && swapCharacter) oldSlot.addCharacter(swapCharacter);
} else {
// Return to original position if not dropped on a valid slot
draggedCharacter.returnToOriginalPosition();
}
// Reset scale
tween(draggedCharacter, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeIn
});
draggedCharacter = null;
}
};
oren_beat
Sound effect
horror_oren_beat
Sound effect
raddy_beat
Sound effect
horror_raddy_effect
Sound effect
wenda_voice
Sound effect
horror_wenda_voice
Sound effect
alt_horror_wenda_effect
Sound effect
jevin_voice
Sound effect
horror_jevin_voice
Sound effect
inky_effect
Sound effect
alt_horror_jevin_voice
Sound effect
horror_inky_effect
Sound effect
Cool_Guy_voice
Sound effect
horror_cool_guy_voice
Sound effect