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/level.ling
# ────────────────────────────────────────────────────────────────────────────
# level.ling — มหาวิหารยักษ์: ฮับ + 4 ปีก, เพดานสูงมาก, ห้องกว้าง/ลึกมาก
# พื้น Y=3.0 · เพดาน Y=-171 (สูง 174) · ห้อง ±256 · ทางเดินแกน (ประตู ±40)
# ปีกลึกถึง z=±960 · ขอบเขต ±960 · พื้นครึ่ง 1000 · ชน union 9 กล่อง
# กล่องทางเดินซ้อนเข้าห้อง +30 → ไม่มีรอยต่อตัน (ข้ามได้ทุกทิศ)
# ────────────────────────────────────────────────────────────────────────────
bind LVL_F = 3.0
bind LVL_C = 0.0 - 171.0
bind ประตู = 40.0
bind พื้นครึ่ง = 1000.0
# ── ผนัง: กระเบื้องกริด — แผ่นใหญ่ขึ้น (ห้องยักษ์) เพื่อ FPS ───────────────────
ฟังก์ชัน วาดผนังเต็ม(ax, az, bx, bz) {
bind dx = bx - ax; bind dz = bz - az
bind len = รากที่สอง(dx*dx + dz*dz)
bind nseg = ปัดลง(len / 56.0) + 1
bind nrow = 4
bind i = 0
ขณะที่ i < nseg {
bind u0 = i / nseg; bind u1 = (i + 1) / nseg
bind x0 = ax + dx*u0; bind z0 = az + dz*u0
bind x1 = ax + dx*u1; bind z1 = az + dz*u1
bind j = 0
ขณะที่ j < nrow {
bind y0 = LVL_F + (LVL_C - LVL_F) * (j / nrow)
bind y1 = LVL_F + (LVL_C - LVL_F) * ((j + 1) / nrow)
ถ้า (i + j) % 2 == 0 { สีดินสอ(12, 16, 46) }
มิฉะนั้น { สีดินสอ(28, 34, 82) }
draw_quad_3d(x0, y0, z0, x1, y0, z1, x1, y1, z1, x0, y1, z0)
bind j = j + 1
}
bind i = i + 1
}
}
ฟังก์ชัน วาดห้องกล่อง(x0, x1, z0, z1, dN, dS, dE, dW) {
ถ้า dN == 1 { วาดผนังเต็ม(x0, z0, 0.0-ประตู, z0) วาดผนังเต็ม(ประตู, z0, x1, z0) }
มิฉะนั้น { วาดผนังเต็ม(x0, z0, x1, z0) }
ถ้า dS == 1 { วาดผนังเต็ม(x0, z1, 0.0-ประตู, z1) วาดผนังเต็ม(ประตู, z1, x1, z1) }
มิฉะนั้น { วาดผนังเต็ม(x0, z1, x1, z1) }
ถ้า dW == 1 { วาดผนังเต็ม(x0, z0, x0, 0.0-ประตู) วาดผนังเต็ม(x0, ประตู, x0, z1) }
มิฉะนั้น { วาดผนังเต็ม(x0, z0, x0, z1) }
ถ้า dE == 1 { วาดผนังเต็ม(x1, z0, x1, 0.0-ประตู) วาดผนังเต็ม(x1, ประตู, x1, z1) }
มิฉะนั้น { วาดผนังเต็ม(x1, z0, x1, z1) }
}
ฟังก์ชัน วาดเสา(cx, cz) {
bind w = 14.0
สีดินสอ(40, 30, 70)
วาดผนังเต็ม(cx-w, cz-w, cx+w, cz-w)
วาดผนังเต็ม(cx+w, cz-w, cx+w, cz+w)
วาดผนังเต็ม(cx+w, cz+w, cx-w, cz+w)
วาดผนังเต็ม(cx-w, cz+w, cx-w, cz-w)
}
ฟังก์ชัน วาดทางเดิน(ax, az, bx, bz) {
วาดผนังเต็ม(ax, az, bx, bz)
}
# ── คบไฟ: ขาแขวน + เปลวไฟวับ ๆ (additive) ที่ตำแหน่งผนัง ─────────────────────
bind คบY = 0.0 - 45.0
ฟังก์ชัน วาดคบไฟ(x, z, t, seed) {
bind fl = 0.86 + ไซน์(t*9.0 + seed)*0.08 + ไซน์(t*15.0 + seed*2.0)*0.04
สีดินสอ(70, 50, 30)
วาดเส้น3มิติ(x, คบY+3.0, z, x, คบY-1.0, z)
อนุภาคทรงกลม(x, คบY-3.0, z, 1.8, 16, t*1.4+seed, floor(255*fl), floor(126*fl), floor(30*fl))
อนุภาคทรงกลม(x, คบY-1.5, z, 1.1, 8, t*1.7+seed, floor(255*fl), floor(178*fl), floor(72*fl))
}
# ── โคมระย้า: โซ่ห้อยจากเพดาน + วงเทียน 6 ดวง (additive) ─────────────────────
ฟังก์ชัน วาดโคมระย้า(cx, cz, t) {
bind hy = 0.0 - 121.0
สีดินสอ(55, 55, 65)
วาดเส้น3มิติ(cx, LVL_C, cz, cx, hy, cz)
bind k = 0
ขณะที่ k < 6 {
bind a = k * 1.0472 + t*0.25
bind rx = cx + โคไซน์(a)*10.0
bind rz = cz + ไซน์(a)*10.0
สีดินสอ(55, 55, 65); วาดเส้น3มิติ(cx, hy, cz, rx, hy, rz)
bind fl = 0.7 + ไซน์(t*10.0 + k*1.7)*0.3
อนุภาคทรงกลม(rx, hy-1.0, rz, 1.0, 8, t*2.0+k, 255, floor(210*fl), floor(120*fl))
bind k = k + 1
}
}
# ภาพคบไฟ 4 ผนัง + โคมระย้า ของห้อง [x0,x1,z0,z1]
# + โวลูเมตริก: แอ่งแสงอุ่นใต้คบไฟ + ลำแสง/แอ่งทองใต้โคมระย้า
# (เกรเดียนต์บวกขอบนุ่ม โปร่งแสง — เห็นสี/รัศมีไฟสาดสะท้อนบนพื้น)
ฟังก์ชัน วาดของห้อง(x0, x1, z0, z1, t) {
bind mx = (x0+x1)*0.5; bind mz = (z0+z1)*0.5
วาดคบไฟ(x0+7.0, mz, t, 0.0)
วาดคบไฟ(x1-7.0, mz, t, 1.3)
วาดคบไฟ(mx, z0+7.0, t, 2.6)
วาดคบไฟ(mx, z1-7.0, t, 3.9)
วาดโคมระย้า(mx, mz, t)
bind fl = 0.86 + ไซน์(t*7.0)*0.08 # วูบตามเปลวไฟ
แอ่งแสง(x0+7.0, LVL_F, mz, 15.0, 255, 150, 58, 0.34*fl)
แอ่งแสง(x1-7.0, LVL_F, mz, 15.0, 255, 150, 58, 0.34*fl)
แอ่งแสง(mx, LVL_F, z0+7.0, 15.0, 255, 150, 58, 0.34*fl)
แอ่งแสง(mx, LVL_F, z1-7.0, 15.0, 255, 150, 58, 0.34*fl)
ลำแสงไฟ(mx, 0.0-121.0, mz, LVL_F, 24.0, 255, 210, 120, 0.16) # ลำแสงโคมระย้า
แอ่งแสง(mx, LVL_F, mz, 30.0, 255, 210, 120, 0.30)
}
# แสงของห้อง: คบไฟ 4 + โคมระย้า (จุดแสงจริง — ต้องเรียกก่อนวาด geometry)
ฟังก์ชัน แสงห้อง(x0, x1, z0, z1, t) {
bind mx = (x0+x1)*0.5; bind mz = (z0+z1)*0.5
เพิ่มแสง(x0+7.0, คบY, mz, 1.0,0.48,0.16, 1.18, 220.0)
เพิ่มแสง(x1-7.0, คบY, mz, 1.0,0.48,0.16, 1.18, 220.0)
เพิ่มแสง(mx, คบY, z0+7.0, 1.0,0.48,0.16, 1.18, 220.0)
เพิ่มแสง(mx, คบY, z1-7.0, 1.0,0.48,0.16, 1.18, 220.0)
เพิ่มแสง(mx, 0.0-121.0, mz, 1.0,0.82,0.52, 1.4, 300.0)
}
ฟังก์ชัน แสงสีเลเวล1(cx, cz, t) {
bind p = 0.55 + ไซน์(t*1.8)*0.10
เพิ่มแสง(0.0, 0.0-96.0, 0.0, 0.38, 0.78, 0.86, 1.05+p, 420.0)
เพิ่มแสง(0.0-176.0, 0.0-52.0, 176.0, 0.86, 0.22, 0.38, 0.95+p*0.35, 300.0)
เพิ่มแสง(176.0, 0.0-52.0, 0.0-176.0, 0.32, 0.62, 0.86, 0.95+p*0.35, 300.0)
เพิ่มแสง(176.0, 0.0-74.0, 176.0, 0.66, 0.34, 0.86, 0.90+p*0.25, 280.0)
เพิ่มแสง(0.0-176.0, 0.0-74.0, 0.0-176.0, 0.86, 0.74, 0.28, 0.90+p*0.25, 280.0)
ถ้า cx*cx + (cz+704.0)*(cz+704.0) < 640000.0 {
เพิ่มแสง(0.0, 0.0-88.0, 0.0-704.0, 0.28, 0.86, 0.68, 1.15, 360.0)
เพิ่มแสง(0.0-140.0, 0.0-42.0, 0.0-704.0, 0.82, 0.30, 0.86, 0.85, 260.0)
เพิ่มแสง(140.0, 0.0-42.0, 0.0-704.0, 0.22, 0.48, 0.86, 0.85, 260.0)
}
ถ้า cx*cx + (cz-704.0)*(cz-704.0) < 640000.0 {
เพิ่มแสง(0.0, 0.0-88.0, 704.0, 0.86, 0.38, 0.26, 1.15, 360.0)
เพิ่มแสง(0.0-140.0, 0.0-42.0, 704.0, 0.86, 0.64, 0.24, 0.85, 260.0)
เพิ่มแสง(140.0, 0.0-42.0, 704.0, 0.34, 0.78, 0.86, 0.85, 260.0)
}
ถ้า (cx-704.0)*(cx-704.0) + cz*cz < 640000.0 {
เพิ่มแสง(704.0, 0.0-88.0, 0.0, 0.48, 0.38, 0.86, 1.15, 360.0)
เพิ่มแสง(704.0, 0.0-42.0, 0.0-140.0, 0.86, 0.26, 0.54, 0.85, 260.0)
เพิ่มแสง(704.0, 0.0-42.0, 140.0, 0.36, 0.86, 0.46, 0.85, 260.0)
}
ถ้า (cx+704.0)*(cx+704.0) + cz*cz < 640000.0 {
เพิ่มแสง(0.0-704.0, 0.0-88.0, 0.0, 0.22, 0.78, 0.86, 1.15, 360.0)
เพิ่มแสง(0.0-704.0, 0.0-42.0, 0.0-140.0, 0.82, 0.38, 0.86, 0.85, 260.0)
เพิ่มแสง(0.0-704.0, 0.0-42.0, 140.0, 0.86, 0.70, 0.32, 0.85, 260.0)
}
}
# จุดแสงทั้งเลเวล (ล้าง+เพิ่ม) — เรียกก่อนวาดพื้น/ผนัง; cull ตามระยะลูก
ฟังก์ชัน ตั้งแสงเลเวล(cx, cz, t) {
ล้างแสง()
แสงห้อง(0.0-64.0, 64.0, 0.0-64.0, 64.0, t)
แสงสีเลเวล1(cx, cz, t)
ถ้า cx*cx + (cz+352.0)*(cz+352.0) < 250000.0 {
เพิ่มแสง(0.0-36.0, คบY, 0.0-352.0, 1.0,0.5,0.18, 1.1, 220.0)
เพิ่มแสง(36.0, คบY, 0.0-352.0, 1.0,0.5,0.18, 1.1, 220.0)
}
ถ้า cx*cx + (cz-352.0)*(cz-352.0) < 250000.0 {
เพิ่มแสง(0.0-36.0, คบY, 352.0, 1.0,0.5,0.18, 1.1, 220.0)
เพิ่มแสง(36.0, คบY, 352.0, 1.0,0.5,0.18, 1.1, 220.0)
}
ถ้า (cx-352.0)*(cx-352.0) + cz*cz < 250000.0 {
เพิ่มแสง(352.0, คบY, 0.0-36.0, 1.0,0.5,0.18, 1.1, 220.0)
เพิ่มแสง(352.0, คบY, 36.0, 1.0,0.5,0.18, 1.1, 220.0)
}
ถ้า (cx+352.0)*(cx+352.0) + cz*cz < 250000.0 {
เพิ่มแสง(0.0-352.0, คบY, 0.0-36.0, 1.0,0.5,0.18, 1.1, 220.0)
เพิ่มแสง(0.0-352.0, คบY, 36.0, 1.0,0.5,0.18, 1.1, 220.0)
}
ถ้า cx*cx + (cz+704.0)*(cz+704.0) < 360000.0 { แสงห้อง(0.0-64.0,64.0,0.0-960.0,0.0-448.0,t) }
ถ้า cx*cx + (cz-704.0)*(cz-704.0) < 360000.0 { แสงห้อง(0.0-64.0,64.0,448.0,960.0,t) }
ถ้า (cx-704.0)*(cx-704.0) + cz*cz < 360000.0 { แสงห้อง(448.0,960.0,0.0-64.0,64.0,t) }
ถ้า (cx+704.0)*(cx+704.0) + cz*cz < 360000.0 { แสงห้อง(0.0-960.0,0.0-448.0,0.0-64.0,64.0,t) }
}
# ── พื้น: กระเบื้องเติม (vector texture) แน่น ๆ รอบลูก (snap กับกริด ไม่ไหล) ──
# ลาย/สีต่างจากผนัง (เขียวอมเทา) + เส้นกริดถี่
# คืน 1 ถ้ามุมทั้ง 4 ของกระเบื้อง (x0..x1, z0..z1 ที่ความสูง y) อยู่หน้า near plane
# ฉาย3มิติ คืน sx = -99999 เมื่อจุดอยู่ที่/หลัง near plane → ถ้ามุมใดหลังกล้องให้ข้าม
# กันอาการ "fan" (จุดยอดหลังกล้องโปรเจกต์พลิกข้ามจอ) ตอนกล้องอยู่ใกล้/ต่ำกับพื้น
ฟังก์ชัน กระเบื้องหน้ากล้อง(x0, y, z0, x1, z1) {
# project the tile CENTRE only (1 projection vs 4 corners → 4× cheaper cull).
# Tiles straddling the near plane still draw and get engine-clipped; a flat
# floor makes the slight edge difference invisible. (Tutorial floor was the
# #1 frame cost: ~800 tiles/frame × 4 projections.)
bind cxm = (x0 + x1) * 0.5; bind czm = (z0 + z1) * 0.5
ถ้า list_get(ฉาย3มิติ(cxm, y, czm), 0) <= 0.0 - 99998.0 { คืน 0 }
คืน 1
}
ฟังก์ชัน วาดพื้น(cx, cz) {
bind S = 18.0
bind n = 15 # รัศมีกริด = 15×18 = 270 ≈ ระยะหมอก (เลยนั้นมองไม่เห็น)
bind bx = ปัดลง(cx / S)
bind bz = ปัดลง(cz / S)
โหมดผสม(0)
set_alpha(1.0)
set_normal_override(0.0, 0.0 - 1.0, 0.0)
# พื้นด้าน (matte): ปิดสเปกคูลาร์/เคลียร์โค้ต — ไม่มีชีนวาว/รอยขาวสาดบนพื้น
set_material("roughness", 0.85)
set_material("specular", 0.05)
set_material("specular_tint", 0.0)
set_material("clearcoat", 0.0)
set_material("clearcoat_roughness", 0.08)
set_material("toon_bands", 4.0)
set_material("shadow_softness", 0.08)
bind i = 0 - n
ขณะที่ i <= n {
bind j = 0 - n
ขณะที่ j <= n {
bind ti = bx + i; bind tj = bz + j
bind x0 = ti * S; bind z0 = tj * S
bind x1 = x0 + S; bind z1 = z0 + S
# ── cull ระยะ (ถูก, ไม่เรียกฟังก์ชัน): ข้ามกระเบื้องเลยหมอก → ตัดมุมกริด ──
bind ddx = (x0 + 9.0) - cx; bind ddz = (z0 + 9.0) - cz
ถ้า ddx*ddx + ddz*ddz < 73000.0 { # ภายใน ~270 หน่วย
ถ้า กระเบื้องหน้ากล้อง(x0, LVL_F, z0, x1, z1) == 1 {
bind par = ti + tj
bind par2 = par - ปัดลง(par / 2.0) * 2
ถ้า par2 == 0 { สีดินสอ(24, 78, 70) }
มิฉะนั้น { สีดินสอ(42, 128, 118) }
วาดสามเหลี่ยม3มิติ(x0, LVL_F, z0, x1, LVL_F, z0, x1, LVL_F, z1)
วาดสามเหลี่ยม3มิติ(x0, LVL_F, z0, x1, LVL_F, z1, x0, LVL_F, z1)
} }
bind j = j + 1
}
bind i = i + 1
}
reset_material()
reset_normal_override()
set_alpha(1.0)
โหมดผสม(0)
}
ฟังก์ชัน วาดเลเวล(t, cx, cz) {
# ── ฮับกลาง [±256], ประตูทุกด้าน (วาดเสมอ) ──
วาดห้องกล่อง(0.0-256.0, 256.0, 0.0-256.0, 256.0, 1, 1, 1, 1)
วาดเสา(160.0, 160.0)
วาดเสา(0.0-160.0, 160.0)
วาดเสา(160.0, 0.0-160.0)
วาดเสา(0.0-160.0, 0.0-160.0)
ถ้า cx*cx + cz*cz < 640000.0 { ลายดอกบัว(0.0, LVL_C, 0.0, 1,0,0, 0,0,1, 60.0, 210.0, 8, t*0.25, t*0.02) }
วาดของห้อง(0.0-64.0, 64.0, 0.0-64.0, 64.0, t)
# ── ปีกวาดเฉพาะที่ใกล้ (cull ~800) ──
ถ้า cx*cx + (cz+704.0)*(cz+704.0) < 640000.0 { # เหนือ
วาดห้องกล่อง(0.0-256.0, 256.0, 0.0-960.0, 0.0-448.0, 0, 1, 0, 0)
วาดทางเดิน(0.0-40.0, 0.0-256.0, 0.0-40.0, 0.0-448.0)
วาดทางเดิน(40.0, 0.0-256.0, 40.0, 0.0-448.0)
ลายดอกบัว(0.0, LVL_C, 0.0-704.0, 1,0,0, 0,0,1, 54.0, 190.0, 6, t*0.25, 1.0)
วาดของห้อง(0.0-64.0, 64.0, 0.0-960.0, 0.0-448.0, t)
วาดคบไฟ(0.0-36.0, 0.0-352.0, t, 5.0)
วาดคบไฟ(36.0, 0.0-352.0, t, 6.0)
}
ถ้า cx*cx + (cz-704.0)*(cz-704.0) < 640000.0 { # ใต้
วาดห้องกล่อง(0.0-256.0, 256.0, 448.0, 960.0, 1, 0, 0, 0)
วาดทางเดิน(0.0-40.0, 256.0, 0.0-40.0, 448.0)
วาดทางเดิน(40.0, 256.0, 40.0, 448.0)
ลายดอกบัว(0.0, LVL_C, 704.0, 1,0,0, 0,0,1, 54.0, 190.0, 6, t*0.25, 2.0)
วาดของห้อง(0.0-64.0, 64.0, 448.0, 960.0, t)
วาดคบไฟ(0.0-36.0, 352.0, t, 5.0)
วาดคบไฟ(36.0, 352.0, t, 6.0)
}
ถ้า (cx-704.0)*(cx-704.0) + cz*cz < 640000.0 { # ออก
วาดห้องกล่อง(448.0, 960.0, 0.0-256.0, 256.0, 0, 0, 0, 1)
วาดทางเดิน(256.0, 0.0-40.0, 448.0, 0.0-40.0)
วาดทางเดิน(256.0, 40.0, 448.0, 40.0)
ลายดอกบัว(704.0, LVL_C, 0.0, 1,0,0, 0,0,1, 54.0, 190.0, 6, t*0.25, 3.0)
วาดของห้อง(448.0, 960.0, 0.0-64.0, 64.0, t)
วาดคบไฟ(352.0, 0.0-36.0, t, 5.0)
วาดคบไฟ(352.0, 36.0, t, 6.0)
}
ถ้า (cx+704.0)*(cx+704.0) + cz*cz < 640000.0 { # ตก
วาดห้องกล่อง(0.0-960.0, 0.0-448.0, 0.0-256.0, 256.0, 0, 0, 1, 0)
วาดทางเดิน(0.0-256.0, 0.0-40.0, 0.0-448.0, 0.0-40.0)
วาดทางเดิน(0.0-256.0, 40.0, 0.0-448.0, 40.0)
ลายดอกบัว(0.0-704.0, LVL_C, 0.0, 1,0,0, 0,0,1, 54.0, 190.0, 6, t*0.25, 4.0)
วาดของห้อง(0.0-960.0, 0.0-448.0, 0.0-64.0, 64.0, t)
วาดคบไฟ(0.0-352.0, 0.0-36.0, t, 5.0)
วาดคบไฟ(0.0-352.0, 36.0, t, 6.0)
}
}
# ════════════════════════════════════════════════════════════════════════════
# การชน: union 9 กล่อง inline — กล่องทางเดินซ้อนเข้าห้อง +30 (ไม่มีรอยต่อตัน)
# ════════════════════════════════════════════════════════════════════════════
ฟังก์ชัน หากล่อง(cx, cz, R) {
bind B = [
0.0-256.0, 256.0, 0.0-256.0, 256.0, # hub
0.0-40.0, 40.0, 0.0-478.0, 0.0-226.0, # N corr (ยืด ±30)
0.0-256.0, 256.0, 0.0-960.0, 0.0-448.0, # N room
0.0-40.0, 40.0, 226.0, 478.0, # S corr
0.0-256.0, 256.0, 448.0, 960.0, # S room
226.0, 478.0, 0.0-40.0, 40.0, # E corr
448.0, 960.0, 0.0-256.0, 256.0, # E room
0.0-478.0, 0.0-226.0, 0.0-40.0, 40.0, # W corr
0.0-960.0, 0.0-448.0, 0.0-256.0, 256.0 # W room
]
bind bpen = 1000000.0; bind bqx = cx; bind bqz = cz
bind i = 0
ขณะที่ i < 36 {
bind x0 = list_get(B, i); bind x1 = list_get(B, i+1)
bind z0 = list_get(B, i+2); bind z1 = list_get(B, i+3)
bind qx = cx; ถ้า qx < x0+R { bind qx = x0+R } ถ้า qx > x1-R { bind qx = x1-R }
bind qz = cz; ถ้า qz < z0+R { bind qz = z0+R } ถ้า qz > z1-R { bind qz = z1-R }
bind p = รากที่สอง((cx-qx)*(cx-qx) + (cz-qz)*(cz-qz))
ถ้า p < bpen { bind bpen = p; bind bqx = qx; bind bqz = qz }
bind i = i + 4
}
คืน [bpen, bqx, bqz]
}
ฟังก์ชัน ชนเสา(ball, cx, cz, px, pz, R) {
bind dx = cx - px; bind dz = cz - pz
bind d = รากที่สอง(dx*dx + dz*dz)
bind rr = 14.0 + R
ถ้า d < rr { ถ้า d > 0.01 {
bind str = (rr - d) * 0.06 + 0.1
ถ้า str > 0.7 { bind str = 0.7 }
เตะนุ่ม(ball, dx/d, 0.0, dz/d, str)
} }
}
ฟังก์ชัน ชนเลเวล(ball, cx, cz, R) {
bind best = หากล่อง(cx, cz, R)
bind pen = list_get(best,0)
ถ้า pen > 0.0 {
bind dx = list_get(best,1) - cx; bind dz = list_get(best,2) - cz
bind dd = รากที่สอง(dx*dx + dz*dz)
ถ้า dd > 0.001 {
bind str = pen * 0.4 + 0.12
ถ้า str > 0.7 { bind str = 0.7 }
เตะนุ่ม(ball, dx/dd, 0.0, dz/dd, str)
}
}
ชนเสา(ball, cx, cz, 160.0, 160.0, R)
ชนเสา(ball, cx, cz, 0.0-160.0, 160.0, R)
ชนเสา(ball, cx, cz, 160.0, 0.0-160.0, R)
ชนเสา(ball, cx, cz, 0.0-160.0, 0.0-160.0, R)
}
ฟังก์ชัน ดึงกล้อง(cx, cz) {
bind best = หากล่อง(cx, cz, 3.0)
คืน [list_get(best,1), list_get(best,2)]
}
# มองเห็น: เส้นจากจุดชม (vx,vz) ไปวัตถุ (ox,oz) โดนผนังไหม → 0 ถ้าโดนบัง, 1 ถ้าเห็น
# สุ่มจุดบนเส้น; ถ้าจุดใดอยู่นอกพื้นเดินได้ (ในผนัง) = ถูกบัง (lvl2=1 → ใช้ลาน proc)
ฟังก์ชัน มองเห็น(vx, vz, ox, oz, lvl2) {
bind k = 1
ขณะที่ k < 6 {
bind f = k / 6.0
bind sx = vx + (ox - vx) * f
bind sz = vz + (oz - vz) * f
bind pen = 0.0
ถ้า lvl2 > 0.5 { bind pen = list_get(หากล่อง2(sx, sz, 0.0), 0) }
มิฉะนั้น { bind pen = list_get(หากล่อง(sx, sz, 0.0), 0) }
ถ้า pen > 0.5 { คืน 0 }
bind k = k + 1
}
คืน 1
}