# Cartoon Bomb

> A classic cartoon bomb: a glossy black ball (about 0.4 m) with a metal cap, a curling rope fuse and a glowing emissive spark, plus an optional cartoon shine highlight. Resize and recolor it for platformers, party games, puzzle hazards, throwable weapons or pirate-themed levels.

![Cartoon Bomb preview](https://codels.download/m/cartoon-bomb.png)

Multi-view sheet (3/4, front, side, top): https://codels.download/m/cartoon-bomb.sheet.png

## Facts

- Category: Items & Weapons › Weapons
- Size (W × H × D): 0.40 × 0.58 × 0.40 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 872 · Meshes: 14 · Materials: 7
- License: CC0-1.0 (Codels built-in)
- Tags: bomb, explosive, cartoon, low-poly, stylized, pirate, party-game, platformer, puzzle, hazard, pickup, weapon, round, emissive, game-ready, instancing-friendly, mobile-friendly, parametric, color-gray, size-small, poly-low
- Page: https://codels.download/models/cartoon-bomb

## Files

| Format | URL |
|---|---|
| three.js ES module (`createCartoonBomb()`) | https://codels.download/m/cartoon-bomb.js |
| React Three Fiber component (`<CartoonBomb />`) | https://codels.download/m/cartoon-bomb.jsx |
| Instancing module (`createCartoonBombInstances(count, place)`, one draw call per material) | https://codels.download/m/cartoon-bomb.instanced.js |
| Standalone HTML demo | https://codels.download/m/cartoon-bomb.html |
| glTF binary | https://codels.download/m/cartoon-bomb.glb |
| glTF binary, Meshopt-compressed (2–3× smaller; GLTFLoader needs `setMeshoptDecoder(MeshoptDecoder)`) | https://codels.download/m/cartoon-bomb.glb?compress=meshopt |
| glTF JSON | https://codels.download/m/cartoon-bomb.gltf |
| OBJ (vertex colors) + MTL | https://codels.download/m/cartoon-bomb.obj · https://codels.download/m/cartoon-bomb.mtl |
| STL | https://codels.download/m/cartoon-bomb.stl |
| CodelSpec JSON | https://codels.download/m/cartoon-bomb.json |

## Parameters

Append them as query parameters to any URL above to get a customized variant (e.g. `?size=...`).

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `size` | number | 0.2 – 0.8 | 0.4 | 0.4 |
| `color` | color | #rrggbb | #24272e | #24272e |
| `lit` | boolean | true \| false | true | true |
| `shine` | boolean | true \| false | true | true |

## Parts

- shell (sphere · shell)
- cap (cylinder · cap)
- capRing (torus · cap)
- fuse (tube · fuse)
- fuseEnd (sphere · burnt)
- sparkCore (octahedron · flame)
- sparkGlow (octahedron · spark)
- spark1 (cone · spark)
- spark2 (cone · spark)
- spark3 (cone · spark)
- spark4 (cone · spark)
- spark5 (cone · spark)
- spark6 (cone · spark)
- shine (sphere · shine)

## How to use

Save the code below as `cartoon-bomb.js`, then:

```js
import { createCartoonBomb } from './cartoon-bomb.js';
const model = createCartoonBomb();
scene.add(model);
```

## Code

```js
/**
 * Cartoon Bomb — Codels 3D model library (https://codels.download/models/cartoon-bomb)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 872 · Size (W × H × D): 0.40 × 0.58 × 0.40 m
 *
 * Usage:
 *   import { createCartoonBomb } from './cartoon-bomb.js';
 *   
 *   const model = createCartoonBomb();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

// Tube along a smooth curve through the given points.
function tube(path, radius, tubularSegments, radialSegments, closed = false) {
  const curve = new THREE.CatmullRomCurve3(path.map(([x, y, z]) => new THREE.Vector3(x, y, z)), closed);
  return new THREE.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
}

export function createCartoonBomb() {
  const root = new THREE.Group();
  root.name = 'CartoonBomb';

  // Materials
  const shellMat = new THREE.MeshStandardMaterial({ name: 'shell', color: 0x24272e, roughness: 0.3, metalness: 0.1 });
  const capMat = new THREE.MeshStandardMaterial({ name: 'cap', color: 0x8e959e, roughness: 0.4, metalness: 0.7, flatShading: true });
  const fuseMat = new THREE.MeshStandardMaterial({ name: 'fuse', color: 0xc9a46a, roughness: 0.9, flatShading: true });
  const burntMat = new THREE.MeshStandardMaterial({ name: 'burnt', color: 0x3b2e25, roughness: 0.9, flatShading: true });
  const sparkMat = new THREE.MeshStandardMaterial({ name: 'spark', color: 0xffd44d, roughness: 0.5, emissive: 0xffb02e, emissiveIntensity: 1.4, flatShading: true });
  const flameMat = new THREE.MeshStandardMaterial({ name: 'flame', color: 0xff6a2a, roughness: 0.5, emissive: 0xff4d1a, emissiveIntensity: 1.2, flatShading: true });
  const shineMat = new THREE.MeshStandardMaterial({ name: 'shine', color: 0xffffff, roughness: 0.3, emissive: 0xffffff, emissiveIntensity: 0.35 });

  // Shared geometries
  const coneGeo = new THREE.ConeGeometry(0.007, 0.04, 4);

  // Parts
  const shell = new THREE.Mesh(new THREE.SphereGeometry(0.2, 16, 12), shellMat);
  shell.name = 'shell';
  shell.position.set(0, 0.2, 0);
  root.add(shell);
  const cap = new THREE.Mesh(new THREE.CylinderGeometry(0.055, 0.06, 0.05, 10), capMat);
  cap.name = 'cap';
  cap.position.set(0, 0.405, 0);
  root.add(cap);
  const capRing = new THREE.Mesh(new THREE.TorusGeometry(0.058, 0.012, 5, 12), capMat);
  capRing.name = 'capRing';
  capRing.position.set(0, 0.425, 0);
  capRing.rotation.set(deg(90), 0, 0);
  root.add(capRing);
  const fuse = new THREE.Mesh(tube([[0, 0.42, 0], [0.005, 0.47, 0.005], [0.035, 0.52, 0.012], [0.085, 0.54, 0.02], [0.125, 0.515, 0.028]], 0.011, 18, 5), fuseMat);
  fuse.name = 'fuse';
  root.add(fuse);
  const fuseEnd = new THREE.Mesh(new THREE.SphereGeometry(0.014, 6, 4), burntMat);
  fuseEnd.name = 'fuseEnd';
  fuseEnd.position.set(0.125, 0.515, 0.028);
  root.add(fuseEnd);
  const sparkCore = new THREE.Mesh(new THREE.OctahedronGeometry(0.03, 0), flameMat);
  sparkCore.name = 'sparkCore';
  sparkCore.position.set(0.131, 0.521, 0.028);
  sparkCore.rotation.set(deg(20), deg(30), deg(10));
  root.add(sparkCore);
  const sparkGlow = new THREE.Mesh(new THREE.OctahedronGeometry(0.02, 0), sparkMat);
  sparkGlow.name = 'sparkGlow';
  sparkGlow.position.set(0.131, 0.521, 0.028);
  sparkGlow.rotation.set(0, deg(45), deg(45));
  sparkGlow.scale.setScalar(1.6);
  root.add(sparkGlow);
  const spark1 = new THREE.Mesh(coneGeo, sparkMat);
  spark1.name = 'spark1';
  spark1.position.set(0.1685, 0.5266, 0.016);
  spark1.rotation.set(0, 0, deg(-75));
  root.add(spark1);
  const spark2 = new THREE.Mesh(coneGeo, sparkMat);
  spark2.name = 'spark2';
  spark2.position.set(0.1366, 0.5585, 0.04);
  spark2.rotation.set(0, 0, deg(-15));
  root.add(spark2);
  const spark3 = new THREE.Mesh(coneGeo, sparkMat);
  spark3.name = 'spark3';
  spark3.position.set(0.0932, 0.5468, 0.016);
  spark3.rotation.set(0, 0, deg(45));
  root.add(spark3);
  const spark4 = new THREE.Mesh(coneGeo, sparkMat);
  spark4.name = 'spark4';
  spark4.position.set(0.0815, 0.5034, 0.04);
  spark4.rotation.set(0, 0, deg(105));
  root.add(spark4);
  const spark5 = new THREE.Mesh(coneGeo, sparkMat);
  spark5.name = 'spark5';
  spark5.position.set(0.1134, 0.4715, 0.016);
  spark5.rotation.set(0, 0, deg(165));
  root.add(spark5);
  const spark6 = new THREE.Mesh(coneGeo, sparkMat);
  spark6.name = 'spark6';
  spark6.position.set(0.1568, 0.4832, 0.04);
  spark6.rotation.set(0, 0, deg(225));
  root.add(spark6);
  const shine = new THREE.Mesh(new THREE.SphereGeometry(0.05, 8, 6), shineMat);
  shine.name = 'shine';
  shine.position.set(-0.0238, 0.3192, 0.155);
  shine.rotation.set(deg(-37.5686), deg(-6.9524), deg(25));
  shine.scale.set(1, 0.55, 0.12);
  root.add(shine);

  root.traverse((o) => {
    if (o.isMesh) {
      o.castShadow = true;
      o.receiveShadow = true;
    }
  });
  return root;
}

export default createCartoonBomb;
```

---
Codels — 3D models as code for three.js. Search more: https://codels.download/api/v1/models?q=<query> · Guide: https://codels.download/llms.txt
