User prompt
Reduce arena shrink time to 45 seconds
User prompt
If you knock your opponent down the sensitivity returns to normal
User prompt
If you knock your opponent down the vulnerability is reset
User prompt
each hit makes you sensitive by a small amount ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Sumo Showdown Arena
Initial prompt
an arena this arena is sometimes round, sometimes square, sometimes rectangular 4 players everyone is single everyone has the right to fall 4 times everyone tries to throw each other down if it exceeds 1 minute the arena gradually shrinks
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Player = Container.expand(function (id, color, x, y) {
var self = Container.call(this);
self.id = id;
self.lives = 4;
self.isDragging = false;
self.isAI = id !== 1; // Player 1 is human, others are AI
self.respawning = false;
self.speed = 5;
self.pushForce = 15;
self.mass = 1;
self.sensitivity = 1; // Base sensitivity to impacts
self.velocity = {
x: 0,
y: 0
};
self.canMove = true;
// Attach the player graphic
self.graphic = self.attachAsset('player' + id, {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0
});
// Create lives display
self.livesContainer = new Container();
self.addChild(self.livesContainer);
self.livesDisplay = [];
for (var i = 0; i < self.lives; i++) {
var life = LK.getAsset('life', {
anchorX: 0.5,
anchorY: 0.5
});
life.x = i * 35 - (self.lives - 1) * 35 / 2;
life.y = -70;
self.livesDisplay.push(life);
self.livesContainer.addChild(life);
}
// Position player
self.x = x;
self.y = y;
// Handle input events
self.down = function (x, y, obj) {
if (self.id === 1 && self.canMove && !self.respawning) {
self.isDragging = true;
console.log("Player dragging started");
}
};
self.up = function (x, y, obj) {
self.isDragging = false;
};
// Method to lose a life
self.loseLife = function () {
if (self.respawning) return;
self.lives--;
if (self.lives >= 0 && self.livesDisplay[self.lives]) {
self.livesContainer.removeChild(self.livesDisplay[self.lives]);
}
LK.getSound('fall').play();
if (self.lives <= 0) {
// Player is eliminated
self.canMove = false;
self.visible = false;
self.eliminated = true;
return true; // Player eliminated
} else {
// Respawn player
self.respawn();
return false; // Player still in game
}
};
// Method to respawn player
self.respawn = function () {
self.respawning = true;
self.alpha = 0.5;
// Place player in a safe position
var angle = Math.random() * Math.PI * 2;
var radius = arena.width * 0.3;
self.x = arena.x + Math.cos(angle) * radius;
self.y = arena.y + Math.sin(angle) * radius;
// Reset velocity
self.velocity.x = 0;
self.velocity.y = 0;
// Partially reset sensitivity on respawn (can't fully escape consequences)
var oldSensitivity = self.sensitivity;
self.sensitivity = Math.max(1, self.sensitivity * 0.7);
// Visual feedback for sensitivity reset
if (oldSensitivity > self.sensitivity) {
tween(self, {
alpha: 0.2
}, {
duration: 300,
onFinish: function onFinish() {
tween(self, {
alpha: 0.5
}, {
duration: 300
});
}
});
}
// Make player immune for a short time
LK.setTimeout(function () {
self.respawning = false;
self.alpha = 1;
}, 2000);
};
// Method to check if player is off the arena
self.checkOffArena = function () {
if (self.respawning) return false;
var dx = self.x - arena.x;
var dy = self.y - arena.y;
var distanceSquared = dx * dx + dy * dy;
// Different check depending on arena shape
if (gameState.arenaShape === 'circle') {
var radiusSquared = Math.pow(arena.width / 2, 2);
return distanceSquared > radiusSquared;
} else if (gameState.arenaShape === 'square') {
var halfWidth = arena.width / 2;
return Math.abs(dx) > halfWidth || Math.abs(dy) > halfWidth;
} else if (gameState.arenaShape === 'rectangle') {
var halfWidth = arena.width / 2;
var halfHeight = arena.height / 2;
return Math.abs(dx) > halfWidth || Math.abs(dy) > halfHeight;
}
return false;
};
// AI movement logic
self.updateAI = function () {
if (!self.isAI || !self.canMove || self.respawning) return;
// Simple AI behavior:
// 1. Move toward center if close to edge
// 2. Otherwise move toward nearest player to push them off
var dx = self.x - arena.x;
var dy = self.y - arena.y;
var distanceToCenter = Math.sqrt(dx * dx + dy * dy);
// If close to edge, move toward center
if (distanceToCenter > arena.width * 0.4) {
var angleToCenter = Math.atan2(arena.y - self.y, arena.x - self.x);
self.velocity.x += Math.cos(angleToCenter) * 0.5;
self.velocity.y += Math.sin(angleToCenter) * 0.5;
} else {
// Find nearest player
var nearestPlayer = null;
var minDistance = Infinity;
for (var i = 0; i < players.length; i++) {
var otherPlayer = players[i];
if (otherPlayer === self || !otherPlayer.canMove || otherPlayer.respawning) continue;
var otherDx = otherPlayer.x - self.x;
var otherDy = otherPlayer.y - self.y;
var distance = Math.sqrt(otherDx * otherDx + otherDy * otherDy);
if (distance < minDistance) {
minDistance = distance;
nearestPlayer = otherPlayer;
}
}
// Move toward nearest player
if (nearestPlayer) {
var angleToPlayer = Math.atan2(nearestPlayer.y - self.y, nearestPlayer.x - self.x);
self.velocity.x += Math.cos(angleToPlayer) * 0.5;
self.velocity.y += Math.sin(angleToPlayer) * 0.5;
}
}
};
// Physics update
self.update = function () {
if (!self.canMove) return;
// Update AI movement
self.updateAI();
// Apply physics
self.velocity.x *= 0.95; // Apply friction
self.velocity.y *= 0.95;
self.x += self.velocity.x;
self.y += self.velocity.y;
// Update visual representation of sensitivity
var baseTint = self.id === 1 ? 0xff0000 : self.id === 2 ? 0x0000ff : self.id === 3 ? 0x00ff00 : 0xffff00;
// Mix in white based on sensitivity to create a visual indicator
var sensitivityFactor = Math.min(1, (self.sensitivity - 1) / 3); // Cap at 4x base sensitivity
var r = (baseTint >> 16 & 0xFF) + (255 - (baseTint >> 16 & 0xFF)) * sensitivityFactor;
var g = (baseTint >> 8 & 0xFF) + (255 - (baseTint >> 8 & 0xFF)) * sensitivityFactor;
var b = (baseTint & 0xFF) + (255 - (baseTint & 0xFF)) * sensitivityFactor;
var newTint = Math.floor(r) << 16 | Math.floor(g) << 8 | Math.floor(b);
self.graphic.tint = newTint;
// Check if off arena
if (self.checkOffArena()) {
var eliminated = self.loseLife();
if (eliminated) {
checkGameEnd();
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var players = [];
var arena;
var timerBar;
var timerBarFill;
var timerText;
var statusText;
var matchTimer = 45; // 45 seconds until arena starts shrinking
var totalMatchTime = 180; // 3 minutes total match time
var gameState = {
started: false,
shrinking: false,
ended: false,
arenaShape: 'circle',
// 'circle', 'square', or 'rectangle'
shrinkAmount: 0.995,
// Arena shrinks to 0.5% per frame when shrinking
roundNumber: 1
};
// Initialize arena
function initArena() {
// Remove old arena if it exists
if (arena) {
game.removeChild(arena);
}
// Create new arena based on current shape
arena = LK.getAsset('arena', {
anchorX: 0.5,
anchorY: 0.5
});
// Set arena dimensions based on shape
if (gameState.arenaShape === 'circle') {
arena.width = 1800;
arena.height = 1800;
} else if (gameState.arenaShape === 'square') {
arena.width = 1600;
arena.height = 1600;
arena.tint = 0x8B4513; // Slightly different color for square
} else if (gameState.arenaShape === 'rectangle') {
arena.width = 2000;
arena.height = 1200;
arena.tint = 0x996633; // Slightly different color for rectangle
}
arena.x = 2048 / 2;
arena.y = 2732 / 2;
game.addChild(arena);
// Make sure arena is behind players
for (var i = 0; i < players.length; i++) {
if (players[i]) {
game.removeChild(players[i]);
game.addChild(players[i]);
}
}
}
// Initialize players
function initPlayers() {
// Clear existing players
for (var i = 0; i < players.length; i++) {
if (players[i]) {
game.removeChild(players[i]);
}
}
players = [];
// Create 4 players
var positions = [{
x: arena.x - arena.width * 0.3,
y: arena.y - arena.height * 0.3
}, {
x: arena.x + arena.width * 0.3,
y: arena.y - arena.height * 0.3
}, {
x: arena.x - arena.width * 0.3,
y: arena.y + arena.height * 0.3
}, {
x: arena.x + arena.width * 0.3,
y: arena.y + arena.height * 0.3
}];
for (var i = 0; i < 4; i++) {
var player = new Player(i + 1, i + 1, positions[i].x, positions[i].y);
// Ensure sensitivity starts at base level for new rounds
player.sensitivity = 1;
players.push(player);
game.addChild(player);
}
}
// Initialize UI
function initUI() {
// Create timer bar
timerBar = LK.getAsset('timer', {
anchorX: 0.5,
anchorY: 0.5
});
timerBar.x = 2048 / 2;
timerBar.y = 80;
timerBarFill = LK.getAsset('timerFill', {
anchorX: 0,
anchorY: 0.5
});
timerBarFill.x = -timerBarFill.width / 2;
timerBarFill.y = 0;
timerBar.addChild(timerBarFill);
game.addChild(timerBar);
// Create timer text
timerText = new Text2("01:00", {
size: 50,
fill: 0xFFFFFF
});
timerText.anchor.set(0.5, 0.5);
timerText.x = 2048 / 2;
timerText.y = 150;
game.addChild(timerText);
// Create status text
statusText = new Text2("Round " + gameState.roundNumber + " - Push opponents off the arena!", {
size: 60,
fill: 0xFFFFFF
});
statusText.anchor.set(0.5, 0.5);
statusText.x = 2048 / 2;
statusText.y = 220;
game.addChild(statusText);
}
// Check for game end
function checkGameEnd() {
var playersAlive = 0;
var lastAlivePlayer = null;
for (var i = 0; i < players.length; i++) {
if (players[i] && players[i].lives > 0) {
playersAlive++;
lastAlivePlayer = players[i];
}
}
if (playersAlive <= 1 && !gameState.ended) {
gameState.ended = true;
if (lastAlivePlayer) {
statusText.setText("Player " + lastAlivePlayer.id + " wins!");
LK.setScore(lastAlivePlayer.id);
// Show win screen after a short delay
LK.setTimeout(function () {
LK.showYouWin();
}, 2000);
} else {
statusText.setText("Draw!");
// Show game over after a short delay
LK.setTimeout(function () {
LK.showGameOver();
}, 2000);
}
}
}
// Reset game for a new round
function startNewRound() {
// Increment round number
gameState.roundNumber++;
// Change arena shape for the next round
if (gameState.arenaShape === 'circle') {
gameState.arenaShape = 'square';
} else if (gameState.arenaShape === 'square') {
gameState.arenaShape = 'rectangle';
} else {
gameState.arenaShape = 'circle';
}
// Reset game state
gameState.started = false;
gameState.shrinking = false;
gameState.ended = false;
matchTimer = 45;
// Initialize game elements
initArena();
initPlayers();
// Update UI
statusText.setText("Round " + gameState.roundNumber + " - Push opponents off the arena!");
// Start the game
gameState.started = true;
}
// Handle dragging the human player
function handleDrag(x, y) {
if (players[0] && players[0].isDragging && players[0].canMove && !players[0].respawning) {
// Calculate direction vector
var dx = x - players[0].x;
var dy = y - players[0].y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Apply force toward the touch position
if (distance > 0) {
var maxSpeed = 10;
var speedX = Math.min(dx, maxSpeed);
var speedY = Math.min(dy, maxSpeed);
players[0].velocity.x += speedX * 0.1;
players[0].velocity.y += speedY * 0.1;
}
}
}
// Collision detection and resolution between players
function handleCollisions() {
for (var i = 0; i < players.length; i++) {
var playerA = players[i];
if (!playerA || !playerA.canMove || playerA.respawning) continue;
for (var j = i + 1; j < players.length; j++) {
var playerB = players[j];
if (!playerB || !playerB.canMove || playerB.respawning) continue;
var dx = playerB.x - playerA.x;
var dy = playerB.y - playerA.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var minDistance = playerA.graphic.width / 2 + playerB.graphic.width / 2;
if (distance < minDistance) {
// Collision detected
LK.getSound('push').play();
// Calculate collision response
var angle = Math.atan2(dy, dx);
var overlap = minDistance - distance;
// Move players apart
var moveX = Math.cos(angle) * overlap * 0.5;
var moveY = Math.sin(angle) * overlap * 0.5;
playerA.x -= moveX;
playerA.y -= moveY;
playerB.x += moveX;
playerB.y += moveY;
// Calculate impulse
var impulse = 2 * (playerA.velocity.x * Math.cos(angle) + playerA.velocity.y * Math.sin(angle) - playerB.velocity.x * Math.cos(angle) - playerB.velocity.y * Math.sin(angle)) / (playerA.mass + playerB.mass);
// Apply impulse with sensitivity factor
playerA.velocity.x -= impulse * playerA.mass * Math.cos(angle) * 1.5 * playerA.sensitivity;
playerA.velocity.y -= impulse * playerA.mass * Math.sin(angle) * 1.5 * playerA.sensitivity;
playerB.velocity.x += impulse * playerB.mass * Math.cos(angle) * 1.5 * playerB.sensitivity;
playerB.velocity.y += impulse * playerB.mass * Math.sin(angle) * 1.5 * playerB.sensitivity;
// Increase sensitivity on collision
playerA.sensitivity += 0.05;
playerB.sensitivity += 0.05;
// Visual feedback for increased sensitivity
tween(playerA.graphic, {
alpha: 0.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(playerA.graphic, {
alpha: 1
}, {
duration: 200
});
}
});
tween(playerB.graphic, {
alpha: 0.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(playerB.graphic, {
alpha: 1
}, {
duration: 200
});
}
});
}
}
}
}
// Format time as MM:SS
function formatTime(seconds) {
var minutes = Math.floor(seconds / 60);
var remainingSeconds = Math.floor(seconds % 60);
return (minutes < 10 ? "0" : "") + minutes + ":" + (remainingSeconds < 10 ? "0" : "") + remainingSeconds;
}
// Update timer
function updateTimer() {
matchTimer -= 1 / 60; // Decrease by 1/60th of a second (assuming 60 FPS)
if (matchTimer <= 0 && !gameState.shrinking) {
// Start shrinking the arena
gameState.shrinking = true;
statusText.setText("Arena is shrinking!");
LK.getSound('warning').play();
// Flash the status text
tween(statusText, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
tween(statusText, {
alpha: 1
}, {
duration: 300
});
}
});
}
// Update timer display
timerText.setText(formatTime(Math.max(0, matchTimer)));
// Update timer bar
var progress = Math.max(0, matchTimer / 45);
timerBarFill.width = 496 * progress;
// If arena is shrinking, change timer color to red
if (gameState.shrinking) {
timerBarFill.tint = 0xFF0000;
}
}
// Initialize the game
function initGame() {
// Set arena shape to circle for first round
gameState.arenaShape = 'circle';
gameState.roundNumber = 1;
// Initialize game elements
initArena();
initPlayers();
initUI();
// Reset game state
gameState.started = true;
gameState.shrinking = false;
gameState.ended = false;
matchTimer = 45;
// Play background music
LK.playMusic('background');
}
// Handle game events
game.down = function (x, y, obj) {
// Forward touch events to the human player
if (players[0]) {
players[0].down(x, y, obj);
}
};
game.up = function (x, y, obj) {
// Forward touch events to the human player
if (players[0]) {
players[0].up(x, y, obj);
}
};
game.move = function (x, y, obj) {
handleDrag(x, y);
};
// Main game loop
game.update = function () {
// Initialize game on first update
if (!gameState.started) {
initGame();
return;
}
// Don't update if game ended
if (gameState.ended) return;
// Update timer
updateTimer();
// Update players
for (var i = 0; i < players.length; i++) {
if (players[i]) {
players[i].update();
}
}
// Handle collisions between players
handleCollisions();
// Shrink arena if time has run out
if (gameState.shrinking && arena.width > 400) {
arena.width *= gameState.shrinkAmount;
arena.height *= gameState.shrinkAmount;
}
};
// Initialize game
initGame(); ===================================================================
--- original.js
+++ change.js
@@ -17,9 +17,8 @@
self.speed = 5;
self.pushForce = 15;
self.mass = 1;
self.sensitivity = 1; // Base sensitivity to impacts
- self.lastPositionBeforeCollision = null; // Track position before collision for knockoff detection
self.velocity = {
x: 0,
y: 0
};
@@ -65,38 +64,8 @@
if (self.lives >= 0 && self.livesDisplay[self.lives]) {
self.livesContainer.removeChild(self.livesDisplay[self.lives]);
}
LK.getSound('fall').play();
- // Check which player knocked this player off
- for (var i = 0; i < players.length; i++) {
- var knocker = players[i];
- if (knocker === self || !knocker.canMove) continue;
- // If this player was recently in collision with the knocker
- if (self.lastPositionBeforeCollision && knocker.lastPositionBeforeCollision) {
- var dx = self.lastPositionBeforeCollision.x - knocker.lastPositionBeforeCollision.x;
- var dy = self.lastPositionBeforeCollision.y - knocker.lastPositionBeforeCollision.y;
- var distance = Math.sqrt(dx * dx + dy * dy);
- // If they were close enough, consider this player knocked off by the knocker
- if (distance < knocker.graphic.width * 1.5) {
- // Reset knocker's sensitivity to normal
- knocker.sensitivity = 1.0;
- // Visual feedback for sensitivity reset
- tween(knocker, {
- alpha: 0.2
- }, {
- duration: 300,
- onFinish: function onFinish() {
- tween(knocker, {
- alpha: 1
- }, {
- duration: 300
- });
- }
- });
- break;
- }
- }
- }
if (self.lives <= 0) {
// Player is eliminated
self.canMove = false;
self.visible = false;
@@ -247,9 +216,9 @@
var timerBar;
var timerBarFill;
var timerText;
var statusText;
-var matchTimer = 60; // 60 seconds until arena starts shrinking
+var matchTimer = 45; // 45 seconds until arena starts shrinking
var totalMatchTime = 180; // 3 minutes total match time
var gameState = {
started: false,
shrinking: false,
@@ -405,9 +374,9 @@
// Reset game state
gameState.started = false;
gameState.shrinking = false;
gameState.ended = false;
- matchTimer = 60;
+ matchTimer = 45;
// Initialize game elements
initArena();
initPlayers();
// Update UI
@@ -466,17 +435,8 @@
playerB.velocity.y += impulse * playerB.mass * Math.sin(angle) * 1.5 * playerB.sensitivity;
// Increase sensitivity on collision
playerA.sensitivity += 0.05;
playerB.sensitivity += 0.05;
- // Track positions before impulse to check if players get knocked off
- playerA.lastPositionBeforeCollision = {
- x: playerA.x,
- y: playerA.y
- };
- playerB.lastPositionBeforeCollision = {
- x: playerB.x,
- y: playerB.y
- };
// Visual feedback for increased sensitivity
tween(playerA.graphic, {
alpha: 0.3
}, {
@@ -535,9 +495,9 @@
}
// Update timer display
timerText.setText(formatTime(Math.max(0, matchTimer)));
// Update timer bar
- var progress = Math.max(0, matchTimer / 60);
+ var progress = Math.max(0, matchTimer / 45);
timerBarFill.width = 496 * progress;
// If arena is shrinking, change timer color to red
if (gameState.shrinking) {
timerBarFill.tint = 0xFF0000;
@@ -555,9 +515,9 @@
// Reset game state
gameState.started = true;
gameState.shrinking = false;
gameState.ended = false;
- matchTimer = 60;
+ matchTimer = 45;
// Play background music
LK.playMusic('background');
}
// Handle game events
bird's eye view of a round rocky arena surrounded by flames decorated with red lava. In-Game asset. 2d. High contrast. No shadows
hearth. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
fighter 1. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
fighter 2. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
fighter 3 . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
fighter 4. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat