01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
}else if(id==='pirate'){
const water=mat('#38b9cb',{roughness:.30,metalness:.12});
box(0,-.18,-41,85,.12,25,water);
for(const x of [-24,24]) box(x,-.06,-6,4,.12,65,water);
function cannon(x,z,s=1){
const g=group(x,0,z,s);
for(const a of [-1,1]){
const w=cyl(a*.65,.48,.15,.49,.19,'#61483b',.49,g);
w.rotation.z=Math.PI/2;
}
box(0,.65,.2,1.5,.37,1.7,'#b18450',false,g);
const barrel=cyl(0,1.05,-.35,.31,1.8,'#627589',.43,g);
barrel.rotation.x=Math.PI/2-.12;
const rim=torus(0,1.16,-1.2,.30,.085,'#d5bb73',g);
sphere(0,1.17,-1.24,.24,'#344257',[1,1,.09],g);
solid(g.children[0],x,z,1.6*s,1.8*s,0,1.5*s);
}
// The ship is a visible landmark at the shoreline; deck-style side routes
// and gangplanks in the playable cove match its timber construction.
const ship=group(0,0,-39);
sphere(0,1,0,1,'#93613c',[11,2.2,3.1],ship);
box(0,2.5,0,19,.5,5,'#c6995f',false,ship);
for(const x of [-7,0,7]){
cyl(x,7,0,.20,11,'#89623e',.13,ship);
box(x,8.2,.1,5.6,4.6,.10,x===0?'#eee0b7':'#e0ceb0',false,ship);
beam([x-3,10.8,0],[x+3,10.8,0],.10,'#89623e',ship);
beam([x,12.2,0],[x-5,3.0,2],.025,'#dfc694',ship);
}
for(const x of [-7,-3,3,7]){
const r=torus(x,1.5,2.8,.45,.10,'#e0bf74',ship);
sphere(x,1.5,2.9,.35,'#3b5266',[1,1,.1],ship);
}
for(const [x,z] of [[-9,8],[9,-13]]) cannon(x,z,1.1);
for(const [x,z] of [[-22,13],[22,9],[-20,-28],[21,-28]]) tree(x,z,1.3,true);
for(const x of [-17,17]) for(let z=-20;z<4;z+=1.4){
const y=z<-11?2.44:(5-z)/16*2.4+.035;
box(x,y,z,z<-11?7.9:4.8,.05,.06,'#775435');
}
// Open treasure cave at left rear: structural roof is high enough to walk in.
for(const x of [-21,-13]) box(x,2.4,-30,2.2,4.8,5.2,'#869893',true);
box(-17,5,-30,10,1.2,5.2,'#829792');
crate(-18,-31,'#85572d',1.3);
box(-18,1.0,-30.30,1.15,.5,.07,'#f3c960');
for(let i=0;i<6;i++) cyl(-16.3+(i%3)*.2,.09,-30.2+Math.floor(i/3)*.2,.15,.13,'#ffda67');
crate(9,-4,'#a77846',1.6);
}