diff --git a/static/js/collisions.js b/static/js/collisions.js
index 70cda7e..4bc83d7 100644
--- a/static/js/collisions.js
+++ b/static/js/collisions.js
@@ -2,6 +2,7 @@ import { gameState } from './gameState.js';
 import { getDistance, getSize, getRandomPosition, findSafeSpawnLocation } from './utils.js';
 import { FOOD_SIZE, FOOD_SCORE, COLLISION_THRESHOLD, FOOD_COUNT, AI_COUNT, STARTING_SCORE, WORLD_SIZE } from './config.js';
 import { respawnAI } from './entities.js';
+import { doTrianglesOverlap, createTriangle } from './triangleCollision.js';
 
 export function handleFoodCollisions() {
     // Player cells eating food
@@ -11,8 +12,15 @@ export function handleFoodCollisions() {
             const playerSize = getSize(playerCell.score);
 
             if (distance < playerSize + FOOD_SIZE) {
-                playerCell.score += FOOD_SCORE;
-                return false;
+                // Create triangles for more precise collision detection
+                const playerTriangle = createTriangle(playerCell.x, playerCell.y, playerSize, playerCell.rotation || 0);
+                const foodTriangle = createTriangle(food.x, food.y, FOOD_SIZE, food.rotation || 0);
+                
+                // Check for triangle overlap
+                if (doTrianglesOverlap(playerTriangle, foodTriangle)) {
+                    playerCell.score += FOOD_SCORE;
+                    return false;
+                }
             }
             return true;
         });
@@ -25,8 +33,15 @@ export function handleFoodCollisions() {
             const aiSize = getSize(ai.score);
 
             if (distance < aiSize + FOOD_SIZE) {
-                ai.score += FOOD_SCORE;
-                return false;
+                // Create triangles for more precise collision detection
+                const aiTriangle = createTriangle(ai.x, ai.y, aiSize, ai.rotation || 0);
+                const foodTriangle = createTriangle(food.x, food.y, FOOD_SIZE, food.rotation || 0);
+                
+                // Check for triangle overlap
+                if (doTrianglesOverlap(aiTriangle, foodTriangle)) {
+                    ai.score += FOOD_SCORE;
+                    return false;
+                }
             }
             return true;
         });
