sandsim/js/physics.js
Kacper Kostka (aider) 34dd7e2d62 Based on the changes you've made, the implementation looks complete and well-structured. The new physics objects (square, circle, and triangle) have been added with the following key features:
1. They can be created using the new buttons in the UI
2. They fall due to gravity
3. They rotate while falling
4. They bounce and collide with world elements
5. They come to rest when they stop moving

The changes have been made to the following files:
- `index.html`: Added new buttons and script reference
- `js/constants.js`: Added new element types for physics objects
- `js/elements/physics_objects.js`: New file with physics object implementation
- `js/physics.js`: Added call to update physics objects
- `js/render.js`: Added rendering of physics objects

The implementation looks solid and should work as expected. Is there anything specific you'd like me to review or explain further about the physics objects?
2025-04-05 17:15:08 +02:00

82 lines
3.1 KiB
JavaScript

// Physics simulation functions
function updatePhysics(timestamp) {
// Check if we should update physics based on the update rate
if (timestamp && lastPhysicsTime && timestamp - lastPhysicsTime < physicsUpdateRate) {
return;
}
lastPhysicsTime = timestamp || 0;
// Update physics objects
updatePhysicsObjects();
// Get visible chunks
const visibleChunks = getVisibleChunks();
// Increment fire update counter
fireUpdateCounter++;
// Process each visible chunk
for (const { chunkX, chunkY, isVisible } of visibleChunks) {
// Skip physics calculations for chunks that are not visible
if (!isVisible) continue;
const chunk = getOrCreateChunk(chunkX, chunkY);
let chunkModified = false;
// Process from bottom to top, right to left for correct gravity simulation
for (let y = CHUNK_SIZE - 1; y >= 0; y--) {
// Alternate direction each row for more natural flow
const startX = y % 2 === 0 ? 0 : CHUNK_SIZE - 1;
const endX = y % 2 === 0 ? CHUNK_SIZE : -1;
const step = y % 2 === 0 ? 1 : -1;
for (let x = startX; x !== endX; x += step) {
const index = y * CHUNK_SIZE + x;
const type = chunk[index];
if (type === EMPTY || type === STONE || type === WOOD || type === LEAF) continue;
const worldX = chunkX * CHUNK_SIZE + x;
const worldY = chunkY * CHUNK_SIZE + y;
// Use a lookup table for faster element updates
const updateFunctions = {
[SAND]: updateSand,
[WATER]: updateWater,
[DIRT]: updateDirt,
[GRASS]: updateGrass,
[SEED]: updateSeed,
[GRASS_BLADE]: updateGrassBlade,
[FLOWER]: updateFlower,
[TREE_SEED]: updateTreeSeed,
[FIRE]: updateFire,
[LAVA]: updateLava
};
const updateFunction = updateFunctions[type];
if (updateFunction) {
const wasModified = updateFunction(worldX, worldY);
if (wasModified) {
chunkModified = true;
}
}
}
}
// Mark chunk as dirty if it was modified
if (chunkModified) {
dirtyChunks.add(getChunkKey(chunkX, chunkY));
}
}
// Adaptive physics rate based on FPS
if (fps < 30 && physicsUpdateRate < 32) {
// If FPS is low, update physics less frequently
physicsUpdateRate = Math.min(32, physicsUpdateRate + 2);
} else if (fps > 50 && physicsUpdateRate > 16) {
// If FPS is high, update physics more frequently
physicsUpdateRate = Math.max(16, physicsUpdateRate - 2);
}
}