The raycaster is faster but more bg=uggyh agghgfghgfhgfgh
This commit is contained in:
parent
e9e1ccc35e
commit
e966771f5b
@ -21,14 +21,43 @@ func (world DefaultWorld) At (position image.Point) int {
|
|||||||
return world.Data[index]
|
return world.Data[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
type Camera struct {
|
type Vector struct {
|
||||||
X, Y float64
|
X, Y float64
|
||||||
Angle float64
|
|
||||||
Fov float64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (camera *Camera) Point () (image.Point) {
|
func (vector Vector) Point () (image.Point) {
|
||||||
return image.Pt(int(camera.X), int(camera.Y))
|
return image.Pt(int(vector.X), int(vector.Y))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vector Vector) Add (other Vector) Vector {
|
||||||
|
return Vector {
|
||||||
|
vector.X + other.X,
|
||||||
|
vector.Y + other.Y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vector Vector) Sub (other Vector) Vector {
|
||||||
|
return Vector {
|
||||||
|
vector.X - other.X,
|
||||||
|
vector.Y - other.Y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vector Vector) Mul (by float64) Vector {
|
||||||
|
return Vector {
|
||||||
|
vector.X * by,
|
||||||
|
vector.Y * by,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vector Vector) Hypot () float64 {
|
||||||
|
return math.Hypot(vector.X, vector.Y)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Camera struct {
|
||||||
|
Vector
|
||||||
|
Angle float64
|
||||||
|
Fov float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (camera *Camera) Rotate (by float64) {
|
func (camera *Camera) Rotate (by float64) {
|
||||||
@ -38,53 +67,115 @@ func (camera *Camera) Rotate (by float64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (camera *Camera) Walk (by float64) {
|
func (camera *Camera) Walk (by float64) {
|
||||||
dx, dy := camera.Delta()
|
delta := camera.Delta()
|
||||||
camera.X += dx * by
|
camera.X += delta.X * by
|
||||||
camera.Y += dy * by
|
camera.Y += delta.Y * by
|
||||||
}
|
}
|
||||||
|
|
||||||
func (camera *Camera) Strafe (by float64) {
|
func (camera *Camera) Strafe (by float64) {
|
||||||
dx, dy := camera.OffsetDelta()
|
delta := camera.OffsetDelta()
|
||||||
camera.X += dx * by
|
camera.X += delta.X * by
|
||||||
camera.Y += dy * by
|
camera.Y += delta.Y * by
|
||||||
}
|
}
|
||||||
|
|
||||||
func (camera *Camera) Delta () (x float64, y float64) {
|
func (camera *Camera) Delta () Vector {
|
||||||
return math.Cos(camera.Angle), math.Sin(camera.Angle)
|
return Vector {
|
||||||
|
math.Cos(camera.Angle),
|
||||||
|
math.Sin(camera.Angle),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (camera *Camera) OffsetDelta () (x float64, y float64) {
|
func (camera *Camera) OffsetDelta () Vector {
|
||||||
offset := math.Pi / 2
|
offset := math.Pi / 2
|
||||||
return math.Cos(camera.Angle + offset), math.Sin(camera.Angle + offset)
|
return Vector {
|
||||||
|
math.Cos(camera.Angle + offset),
|
||||||
|
math.Sin(camera.Angle + offset),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Ray struct {
|
type Ray struct {
|
||||||
X, Y float64
|
Vector
|
||||||
Angle float64
|
Angle float64
|
||||||
Precision int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ray *Ray) Cast (world World, max int) (distance float64) {
|
func (ray *Ray) Cast (world World, max int) (distance float64, hit Vector) {
|
||||||
precision := 64
|
// return ray.castV(world, max)
|
||||||
|
if world.At(ray.Point()) > 0 {
|
||||||
|
return 0, Vector { }
|
||||||
|
}
|
||||||
|
hDistance, hPos := ray.castH(world, max)
|
||||||
|
vDistance, vPos := ray.castV(world, max)
|
||||||
|
if hDistance < vDistance {
|
||||||
|
return hDistance, hPos
|
||||||
|
} else {
|
||||||
|
return vDistance, vPos
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dX := math.Cos(ray.Angle) / float64(precision)
|
func (ray *Ray) castH (world World, max int) (distance float64, hit Vector) {
|
||||||
dY := math.Sin(ray.Angle) / float64(precision)
|
var position Vector
|
||||||
origX, origY := ray.X, ray.Y
|
var delta Vector
|
||||||
|
ray.Angle = math.Mod(ray.Angle, math.Pi * 2)
|
||||||
|
if ray.Angle < 0 {
|
||||||
|
ray.Angle += math.Pi * 2
|
||||||
|
}
|
||||||
|
tan := math.Tan(math.Pi - ray.Angle)
|
||||||
|
if ray.Angle > math.Pi {
|
||||||
|
// facing up
|
||||||
|
position.Y = math.Floor(ray.Y) - (1.0 / 64)
|
||||||
|
delta.Y = -1
|
||||||
|
} else if ray.Angle < math.Pi {
|
||||||
|
// facing down
|
||||||
|
position.Y = math.Floor(ray.Y) + 1
|
||||||
|
delta.Y = 1
|
||||||
|
} else {
|
||||||
|
// facing straight left or right
|
||||||
|
return float64(max), Vector { }
|
||||||
|
}
|
||||||
|
position.X = ray.X + (ray.Y - position.Y) / tan
|
||||||
|
delta.X = -delta.Y / tan
|
||||||
|
|
||||||
wall := 0
|
// cast da ray
|
||||||
depth := 0
|
steps := 0
|
||||||
for wall == 0 && depth < max * precision {
|
for {
|
||||||
ray.X += dX
|
cell := world.At(position.Point())
|
||||||
ray.Y += dY
|
if cell > 0 || steps > max { break }
|
||||||
wall = world.At(ray.Point())
|
position = position.Add(delta)
|
||||||
depth ++
|
steps ++
|
||||||
}
|
}
|
||||||
|
|
||||||
distanceX := origX - ray.X
|
return position.Sub(ray.Vector).Hypot(), position
|
||||||
distanceY := origY - ray.Y
|
|
||||||
return math.Sqrt(distanceX * distanceX + distanceY * distanceY)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ray *Ray) Point () (image.Point) {
|
func (ray *Ray) castV (world World, max int) (distance float64, hit Vector) {
|
||||||
return image.Pt(int(ray.X), int(ray.Y))
|
var position Vector
|
||||||
|
var delta Vector
|
||||||
|
tan := math.Tan(math.Pi - ray.Angle)
|
||||||
|
offsetAngle := math.Mod(ray.Angle + math.Pi / 2, math.Pi * 2)
|
||||||
|
if offsetAngle > math.Pi {
|
||||||
|
// facing left
|
||||||
|
position.X = math.Floor(ray.X) - (1.0 / 64)
|
||||||
|
delta.X = -1
|
||||||
|
} else if offsetAngle < math.Pi {
|
||||||
|
// facing right
|
||||||
|
position.X = math.Floor(ray.X) + 1
|
||||||
|
delta.X = 1
|
||||||
|
} else {
|
||||||
|
// facing straight left or right
|
||||||
|
return float64(max), Vector { }
|
||||||
|
}
|
||||||
|
position.Y = ray.Y + (ray.X - position.X) * tan
|
||||||
|
delta.Y = -delta.X * tan
|
||||||
|
|
||||||
|
// cast da ray
|
||||||
|
steps := 0
|
||||||
|
for {
|
||||||
|
cell := world.At(position.Point())
|
||||||
|
if cell > 0 || steps > max { break }
|
||||||
|
position = position.Add(delta)
|
||||||
|
steps ++
|
||||||
|
}
|
||||||
|
|
||||||
|
return position.Sub(ray.Vector).Hypot(), position
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
// import "fmt"
|
||||||
import "math"
|
import "math"
|
||||||
|
import "image"
|
||||||
import "image/color"
|
import "image/color"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/input"
|
import "git.tebibyte.media/sashakoshka/tomo/input"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/config"
|
import "git.tebibyte.media/sashakoshka/tomo/config"
|
||||||
@ -32,9 +34,11 @@ type Raycaster struct {
|
|||||||
func NewRaycaster (world World) (element *Raycaster) {
|
func NewRaycaster (world World) (element *Raycaster) {
|
||||||
element = &Raycaster {
|
element = &Raycaster {
|
||||||
Camera: Camera {
|
Camera: Camera {
|
||||||
X: 2,
|
Vector: Vector {
|
||||||
Y: 2,
|
X: 1.5,
|
||||||
Angle: 1,
|
Y: 1.5,
|
||||||
|
},
|
||||||
|
Angle: math.Pi / 3,
|
||||||
Fov: 1,
|
Fov: 1,
|
||||||
},
|
},
|
||||||
world: world,
|
world: world,
|
||||||
@ -103,16 +107,13 @@ func (element *Raycaster) drawAll () {
|
|||||||
width := bounds.Dx()
|
width := bounds.Dx()
|
||||||
height := bounds.Dy()
|
height := bounds.Dy()
|
||||||
|
|
||||||
ray := Ray {
|
ray := Ray { Angle: element.Camera.Angle - element.Camera.Fov / 2 }
|
||||||
Angle: element.Camera.Angle - element.Camera.Fov / 2,
|
|
||||||
Precision: 64,
|
|
||||||
}
|
|
||||||
|
|
||||||
for x := 0; x < width; x ++ {
|
for x := 0; x < width; x ++ {
|
||||||
ray.X = element.Camera.X
|
ray.X = element.Camera.X
|
||||||
ray.Y = element.Camera.Y
|
ray.Y = element.Camera.Y
|
||||||
|
|
||||||
distance := ray.Cast(element.world, 8)
|
distance, _ := ray.Cast(element.world, 8)
|
||||||
distanceFac := float64(distance) / 8
|
distanceFac := float64(distance) / 8
|
||||||
distance *= math.Cos(ray.Angle - element.Camera.Angle)
|
distance *= math.Cos(ray.Angle - element.Camera.Angle)
|
||||||
|
|
||||||
@ -150,4 +151,54 @@ func (element *Raycaster) drawAll () {
|
|||||||
// increment angle
|
// increment angle
|
||||||
ray.Angle += element.Camera.Fov / float64(width)
|
ray.Angle += element.Camera.Fov / float64(width)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// element.drawMinimap()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *Raycaster) drawMinimap () {
|
||||||
|
bounds := element.Bounds()
|
||||||
|
scale := 16
|
||||||
|
for y := 0; y < 10; y ++ {
|
||||||
|
for x := 0; x < 10; x ++ {
|
||||||
|
cellPt := image.Pt(x, y)
|
||||||
|
cell := element.world.At(cellPt)
|
||||||
|
cellBounds :=
|
||||||
|
image.Rectangle {
|
||||||
|
cellPt.Mul(scale),
|
||||||
|
cellPt.Add(image.Pt(1, 1)).Mul(scale),
|
||||||
|
}.Add(bounds.Min)
|
||||||
|
cellColor := color.RGBA { 0x22, 0x22, 0x22, 0xFF }
|
||||||
|
if cell == 1 {
|
||||||
|
cellColor = color.RGBA { 0xFF, 0xFF, 0xFF, 0xFF }
|
||||||
|
}
|
||||||
|
artist.FillRectangle (
|
||||||
|
element.core,
|
||||||
|
artist.NewUniform(cellColor),
|
||||||
|
cellBounds.Inset(1))
|
||||||
|
}}
|
||||||
|
|
||||||
|
playerPt := element.Camera.Mul(float64(scale)).Point().Add(bounds.Min)
|
||||||
|
playerAnglePt :=
|
||||||
|
element.Camera.Add(element.Camera.Delta()).
|
||||||
|
Mul(float64(scale)).Point().Add(bounds.Min)
|
||||||
|
ray := Ray { Vector: element.Camera.Vector, Angle: element.Camera.Angle }
|
||||||
|
_, hit := ray.Cast(element.world, 8)
|
||||||
|
hitPt := hit.Mul(float64(scale)).Point().Add(bounds.Min)
|
||||||
|
// fmt.Println(rayDistance)
|
||||||
|
|
||||||
|
playerBounds := image.Rectangle { playerPt, playerPt }.Inset(scale / -8)
|
||||||
|
artist.FillEllipse (
|
||||||
|
element.core,
|
||||||
|
artist.Uhex(0xFFFFFFFF),
|
||||||
|
playerBounds)
|
||||||
|
artist.Line (
|
||||||
|
element.core,
|
||||||
|
artist.Uhex(0xFFFFFFFF), 1,
|
||||||
|
playerPt,
|
||||||
|
playerAnglePt)
|
||||||
|
artist.Line (
|
||||||
|
element.core,
|
||||||
|
artist.Uhex(0x00FF00FF), 1,
|
||||||
|
playerPt,
|
||||||
|
hitPt)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user