@@ -45,22 +60,31 @@ export function handlePlayerAICollisions() {
             if (aiIndicesToRemove.has(aiIndex)) return;
             if (playerCellsToRemove.has(playerCellIndex)) return;
 
+            // First do a quick circle-based distance check for performance
             const distance = getDistance(playerCell, ai);
             const playerSize = getSize(playerCell.score);
             const aiSize = getSize(ai.score);
             const minDistance = playerSize + aiSize;
 
-            if (distance < minDistance) {
-                // Player cell is bigger
-                if (playerSize > aiSize * COLLISION_THRESHOLD) {
-                    const currentGain = scoreGains.get(playerCellIndex) || 0;
-                    scoreGains.set(playerCellIndex, currentGain + ai.score + 100);
-                    aiIndicesToRemove.add(aiIndex);
-                }
-                // AI is bigger
-                else if (aiSize > playerSize * COLLISION_THRESHOLD) {
-                    ai.score += playerCell.score + 100;
-                    playerCellsToRemove.add(playerCellIndex);
+            // Only perform triangle collision if circles are close enough
+            if (distance < minDistance * 1.5) {
+                // Create triangles for more precise collision detection
+                const playerTriangle = createTriangle(playerCell.x, playerCell.y, playerSize, playerCell.rotation || 0);
+                const aiTriangle = createTriangle(ai.x, ai.y, aiSize, ai.rotation || 0);
+                
+                // Check for triangle overlap
+                if (doTrianglesOverlap(playerTriangle, aiTriangle)) {
+                    // Player cell is bigger
+                    if (playerSize > aiSize * COLLISION_THRESHOLD) {
+                        const currentGain = scoreGains.get(playerCellIndex) || 0;
+                        scoreGains.set(playerCellIndex, currentGain + ai.score + 100);
+                        aiIndicesToRemove.add(aiIndex);
+                    }
+                    // AI is bigger
+                    else if (aiSize > playerSize * COLLISION_THRESHOLD) {
+                        ai.score += playerCell.score + 100;
+                        playerCellsToRemove.add(playerCellIndex);
+                    }
                 }
             }
         });
@@ -115,16 +139,24 @@ export function handleAIAICollisions() {
             const ai2Size = getSize(ai2.score);
             const minDistance = ai1Size + ai2Size;
 
-            if (distance < minDistance) {
-                if (ai1Size > ai2Size * COLLISION_THRESHOLD) {
-                    const currentGain = scoreGains.get(i) || 0;
-                    scoreGains.set(i, currentGain + ai2.score + 100);
-                    aisToRemove.add(j);
-                } else if (ai2Size > ai1Size * COLLISION_THRESHOLD) {
-                    const currentGain = scoreGains.get(j) || 0;
-                    scoreGains.set(j, currentGain + ai1.score + 100);
-                    aisToRemove.add(i);
-                    break;
+            // Only perform triangle collision if circles are close enough
+            if (distance < minDistance * 1.5) {
+                // Create triangles for more precise collision detection
+                const ai1Triangle = createTriangle(ai1.x, ai1.y, ai1Size, ai1.rotation || 0);
+                const ai2Triangle = createTriangle(ai2.x, ai2.y, ai2Size, ai2.rotation || 0);
+                
+                // Check for triangle overlap
+                if (doTrianglesOverlap(ai1Triangle, ai2Triangle)) {
+                    if (ai1Size > ai2Size * COLLISION_THRESHOLD) {
+                        const currentGain = scoreGains.get(i) || 0;
+                        scoreGains.set(i, currentGain + ai2.score + 100);
+                        aisToRemove.add(j);
+                    } else if (ai2Size > ai1Size * COLLISION_THRESHOLD) {
+                        const currentGain = scoreGains.get(j) || 0;
+                        scoreGains.set(j, currentGain + ai1.score + 100);
+                        aisToRemove.add(i);
+                        break;
+                    }
                 }
             }
         }
@@ -150,7 +182,8 @@ export function respawnEntities() {
         gameState.food.push({
             x: pos.x,
             y: pos.y,
-            color: `hsl(${Math.random() * 360}, 50%, 50%)`
+            color: `hsl(${Math.random() * 360}, 50%, 50%)`,
+            rotation: Math.random() * Math.PI * 2 // Add random rotation
         });
     }
 
@@ -160,6 +193,10 @@ export function respawnEntities() {
         const newAI = respawnAI();
         newAI.x = safePos.x;
         newAI.y = safePos.y;
+        // Ensure AI has rotation property
+        if (!newAI.hasOwnProperty('rotation')) {
+            newAI.rotation = Math.random() * Math.PI * 2;
+        }
         gameState.aiPlayers.push(newAI);
     }
 
@@ -171,7 +208,8 @@ export function respawnEntities() {
             y: safePos.y,
             score: STARTING_SCORE,
             velocityX: 0,
-            velocityY: 0
+            velocityY: 0,
+            rotation: Math.random() * Math.PI * 2 // Add initial rotation
         });
     }
 }
\ No newline at end of file
diff --git a/static/js/entities.js b/static/js/entities.js
index 01441f2..96b75bd 100644
--- a/static/js/entities.js
+++ b/static/js/entities.js
@@ -165,6 +165,7 @@ function updateCellMerging() {
 }
 
 export function updatePlayer() {
+    // Calculate direction towards mouse
     const dx = mouse.x - window.innerWidth / 2;
     const dy = mouse.y - window.innerHeight / 2;
     const distance = Math.sqrt(dx * dx + dy * dy);
@@ -187,6 +188,11 @@ export function updatePlayer() {
             // Update position
             cell.x = Math.max(0, Math.min(WORLD_SIZE, cell.x + cell.velocityX));
             cell.y = Math.max(0, Math.min(WORLD_SIZE, cell.y + cell.velocityY));
+            
+            // Update rotation based on movement direction
+            if (Math.abs(cell.velocityX) > 0.01 || Math.abs(cell.velocityY) > 0.01) {
+                cell.rotation = Math.atan2(cell.velocityY, cell.velocityX);
+            }
         });
     }
 
