sandsim/js/elements/rabbit.js
Kacper Kostka (aider) 60c2db558f feat: Add rabbit element with jumping and movement behaviors
This commit introduces a new rabbit element with the following features:
- Jumping mechanics with variable height
- Random direction changes
- Falling and basic ground interaction
- Color variations
- Avoidance of water

The changes include:
- Added RABBIT constant to element types
- Created rabbit.js with updateRabbit function
- Added RABBIT_COLORS to constants
- Implemented basic rabbit movement and behavior logic
2025-04-05 15:57:54 +02:00

111 lines
4.1 KiB
JavaScript

// Rabbit element behaviors
function updateRabbit(x, y) {
const metadata = getMetadata(x, y) || {};
// Initialize rabbit metadata if it doesn't exist
if (!metadata.initialized) {
metadata.initialized = true;
metadata.jumpCooldown = 0;
metadata.direction = Math.random() > 0.5 ? 1 : -1; // 1 for right, -1 for left
metadata.jumpHeight = 0;
metadata.colorIndex = Math.floor(Math.random() * RABBIT_COLORS.length);
setMetadata(x, y, metadata);
return true;
}
// Update metadata
metadata.jumpCooldown = Math.max(0, metadata.jumpCooldown - 1);
// Check if rabbit is on solid ground
const onGround = getPixel(x, y + 1) !== EMPTY && getPixel(x, y + 1) !== WATER;
// Rabbit falls if there's nothing below
if (!onGround && metadata.jumpHeight <= 0) {
if (getPixel(x, y + 1) === EMPTY) {
setPixel(x, y, EMPTY);
setPixel(x, y + 1, RABBIT);
moveMetadata(x, y, x, y + 1);
return true;
}
// Rabbit can swim but prefers not to
else if (getPixel(x, y + 1) === WATER) {
// 50% chance to swim down or stay in place
if (Math.random() < 0.5) {
setPixel(x, y, EMPTY);
setPixel(x, y + 1, RABBIT);
moveMetadata(x, y, x, y + 1);
return true;
}
// When in water, try to jump out
metadata.jumpCooldown = 0;
}
}
// Rabbit jumps occasionally when on ground
if (onGround && metadata.jumpCooldown === 0) {
// Start a jump
metadata.jumpHeight = 3 + Math.floor(Math.random() * 2); // Jump 3-4 blocks high
metadata.jumpCooldown = 30 + Math.floor(Math.random() * 50); // Wait 30-80 frames before next jump
// Randomly change direction sometimes
if (Math.random() < 0.3) {
metadata.direction = -metadata.direction;
}
setMetadata(x, y, metadata);
}
// Execute jump if jump height is positive
if (metadata.jumpHeight > 0) {
// Move up
if (getPixel(x, y - 1) === EMPTY) {
setPixel(x, y, EMPTY);
setPixel(x, y - 1, RABBIT);
moveMetadata(x, y, x, y - 1);
metadata.jumpHeight--;
setMetadata(x, y - 1, metadata);
return true;
}
// If can't move up, try moving diagonally up in current direction
else if (getPixel(x + metadata.direction, y - 1) === EMPTY) {
setPixel(x, y, EMPTY);
setPixel(x + metadata.direction, y - 1, RABBIT);
moveMetadata(x, y, x + metadata.direction, y - 1);
metadata.jumpHeight--;
setMetadata(x + metadata.direction, y - 1, metadata);
return true;
}
// If can't move diagonally up, try moving horizontally
else if (getPixel(x + metadata.direction, y) === EMPTY) {
setPixel(x, y, EMPTY);
setPixel(x + metadata.direction, y, RABBIT);
moveMetadata(x, y, x + metadata.direction, y);
metadata.jumpHeight = 0; // End jump if blocked
setMetadata(x + metadata.direction, y, metadata);
return true;
}
// If completely blocked, end jump
else {
metadata.jumpHeight = 0;
setMetadata(x, y, metadata);
}
}
// Move horizontally when not jumping
else if (metadata.jumpCooldown > 0 && metadata.jumpCooldown < 15 && onGround) {
// Hop horizontally between jumps
if (getPixel(x + metadata.direction, y) === EMPTY) {
setPixel(x, y, EMPTY);
setPixel(x + metadata.direction, y, RABBIT);
moveMetadata(x, y, x + metadata.direction, y);
return true;
}
// If blocked, try to change direction
else {
metadata.direction = -metadata.direction;
setMetadata(x, y, metadata);
}
}
return false;
}