/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Bone = Container.expand(function () { var self = Container.call(this); var boneGraphics = self.attachAsset('bone', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.direction = 1; // 1 for right, -1 for left self.creationTime = LK.ticks; // Track when bone was created self.update = function () { self.x += self.speed * self.direction; }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); self.bulletType = 'orange'; // 'orange' or 'blue' self.speed = 6; self.directionX = 0; self.directionY = 0; self.creationTime = LK.ticks; // Track when bullet was created var bulletGraphics; if (self.bulletType === 'orange') { bulletGraphics = self.attachAsset('orangeBullet', { anchorX: 0.5, anchorY: 0.5 }); } else { bulletGraphics = self.attachAsset('blueBullet', { anchorX: 0.5, anchorY: 0.5 }); } self.update = function () { if (self.isChasing) { // Update direction to chase chara var dx = chara.x - self.x; var dy = chara.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.directionX = dx / distance * 0.8; self.directionY = dy / distance * 0.8; } } if (self.gravityEffect) { // Add gravity effect self.directionY += 0.02; } self.x += self.speed * self.directionX; self.y += self.speed * self.directionY; }; return self; }); var Chara = Container.expand(function () { var self = Container.call(this); var charaGraphics = self.attachAsset('chara', { anchorX: 0.5, anchorY: 1.0 }); self.health = 100; self.maxHealth = 100; self.invulnerable = false; self.canAttack = true; self.takeDamage = function (damage) { if (!self.invulnerable) { self.health -= damage; self.invulnerable = true; // Flash red when hit LK.effects.flashObject(self, 0xff0000, 500); LK.getSound('hit').play(); // Brief invulnerability period LK.setTimeout(function () { self.invulnerable = false; }, 1000); if (self.health <= 0) { LK.showGameOver(); } } }; return self; }); var GasterBlaster = Container.expand(function () { var self = Container.call(this); var blasterGraphics = self.attachAsset('sans', { anchorX: 0.5, anchorY: 0.5 }); blasterGraphics.scaleX = 1.5; blasterGraphics.scaleY = 1.5; self.chargingTime = 0; self.isCharging = true; self.isFiring = false; self.laserBeam = null; self.creationTime = LK.ticks; self.update = function () { if (self.isCharging) { self.chargingTime++; // Flash white while charging if (self.chargingTime % 10 < 5) { blasterGraphics.tint = 0xFFFFFF; } else { blasterGraphics.tint = 0xFFFFFF; } // Start firing after 2 seconds if (self.chargingTime >= 120) { self.startFiring(); } } }; self.startFiring = function () { self.isCharging = false; self.isFiring = true; blasterGraphics.tint = 0xFFFFFF; // Create laser beam self.laserBeam = LK.getAsset('healthBar', { anchorX: 0, anchorY: 0.5, width: 2048, height: 20 }); self.laserBeam.x = self.x; self.laserBeam.y = self.y; self.laserBeam.tint = 0xFFFF00; game.addChild(self.laserBeam); // Fire for 1 second then destroy LK.setTimeout(function () { if (self.laserBeam) { self.laserBeam.destroy(); } self.destroy(); }, 1000); }; return self; }); var Sans = Container.expand(function () { var self = Container.call(this); var sansGraphics = self.attachAsset(selectedSansSkin, { anchorX: 0.5, anchorY: 1.0 }); self.health = 100; self.phase = 1; self.attackTimer = 0; self.isAttacking = false; self.currentSkin = selectedSansSkin; // Track current skin self.updateSkin = function () { // If skin has changed, update the graphics if (self.currentSkin !== selectedSansSkin) { // Remove old graphics self.removeChild(sansGraphics); // Create new graphics with selected skin sansGraphics = self.attachAsset(selectedSansSkin, { anchorX: 0.5, anchorY: 1.0 }); self.currentSkin = selectedSansSkin; } }; self.update = function () { // Update skin if changed self.updateSkin(); self.attackTimer++; // Trigger attack patterns based on timer if (self.attackTimer % 120 === 0 && !self.isAttacking) { self.startAttack(); } }; self.startAttack = function () { self.isAttacking = true; // Reset attack timer for next attack LK.setTimeout(function () { self.isAttacking = false; }, 2000); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game state variables var gameState = 'menu'; // 'menu', 'skinSelection', or 'playing' var gamePhase = 1; var attackPattern = 0; var patternTimer = 0; var survivalTime = 0; var selectedSansSkin = 'sans'; // Default skin var sansSkins = ['sans', 'sans_blue', 'sans_red', 'sans_green', 'sans_purple', 'sans_gold', 'sans_dark', 'sans_purple']; // Available skins array var selectedSkinIndex = 0; // Attack speed multipliers for different skins (higher = faster attacks) var skinSpeedMultipliers = { 'sans': 1.0, // Normal speed 'sans_blue': 1.0, // Normal speed 'sans_red': 1.0, // Normal speed 'sans_green': 1.0, // Normal speed 'sans_purple': 1.0, // Normal speed 'sans_gold': 1.5, // Second fastest 'sans_dark': 2.0 // Fastest }; // Menu UI elements var titleText; var playButton; var skinButton; var skinText; // Create start screen UI titleText = new Text2('CHARA VS SANS', { size: 120, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 800; game.addChild(titleText); playButton = LK.getAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1200, width: 400, height: 120 }); playButton.tint = 0x00FF00; game.addChild(playButton); var playButtonText = new Text2('PLAY', { size: 80, fill: 0xFFFFFF }); playButtonText.anchor.set(0.5, 0.5); playButtonText.x = 1024; playButtonText.y = 1200; game.addChild(playButtonText); skinButton = LK.getAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1400, width: 500, height: 100 }); skinButton.tint = 0x0066FF; game.addChild(skinButton); skinText = new Text2('SKIN: SANS', { size: 60, fill: 0xFFFFFF }); skinText.anchor.set(0.5, 0.5); skinText.x = 1024; skinText.y = 1400; game.addChild(skinText); // Skin selection screen elements (initially hidden) var skinScreenTitle; var skinBoxes = []; var backButton; skinScreenTitle = new Text2('SELECT SANS SKIN', { size: 100, fill: 0xFFFFFF }); skinScreenTitle.anchor.set(0.5, 0.5); skinScreenTitle.x = 1024; skinScreenTitle.y = 400; skinScreenTitle.visible = false; game.addChild(skinScreenTitle); // Create 6 skin selection boxes in 2 rows of 3 var skinNames = ['CLASSIC', 'BLUE', 'RED', 'GREEN', 'PURPLE', 'GOLD', 'DARK', 'PURPLE2']; var skinColors = [0x888888, 0x0066FF, 0xFF0000, 0x00FF00, 0x9900FF, 0xFFD700, 0x333333, 0xAA44FF]; var skinImages = []; var skinNameTexts = []; for (var i = 0; i < 8; i++) { var skinBox = LK.getAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, width: 280, height: 180 }); var row = Math.floor(i / 4); var col = i % 4; skinBox.x = 300 + col * 360; skinBox.y = 800 + row * 280; skinBox.tint = skinColors[i]; skinBox.visible = false; skinBoxes.push(skinBox); game.addChild(skinBox); // Add Sans skin image on top of the box var skinImage = LK.getAsset(sansSkins[i], { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); skinImage.x = skinBox.x; skinImage.y = skinBox.y - 20; skinImage.visible = false; skinImages.push(skinImage); game.addChild(skinImage); // Add skin name text below the box var skinNameText = new Text2(skinNames[i], { size: 40, fill: 0xFFFFFF }); skinNameText.anchor.set(0.5, 0.5); skinNameText.x = skinBox.x; skinNameText.y = skinBox.y + 130; skinNameText.visible = false; skinNameTexts.push(skinNameText); game.addChild(skinNameText); } // Back button for skin selection backButton = LK.getAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1800, width: 300, height: 100 }); backButton.tint = 0xFF6600; backButton.visible = false; game.addChild(backButton); var backButtonText = new Text2('BACK', { size: 60, fill: 0x000000 }); backButtonText.anchor.set(0.5, 0.5); backButtonText.x = 1024; backButtonText.y = 1800; backButtonText.visible = false; game.addChild(backButtonText); // Battle area setup (initially hidden) var battleArea = game.addChild(LK.getAsset('battleArea', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1800 })); battleArea.visible = false; // Create characters (initially hidden) var chara = game.addChild(new Chara()); chara.x = 1024; chara.y = 1750; chara.visible = false; var sans = game.addChild(new Sans()); sans.x = 1024; sans.y = 1400; sans.visible = false; // Health UI (initially hidden) var healthBg = LK.getAsset('healthBg', { anchorX: 0.5, anchorY: 0, x: 0, y: 100 }); LK.gui.top.addChild(healthBg); healthBg.visible = false; var healthBar = LK.getAsset('healthBar', { anchorX: 0.5, anchorY: 0, x: 0, y: 100 }); LK.gui.top.addChild(healthBar); healthBar.visible = false; // Score display (initially hidden) var scoreText = new Text2('Time: 0', { size: 80, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.topRight.addChild(scoreText); scoreText.x = -150; scoreText.y = 50; scoreText.visible = false; // Attack arrays var bones = []; var bullets = []; var gasterBlasters = []; // Function to start the game function startGame() { gameState = 'playing'; // Hide menu elements titleText.visible = false; playButton.visible = false; playButtonText.visible = false; skinButton.visible = false; skinText.visible = false; // Show game elements battleArea.visible = true; chara.visible = true; sans.visible = true; healthBg.visible = true; healthBar.visible = true; scoreText.visible = true; // Reset game state chara.health = 100; survivalTime = 0; patternTimer = 0; attackPattern = 0; } // Function to show skin selection screen function showSkinSelection() { gameState = 'skinSelection'; // Hide menu elements titleText.visible = false; playButton.visible = false; playButtonText.visible = false; skinButton.visible = false; skinText.visible = false; // Show skin selection elements skinScreenTitle.visible = true; backButton.visible = true; backButtonText.visible = true; for (var i = 0; i < skinBoxes.length; i++) { skinBoxes[i].visible = true; skinImages[i].visible = true; skinNameTexts[i].visible = true; } } // Function to go back to main menu function showMainMenu() { gameState = 'menu'; // Hide skin selection elements skinScreenTitle.visible = false; backButton.visible = false; backButtonText.visible = false; for (var i = 0; i < skinBoxes.length; i++) { skinBoxes[i].visible = false; skinImages[i].visible = false; skinNameTexts[i].visible = false; } // Show menu elements titleText.visible = true; playButton.visible = true; playButtonText.visible = true; skinButton.visible = true; skinText.visible = true; } // Function to select a skin function selectSkin(skinIndex) { selectedSkinIndex = skinIndex; selectedSansSkin = sansSkins[skinIndex]; skinText.setText('SKIN: ' + ['CLASSIC', 'BLUE', 'RED', 'GREEN', 'PURPLE', 'GOLD', 'DARK', 'PURPLE2'][skinIndex]); showMainMenu(); } // Drag controls var isDragging = false; game.down = function (x, y, obj) { if (gameState === 'menu') { // Check if play button was clicked if (x >= 824 && x <= 1224 && y >= 1140 && y <= 1260) { startGame(); return; } // Check if skin button was clicked if (x >= 774 && x <= 1274 && y >= 1350 && y <= 1450) { showSkinSelection(); return; } } else if (gameState === 'skinSelection') { // Check skin box clicks for (var i = 0; i < skinBoxes.length; i++) { var skinBox = skinBoxes[i]; if (x >= skinBox.x - 150 && x <= skinBox.x + 150 && y >= skinBox.y - 100 && y <= skinBox.y + 100) { selectSkin(i); return; } } // Check back button click if (x >= 874 && x <= 1174 && y >= 1750 && y <= 1850) { showMainMenu(); return; } } else if (gameState === 'playing') { isDragging = true; chara.x = x; chara.y = Math.max(y, 1600); // Keep in battle area } }; game.move = function (x, y, obj) { if (isDragging && gameState === 'playing') { chara.x = Math.max(100, Math.min(1948, x)); // Keep within screen bounds chara.y = Math.max(1600, Math.min(2000, y)); // Keep in battle area } }; game.up = function (x, y, obj) { if (gameState === 'playing') { isDragging = false; } }; // Attack pattern functions function createBoneWall() { var numBones = 5; var startY = 1500; var spacing = 80; for (var i = 0; i < numBones; i++) { var bone = new Bone(); bone.x = -100; bone.y = startY + i * spacing; bone.direction = 1; bones.push(bone); game.addChild(bone); } LK.getSound('attack').play(); } function createBulletSpiral() { var centerX = 1024; var centerY = 1500; var numBullets = 8; for (var i = 0; i < numBullets; i++) { var bullet = new Bullet(); bullet.bulletType = i % 2 === 0 ? 'orange' : 'blue'; bullet.x = centerX; bullet.y = centerY; var angle = i / numBullets * Math.PI * 2; bullet.directionX = Math.cos(angle); bullet.directionY = Math.sin(angle); bullets.push(bullet); game.addChild(bullet); } LK.getSound('attack').play(); } function createRandomBullets() { var numBullets = 6; for (var i = 0; i < numBullets; i++) { var bullet = new Bullet(); bullet.bulletType = Math.random() > 0.5 ? 'orange' : 'blue'; bullet.x = Math.random() * 1800 + 124; bullet.y = 1300; // Aim towards chara var dx = chara.x - bullet.x; var dy = chara.y - bullet.y; var distance = Math.sqrt(dx * dx + dy * dy); bullet.directionX = dx / distance; bullet.directionY = dy / distance; bullets.push(bullet); game.addChild(bullet); } LK.getSound('attack').play(); } function createBoneSlam() { // Create bones falling from top var numBones = 8; for (var i = 0; i < numBones; i++) { var bone = new Bone(); bone.x = 200 + i * 200; bone.y = 1200; bone.direction = 0; bone.speed = 0; bone.rotation = Math.PI / 2; // Horizontal bones.push(bone); game.addChild(bone); // Animate slam down with tween tween(bone, { y: 1900 }, { duration: 800, easing: tween.easeIn }); } LK.getSound('attack').play(); } function createTeleportBones() { // Sans teleports bones around the battle area var positions = [{ x: 300, y: 1600 }, { x: 700, y: 1700 }, { x: 1100, y: 1650 }, { x: 1500, y: 1750 }, { x: 1800, y: 1600 }]; for (var i = 0; i < positions.length; i++) { var bone = new Bone(); bone.x = positions[i].x; bone.y = positions[i].y; bone.direction = 0; bone.speed = 0; bone.alpha = 0; bones.push(bone); game.addChild(bone); // Fade in effect tween(bone, { alpha: 1 }, { duration: 500, easing: tween.easeOut }); } LK.getSound('attack').play(); } function createGravityWave() { // Create a wave of bullets that curve downward var numBullets = 12; var startX = 100; for (var i = 0; i < numBullets; i++) { var bullet = new Bullet(); bullet.bulletType = 'blue'; bullet.x = startX + i * 150; bullet.y = 1400; bullet.directionX = 0.3; bullet.directionY = 0.1; bullet.gravityEffect = true; bullets.push(bullet); game.addChild(bullet); } LK.getSound('attack').play(); } function createCircularTrap() { // Create a circle of bones that closes in var numBones = 16; var centerX = 1024; var centerY = 1700; var radius = 600; for (var i = 0; i < numBones; i++) { var bone = new Bone(); var angle = i / numBones * Math.PI * 2; bone.x = centerX + Math.cos(angle) * radius; bone.y = centerY + Math.sin(angle) * radius; bone.direction = 0; bone.speed = 0; bone.rotation = angle + Math.PI / 2; bones.push(bone); game.addChild(bone); // Move bones inward tween(bone, { x: centerX + Math.cos(angle) * 200, y: centerY + Math.sin(angle) * 200 }, { duration: 2000, easing: tween.easeInOut }); } LK.getSound('attack').play(); } function createBulletWave() { // Horizontal wave of bullets var numBullets = 10; for (var i = 0; i < numBullets; i++) { var bullet = new Bullet(); bullet.bulletType = i % 3 === 0 ? 'orange' : 'blue'; bullet.x = -50; bullet.y = 1500 + Math.sin(i * 0.5) * 100; bullet.directionX = 1; bullet.directionY = Math.sin(i * 0.8) * 0.3; bullet.speed = 4 + i * 0.2; bullets.push(bullet); game.addChild(bullet); } LK.getSound('attack').play(); } function createChasingBullets() { // Bullets that follow chara's position var numBullets = 4; for (var i = 0; i < numBullets; i++) { var bullet = new Bullet(); bullet.bulletType = 'orange'; bullet.x = 200 + i * 400; bullet.y = 1300; bullet.isChasing = true; bullet.speed = 2; bullets.push(bullet); game.addChild(bullet); } LK.getSound('attack').play(); } function createGasterBlasters() { // Create multiple Gaster Blasters that charge and fire laser beams at random positions var numBlasters = 3; for (var i = 0; i < numBlasters; i++) { var blaster = new GasterBlaster(); // Generate random position across the battle area blaster.x = Math.random() * 1800 + 124; // Random X between 124 and 1924 blaster.y = Math.random() * 400 + 1400; // Random Y between 1400 and 1800 (battle area) gasterBlasters.push(blaster); game.addChild(blaster); // Stagger the blaster appearances tween(blaster, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.easeOut }); } LK.getSound('attack').play(); } game.update = function () { // Only run game logic when playing if (gameState !== 'playing') { return; } survivalTime++; patternTimer++; // Update score display var timeSeconds = Math.floor(survivalTime / 60); scoreText.setText('Time: ' + timeSeconds + 's'); LK.setScore(timeSeconds); // Update health bar var healthPercent = chara.health / chara.maxHealth; healthBar.scaleX = healthPercent; // Trigger attack patterns with skin-based speed multipliers var attackDelay = Math.floor(180 / skinSpeedMultipliers[selectedSansSkin]); if (patternTimer % attackDelay === 0) { // Attack frequency based on selected skin attackPattern = Math.floor(Math.random() * 10); switch (attackPattern) { case 0: createBoneWall(); break; case 1: createBulletSpiral(); break; case 2: createRandomBullets(); break; case 3: createBoneSlam(); break; case 4: createTeleportBones(); break; case 5: createGravityWave(); break; case 6: createCircularTrap(); break; case 7: createBulletWave(); break; case 8: createChasingBullets(); break; case 9: createGasterBlasters(); break; } } // Update and check bones for (var i = bones.length - 1; i >= 0; i--) { var bone = bones[i]; // Check collision with chara if (bone.intersects(chara)) { chara.takeDamage(20); } // Remove bones after 5 seconds (5 seconds = 300 ticks at 60fps) if (LK.ticks - bone.creationTime >= 300) { bone.destroy(); bones.splice(i, 1); continue; } // Remove off-screen bones if (bone.x > 2200 || bone.x < -200) { bone.destroy(); bones.splice(i, 1); } } // Update and check bullets for (var j = bullets.length - 1; j >= 0; j--) { var bullet = bullets[j]; // Check collision with chara if (bullet.intersects(chara)) { chara.takeDamage(15); bullet.destroy(); bullets.splice(j, 1); continue; } // Remove bullets after 5 seconds (5 seconds = 300 ticks at 60fps) if (LK.ticks - bullet.creationTime >= 300) { bullet.destroy(); bullets.splice(j, 1); continue; } // Remove off-screen bullets if (bullet.x > 2200 || bullet.x < -200 || bullet.y > 2800 || bullet.y < -100) { bullet.destroy(); bullets.splice(j, 1); } } // Update and check Gaster Blasters for (var k = gasterBlasters.length - 1; k >= 0; k--) { var blaster = gasterBlasters[k]; // Check laser beam collision with chara if (blaster.isFiring && blaster.laserBeam && blaster.laserBeam.intersects(chara)) { chara.takeDamage(25); } // Remove blasters after 5 seconds if (LK.ticks - blaster.creationTime >= 300) { if (blaster.laserBeam) { blaster.laserBeam.destroy(); } blaster.destroy(); gasterBlasters.splice(k, 1); } } // Win condition - survive for 2 minutes (7200 ticks) if (survivalTime >= 7200) { LK.showYouWin(); } // Increase difficulty over time if (survivalTime % 1800 === 0) { // Every 30 seconds gamePhase++; // Reduce pattern delay for increased difficulty with skin multiplier var baseDelay = Math.floor(120 / skinSpeedMultipliers[selectedSansSkin]); if (patternTimer % baseDelay === 0) { patternTimer = Math.floor(60 / skinSpeedMultipliers[selectedSansSkin]); // Faster attacks based on skin } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bone = Container.expand(function () {
var self = Container.call(this);
var boneGraphics = self.attachAsset('bone', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.direction = 1; // 1 for right, -1 for left
self.creationTime = LK.ticks; // Track when bone was created
self.update = function () {
self.x += self.speed * self.direction;
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
self.bulletType = 'orange'; // 'orange' or 'blue'
self.speed = 6;
self.directionX = 0;
self.directionY = 0;
self.creationTime = LK.ticks; // Track when bullet was created
var bulletGraphics;
if (self.bulletType === 'orange') {
bulletGraphics = self.attachAsset('orangeBullet', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
bulletGraphics = self.attachAsset('blueBullet', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.update = function () {
if (self.isChasing) {
// Update direction to chase chara
var dx = chara.x - self.x;
var dy = chara.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.directionX = dx / distance * 0.8;
self.directionY = dy / distance * 0.8;
}
}
if (self.gravityEffect) {
// Add gravity effect
self.directionY += 0.02;
}
self.x += self.speed * self.directionX;
self.y += self.speed * self.directionY;
};
return self;
});
var Chara = Container.expand(function () {
var self = Container.call(this);
var charaGraphics = self.attachAsset('chara', {
anchorX: 0.5,
anchorY: 1.0
});
self.health = 100;
self.maxHealth = 100;
self.invulnerable = false;
self.canAttack = true;
self.takeDamage = function (damage) {
if (!self.invulnerable) {
self.health -= damage;
self.invulnerable = true;
// Flash red when hit
LK.effects.flashObject(self, 0xff0000, 500);
LK.getSound('hit').play();
// Brief invulnerability period
LK.setTimeout(function () {
self.invulnerable = false;
}, 1000);
if (self.health <= 0) {
LK.showGameOver();
}
}
};
return self;
});
var GasterBlaster = Container.expand(function () {
var self = Container.call(this);
var blasterGraphics = self.attachAsset('sans', {
anchorX: 0.5,
anchorY: 0.5
});
blasterGraphics.scaleX = 1.5;
blasterGraphics.scaleY = 1.5;
self.chargingTime = 0;
self.isCharging = true;
self.isFiring = false;
self.laserBeam = null;
self.creationTime = LK.ticks;
self.update = function () {
if (self.isCharging) {
self.chargingTime++;
// Flash white while charging
if (self.chargingTime % 10 < 5) {
blasterGraphics.tint = 0xFFFFFF;
} else {
blasterGraphics.tint = 0xFFFFFF;
}
// Start firing after 2 seconds
if (self.chargingTime >= 120) {
self.startFiring();
}
}
};
self.startFiring = function () {
self.isCharging = false;
self.isFiring = true;
blasterGraphics.tint = 0xFFFFFF;
// Create laser beam
self.laserBeam = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0.5,
width: 2048,
height: 20
});
self.laserBeam.x = self.x;
self.laserBeam.y = self.y;
self.laserBeam.tint = 0xFFFF00;
game.addChild(self.laserBeam);
// Fire for 1 second then destroy
LK.setTimeout(function () {
if (self.laserBeam) {
self.laserBeam.destroy();
}
self.destroy();
}, 1000);
};
return self;
});
var Sans = Container.expand(function () {
var self = Container.call(this);
var sansGraphics = self.attachAsset(selectedSansSkin, {
anchorX: 0.5,
anchorY: 1.0
});
self.health = 100;
self.phase = 1;
self.attackTimer = 0;
self.isAttacking = false;
self.currentSkin = selectedSansSkin; // Track current skin
self.updateSkin = function () {
// If skin has changed, update the graphics
if (self.currentSkin !== selectedSansSkin) {
// Remove old graphics
self.removeChild(sansGraphics);
// Create new graphics with selected skin
sansGraphics = self.attachAsset(selectedSansSkin, {
anchorX: 0.5,
anchorY: 1.0
});
self.currentSkin = selectedSansSkin;
}
};
self.update = function () {
// Update skin if changed
self.updateSkin();
self.attackTimer++;
// Trigger attack patterns based on timer
if (self.attackTimer % 120 === 0 && !self.isAttacking) {
self.startAttack();
}
};
self.startAttack = function () {
self.isAttacking = true;
// Reset attack timer for next attack
LK.setTimeout(function () {
self.isAttacking = false;
}, 2000);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game state variables
var gameState = 'menu'; // 'menu', 'skinSelection', or 'playing'
var gamePhase = 1;
var attackPattern = 0;
var patternTimer = 0;
var survivalTime = 0;
var selectedSansSkin = 'sans'; // Default skin
var sansSkins = ['sans', 'sans_blue', 'sans_red', 'sans_green', 'sans_purple', 'sans_gold', 'sans_dark', 'sans_purple']; // Available skins array
var selectedSkinIndex = 0;
// Attack speed multipliers for different skins (higher = faster attacks)
var skinSpeedMultipliers = {
'sans': 1.0,
// Normal speed
'sans_blue': 1.0,
// Normal speed
'sans_red': 1.0,
// Normal speed
'sans_green': 1.0,
// Normal speed
'sans_purple': 1.0,
// Normal speed
'sans_gold': 1.5,
// Second fastest
'sans_dark': 2.0 // Fastest
};
// Menu UI elements
var titleText;
var playButton;
var skinButton;
var skinText;
// Create start screen UI
titleText = new Text2('CHARA VS SANS', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
game.addChild(titleText);
playButton = LK.getAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1200,
width: 400,
height: 120
});
playButton.tint = 0x00FF00;
game.addChild(playButton);
var playButtonText = new Text2('PLAY', {
size: 80,
fill: 0xFFFFFF
});
playButtonText.anchor.set(0.5, 0.5);
playButtonText.x = 1024;
playButtonText.y = 1200;
game.addChild(playButtonText);
skinButton = LK.getAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1400,
width: 500,
height: 100
});
skinButton.tint = 0x0066FF;
game.addChild(skinButton);
skinText = new Text2('SKIN: SANS', {
size: 60,
fill: 0xFFFFFF
});
skinText.anchor.set(0.5, 0.5);
skinText.x = 1024;
skinText.y = 1400;
game.addChild(skinText);
// Skin selection screen elements (initially hidden)
var skinScreenTitle;
var skinBoxes = [];
var backButton;
skinScreenTitle = new Text2('SELECT SANS SKIN', {
size: 100,
fill: 0xFFFFFF
});
skinScreenTitle.anchor.set(0.5, 0.5);
skinScreenTitle.x = 1024;
skinScreenTitle.y = 400;
skinScreenTitle.visible = false;
game.addChild(skinScreenTitle);
// Create 6 skin selection boxes in 2 rows of 3
var skinNames = ['CLASSIC', 'BLUE', 'RED', 'GREEN', 'PURPLE', 'GOLD', 'DARK', 'PURPLE2'];
var skinColors = [0x888888, 0x0066FF, 0xFF0000, 0x00FF00, 0x9900FF, 0xFFD700, 0x333333, 0xAA44FF];
var skinImages = [];
var skinNameTexts = [];
for (var i = 0; i < 8; i++) {
var skinBox = LK.getAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
width: 280,
height: 180
});
var row = Math.floor(i / 4);
var col = i % 4;
skinBox.x = 300 + col * 360;
skinBox.y = 800 + row * 280;
skinBox.tint = skinColors[i];
skinBox.visible = false;
skinBoxes.push(skinBox);
game.addChild(skinBox);
// Add Sans skin image on top of the box
var skinImage = LK.getAsset(sansSkins[i], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
skinImage.x = skinBox.x;
skinImage.y = skinBox.y - 20;
skinImage.visible = false;
skinImages.push(skinImage);
game.addChild(skinImage);
// Add skin name text below the box
var skinNameText = new Text2(skinNames[i], {
size: 40,
fill: 0xFFFFFF
});
skinNameText.anchor.set(0.5, 0.5);
skinNameText.x = skinBox.x;
skinNameText.y = skinBox.y + 130;
skinNameText.visible = false;
skinNameTexts.push(skinNameText);
game.addChild(skinNameText);
}
// Back button for skin selection
backButton = LK.getAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1800,
width: 300,
height: 100
});
backButton.tint = 0xFF6600;
backButton.visible = false;
game.addChild(backButton);
var backButtonText = new Text2('BACK', {
size: 60,
fill: 0x000000
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = 1024;
backButtonText.y = 1800;
backButtonText.visible = false;
game.addChild(backButtonText);
// Battle area setup (initially hidden)
var battleArea = game.addChild(LK.getAsset('battleArea', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1800
}));
battleArea.visible = false;
// Create characters (initially hidden)
var chara = game.addChild(new Chara());
chara.x = 1024;
chara.y = 1750;
chara.visible = false;
var sans = game.addChild(new Sans());
sans.x = 1024;
sans.y = 1400;
sans.visible = false;
// Health UI (initially hidden)
var healthBg = LK.getAsset('healthBg', {
anchorX: 0.5,
anchorY: 0,
x: 0,
y: 100
});
LK.gui.top.addChild(healthBg);
healthBg.visible = false;
var healthBar = LK.getAsset('healthBar', {
anchorX: 0.5,
anchorY: 0,
x: 0,
y: 100
});
LK.gui.top.addChild(healthBar);
healthBar.visible = false;
// Score display (initially hidden)
var scoreText = new Text2('Time: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.topRight.addChild(scoreText);
scoreText.x = -150;
scoreText.y = 50;
scoreText.visible = false;
// Attack arrays
var bones = [];
var bullets = [];
var gasterBlasters = [];
// Function to start the game
function startGame() {
gameState = 'playing';
// Hide menu elements
titleText.visible = false;
playButton.visible = false;
playButtonText.visible = false;
skinButton.visible = false;
skinText.visible = false;
// Show game elements
battleArea.visible = true;
chara.visible = true;
sans.visible = true;
healthBg.visible = true;
healthBar.visible = true;
scoreText.visible = true;
// Reset game state
chara.health = 100;
survivalTime = 0;
patternTimer = 0;
attackPattern = 0;
}
// Function to show skin selection screen
function showSkinSelection() {
gameState = 'skinSelection';
// Hide menu elements
titleText.visible = false;
playButton.visible = false;
playButtonText.visible = false;
skinButton.visible = false;
skinText.visible = false;
// Show skin selection elements
skinScreenTitle.visible = true;
backButton.visible = true;
backButtonText.visible = true;
for (var i = 0; i < skinBoxes.length; i++) {
skinBoxes[i].visible = true;
skinImages[i].visible = true;
skinNameTexts[i].visible = true;
}
}
// Function to go back to main menu
function showMainMenu() {
gameState = 'menu';
// Hide skin selection elements
skinScreenTitle.visible = false;
backButton.visible = false;
backButtonText.visible = false;
for (var i = 0; i < skinBoxes.length; i++) {
skinBoxes[i].visible = false;
skinImages[i].visible = false;
skinNameTexts[i].visible = false;
}
// Show menu elements
titleText.visible = true;
playButton.visible = true;
playButtonText.visible = true;
skinButton.visible = true;
skinText.visible = true;
}
// Function to select a skin
function selectSkin(skinIndex) {
selectedSkinIndex = skinIndex;
selectedSansSkin = sansSkins[skinIndex];
skinText.setText('SKIN: ' + ['CLASSIC', 'BLUE', 'RED', 'GREEN', 'PURPLE', 'GOLD', 'DARK', 'PURPLE2'][skinIndex]);
showMainMenu();
}
// Drag controls
var isDragging = false;
game.down = function (x, y, obj) {
if (gameState === 'menu') {
// Check if play button was clicked
if (x >= 824 && x <= 1224 && y >= 1140 && y <= 1260) {
startGame();
return;
}
// Check if skin button was clicked
if (x >= 774 && x <= 1274 && y >= 1350 && y <= 1450) {
showSkinSelection();
return;
}
} else if (gameState === 'skinSelection') {
// Check skin box clicks
for (var i = 0; i < skinBoxes.length; i++) {
var skinBox = skinBoxes[i];
if (x >= skinBox.x - 150 && x <= skinBox.x + 150 && y >= skinBox.y - 100 && y <= skinBox.y + 100) {
selectSkin(i);
return;
}
}
// Check back button click
if (x >= 874 && x <= 1174 && y >= 1750 && y <= 1850) {
showMainMenu();
return;
}
} else if (gameState === 'playing') {
isDragging = true;
chara.x = x;
chara.y = Math.max(y, 1600); // Keep in battle area
}
};
game.move = function (x, y, obj) {
if (isDragging && gameState === 'playing') {
chara.x = Math.max(100, Math.min(1948, x)); // Keep within screen bounds
chara.y = Math.max(1600, Math.min(2000, y)); // Keep in battle area
}
};
game.up = function (x, y, obj) {
if (gameState === 'playing') {
isDragging = false;
}
};
// Attack pattern functions
function createBoneWall() {
var numBones = 5;
var startY = 1500;
var spacing = 80;
for (var i = 0; i < numBones; i++) {
var bone = new Bone();
bone.x = -100;
bone.y = startY + i * spacing;
bone.direction = 1;
bones.push(bone);
game.addChild(bone);
}
LK.getSound('attack').play();
}
function createBulletSpiral() {
var centerX = 1024;
var centerY = 1500;
var numBullets = 8;
for (var i = 0; i < numBullets; i++) {
var bullet = new Bullet();
bullet.bulletType = i % 2 === 0 ? 'orange' : 'blue';
bullet.x = centerX;
bullet.y = centerY;
var angle = i / numBullets * Math.PI * 2;
bullet.directionX = Math.cos(angle);
bullet.directionY = Math.sin(angle);
bullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('attack').play();
}
function createRandomBullets() {
var numBullets = 6;
for (var i = 0; i < numBullets; i++) {
var bullet = new Bullet();
bullet.bulletType = Math.random() > 0.5 ? 'orange' : 'blue';
bullet.x = Math.random() * 1800 + 124;
bullet.y = 1300;
// Aim towards chara
var dx = chara.x - bullet.x;
var dy = chara.y - bullet.y;
var distance = Math.sqrt(dx * dx + dy * dy);
bullet.directionX = dx / distance;
bullet.directionY = dy / distance;
bullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('attack').play();
}
function createBoneSlam() {
// Create bones falling from top
var numBones = 8;
for (var i = 0; i < numBones; i++) {
var bone = new Bone();
bone.x = 200 + i * 200;
bone.y = 1200;
bone.direction = 0;
bone.speed = 0;
bone.rotation = Math.PI / 2; // Horizontal
bones.push(bone);
game.addChild(bone);
// Animate slam down with tween
tween(bone, {
y: 1900
}, {
duration: 800,
easing: tween.easeIn
});
}
LK.getSound('attack').play();
}
function createTeleportBones() {
// Sans teleports bones around the battle area
var positions = [{
x: 300,
y: 1600
}, {
x: 700,
y: 1700
}, {
x: 1100,
y: 1650
}, {
x: 1500,
y: 1750
}, {
x: 1800,
y: 1600
}];
for (var i = 0; i < positions.length; i++) {
var bone = new Bone();
bone.x = positions[i].x;
bone.y = positions[i].y;
bone.direction = 0;
bone.speed = 0;
bone.alpha = 0;
bones.push(bone);
game.addChild(bone);
// Fade in effect
tween(bone, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
}
LK.getSound('attack').play();
}
function createGravityWave() {
// Create a wave of bullets that curve downward
var numBullets = 12;
var startX = 100;
for (var i = 0; i < numBullets; i++) {
var bullet = new Bullet();
bullet.bulletType = 'blue';
bullet.x = startX + i * 150;
bullet.y = 1400;
bullet.directionX = 0.3;
bullet.directionY = 0.1;
bullet.gravityEffect = true;
bullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('attack').play();
}
function createCircularTrap() {
// Create a circle of bones that closes in
var numBones = 16;
var centerX = 1024;
var centerY = 1700;
var radius = 600;
for (var i = 0; i < numBones; i++) {
var bone = new Bone();
var angle = i / numBones * Math.PI * 2;
bone.x = centerX + Math.cos(angle) * radius;
bone.y = centerY + Math.sin(angle) * radius;
bone.direction = 0;
bone.speed = 0;
bone.rotation = angle + Math.PI / 2;
bones.push(bone);
game.addChild(bone);
// Move bones inward
tween(bone, {
x: centerX + Math.cos(angle) * 200,
y: centerY + Math.sin(angle) * 200
}, {
duration: 2000,
easing: tween.easeInOut
});
}
LK.getSound('attack').play();
}
function createBulletWave() {
// Horizontal wave of bullets
var numBullets = 10;
for (var i = 0; i < numBullets; i++) {
var bullet = new Bullet();
bullet.bulletType = i % 3 === 0 ? 'orange' : 'blue';
bullet.x = -50;
bullet.y = 1500 + Math.sin(i * 0.5) * 100;
bullet.directionX = 1;
bullet.directionY = Math.sin(i * 0.8) * 0.3;
bullet.speed = 4 + i * 0.2;
bullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('attack').play();
}
function createChasingBullets() {
// Bullets that follow chara's position
var numBullets = 4;
for (var i = 0; i < numBullets; i++) {
var bullet = new Bullet();
bullet.bulletType = 'orange';
bullet.x = 200 + i * 400;
bullet.y = 1300;
bullet.isChasing = true;
bullet.speed = 2;
bullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('attack').play();
}
function createGasterBlasters() {
// Create multiple Gaster Blasters that charge and fire laser beams at random positions
var numBlasters = 3;
for (var i = 0; i < numBlasters; i++) {
var blaster = new GasterBlaster();
// Generate random position across the battle area
blaster.x = Math.random() * 1800 + 124; // Random X between 124 and 1924
blaster.y = Math.random() * 400 + 1400; // Random Y between 1400 and 1800 (battle area)
gasterBlasters.push(blaster);
game.addChild(blaster);
// Stagger the blaster appearances
tween(blaster, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeOut
});
}
LK.getSound('attack').play();
}
game.update = function () {
// Only run game logic when playing
if (gameState !== 'playing') {
return;
}
survivalTime++;
patternTimer++;
// Update score display
var timeSeconds = Math.floor(survivalTime / 60);
scoreText.setText('Time: ' + timeSeconds + 's');
LK.setScore(timeSeconds);
// Update health bar
var healthPercent = chara.health / chara.maxHealth;
healthBar.scaleX = healthPercent;
// Trigger attack patterns with skin-based speed multipliers
var attackDelay = Math.floor(180 / skinSpeedMultipliers[selectedSansSkin]);
if (patternTimer % attackDelay === 0) {
// Attack frequency based on selected skin
attackPattern = Math.floor(Math.random() * 10);
switch (attackPattern) {
case 0:
createBoneWall();
break;
case 1:
createBulletSpiral();
break;
case 2:
createRandomBullets();
break;
case 3:
createBoneSlam();
break;
case 4:
createTeleportBones();
break;
case 5:
createGravityWave();
break;
case 6:
createCircularTrap();
break;
case 7:
createBulletWave();
break;
case 8:
createChasingBullets();
break;
case 9:
createGasterBlasters();
break;
}
}
// Update and check bones
for (var i = bones.length - 1; i >= 0; i--) {
var bone = bones[i];
// Check collision with chara
if (bone.intersects(chara)) {
chara.takeDamage(20);
}
// Remove bones after 5 seconds (5 seconds = 300 ticks at 60fps)
if (LK.ticks - bone.creationTime >= 300) {
bone.destroy();
bones.splice(i, 1);
continue;
}
// Remove off-screen bones
if (bone.x > 2200 || bone.x < -200) {
bone.destroy();
bones.splice(i, 1);
}
}
// Update and check bullets
for (var j = bullets.length - 1; j >= 0; j--) {
var bullet = bullets[j];
// Check collision with chara
if (bullet.intersects(chara)) {
chara.takeDamage(15);
bullet.destroy();
bullets.splice(j, 1);
continue;
}
// Remove bullets after 5 seconds (5 seconds = 300 ticks at 60fps)
if (LK.ticks - bullet.creationTime >= 300) {
bullet.destroy();
bullets.splice(j, 1);
continue;
}
// Remove off-screen bullets
if (bullet.x > 2200 || bullet.x < -200 || bullet.y > 2800 || bullet.y < -100) {
bullet.destroy();
bullets.splice(j, 1);
}
}
// Update and check Gaster Blasters
for (var k = gasterBlasters.length - 1; k >= 0; k--) {
var blaster = gasterBlasters[k];
// Check laser beam collision with chara
if (blaster.isFiring && blaster.laserBeam && blaster.laserBeam.intersects(chara)) {
chara.takeDamage(25);
}
// Remove blasters after 5 seconds
if (LK.ticks - blaster.creationTime >= 300) {
if (blaster.laserBeam) {
blaster.laserBeam.destroy();
}
blaster.destroy();
gasterBlasters.splice(k, 1);
}
}
// Win condition - survive for 2 minutes (7200 ticks)
if (survivalTime >= 7200) {
LK.showYouWin();
}
// Increase difficulty over time
if (survivalTime % 1800 === 0) {
// Every 30 seconds
gamePhase++;
// Reduce pattern delay for increased difficulty with skin multiplier
var baseDelay = Math.floor(120 / skinSpeedMultipliers[selectedSansSkin]);
if (patternTimer % baseDelay === 0) {
patternTimer = Math.floor(60 / skinSpeedMultipliers[selectedSansSkin]); // Faster attacks based on skin
}
}
};
Corazón pixel art de color rojo. In-Game asset. 2d. High contrast. No shadows
Un hueso de sans. In-Game asset. 2d. High contrast. No shadows
Sans todo poderoso. In-Game asset. 2d. High contrast. No shadows
a blue ball (no de deporte solo una pelota azul). In-Game asset. 2d. High contrast. No shadows
Sans de color azul. In-Game asset. 2d. High contrast. No shadows
Sans color rojo. In-Game asset. 2d. High contrast. No shadows
Sans pintado de color verde. In-Game asset. 2d. High contrast. No shadows
Sans color morado. In-Game asset. 2d. High contrast. No shadows
Sans de color dorado épico y brillante. In-Game asset. 2d. High contrast. No shadows
Sans consumido por la oscuridad misma sans oscuro y maligno. In-Game asset. 2d. High contrast. No shadows