@@ -221,6 +227,7 @@ export function splitPlayerCell(cell) {
         score: cell.score / 2,
         velocityX: direction.x * SPLIT_VELOCITY,
         velocityY: direction.y * SPLIT_VELOCITY,
+        rotation: Math.atan2(direction.y, direction.x), // Set rotation based on split direction
         splitTime: now
     };
 
@@ -228,6 +235,7 @@ export function splitPlayerCell(cell) {
     cell.score /= 2;
     cell.velocityX = -direction.x * SPLIT_VELOCITY * 0.5;
     cell.velocityY = -direction.y * SPLIT_VELOCITY * 0.5;
+    cell.rotation = Math.atan2(-direction.y, -direction.x); // Update rotation based on new direction
     cell.splitTime = now;
 
     // Add new cell
@@ -256,6 +264,9 @@ export function updateAI() {
 
         ai.x = Math.max(0, Math.min(WORLD_SIZE, ai.x));
         ai.y = Math.max(0, Math.min(WORLD_SIZE, ai.y));
+        
+        // Update rotation to match movement direction
+        ai.rotation = ai.direction;
     });
 }
 
@@ -272,7 +283,21 @@ export function initEntities() {
         gameState.food.push({
             x: pos.x,
             y: pos.y,
-            color: `hsl(${Math.random() * 360}, 50%, 50%)`
+            color: `hsl(${Math.random() * 360}, 50%, 50%)`,
+            rotation: Math.random() * Math.PI * 2 // Random rotation for triangular food
+        });
+    }
+
+    // Ensure player has at least one cell
+    if (gameState.playerCells.length === 0) {
+        const safePos = findSafeSpawnLocation(gameState);
+        gameState.playerCells.push({
+            x: safePos.x,
+            y: safePos.y,
+            score: STARTING_SCORE,
+            velocityX: 0,
+            velocityY: 0,
+            rotation: 0 // Initial rotation for triangle rendering
         });
     }
 
@@ -285,6 +310,7 @@ export function initEntities() {
             score: AI_STARTING_SCORE,
             color: `hsl(${Math.random() * 360}, 70%, 50%)`,
             direction: Math.random() * Math.PI * 2,
+            rotation: Math.random() * Math.PI * 2, // Initial rotation for triangle rendering
             name: getUnusedAIName()
         };
         gameState.aiPlayers.push(ai);
