soul-symphony-ling
↓ 0 downloadsSoul Symphony — Ling Edition. A spiritual 3D adventure in the soul realm: collect the letters of the world-song, clear the monster lattice, and duel in the arcade arena. Wind Waker-style toon renderer with volumetric light pools, SSAO, bloom and oil-slick tilt-shift — all ling-lang vectors.
Keywords game, 3d, toon, music, soul-symphony
lingfu install soul-symphony-lingCode / Files (1947)
game/arcade.ling
# ════════════════════════════════════════════════════════════════════════════
# arcade.ling — โหมดอาร์เคด: ปรับแต่งลูก (สี/สแตมป์/แบนด์/ชื่อ) + ต่อสู้ศัตรู AI
# วาดลูกแต่ง = body orb (สีกำหนดเอง) + สแตมป์ขั้วบน/ล่าง + แบนด์รอบเส้นศูนย์สูตร
# สแตมป์/แบนด์ = สามเหลี่ยมเติม (fill) + สีดินสอ → คุมสี/รูปทรงได้แม่นยำ
# ════════════════════════════════════════════════════════════════════════════
bind STAMP_N = 8
bind BAND_N = 8
# ── สว็อตช์สี: สี่เหลี่ยมเติมที่ (x,y) ครึ่งขนาด s ──
ฟังก์ชัน วาดสว็อตช์(x, y, s, r, g, b) {
สีดินสอ(r, g, b)
วาดสามเหลี่ยม3มิติ(x-s, y-s, 0.0, x+s, y-s, 0.0, x+s, y+s, 0.0)
วาดสามเหลี่ยม3มิติ(x-s, y-s, 0.0, x+s, y+s, 0.0, x-s, y+s, 0.0)
}
# ── เฉดสี (0..1) → [r,g,b] สดใส ──
ฟังก์ชัน สีจากเฉด(h) {
bind r = ไซน์(h*6.28319) * 0.5 + 0.5
bind g = ไซน์(h*6.28319 + 2.094) * 0.5 + 0.5
bind b = ไซน์(h*6.28319 + 4.189) * 0.5 + 0.5
คืน [floor(r*200+55), floor(g*200+55), floor(b*200+55)]
}
# ── สแตมป์: ตราเวกเตอร์เติม (fill) ในระนาบ xz ที่ (ox,oy,oz) ขนาด s, หมุน rot ──
# (ตั้งสีดินสอก่อนเรียก)
ฟังก์ชัน วาดสแตมป์(id, ox, oy, oz, s, rot) {
ถ้า id == 0 { # ดาว 5 แฉก (พัดจากจุดศูนย์กลาง)
bind k = 0
ขณะที่ k < 10 {
bind a0 = rot + k * 0.62832; bind a1 = rot + (k + 1) * 0.62832
bind r0 = 0.42; ถ้า k - ปัดลง(k/2.0)*2 == 0 { bind r0 = 1.0 }
bind r1 = 0.42; ถ้า (k + 1) - ปัดลง((k + 1)/2.0)*2 == 0 { bind r1 = 1.0 }
วาดสามเหลี่ยม3มิติ(ox, oy, oz, ox+โคไซน์(a0)*r0*s, oy, oz+ไซน์(a0)*r0*s, ox+โคไซน์(a1)*r1*s, oy, oz+ไซน์(a1)*r1*s)
bind k = k + 1
}
}
ถ้า id == 1 { # เฟือง/จักร (พัด รัศมีสลับ = ฟันเฟือง)
bind k = 0
ขณะที่ k < 16 {
bind a0 = rot + k * 0.3927; bind a1 = rot + (k + 1) * 0.3927
bind r0 = 0.66; ถ้า k - ปัดลง(k/2.0)*2 == 0 { bind r0 = 1.0 }
bind r1 = 0.66; ถ้า (k + 1) - ปัดลง((k + 1)/2.0)*2 == 0 { bind r1 = 1.0 }
วาดสามเหลี่ยม3มิติ(ox, oy, oz, ox+โคไซน์(a0)*r0*s, oy, oz+ไซน์(a0)*r0*s, ox+โคไซน์(a1)*r1*s, oy, oz+ไซน์(a1)*r1*s)
bind k = k + 1
}
}
ถ้า id == 2 { # เพชร (ข้าวหลามตัด — 2 สามเหลี่ยม)
bind p0x = ox+โคไซน์(rot)*s; bind p0z = oz+ไซน์(rot)*s
bind p1x = ox+โคไซน์(rot+1.5708)*s; bind p1z = oz+ไซน์(rot+1.5708)*s
bind p2x = ox+โคไซน์(rot+3.14159)*s; bind p2z = oz+ไซน์(rot+3.14159)*s
bind p3x = ox+โคไซน์(rot+4.71239)*s; bind p3z = oz+ไซน์(rot+4.71239)*s
วาดสามเหลี่ยม3มิติ(p0x,oy,p0z, p1x,oy,p1z, p2x,oy,p2z)
วาดสามเหลี่ยม3มิติ(p0x,oy,p0z, p2x,oy,p2z, p3x,oy,p3z)
}
ถ้า id == 3 { # สามเหลี่ยม (1 ฟิล)
bind a0 = rot; bind a1 = rot + 2.0944; bind a2 = rot + 4.18879
วาดสามเหลี่ยม3มิติ(ox+โคไซน์(a0)*s,oy,oz+ไซน์(a0)*s, ox+โคไซน์(a1)*s,oy,oz+ไซน์(a1)*s, ox+โคไซน์(a2)*s,oy,oz+ไซน์(a2)*s)
}
ถ้า id == 4 { # กากบาท/บวก (2 แท่งเติม = 4 สามเหลี่ยม)
bind w = s * 0.32
วาดสามเหลี่ยม3มิติ(ox-s,oy,oz-w, ox+s,oy,oz-w, ox+s,oy,oz+w)
วาดสามเหลี่ยม3มิติ(ox-s,oy,oz-w, ox+s,oy,oz+w, ox-s,oy,oz+w)
วาดสามเหลี่ยม3มิติ(ox-w,oy,oz-s, ox+w,oy,oz-s, ox+w,oy,oz+s)
วาดสามเหลี่ยม3มิติ(ox-w,oy,oz-s, ox+w,oy,oz+s, ox-w,oy,oz+s)
}
}
# ── แบนด์: ลายเติม (fill) รอบเส้นศูนย์สูตร (วนรอบไร้รอยต่อ) — ตั้งสีดินสอก่อน ──
ฟังก์ชัน วาดแบนด์(id, cx, cy, cz, R, t) {
bind N = 24
bind k = 0
ถ้า id == 0 { # แท่งตั้งเติม (มีช่องว่างระหว่างแท่ง)
ขณะที่ k < N {
bind a0 = t*0.3 + k * 6.28319 / N; bind a1 = t*0.3 + (k + 0.5) * 6.28319 / N
bind ax=cx+โคไซน์(a0)*R; bind az=cz+ไซน์(a0)*R
bind bx=cx+โคไซน์(a1)*R; bind bz=cz+ไซน์(a1)*R
วาดสามเหลี่ยม3มิติ(ax,cy-0.6,az, bx,cy-0.6,bz, bx,cy+0.6,bz)
วาดสามเหลี่ยม3มิติ(ax,cy-0.6,az, bx,cy+0.6,bz, ax,cy+0.6,az)
bind k = k + 1
}
}
ถ้า id == 1 { # ฟันเลื่อย (สามเหลี่ยมยอดขึ้น/ลงสลับ)
ขณะที่ k < N {
bind a0 = t*0.3 + k * 6.28319 / N; bind a1 = t*0.3 + (k + 1) * 6.28319 / N
bind am = (a0 + a1) * 0.5
bind ax=cx+โคไซน์(a0)*R; bind az=cz+ไซน์(a0)*R
bind bx=cx+โคไซน์(a1)*R; bind bz=cz+ไซน์(a1)*R
bind mx=cx+โคไซน์(am)*R; bind mz=cz+ไซน์(am)*R
bind ty = cy - 0.85; ถ้า k - ปัดลง(k/2.0)*2 == 0 { bind ty = cy + 0.85 }
วาดสามเหลี่ยม3มิติ(ax,cy,az, bx,cy,bz, mx,ty,mz)
bind k = k + 1
}
}
ถ้า id == 2 { # แถบทึบ (วงแหวนตันรอบกลาง)
ขณะที่ k < N {
bind a0 = t*0.3 + k * 6.28319 / N; bind a1 = t*0.3 + (k + 1) * 6.28319 / N
bind ax=cx+โคไซน์(a0)*R; bind az=cz+ไซน์(a0)*R
bind bx=cx+โคไซน์(a1)*R; bind bz=cz+ไซน์(a1)*R
วาดสามเหลี่ยม3มิติ(ax,cy-0.7,az, bx,cy-0.7,bz, bx,cy+0.7,bz)
วาดสามเหลี่ยม3มิติ(ax,cy-0.7,az, bx,cy+0.7,bz, ax,cy+0.7,az)
bind k = k + 1
}
}
ถ้า id == 3 { # เพชรเติมเรียงรอบ
bind M = 12
ขณะที่ k < M {
bind a = t*0.3 + k * 6.28319 / M
bind px = cx + โคไซน์(a)*R; bind pz = cz + ไซน์(a)*R
bind ox = โคไซน์(a)*0.6; bind oz = ไซน์(a)*0.6
วาดสามเหลี่ยม3มิติ(px,cy-0.8,pz, px+ox,cy,pz+oz, px,cy+0.8,pz)
วาดสามเหลี่ยม3มิติ(px,cy-0.8,pz, px,cy+0.8,pz, px-ox,cy,pz-oz)
bind k = k + 1
}
}
}
# ── วาดเมชจาก blob (pos+idx) แบบเติม + สีสุ่มคงที่ต่อหน้า (hueBase แยกแต่ละเมช) ──
ฟังก์ชัน วาดเมชสุ่มสี(P, I, ox, oy, oz, scale, hueBase) {
bind n = ความยาว(I)
bind k = 0; bind f = 0.0
ขณะที่ k + 2 < n {
bind a = list_get(I,k)*3; bind b = list_get(I,k+1)*3; bind c = list_get(I,k+2)*3
bind h = hueBase + f * 0.6
สีดินสอ(floor((ไซน์(h)*0.5+0.5)*150+55), floor((ไซน์(h+2.094)*0.5+0.5)*150+55), floor((ไซน์(h+4.189)*0.5+0.5)*150+55))
วาดสามเหลี่ยม3มิติ(
ox+list_get(P,a)*scale, oy+list_get(P,a+1)*scale, oz+list_get(P,a+2)*scale,
ox+list_get(P,b)*scale, oy+list_get(P,b+1)*scale, oz+list_get(P,b+2)*scale,
ox+list_get(P,c)*scale, oy+list_get(P,c+1)*scale, oz+list_get(P,c+2)*scale)
bind k = k + 3; bind f = f + 1.0
}
}
# ── อารีนาจาก arena.glb (InnerWalls/Floor/Trough) — สีสุ่มต่อหน้า ──
ฟังก์ชัน วาดอารีนาโมเดล(ox, oy, oz, scale) {
วาดเมช(arena_Cube_pos, arena_Cube_idx, ox, oy, oz, scale, 1) # native batched (ling-gpu)
วาดเมช(arena_Cube_001_pos, arena_Cube_001_idx, ox, oy, oz, scale, 1)
วาดเมช(arena_Cube_002_pos, arena_Cube_002_idx, ox, oy, oz, scale, 1)
}
# ── 6 ดาบพิคอัพ (อาร์เคด): item id (พลังพิเศษต่างกัน) + สี + ตราบิลบอร์ด ──
# 3=Torpedo 5=DualSword 6=Burn 7=Freeze 8=Nova 9=Quake (พลังของแต่ละไอเทม)
bind ดาบไอดี = [3, 5, 6, 7, 8, 9]
bind ดาบสี = [[120,200,255],[210,228,255],[255,120,40],[150,220,255],[220,160,255],[255,200,120]]
# ── สเตตัสดาบ 6 เล่ม: [cooldown, power, range, comboMax, R, G, B] ──
# 0 Quick · 1 Great · 2 Twin · 3 Flame · 4 Frost · 5 Nova
bind ดาบสเตตัส = [
[0.20, 1.1, 15.0, 3.0, 120,200,255],
[0.55, 3.4, 23.0, 1.0, 255,120,70],
[0.14, 0.8, 13.0, 4.0, 210,228,255],
[0.38, 1.9, 18.0, 2.0, 255,150,40],
[0.44, 1.7, 18.0, 2.0, 150,220,255],
[0.62, 2.8, 26.0, 1.0, 220,160,255]
]
# อาร์คเติม: เสี้ยวพระจันทร์เติม (strip ระหว่าง rad-width..rad ตามมุม yaw±span*prog) ที่ y=cy
ฟังก์ชัน อาร์คเติม(cx, cy, cz, yaw, span, rad, width, prog, r, g, b) {
สีดินสอ(r, g, b)
bind n = 9; bind k = 0
ขณะที่ k < n {
bind a0 = yaw - span + (k / 9.0) * 2.0*span*prog
bind a1 = yaw - span + ((k + 1) / 9.0) * 2.0*span*prog
bind o0x = cx+ไซน์(a0)*rad; bind o0z = cz+โคไซน์(a0)*rad
bind o1x = cx+ไซน์(a1)*rad; bind o1z = cz+โคไซน์(a1)*rad
bind i0x = cx+ไซน์(a0)*(rad-width); bind i0z = cz+โคไซน์(a0)*(rad-width)
bind i1x = cx+ไซน์(a1)*(rad-width); bind i1z = cz+โคไซน์(a1)*(rad-width)
วาดสามเหลี่ยม3มิติ(i0x,cy,i0z, o0x,cy,o0z, o1x,cy,o1z)
วาดสามเหลี่ยม3มิติ(i0x,cy,i0z, o1x,cy,o1z, i1x,cy,i1z)
bind k = k + 1
}
}
# วาดสแลชเติม: เอฟเฟกต์ฟันแบบเติม ต่างกันต่อชนิดดาบ (typ 0..5)
ฟังก์ชัน วาดสแลชเติม(typ, cx, cy, cz, yaw, prog, rad, r, g, b) {
โหมดผสม(1)
bind fwx = ไซน์(yaw); bind fwz = โคไซน์(yaw)
ถ้า typ == 0 { อาร์คเติม(cx, cy, cz, yaw, 1.0, rad, 2.5, prog, r,g,b) }
ถ้า typ == 1 { อาร์คเติม(cx, cy, cz, yaw, 1.7, rad, 5.0, prog, r,g,b) }
ถ้า typ == 2 { อาร์คเติม(cx, cy-1.2, cz, yaw, 1.2, rad, 2.0, prog, r,g,b) อาร์คเติม(cx, cy+1.2, cz, yaw, 1.2, rad, 2.0, prog, r,g,b) }
ถ้า typ == 3 { อาร์คเติม(cx, cy, cz, yaw, 1.3, rad, 3.2, prog, r,g,b) อนุภาคทรงกลม(cx+fwx*rad*0.8, cy, cz+fwz*rad*0.8, 2.4, 18, prog*4.0, r, g, floor(b*0.3)) }
ถ้า typ == 4 {
อาร์คเติม(cx, cy, cz, yaw, 1.3, rad, 3.0, prog, r,g,b)
bind sk = 0
ขณะที่ sk < 4 { bind sa = yaw - 1.0 + sk*0.66
วาดสามเหลี่ยม3มิติ(cx+ไซน์(sa)*rad, cy-1.6, cz+โคไซน์(sa)*rad, cx+ไซน์(sa)*rad*1.12, cy, cz+โคไซน์(sa)*rad*1.12, cx+ไซน์(sa)*rad, cy+1.6, cz+โคไซน์(sa)*rad)
bind sk = sk + 1 }
}
ถ้า typ == 5 {
bind r2 = rad * prog; bind nk = 0
ขณะที่ nk < 16 { bind na0 = nk*0.3927; bind na1 = (nk+1)*0.3927
วาดสามเหลี่ยม3มิติ(cx+ไซน์(na0)*(r2-3.0),cy,cz+โคไซน์(na0)*(r2-3.0), cx+ไซน์(na0)*r2,cy,cz+โคไซน์(na0)*r2, cx+ไซน์(na1)*r2,cy,cz+โคไซน์(na1)*r2)
วาดสามเหลี่ยม3มิติ(cx+ไซน์(na0)*(r2-3.0),cy,cz+โคไซน์(na0)*(r2-3.0), cx+ไซน์(na1)*r2,cy,cz+โคไซน์(na1)*r2, cx+ไซน์(na1)*(r2-3.0),cy,cz+โคไซน์(na1)*(r2-3.0))
bind nk = nk + 1 }
}
flush_3d(); โหมดผสม(0)
}
# เส้นบิลบอร์ด: จุด 2D (ax,ay)->(bx,by) ในระนาบหันกล้อง ที่ฐานโลก (wx,wy,wz); rx,rz = แกนขวา (yaw)
ฟังก์ชัน เส้นป้าย(wx, wy, wz, ax, ay, bx, by, rx, rz) {
วาดเส้น3มิติ(wx + ax*rx, wy - ay, wz + ax*rz, wx + bx*rx, wy - by, wz + bx*rz)
}
# สามเหลี่ยมเติมจาก 3 จุด 2D (a=แนวขวากล้อง, b=แนวตั้ง/ขึ้น) ในระนาบหันกล้อง
ฟังก์ชัน สามเหลี่ยมป้าย(cx, cy, cz, a0, b0, a1, b1, a2, b2, rx, rz) {
วาดสามเหลี่ยม3มิติ(cx+a0*rx, cy-b0, cz+a0*rz, cx+a1*rx, cy-b1, cz+a1*rz, cx+a2*rx, cy-b2, cz+a2*rz)
}
# ── สแลชทิศทาง: ฟันโค้งเติม ตามมุม dirAngle (0=นอน, ทวน 45° ต่อทิศ), กวาดตาม prog ──
ฟังก์ชัน วาดสแลชทิศ(cx, cy, cz, camYaw, dirAngle, prog, len, r, g, b) {
โหมดผสม(1)
bind rx = โคไซน์(camYaw); bind rz = 0.0 - ไซน์(camYaw)
bind ca = โคไซน์(dirAngle); bind sa = ไซน์(dirAngle) # แกนหลักใบมีด (2D)
bind px = 0.0 - sa; bind py = ca # แกนตั้งฉาก (ความหนา)
สีดินสอ(r, g, b)
bind sweep = 0.0 - 1.0 + prog*2.0
bind k = 0
ขณะที่ k < 10 {
bind t0 = 0.0 - 1.0 + (k/10.0)*2.0
bind t1 = 0.0 - 1.0 + ((k+1)/10.0)*2.0
ถ้า t0 < sweep {
bind w0 = (1.0 - t0*t0)*len*0.3
bind w1 = (1.0 - t1*t1)*len*0.3
bind c0a = ca*t0*len; bind c0b = sa*t0*len
bind c1a = ca*t1*len; bind c1b = sa*t1*len
สามเหลี่ยมป้าย(cx,cy,cz, c0a+px*w0, c0b+py*w0, c0a-px*w0, c0b-py*w0, c1a+px*w1, c1b+py*w1, rx, rz)
สามเหลี่ยมป้าย(cx,cy,cz, c0a-px*w0, c0b-py*w0, c1a-px*w1, c1b-py*w1, c1a+px*w1, c1b+py*w1, rx, rz)
}
bind k = k + 1
}
flush_3d(); โหมดผสม(0)
}
# ── ริบบิ้นสแลช: ระนาบแบนที่โค้งตามการเหวี่ยง (เหวี่ยงรอบแกนเล็ง, เอียงตามเส้นฟัน) ──
# aimYaw = ทิศเหวี่ยง · roll = เอียงเส้นฟัน (0=นอน, π/2=ตั้ง) · prog 0..1 · reach = ระยะใบมีด
ฟังก์ชัน วาดริบบิ้นสแลช(cx, cy, cz, aimYaw, roll, prog, reach, r, g, b, sat, spin) {
โหมดผสม(1)
bind roll = roll + spin # หมุนระนาบตามอินพุตไมค์
bind fade = 1.0 - prog # จางออก
bind lum = r*0.30 + g*0.59 + b*0.11 # ปรับอิ่มสีตาม FFT เพลง
bind sr = lum + (r-lum)*sat; bind sg = lum + (g-lum)*sat; bind sb = lum + (b-lum)*sat
ถ้า sr < 0.0 { bind sr = 0.0 } ถ้า sr > 255.0 { bind sr = 255.0 }
ถ้า sg < 0.0 { bind sg = 0.0 } ถ้า sg > 255.0 { bind sg = 255.0 }
ถ้า sb < 0.0 { bind sb = 0.0 } ถ้า sb > 255.0 { bind sb = 255.0 }
สีดินสอ(floor(sr*fade), floor(sg*fade), floor(sb*fade))
bind fwx = ไซน์(aimYaw); bind fwz = โคไซน์(aimYaw) # แกนเล็ง (หน้า)
bind ppx = ไซน์(aimYaw + 1.5708); bind ppz = โคไซน์(aimYaw + 1.5708) # แกนตั้งฉากแนวนอน
bind cr = โคไซน์(roll); bind srl = ไซน์(roll)
bind sdx = ppx*cr; bind sdy = 0.0 - srl; bind sdz = ppz*cr # แกนเหวี่ยง = perp*cos(roll) + up*sin(roll)
bind span = 1.45
bind rOut = reach * (0.45 + prog*0.85) # โตขึ้น (scale out)
bind rIn = rOut * 0.10 # ใบหนาขึ้น (ดาบหนา)
bind k = 0
ขณะที่ k < 10 {
bind f0 = k / 10.0; bind f1 = (k + 1) / 10.0
ถ้า f0 < prog {
bind a0 = 0.0 - span + f0*2.0*span; bind a1 = 0.0 - span + f1*2.0*span
bind c0 = โคไซน์(a0); bind s0 = ไซน์(a0); bind c1 = โคไซน์(a1); bind s1 = ไซน์(a1)
bind d0x = fwx*c0 + sdx*s0; bind d0y = sdy*s0; bind d0z = fwz*c0 + sdz*s0
bind d1x = fwx*c1 + sdx*s1; bind d1y = sdy*s1; bind d1z = fwz*c1 + sdz*s1
วาดสามเหลี่ยม3มิติ(cx+d0x*rIn,cy+d0y*rIn,cz+d0z*rIn, cx+d0x*rOut,cy+d0y*rOut,cz+d0z*rOut, cx+d1x*rOut,cy+d1y*rOut,cz+d1z*rOut)
วาดสามเหลี่ยม3มิติ(cx+d0x*rIn,cy+d0y*rIn,cz+d0z*rIn, cx+d1x*rOut,cy+d1y*rOut,cz+d1z*rOut, cx+d1x*rIn,cy+d1y*rIn,cz+d1z*rIn)
}
bind k = k + 1
}
flush_3d(); โหมดผสม(0)
}
# ── สีรุ้ง ROYGBIV จากสเปกตรัม FFT: ผสมสีรุ้ง 8 ย่านถ่วงด้วยพลังงาน → "คลื่นเสียง" ──
ฟังก์ชัน สีรุ้งFFT(bands) {
bind ROYG = [255,0,0, 255,127,0, 255,230,0, 60,230,0, 0,160,255, 50,30,230, 150,0,225, 220,0,160]
bind cr = 6.0; bind cg = 6.0; bind cb = 10.0; bind tot = 0.05
bind i = 0
ขณะที่ i < 8 {
bind e = list_get(bands, i); ถ้า e < 0.0 { bind e = 0.0 }
bind e = e*e # เน้นย่านเด่น
bind b3 = i*3
bind cr = cr + list_get(ROYG,b3)*e
bind cg = cg + list_get(ROYG,b3+1)*e
bind cb = cb + list_get(ROYG,b3+2)*e
bind tot = tot + e
bind i = i + 1
}
คืน [cr/tot, cg/tot, cb/tot]
}
# ── ดาบเหวี่ยง: ใบมีดที่กวาดตามส่วนโค้งเดียวกับสแลช (นอน/ตั้ง/ทแยง/กลับ) ──
ฟังก์ชัน วาดดาบเหวี่ยง(cx, cy, cz, aimYaw, roll, prog, reach, r, g, b) {
โหมดผสม(0)
bind span = 1.45
bind a = 0.0 - span + prog*2.0*span # มุมเหวี่ยงปัจจุบัน (ขอบนำ)
bind fwx = ไซน์(aimYaw); bind fwz = โคไซน์(aimYaw)
bind ppx = ไซน์(aimYaw + 1.5708); bind ppz = โคไซน์(aimYaw + 1.5708)
bind cr = โคไซน์(roll); bind srl = ไซน์(roll)
bind sdx = ppx*cr; bind sdy = 0.0 - srl; bind sdz = ppz*cr # แกนเหวี่ยง (เอียงตามทิศฟัน)
bind c = โคไซน์(a); bind s = ไซน์(a)
bind dx = fwx*c + sdx*s; bind dy = sdy*s; bind dz = fwz*c + sdz*s # ทิศใบมีด
bind ta = a + 1.5708; bind tc = โคไซน์(ta); bind ts = ไซน์(ta)
bind tx = fwx*tc + sdx*ts; bind ty = sdy*ts; bind tz = fwz*tc + sdz*ts # tangent (ความหนา)
bind rH = reach*0.18; bind rT = reach*1.15; bind w = reach*0.06
bind hax = cx+dx*rH+tx*w; bind hay = cy+dy*rH+ty*w; bind haz = cz+dz*rH+tz*w
bind hbx = cx+dx*rH-tx*w; bind hby = cy+dy*rH-ty*w; bind hbz = cz+dz*rH-tz*w
bind tpx = cx+dx*rT; bind tpy = cy+dy*rT; bind tpz = cz+dz*rT
สีดินสอ(228, 232, 248) # ใบมีดเงิน (สามเหลี่ยมเรียว)
วาดสามเหลี่ยม3มิติ(hax,hay,haz, hbx,hby,hbz, tpx,tpy,tpz)
สีดินสอ(r, g, b) # การ์ด (สีดาบ)
วาดเส้น3มิติ(cx+dx*rH+tx*w*2.6, cy+dy*rH+ty*w*2.6, cz+dz*rH+tz*w*2.6, cx+dx*rH-tx*w*2.6, cy+dy*rH-ty*w*2.6, cz+dz*rH-tz*w*2.6)
flush_3d()
}
# ── เทรลแหวน: ลิสต์แบนของ N ตัวอย่าง × 6 ช่อง (px,py,pz, vx,vy,vz) ──
ฟังก์ชัน รายการศูนย์(n) {
bind L = []; bind i = 0
ขณะที่ i < n { bind L = list_push(L, 0.0); bind i = i + 1 }
คืน L
}
# เขียนตัวอย่างใหม่ลงหัวบัฟเฟอร์ (ตำแหน่ง+ความเร็ว) → คืนบัฟใหม่
ฟังก์ชัน เขียนเทรล(buf, head, px, py, pz, vx, vy, vz) {
bind b = floor(head)*6
bind buf = ตั้งรายการ(buf, b, px)
bind buf = ตั้งรายการ(buf, b+1, py)
bind buf = ตั้งรายการ(buf, b+2, pz)
bind buf = ตั้งรายการ(buf, b+3, vx)
bind buf = ตั้งรายการ(buf, b+4, vy)
bind buf = ตั้งรายการ(buf, b+5, vz)
คืน buf
}
# วาดเทรลแหวน: แหวนโซนิคบูม (เก่า=ใหญ่+จาง, ใหม่=เล็ก+สว่าง) ตั้งฉากกับทิศวิ่ง
# + แกนหนาเรียวลอดผ่านศูนย์กลางแหวน จางหายไปด้านท้าย
# สี: ผสมพาเลตลูก (br,bg,bb) + สีดาบ (sr,sg,sb), ปรับอิ่มสีด้วย sat (จาก FFT เพลง)
# spin = หมุนแหวน/แกนรอบทิศวิ่ง (จากไมค์) ; แกนเรียวกลับทาง (เก่า=หนา)
ฟังก์ชัน วาดเทรลแหวน(buf, head, N, br, bg, bb, sr, sg, sb, sat, spin) {
โหมดผสม(1) # บวกแสง (เรืองแสง)
bind seg = 9.0
bind bcr = (br + sr)*0.5; bind bcg = (bg + sg)*0.5; bind bcb = (bb + sb)*0.5 # ผสมพาเลต+ดาบ
bind lum = bcr*0.30 + bcg*0.59 + bcb*0.11
bind cr = lum + (bcr - lum)*sat; bind cg = lum + (bcg - lum)*sat; bind cb = lum + (bcb - lum)*sat
ถ้า cr < 0.0 { bind cr = 0.0 } ถ้า cr > 255.0 { bind cr = 255.0 }
ถ้า cg < 0.0 { bind cg = 0.0 } ถ้า cg > 255.0 { bind cg = 255.0 }
ถ้า cb < 0.0 { bind cb = 0.0 } ถ้า cb > 255.0 { bind cb = 255.0 }
bind csp = โคไซน์(spin); bind ssp = ไซน์(spin)
bind havePrev = 0.0
bind pcx = 0.0; bind pcy = 0.0; bind pcz = 0.0
bind pux = 0.0; bind puy = 0.0; bind puz = 0.0; bind page = 0.0
bind i = 0.0
ขณะที่ i < N {
bind idx = floor((head + i) % N) # i=0 เก่าสุด … i=N-1 ใหม่สุด
bind b = idx*6
bind px = list_get(buf, b); bind py = list_get(buf, b+1); bind pz = list_get(buf, b+2)
bind vx = list_get(buf, b+3); bind vy = list_get(buf, b+4); bind vz = list_get(buf, b+5)
bind sp = รากที่สอง(vx*vx + vy*vy + vz*vz)
ถ้า sp > 0.012 {
bind age = (N - 1.0 - i) / N # ใหม่สุด≈0 … เก่าสุด≈1
bind fade = 1.0 - age # ใหม่=สว่าง, เก่า=จาง
bind alpha = fade * fade
set_alpha(alpha)
bind rad = (0.25 + sp*3.6) * (0.4 + age*1.4) # ขนาดแปรตามความเร็ว; เก่า=ขยาย (โซนิคบูม)
bind inv = 1.0 / sp
bind dxn = vx*inv; bind dyn = vy*inv; bind dzn = vz*inv
bind ux = 0.0 - dzn; bind uz = dxn # u = cross(d, up).xz
bind ul = รากที่สอง(ux*ux + uz*uz)
ถ้า ul < 0.0001 { bind ux = 1.0; bind uz = 0.0; bind ul = 1.0 }
bind u0x = ux/ul; bind u0y = 0.0; bind u0z = uz/ul
bind w0x = dyn*u0z - dzn*u0y; bind w0y = dzn*u0x - dxn*u0z; bind w0z = dxn*u0y - dyn*u0x # w = cross(d,u)
# หมุน (u,w) รอบทิศวิ่ง d ตามอินพุตไมค์
bind uix = u0x*csp + w0x*ssp; bind uiy = u0y*csp + w0y*ssp; bind uiz = u0z*csp + w0z*ssp
bind wx = w0x*csp - u0x*ssp; bind wy = w0y*csp - u0y*ssp; bind wz = w0z*csp - u0z*ssp
สีดินสอ(cr*fade, cg*fade, cb*fade)
bind k = 0.0
ขณะที่ k < seg {
bind a0 = (k / seg) * 6.2832; bind a1 = ((k+1.0) / seg) * 6.2832
bind c0 = โคไซน์(a0); bind s0 = ไซน์(a0); bind c1 = โคไซน์(a1); bind s1 = ไซน์(a1)
วาดเส้น3มิติ(px + (uix*c0 + wx*s0)*rad, py + (uiy*c0 + wy*s0)*rad, pz + (uiz*c0 + wz*s0)*rad, px + (uix*c1 + wx*s1)*rad, py + (uiy*c1 + wy*s1)*rad, pz + (uiz*c1 + wz*s1)*rad)
bind k = k + 1.0
}
ถ้า havePrev > 0.5 {
bind wN = 0.1 + age*0.6; bind wP = 0.1 + page*0.6 # แกนเรียวกลับทาง (เก่า=หนา)
bind ax = pcx + pux*wP; bind ay = pcy + puy*wP; bind az = pcz + puz*wP
bind bx = pcx - pux*wP; bind by = pcy - puy*wP; bind bz = pcz - puz*wP
bind cx2 = px + uix*wN; bind cy2 = py + uiy*wN; bind cz2 = pz + uiz*wN
bind dx2 = px - uix*wN; bind dy2 = py - uiy*wN; bind dz2 = pz - uiz*wN
สีดินสอ((cr+255.0)*0.5*fade, (cg+255.0)*0.5*fade, (cb+255.0)*0.5*fade) # แกนสว่างกว่าแหวน
วาดสามเหลี่ยม3มิติ(ax,ay,az, bx,by,bz, dx2,dy2,dz2)
วาดสามเหลี่ยม3มิติ(ax,ay,az, dx2,dy2,dz2, cx2,cy2,cz2)
}
bind pcx = px; bind pcy = py; bind pcz = pz
bind pux = uix; bind puy = uiy; bind puz = uiz; bind page = age
bind havePrev = 1.0
}
bind i = i + 1.0
}
set_alpha(1.0)
flush_3d(); โหมดผสม(0)
}
# ── ดีบักฮิตบ็อกซ์: วงกลมเส้นแดงบนระนาบ XZ ที่ y ──
ฟังก์ชัน วาดฮิตบ็อกซ์(cx, cy, cz, r) {
โหมดผสม(1); สีดินสอ(255, 60, 60)
bind k = 0; bind px = cx + r; bind pz = cz
ขณะที่ k < 24 {
bind a = ((k + 1) / 24.0) * 6.28318
bind nx = cx + โคไซน์(a)*r; bind nz = cz + ไซน์(a)*r
วาดเส้น3มิติ(px, cy, pz, nx, cy, nz)
bind px = nx; bind pz = nz; bind k = k + 1
}
flush_3d(); โหมดผสม(0)
}
# ── ตัวเลขลอยแบบ 7-ส่วน (บิลบอร์ด) — ฟอนต์เวกเตอร์ไม่มีเลข เลยวาดเอง ──
ฟังก์ชัน บิตมี(mask, bit) { คืน floor(mask/bit) - floor(mask/(bit*2.0))*2.0 }
ฟังก์ชัน เลข7ส่วน(dg, wx, wy, wz, dx, w, h, rx, rz) {
bind masks = [63,6,91,79,102,109,125,7,127,111] # a=1,b=2,c=4,d=8,e=16,f=32,g=64
bind m = list_get(masks, floor(dg)); bind h2 = h*0.5
ถ้า บิตมี(m,1) > 0.5 { เส้นป้าย(wx,wy,wz, dx,h, dx+w,h, rx,rz) }
ถ้า บิตมี(m,2) > 0.5 { เส้นป้าย(wx,wy,wz, dx+w,h, dx+w,h2, rx,rz) }
ถ้า บิตมี(m,4) > 0.5 { เส้นป้าย(wx,wy,wz, dx+w,h2, dx+w,0.0, rx,rz) }
ถ้า บิตมี(m,8) > 0.5 { เส้นป้าย(wx,wy,wz, dx,0.0, dx+w,0.0, rx,rz) }
ถ้า บิตมี(m,16) > 0.5 { เส้นป้าย(wx,wy,wz, dx,h2, dx,0.0, rx,rz) }
ถ้า บิตมี(m,32) > 0.5 { เส้นป้าย(wx,wy,wz, dx,h, dx,h2, rx,rz) }
ถ้า บิตมี(m,64) > 0.5 { เส้นป้าย(wx,wy,wz, dx,h2, dx+w,h2, rx,rz) }
}
# n (จำนวนเต็ม 0..999) ลอยที่ (wx,wy,wz) สูง s, หันกล้อง camYaw, สี r,g,b
# เลขลอยเหนือหัว: ฟอนต์อังกฤษ + เครื่องหมาย, วนสี ROYGBIV เร็ว (~60 สี/วิ)
ฟังก์ชัน วาดเลขRGB(n, sign, wx, wy, wz, s, camYaw, t) {
bind ph = floor(t*60.0) * 0.10472 # 60 ก้าวสี/วินาที
bind cr = floor((ไซน์(ph)*0.5+0.5)*255.0)
bind cg = floor((ไซน์(ph+2.094)*0.5+0.5)*255.0)
bind cb = floor((ไซน์(ph+4.189)*0.5+0.5)*255.0)
bind str = to_str(floor(n))
ถ้า sign > 0.5 { bind str = "+" + str }
ถ้า sign < 0.0-0.5 { bind str = "-" + str }
โหมดผสม(1); สีดินสอ(cr, cg, cb)
วาดสตริงป้าย(str, wx, wy, wz, s, camYaw)
flush_3d(); โหมดผสม(0)
}
ฟังก์ชัน วาดเลขป้าย(n, sign, wx, wy, wz, s, camYaw, r, g, b) {
bind rx = โคไซน์(camYaw); bind rz = 0.0 - ไซน์(camYaw)
สีดินสอ(r, g, b)
bind nn = floor(n); ถ้า nn < 0.0 { bind nn = 0.0 }
bind nd = 1; ถ้า nn >= 10.0 { bind nd = 2 } ถ้า nn >= 100.0 { bind nd = 3 }
bind w = s*0.6; bind gap = s*0.34
bind sw = 0.0; ถ้า sign != 0.0 { bind sw = w + gap } # ช่องเครื่องหมาย +/-
bind startx = 0.0 - (nd*w + (nd-1)*gap + sw)*0.5
bind h2 = s*0.5
ถ้า sign != 0.0 {
เส้นป้าย(wx,wy,wz, startx, h2, startx+w, h2, rx,rz) # ขีดนอน (−)
ถ้า sign > 0.0 { เส้นป้าย(wx,wy,wz, startx+w*0.5, h2-w*0.55, startx+w*0.5, h2+w*0.55, rx,rz) } # ขีดตั้ง → (+)
bind startx = startx + sw
}
bind p = 0
ขณะที่ p < nd {
bind pw = nd - 1 - p; bind divv = 1.0
bind q = 0; ขณะที่ q < pw { bind divv = divv*10.0; bind q = q+1 }
bind dg = floor(nn/divv) - floor(nn/(divv*10.0))*10.0
เลข7ส่วน(dg, wx, wy, wz, startx + p*(w+gap), w, s, rx, rz)
bind p = p+1
}
}
# ── ไฮสกอร์: แทรกแบบเรียงมาก→น้อย, ตัดเหลือ 10 → คืน [names, scores] ──
ฟังก์ชัน แทรกไฮสกอร์(names, scores, nm, sc) {
bind nN = []; bind nS = []; bind placed = 0.0; bind i = 0
ขณะที่ i < ความยาว(scores) {
ถ้า placed < 0.5 { ถ้า sc > list_get(scores, i) { bind nN = list_push(nN, nm); bind nS = list_push(nS, sc); bind placed = 1.0 } }
bind nN = list_push(nN, list_get(names, i)); bind nS = list_push(nS, list_get(scores, i))
bind i = i + 1
}
ถ้า placed < 0.5 { bind nN = list_push(nN, nm); bind nS = list_push(nS, sc) }
bind cN = []; bind cS = []; bind j = 0
ขณะที่ j < ความยาว(nS) { ถ้า j < 10 { bind cN = list_push(cN, list_get(nN, j)); bind cS = list_push(cS, list_get(nS, j)) } bind j = j + 1 }
คืน [cN, cS]
}
# ── บันทึกไฮสกอร์ → highscores.dat ("name,score;...") ──
ฟังก์ชัน บันทึกไฮสกอร์(names, scores) {
bind out = ""; bind i = 0
ขณะที่ i < ความยาว(scores) {
ถ้า i > 0 { bind out = out + ";" }
bind out = out + list_get(names, i) + "," + to_str(floor(list_get(scores, i)))
bind i = i + 1
}
เขียนไฟล์("highscores.dat", out)
คืน 0
}
# ── วาดตารางไฮสกอร์ (ชื่อ a-z + คะแนน 7-ส่วน) ──
# ── พื้นหลังไฮสกอร์: 4 ออร์บ AI สู้กันในอารีนา (หลังตารางคะแนน, หรี่แสง) ──
ฟังก์ชัน วาดเอไออารีนาพื้นหลัง(t) {
โหมดผสม(1)
bind i = 0
ขณะที่ i < 4 {
bind ph = i * 1.5708
bind sp = 0.55 + i*0.13
bind ox = โคไซน์(t*sp + ph) * (7.0 + i*0.6)
bind oy = ไซน์(t*0.9 + ph) * 4.0
bind oz = 16.0 + ไซน์(t*sp*0.7 + ph) * 4.0
bind cr = floor((ไซน์(ph)*0.5+0.5)*180+50)
bind cg = floor((ไซน์(ph+2.094)*0.5+0.5)*180+50)
bind cb = floor((ไซน์(ph+4.189)*0.5+0.5)*180+50)
orb_particles(ox, oy, oz, 1.1, 28.0, t*1.4+i*2.0, floor(cr*0.55), floor(cg*0.55), floor(cb*0.55))
สีดินสอ(floor(cr*0.7), floor(cg*0.7), floor(cb*0.7))
อนุภาคทรงกลม(ox, oy, oz, 0.7, 10, t*2.0+i, cr, cg, cb)
bind i = i + 1
}
bind cl = ไซน์(t*1.9) # ปะทะกลางสนามเป็นจังหวะ
ถ้า cl > 0.7 { สีดินสอ(255, 235, 190); อนุภาคทรงกลม(ไซน์(t*1.3)*4.0, โคไซน์(t)*2.0, 15.0, (cl-0.7)*9.0, 12, t*5.0, 255, 235, 190) }
flush_3d(); โหมดผสม(0)
}
ฟังก์ชัน วาดไฮสกอร์(names, scores, t) {
โหมดผสม(1)
สีดินสอ(255, 220, 90); วาดสตริง("high scores", 0.0, 0.0-7.2, 0.0, 1.1, 1)
bind n = ความยาว(scores); ถ้า n > 8 { bind n = 8 }
bind i = 0
ขณะที่ i < n {
bind yy = 0.0-4.5 + i*1.5; bind c = 245 - i*16
สีดินสอ(c, c, 210); วาดสตริง(list_get(names, i), 0.0-5.5, yy, 0.0, 0.6, 1)
วาดเลขป้าย(list_get(scores, i), 0.0, 6.5, yy + 0.35, 0.0, 0.8, 0.0, 255, 225, 110)
bind i = i + 1
}
flush_3d(); โหมดผสม(0)
}
# ── ดาบพิคอัพ slot 0..5 ที่ (wx,wy,wz) ขนาด s, หันกล้อง, บ๊อบตามเวลา ──
ฟังก์ชัน วาดดาบพิค(slot, wx, wy, wz, s, camYaw, t) {
bind rx = โคไซน์(camYaw); bind rz = 0.0 - ไซน์(camYaw)
bind c = list_get(ดาบสี, slot)
bind by = wy + ไซน์(t*2.0 + slot)*0.5
โหมดผสม(1)
สีดินสอ(list_get(c,0), list_get(c,1), list_get(c,2))
อนุภาคทรงกลม(wx, by + s*1.1, wz, 0.8, 12, t*2.0+slot, list_get(c,0), list_get(c,1), list_get(c,2))
เส้นป้าย(wx, by, wz, 0.0, 0.0-s, 0.0, s*0.5, rx, rz) # ใบดาบ
เส้นป้าย(wx, by, wz, 0.0-s*0.45, s*0.45, s*0.45, s*0.45, rx, rz) # ด้ามขวาง
ถ้า slot == 0 { เส้นป้าย(wx,by,wz, 0.0,0.0-s, s*0.3,0.0-s*0.55, rx,rz) เส้นป้าย(wx,by,wz, 0.0,0.0-s, 0.0-s*0.3,0.0-s*0.55, rx,rz) } # หัวลูกศร
ถ้า slot == 1 { เส้นป้าย(wx,by,wz, s*0.3,0.0-s, s*0.3,s*0.5, rx,rz) } # ใบคู่
ถ้า slot == 2 { เส้นป้าย(wx,by,wz, 0.0,0.0-s*0.4, s*0.25,0.0-s*0.05, rx,rz) เส้นป้าย(wx,by,wz, s*0.25,0.0-s*0.05, 0.0,s*0.25, rx,rz) } # เปลว
ถ้า slot == 3 { เส้นป้าย(wx,by,wz, 0.0,0.0-s*0.45, s*0.3,0.0-s*0.1, rx,rz) เส้นป้าย(wx,by,wz, s*0.3,0.0-s*0.1, 0.0,s*0.25, rx,rz) เส้นป้าย(wx,by,wz, 0.0,s*0.25, 0.0-s*0.3,0.0-s*0.1, rx,rz) เส้นป้าย(wx,by,wz, 0.0-s*0.3,0.0-s*0.1, 0.0,0.0-s*0.45, rx,rz) } # เพชรน้ำแข็ง
ถ้า slot == 4 { bind k = 0 ขณะที่ k < 8 { bind a0 = k*0.7854 bind a1 = (k+1)*0.7854 เส้นป้าย(wx,by,wz, โคไซน์(a0)*s*0.45,0.0-s*0.25+ไซน์(a0)*s*0.45, โคไซน์(a1)*s*0.45,0.0-s*0.25+ไซน์(a1)*s*0.45, rx,rz) bind k = k+1 } } # วงโนวา
ถ้า slot == 5 { เส้นป้าย(wx,by,wz, 0.0-s*0.45,s*0.2, s*0.45,s*0.2, rx,rz) } # ด้ามคู่ (quake)
flush_3d(); โหมดผสม(0)
}
# ── ป้ายลอยแบบบิลบอร์ด: หันเข้าหากล้อง (yaw), แนวนอนเสมอ, ขนาดจอคงที่ ──
# ชดเชยระยะ: sc ∝ ระยะกล้อง → ไม่ย่อ/ขยายตามใกล้ไกล (zdist เกมเพลย์ 4.6, focal 1080)
ฟังก์ชัน วาดสตริงป้าย(s, ox, oy, oz, sscale, camYaw) {
bind q = ฉาย3มิติ(ox, oy, oz)
ถ้า list_get(q,0) <= 0.0 - 99998.0 { คืน 0 } # หลังกล้อง → ข้าม
bind d = list_get(q,2) + 4.6
ถ้า d < 1.0 { bind d = 1.0 }
bind sc = sscale * d * 0.030
bind rx = โคไซน์(camYaw); bind rz = 0.0 - ไซน์(camYaw) # แกนขวา (บิลบอร์ด yaw)
bind n = ความยาว(s)
bind adv = sc * 0.66
bind startk = 0.0 - (n - 1) * 0.5
bind i = 0
ขณะที่ i < n {
bind ch = ส่วนสตริง(s, i, 1)
bind code = ตัวอักษรเป็นดัชนี(ch)
ถ้า code >= 0 {
bind off = (startk + i) * adv
วาดอักขระEnglish(code, ox + rx*off, oy, oz + rz*off, rx,0,rz, 0,0.0-1.0,0, sc)
}
bind i = i + 1
}
}
# ── ศัตรู: ตารางชื่อ + คำคัตเอาต์ ──
bind ศัตรูชื่อ = ["Nyx","Ling","yisen","Zev","Quo","Vox","Jade","Bryn","Cade","Dax","Fynn","Gael","Hal","Ivo","Kael","Mika","Orin","Pax","Rune","Sage","Tynan","Ulla","Wren","Xena","Yael","Zion"]
bind บอสชื่อ = ["The Warden","Omega","Void King","Apex","Nemesis","The Maw"]
bind คำเปิด = ["lock in","spin the dice","cut the line","push the pace","break the seal","light the fuse","draw first blood"]
bind คำตี = ["nice read","too slow","right there","clean shot","bad move"]
bind คำเพล = ["fading fast","can't hold","almost done","no more left","falling apart"]
bind คำใบ้ = ["watch your flank","don't panic","move now","bait it out"]
ฟังก์ชัน สุ่มในรายการ(lst) { คืน list_get(lst, floor(สุ่ม() * ความยาว(lst))) }
ฟังก์ชัน ดึงคำเปิด() { คืน สุ่มในรายการ(คำเปิด) }
ฟังก์ชัน ดึงคำตี() { คืน สุ่มในรายการ(คำตี) }
ฟังก์ชัน ดึงคำเพล() { คืน สุ่มในรายการ(คำเพล) }
ฟังก์ชัน ดึงคำใบ้() { คืน สุ่มในรายการ(คำใบ้) }
# สร้างศัตรู: คืน [hpMax, def, res, atk, cool, diff, bodyHue, stampHue, bandHue, stamp, band, name]
# สเตตัส/ดิฟ ขึ้นตามรอบ (Smash-style gauntlet)
ฟังก์ชัน สร้างศัตรู(รอบ) {
ถ้า รอบ >= 10.0 { # ── บอสจบ (รอบ 10) ──
คืน [620.0, 6.0, 0.45, 15.0, 0.5, 0.95, สุ่ม(), สุ่ม(), สุ่ม(), floor(สุ่ม()*STAMP_N), floor(สุ่ม()*BAND_N), สุ่มในรายการ(บอสชื่อ)]
}
bind hpMax = 55.0 + รอบ * 16.0
bind def = รอบ * 0.6
bind res = รอบ * 0.04; ถ้า res > 0.45 { bind res = 0.45 }
bind atk = 4.0 + รอบ * 1.5
bind cool = 1.7 - รอบ * 0.08; ถ้า cool < 0.6 { bind cool = 0.6 }
bind diff = รอบ * 0.09; ถ้า diff > 0.9 { bind diff = 0.9 }
คืน [hpMax, def, res, atk, cool, diff, สุ่ม(), สุ่ม(), สุ่ม(), floor(สุ่ม()*STAMP_N), floor(สุ่ม()*BAND_N), สุ่มในรายการ(ศัตรูชื่อ)]
}
# ── วาดศัตรู: ลูกแต่ง (สีตามฮิว) + แฟลชโดนตี + วงการ์ด + ป้ายชื่อลอย ──
ฟังก์ชัน วาดศัตรู(fx, fy, fz, R, bh, sh, nh, stamp, band, t, hurt, guard, name, camYaw) {
bind cb = สีจากเฉด(bh); bind cs = สีจากเฉด(sh); bind cn = สีจากเฉด(nh)
bind br = list_get(cb,0); bind bg = list_get(cb,1); bind bb = list_get(cb,2)
ถ้า hurt > 0.0 { bind br = 255; bind bg = floor(120 + hurt*400); bind bb = floor(120 + hurt*400) }
วาดลูกแต่ง(fx, fy, fz, R, br,bg,bb,
list_get(cs,0),list_get(cs,1),list_get(cs,2),
list_get(cn,0),list_get(cn,1),list_get(cn,2),
stamp, band, t, 0.0)
ถ้า guard > 0.5 {
โหมดผสม(1); สีดินสอ(255, 210, 90)
bind gk = 0
ขณะที่ gk < 16 {
bind a0 = gk * 0.3927; bind a1 = (gk + 1) * 0.3927
วาดเส้น3มิติ(fx+โคไซน์(a0)*R*1.6, fy, fz+ไซน์(a0)*R*1.6, fx+โคไซน์(a1)*R*1.6, fy, fz+ไซน์(a1)*R*1.6)
bind gk = gk + 1
}
flush_3d(); โหมดผสม(0)
}
โหมดผสม(1); สีดินสอ(255, 235, 190); วาดสตริงป้าย(name, fx, fy - R - 3.5, fz, 1.0, camYaw); flush_3d(); โหมดผสม(0)
}
# ── แถบเลือด HUD (มุมจอ): พื้นเทา + เติมตามอัตราส่วน, ป้ายชื่อ ──
# ใช้กล้องโอเวอร์เลย์ 2D (เรียกหลัง ตั้งกล้องมอง overlay) — x,y โลก, w กว้าง
ฟังก์ชัน แถบHP(x, y, w, frac, r, g, b, name, ชิด) {
ถ้า frac < 0.0 { bind frac = 0.0 }
สีดินสอ(40, 40, 55)
วาดสามเหลี่ยม3มิติ(x, y-0.5, 0.0, x+w, y-0.5, 0.0, x+w, y+0.5, 0.0)
วาดสามเหลี่ยม3มิติ(x, y-0.5, 0.0, x+w, y+0.5, 0.0, x, y+0.5, 0.0)
bind fw = w * frac
bind fx0 = x; ถ้า ชิด > 0.5 { bind fx0 = x + w - fw } # ชิด=1 → เติมจากขวา (ศัตรู)
สีดินสอ(r, g, b)
วาดสามเหลี่ยม3มิติ(fx0, y-0.5, 0.0, fx0+fw, y-0.5, 0.0, fx0+fw, y+0.5, 0.0)
วาดสามเหลี่ยม3มิติ(fx0, y-0.5, 0.0, fx0+fw, y+0.5, 0.0, fx0, y+0.5, 0.0)
โหมดผสม(1); สีดินสอ(235, 235, 255)
bind nx = x; ถ้า ชิด > 0.5 { bind nx = x + w - ความยาว(name)*0.45 }
วาดสตริง(name, nx + 1.5, y - 1.6, 0.0, 0.5, 1)
โหมดผสม(0)
}
# ── ลูกแต่ง: body orb (สี) + โครงทรงกลม + สแตมป์ขั้วบน/ล่าง + แบนด์รอบกลาง ──
ฟังก์ชัน วาดลูกแต่ง(cx, cy, cz, R, br,bg,bb, sr,sg,sb, ar,ag,ab, stampId, bandId, t, fxId) {
bind tb = t; bind tc = t*0.6; bind Rs = R; bind bandCy = cy # เอฟเฟกต์ (fx 0 = นิ่ง)
ถ้า fxId == 1.0 { bind tb = t*3.0; bind tc = t*2.2 } # spin: หมุนเร็ว
ถ้า fxId == 2.0 { bind Rs = R * (1.0 + 0.09*ไซน์(t*3.0)) } # pulse: เต้น
ถ้า fxId == 3.0 { bind tb = t*2.6; bind bandCy = cy + ไซน์(t*1.6)*R*0.45 } # orbit: แบนด์บ๊อบ+หมุน
# body = อนุภาคเรืองแสง (additive)
โหมดผสม(1)
orb_particles(cx, cy, cz, Rs*0.95, 600.0, t, br, bg, bb) # ของเหลว: สีลำตัว (ชั้นนอก)
orb_particles(cx, cy, cz, Rs*0.68, 340.0, t*1.3+2.0, sr, sg, sb) # สีสแตมป์ (ชั้นกลาง)
orb_particles(cx, cy, cz, Rs*0.42, 200.0, t*1.7+4.0, ar, ag, ab) # สีแบนด์ (ชั้นใน)
flush_3d()
# โครงทรงกลม (วงละติจูด) ให้เห็นเป็นลูกชัดขึ้น
สีดินสอ(floor(br*0.5), floor(bg*0.5), floor(bb*0.5))
bind lat = 0
ขณะที่ lat < 3 {
bind ly = cy + (lat - 1) * R * 0.55
bind lr = รากที่สอง(R*R - (ly-cy)*(ly-cy))
bind k = 0
ขณะที่ k < 20 {
bind a0 = k * 0.31416; bind a1 = (k + 1) * 0.31416
วาดเส้น3มิติ(cx+โคไซน์(a0)*lr, ly, cz+ไซน์(a0)*lr, cx+โคไซน์(a1)*lr, ly, cz+ไซน์(a1)*lr)
bind k = k + 1
}
bind lat = lat + 1
}
flush_3d()
# สแตมป์ + แบนด์ = ฟิลทึบ (normal blend)
โหมดผสม(0)
สีดินสอ(sr, sg, sb)
วาดสแตมป์(stampId, cx, cy - Rs*1.0, cz, Rs*0.5, tc) # ขั้วบน (เล็กลง)
วาดสแตมป์(stampId, cx, cy + Rs*1.0, cz, Rs*0.5, 0.0 - tc) # ขั้วล่าง
สีดินสอ(ar, ag, ab) # ลายเล็กในแกน (สีแบนด์) — สองโทน หมุนสวน
วาดสแตมป์(stampId, cx, cy - Rs*1.0, cz, Rs*0.26, 0.0 - tc*1.5)
วาดสแตมป์(stampId, cx, cy + Rs*1.0, cz, Rs*0.26, tc*1.5)
สีดินสอ(ar, ag, ab)
วาดแบนด์(bandId, cx, bandCy, cz, Rs*1.03, tb)
flush_3d()
}