Files
ngzz-mc/internal/physics/player_test.go
2026-09-19 14:21:08 +08:00

106 lines
2.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package physics
import "testing"
// planeWorld 测试世界y < 63 全固体y >= 63 空气x == 5 一堵墙。
type planeWorld struct{}
func (planeWorld) Solid(x, y, z int32) bool {
return y < 63 || x == 5
}
func (planeWorld) Fluid(x, y, z int32) bool { return false }
// TestFallOntoGround 下落 → 停在 63 层顶部浮点余量内OnGround 置位。
func TestFallOntoGround(t *testing.T) {
w := planeWorld{}
p := NewPlayer(0.5, 80, 0.5)
for i := 0; i < 200; i++ {
p.Tick(w, 1.0/20)
}
if p.Pos[1] < 63 || p.Pos[1] >= 63.5 {
t.Fatalf("脚底期望 [63, 63.5),实际 %v", p.Pos[1])
}
if !p.OnGround {
t.Fatal("应判定落地")
}
}
// TestWallBlock 水平移动撞墙不穿墙(物理与碰撞.md §8 踩坑)。
func TestWallBlock(t *testing.T) {
w := planeWorld{}
p := NewPlayer(4.0, 63, 0.5) // 墙在 x=5玩家宽 0.6(右缘 4.3
p.Vel[0] = 10
p.Tick(w, 1.0/20)
if p.Pos[0]+p.Width/2 > 5 {
t.Fatalf("穿墙:右缘 %v 超过墙 x=5", p.Pos[0]+p.Width/2)
}
}
// TestJump 起跳与回落。
func TestJump(t *testing.T) {
w := planeWorld{}
p := NewPlayer(0.5, 63, 0.5)
p.Tick(w, 1.0/20) // 先落地判定
if !p.OnGround {
t.Fatal("初始应在地面")
}
p.Jump()
peak := 0.0
for i := 0; i < 100; i++ {
p.Tick(w, 1.0/20)
if p.Pos[1] > peak {
peak = p.Pos[1]
}
if p.OnGround && i > 5 {
break
}
}
if peak < 64.0 {
t.Fatalf("起跳高度过低: %v", peak)
}
}
type waterWorld struct{}
func (waterWorld) Solid(x, y, z int32) bool { return y < 50 }
func (waterWorld) Fluid(x, y, z int32) bool { return y >= 50 && y <= 56 }
func TestOxygenDrainAndRefill(t *testing.T) {
w := waterWorld{}
p := NewPlayer(0.5, 52, 0.5) // 眼睛约 53.6,在水中
p.updateFluid(w)
if !p.EyeInWater {
t.Fatal("眼睛应在水中")
}
p.TickAir(1)
if p.Air >= AirMax {
t.Fatalf("水下氧气应递减,实际 %v", p.Air)
}
for i := 0; i < 20; i++ {
p.TickAir(1)
}
if p.Air != 0 {
t.Fatalf("长时间潜水氧气应为 0实际 %v", p.Air)
}
p.Pos[1] = 60 // 出水
p.updateFluid(w)
p.TickAir(0.05)
if p.Air != AirMax {
t.Fatalf("出水应回满氧气,实际 %v", p.Air)
}
}
func TestSwimUpWithoutGround(t *testing.T) {
w := waterWorld{}
p := NewPlayer(0.5, 53, 0.5)
p.updateFluid(w)
if !p.InWater {
t.Fatal("应在水中")
}
p.OnGround = false
p.SwimUp()
if p.Vel[1] <= 0 {
t.Fatal("水中上浮速度应 > 0")
}
}