@@ -301,6 +327,7 @@ export function initEntities() {
 export function respawnAI() {
     const pos = getRandomPosition();
     const name = getUnusedAIName();
+    const rotation = Math.random() * Math.PI * 2;
     
     return {
         x: pos.x,
@@ -308,6 +335,7 @@ export function respawnAI() {
         score: AI_STARTING_SCORE,
         color: `hsl(${Math.random() * 360}, 70%, 50%)`,
         direction: Math.random() * Math.PI * 2,
+        rotation: rotation, // Add rotation for triangle rendering
         name: name
     };
 }
\ No newline at end of file
diff --git a/static/js/renderer.js b/static/js/renderer.js
index fc0853d..b01d9cb 100644
--- a/static/js/renderer.js
+++ b/static/js/renderer.js
@@ -1,6 +1,7 @@
 import { gameState } from './gameState.js';
 import { getSize, calculateCenterOfMass } from './utils.js';
 import { WORLD_SIZE, COLORS, FOOD_SIZE } from './config.js';
+import { createTriangle } from './triangleCollision.js';
 
 let canvas, ctx, minimapCanvas, minimapCtx, scoreElement, leaderboardContent;
 
@@ -29,14 +30,30 @@ function drawCircle(x, y, value, color, isFood) {
     ctx.fill();
 }
 
-function drawCellWithName(x, y, score, color, name) {
-    const size = getSize(score);
+function drawTriangle(x, y, size, color, rotation = 0) {
+    // Create a triangle shape
+    const triangle = createTriangle(x, y, size, rotation);
     
-    // Draw cell
     ctx.beginPath();
-    ctx.arc(x, y, size, 0, Math.PI * 2);
+    ctx.moveTo(triangle.x1, triangle.y1);
+    ctx.lineTo(triangle.x2, triangle.y2);
+    ctx.lineTo(triangle.x3, triangle.y3);
+    ctx.closePath();
+    
     ctx.fillStyle = color;
     ctx.fill();
+    
+    // Add a subtle stroke for better visibility
+    ctx.strokeStyle = 'rgba(0, 0, 0, 0.3)';
+    ctx.lineWidth = 1;
+    ctx.stroke();
+}
+
+function drawCellWithName(x, y, score, color, name, rotation = 0) {
+    const size = getSize(score);
+    
+    // Draw cell as a triangle
+    drawTriangle(x, y, size, color, rotation);
 
     // Draw name
     if (size > 20) {  // Only draw name if cell is big enough
@@ -77,7 +94,7 @@ export function drawGame() {
         
         if (screenX >= -FOOD_SIZE && screenX <= canvas.width + FOOD_SIZE &&
             screenY >= -FOOD_SIZE && screenY <= canvas.height + FOOD_SIZE) {
-            drawCircle(screenX, screenY, FOOD_SIZE, food.color, true);
+            drawTriangle(screenX, screenY, FOOD_SIZE, food.color, food.rotation);
         }
     });
 
@@ -89,7 +106,7 @@ export function drawGame() {
         
         if (screenX >= -size && screenX <= canvas.width + size &&
             screenY >= -size && screenY <= canvas.height + size) {
-            drawCellWithName(screenX, screenY, ai.score, ai.color, ai.name);
+            drawCellWithName(screenX, screenY, ai.score, ai.color, ai.name, ai.rotation);
         }
     });
 
@@ -101,7 +118,7 @@ export function drawGame() {
         
         if (screenX >= -size && screenX <= canvas.width + size &&
             screenY >= -size && screenY <= canvas.height + size) {
-            drawCellWithName(screenX, screenY, cell.score, COLORS.PLAYER, gameState.playerName);
+            drawCellWithName(screenX, screenY, cell.score, COLORS.PLAYER, gameState.playerName, cell.rotation);
         }
     });
 
diff --git a/static/js/triangleCollision.js b/static/js/triangleCollision.js
new file mode 100644
index 0000000..334075b
--- /dev/null
+++ b/static/js/triangleCollision.js
@@ -0,0 +1,222 @@
+/**
+ * Triangle Collision Detection Module
+ * Implements algorithms for detecting overlap between triangles
+ */
+
+/**
+ * Represents a triangle with three vertices
+ * @typedef {Object} Triangle
+ * @property {number} x1 - x-coordinate of first vertex
+ * @property {number} y1 - y-coordinate of first vertex
+ * @property {number} x2 - x-coordinate of second vertex
+ * @property {number} y2 - y-coordinate of second vertex
+ * @property {number} x3 - x-coordinate of third vertex
+ * @property {number} y3 - y-coordinate of third vertex
+ */
+
+/**
+ * Determines if a point is inside a triangle using barycentric coordinates
+ * @param {number} px - x-coordinate of the point
+ * @param {number} py - y-coordinate of the point
+ * @param {Triangle} triangle - The triangle to check against
+ * @returns {boolean} - True if the point is inside the triangle
+ */
+export function isPointInTriangle(px, py, triangle) {
+    const { x1, y1, x2, y2, x3, y3 } = triangle;
+    
+    // Calculate barycentric coordinates
+    const denominator = ((y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3));
+    
+    // Avoid division by zero
+    if (Math.abs(denominator) < 0.0001) return false;
+    
+    const a = ((y2 - y3) * (px - x3) + (x3 - x2) * (py - y3)) / denominator;
+    const b = ((y3 - y1) * (px - x3) + (x1 - x3) * (py - y3)) / denominator;
+    const c = 1 - a - b;
+    
+    // Point is inside if all barycentric coordinates are between 0 and 1
+    return a >= 0 && a <= 1 && b >= 0 && b <= 1 && c >= 0 && c <= 1;
+}
+
+/**
+ * Checks if a line segment intersects with another line segment
+ * @param {number} x1 - x-coordinate of first point of first line
+ * @param {number} y1 - y-coordinate of first point of first line
+ * @param {number} x2 - x-coordinate of second point of first line
+ * @param {number} y2 - y-coordinate of second point of first line
+ * @param {number} x3 - x-coordinate of first point of second line
+ * @param {number} y3 - y-coordinate of first point of second line
+ * @param {number} x4 - x-coordinate of second point of second line
+ * @param {number} y4 - y-coordinate of second point of second line
+ * @returns {boolean} - True if the line segments intersect
+ */
+export function doLinesIntersect(x1, y1, x2, y2, x3, y3, x4, y4) {
+    // Special case: Check if the lines are actually the same line segment
+    if ((x1 === x3 && y1 === y3 && x2 === x4 && y2 === y4) ||
+        (x1 === x4 && y1 === y4 && x2 === x3 && y2 === y3)) {
+        return true;
+    }
+    
+    // Check for the case where one of the endpoints of one line is on the other line
+    // This is a more robust approach for detecting intersections
+    
+    // Function to check if point (px,py) is on line segment (x1,y1)-(x2,y2)
+    function isPointOnLine(px, py, lx1, ly1, lx2, ly2) {
+        // Check if point is within the bounding box of the line segment
+        if (px < Math.min(lx1, lx2) - 0.0001 || px > Math.max(lx1, lx2) + 0.0001 ||
+            py < Math.min(ly1, ly2) - 0.0001 || py > Math.max(ly1, ly2) + 0.0001) {
+            return false;
+        }
+        
+        // Check if point is on the line using cross product
+        const cross = (py - ly1) * (lx2 - lx1) - (px - lx1) * (ly2 - ly1);
+        return Math.abs(cross) < 0.0001;
+    }
+    
+    // Check if any endpoint of one line is on the other line
+    if (isPointOnLine(x1, y1, x3, y3, x4, y4) ||
+        isPointOnLine(x2, y2, x3, y3, x4, y4) ||
+        isPointOnLine(x3, y3, x1, y1, x2, y2) ||
+        isPointOnLine(x4, y4, x1, y1, x2, y2)) {
+        return true;
+    }
+    
+    // Calculate the direction of the lines
+    const d1x = x2 - x1;
+    const d1y = y2 - y1;
+    const d2x = x4 - x3;
+    const d2y = y4 - y3;
+    
+    // Calculate the determinant
+    const denominator = d1y * d2x - d1x * d2y;
+    
+    // Lines are parallel if denominator is close to 0
+    if (Math.abs(denominator) < 0.0001) return false;
+    
+    // Calculate the parameters for the intersection point
+    const d3x = x1 - x3;
+    const d3y = y1 - y3;
+    
+    const t1 = (d2x * d3y - d2y * d3x) / denominator;
+    const t2 = (d1x * d3y - d1y * d3x) / denominator;
+    
+    // Check if the intersection point is within both line segments
+    return t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1;
+}
+
+/**
+ * Checks if two triangles overlap using vertex inclusion and edge intersection tests
+ * @param {Triangle} triangle1 - First triangle
+ * @param {Triangle} triangle2 - Second triangle
+ * @returns {boolean} - True if the triangles overlap
+ */
+export function doTrianglesOverlap(triangle1, triangle2) {
+    // Null check for triangles
+    if (!triangle1 || !triangle2) return false;
+    
+    // Ensure all properties exist
+    const t1Props = ['x1', 'y1', 'x2', 'y2', 'x3', 'y3'];
+    const t2Props = ['x1', 'y1', 'x2', 'y2', 'x3', 'y3'];
+    
+    for (const prop of t1Props) {
+        if (triangle1[prop] === undefined) return false;
+    }
+    
+    for (const prop of t2Props) {
+        if (triangle2[prop] === undefined) return false;
+    }
+    
+    // Check if any vertex of triangle1 is inside triangle2
+    if (isPointInTriangle(triangle1.x1, triangle1.y1, triangle2) ||
+        isPointInTriangle(triangle1.x2, triangle1.y2, triangle2) ||
+        isPointInTriangle(triangle1.x3, triangle1.y3, triangle2)) {
+        return true;
+    }
+    
+    // Check if any vertex of triangle2 is inside triangle1
+    if (isPointInTriangle(triangle2.x1, triangle2.y1, triangle1) ||
+        isPointInTriangle(triangle2.x2, triangle2.y2, triangle1) ||
+        isPointInTriangle(triangle2.x3, triangle2.y3, triangle1)) {
+        return true;
+    }
+    
+    // Check if any edge of triangle1 intersects with any edge of triangle2
+    const edges1 = [
+        [triangle1.x1, triangle1.y1, triangle1.x2, triangle1.y2],
+        [triangle1.x2, triangle1.y2, triangle1.x3, triangle1.y3],
+        [triangle1.x3, triangle1.y3, triangle1.x1, triangle1.y1]
+    ];
+    
+    const edges2 = [
+        [triangle2.x1, triangle2.y1, triangle2.x2, triangle2.y2],
+        [triangle2.x2, triangle2.y2, triangle2.x3, triangle2.y3],
+        [triangle2.x3, triangle2.y3, triangle2.x1, triangle2.y1]
+    ];
+    
+    for (const [x1, y1, x2, y2] of edges1) {
+        for (const [x3, y3, x4, y4] of edges2) {
+            if (doLinesIntersect(x1, y1, x2, y2, x3, y3, x4, y4)) {
+                return true;
+            }
+        }
+    }
+    
+    return false;
+}
+
+/**
+ * Creates a triangle with the given center point and size
+ * @param {number} x - x-coordinate of the center
+ * @param {number} y - y-coordinate of the center
+ * @param {number} size - Size of the triangle (distance from center to vertices)
+ * @param {number} rotation - Rotation angle in radians
+ * @returns {Triangle} - A triangle object
+ */
+export function createTriangle(x, y, size, rotation = 0) {
+    // Create an equilateral triangle with a slightly larger size for better collision detection
+    // Using 1.1 * size to make the collision area slightly larger than the visual triangle
+    const collisionSize = size * 1.1; // Slightly larger collision area
+    
+    const angle1 = rotation;
+    const angle2 = rotation + (2 * Math.PI / 3);
+    const angle3 = rotation + (4 * Math.PI / 3);
+    
+    return {
+        x1: x + collisionSize * Math.cos(angle1),
+        y1: y + collisionSize * Math.sin(angle1),
+        x2: x + collisionSize * Math.cos(angle2),
+        y2: y + collisionSize * Math.sin(angle2),
+        x3: x + collisionSize * Math.cos(angle3),
+        y3: y + collisionSize * Math.sin(angle3)
+    };
+}
+
+/**
+ * Calculates the area of a triangle
+ * @param {Triangle} triangle - The triangle
+ * @returns {number} - The area of the triangle
+ */
+export function calculateTriangleArea(triangle) {
+    const { x1, y1, x2, y2, x3, y3 } = triangle;
+    return Math.abs((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2);
+}
+
+/**
+ * Checks if a point is inside a convex polygon
+ * @param {number} x - x-coordinate of the point
+ * @param {number} y - y-coordinate of the point
+ * @param {Array<{x: number, y: number}>} polygon - Array of polygon vertices
+ * @returns {boolean} - True if the point is inside the polygon
+ */
+export function isPointInPolygon(x, y, polygon) {
+    let inside = false;
+    for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
+        const xi = polygon[i].x, yi = polygon[i].y;
+        const xj = polygon[j].x, yj = polygon[j].y;
+        
+        const intersect = ((yi > y) !== (yj > y)) &&
+            (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
+        if (intersect) inside = !inside;
+    }
+    return inside;
+}
