entity: physics rewrite
This commit is contained in:
parent
25872b257d
commit
37ee76e9fc
Binary file not shown.
@ -16,8 +16,11 @@ func init() {
|
|||||||
|
|
||||||
func (PlayerBehaviour) Name() string { return "player" }
|
func (PlayerBehaviour) Name() string { return "player" }
|
||||||
|
|
||||||
func (PlayerBehaviour) Hitbox(pos itype.Vec3d, dataset itype.Dataset) itype.Vec3d {
|
func (PlayerBehaviour) Hitbox(pos itype.Vec3d, dataset itype.Dataset) []itype.Boxd {
|
||||||
return itype.Vec3d{0.6, 1.8, 0.6}
|
return []itype.Boxd{{
|
||||||
|
OffX: -0.3, OffY: 0, OffZ: -0.3,
|
||||||
|
SizeX: 0.6, SizeY: 1.8, SizeZ: 0.6,
|
||||||
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (PlayerBehaviour) EyeHeight(pos itype.Vec3d, dataset itype.Dataset) float64 {
|
func (PlayerBehaviour) EyeHeight(pos itype.Vec3d, dataset itype.Dataset) float64 {
|
||||||
|
@ -3,27 +3,26 @@ package entity
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"edgaru089.ml/go/gl01/internal/util"
|
|
||||||
"edgaru089.ml/go/gl01/internal/util/itype"
|
"edgaru089.ml/go/gl01/internal/util/itype"
|
||||||
"edgaru089.ml/go/gl01/internal/world"
|
"edgaru089.ml/go/gl01/internal/world"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EntityBehaviour describes the behaviour of a type of entity with the same Name.
|
// EntityBehaviour describes the behaviour of a type of entity with the same Name.
|
||||||
|
// It should hold no data of its own.
|
||||||
type EntityBehaviour interface {
|
type EntityBehaviour interface {
|
||||||
// Name returns the type Name of the behaviour.
|
// Name returns the type Name of the behaviour.
|
||||||
Name() string
|
Name() string
|
||||||
|
|
||||||
// Hitbox gets the size of the hitbox of the entity.
|
// Hitbox gets the hitbox(s) of the entity.
|
||||||
//
|
//
|
||||||
// The hitbox is positioned with the position coordinates pointing to
|
// The hitbox is in entity-local coordinates, originating from the position.
|
||||||
// the center of the bottom of the box.
|
Hitbox(pos itype.Vec3d, dataset itype.Dataset) []itype.Boxd
|
||||||
Hitbox(pos itype.Vec3d, dataset itype.Dataset) itype.Vec3d
|
|
||||||
|
|
||||||
// EyeHeight gets the height of the eye of the entity.
|
// EyeHeight gets the height of the eye of the entity.
|
||||||
EyeHeight(pos itype.Vec3d, dataset itype.Dataset) float64
|
EyeHeight(pos itype.Vec3d, dataset itype.Dataset) float64
|
||||||
|
|
||||||
// Update is called on every frame.
|
// Update is called on every frame.
|
||||||
// It should be used to update physics.
|
// It should be used to update the behaviour of the entity.
|
||||||
Update(pos itype.Vec3d, dataset itype.Dataset, world *world.World, deltaTime time.Duration)
|
Update(pos itype.Vec3d, dataset itype.Dataset, world *world.World, deltaTime time.Duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,14 +44,14 @@ func RegisterEntityBehaviour(b EntityBehaviour) bool {
|
|||||||
// Entity is a struct holding a Behaviour, a Position and a Speed.
|
// Entity is a struct holding a Behaviour, a Position and a Speed.
|
||||||
type Entity struct {
|
type Entity struct {
|
||||||
b EntityBehaviour
|
b EntityBehaviour
|
||||||
pos, speed itype.Vec3d // pos has a origin of the **center of the bottom** of the hitbox
|
pos, speed itype.Vec3d // pos should have a origin of the **center of the bottom** of the hitbox
|
||||||
ds itype.Dataset
|
ds itype.Dataset
|
||||||
|
|
||||||
name string // a shortcut to b.Name(), the typename
|
name string // a shortcut to b.Name(), the typename
|
||||||
|
|
||||||
|
// physics stuff
|
||||||
onGround bool
|
onGround bool
|
||||||
worldbox []itype.Boxd
|
worldbox []itype.Boxd
|
||||||
hp []itype.Vec3d
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEntity(typename string, pos itype.Vec3d) *Entity {
|
func NewEntity(typename string, pos itype.Vec3d) *Entity {
|
||||||
@ -84,16 +83,16 @@ func (e *Entity) SetSpeed(speed itype.Vec3d) {
|
|||||||
e.speed = speed
|
e.speed = speed
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Entity) Hitbox() itype.Vec3d {
|
func (e *Entity) Hitbox() []itype.Boxd {
|
||||||
return e.b.Hitbox(e.pos, e.ds)
|
return e.b.Hitbox(e.pos, e.ds)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Entity) Accelerate(x, y, z float64) {
|
func (e *Entity) Accelerate(x, y, z float64) {
|
||||||
/*e.speed[0] += x
|
e.speed[0] += x
|
||||||
e.speed[1] += y
|
e.speed[1] += y
|
||||||
e.speed[2] += z*/
|
e.speed[2] += z
|
||||||
vec := itype.Vec3d{x, y, z}
|
/*vec := itype.Vec3d{x, y, z}
|
||||||
e.speed = util.BunnyhopAccelerate(vec, e.speed, vec.Length(), 8)
|
e.speed = util.BunnyhopAccelerate(vec, e.speed, vec.Length(), 8)*/
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Entity) OnGround() bool {
|
func (e *Entity) OnGround() bool {
|
||||||
|
@ -9,262 +9,187 @@ import (
|
|||||||
"edgaru089.ml/go/gl01/internal/world"
|
"edgaru089.ml/go/gl01/internal/world"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (e *Entity) worldHitbox(hitbox itype.Vec3d) itype.Boxd {
|
// WorldHitbox returns the hitboxes of the entity, in world coordinates.
|
||||||
return itype.Boxd{
|
func (e *Entity) WorldHitbox() []itype.Boxd {
|
||||||
OffX: e.pos[0] - hitbox[0]/2,
|
boxes := e.Hitbox()
|
||||||
OffY: e.pos[1],
|
for i := range boxes {
|
||||||
OffZ: e.pos[2] - hitbox[2]/2,
|
boxes[i] = boxes[i].Offset(e.pos)
|
||||||
SizeX: hitbox[0],
|
|
||||||
SizeY: hitbox[1],
|
|
||||||
SizeZ: hitbox[2],
|
|
||||||
}
|
}
|
||||||
}
|
return boxes
|
||||||
|
|
||||||
// WorldHitbox returns the hitbox of the entity, in world coordinates.
|
|
||||||
func (e *Entity) WorldHitbox() itype.Boxd {
|
|
||||||
return e.worldHitbox(e.b.Hitbox(e.pos, e.ds))
|
|
||||||
}
|
|
||||||
|
|
||||||
// the distance between hitpoints, in blocks
|
|
||||||
const HitpointMeshLen = 0.4
|
|
||||||
|
|
||||||
func (e *Entity) boxHitpoints(points []itype.Vec3d, hitbox itype.Boxd) []itype.Vec3d {
|
|
||||||
|
|
||||||
box := hitbox
|
|
||||||
base := box.MinPoint()
|
|
||||||
points = points[0:0]
|
|
||||||
|
|
||||||
// add the bounding points first
|
|
||||||
points = append(points,
|
|
||||||
base,
|
|
||||||
base.Add(itype.Vec3d{box.SizeX, 0, 0}),
|
|
||||||
base.Add(itype.Vec3d{0, box.SizeY, 0}),
|
|
||||||
base.Add(itype.Vec3d{0, 0, box.SizeZ}),
|
|
||||||
base.Add(itype.Vec3d{box.SizeX, box.SizeY, 0}),
|
|
||||||
base.Add(itype.Vec3d{0, box.SizeY, box.SizeZ}),
|
|
||||||
base.Add(itype.Vec3d{box.SizeX, 0, box.SizeZ}),
|
|
||||||
base.Add(itype.Vec3d{box.SizeX, box.SizeY, box.SizeZ}),
|
|
||||||
)
|
|
||||||
return points
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MoveEps is a small value used to indicate a tiny amount more than zero.
|
// MoveEps is a small value used to indicate a tiny amount more than zero.
|
||||||
const MoveEps = 1e-7
|
const MoveEps = 1e-7
|
||||||
|
|
||||||
// tells if the point is already stuck inside a block hitbox
|
// move attempts to move the entity by delta in the world.
|
||||||
func pointStuck(point itype.Vec3d, w *world.World) bool {
|
// It does not change anything in e.
|
||||||
blockid := point.Floor()
|
func (e *Entity) move(delta itype.Vec3d, w *world.World) (finDelta itype.Vec3d, finVelocity itype.Vec3d, onGround bool) {
|
||||||
block := w.Block(blockid)
|
|
||||||
return block.Id != 0 &&
|
// Get the hitboxes and the blocks region covering it
|
||||||
block.Behaviour.Appearance(
|
hb := e.WorldHitbox()
|
||||||
point.Floor(),
|
hbmin, hbmax := itype.Vec3d{1000000000, 1000000000, 1000000000}, itype.Vec3d{-1000000000, -1000000000, -1000000000}
|
||||||
block.Aux,
|
for _, b := range hb {
|
||||||
block.Dataset,
|
bmin, bmax := b.MinPoint(), b.MaxPoint()
|
||||||
w,
|
hbmin[0] = util.Mind(hbmin[0], bmin[0])
|
||||||
).Hitbox.Offset(blockid.ToFloat64()).Contains(point)
|
hbmin[1] = util.Mind(hbmin[1], bmin[1])
|
||||||
|
hbmin[2] = util.Mind(hbmin[2], bmin[2])
|
||||||
|
hbmax[0] = util.Maxd(hbmax[0], bmax[0])
|
||||||
|
hbmax[1] = util.Maxd(hbmax[1], bmax[1])
|
||||||
|
hbmax[2] = util.Maxd(hbmax[2], bmax[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
// the move series functions should be called with e.hp already filled
|
// So this is the region of blocks we should calculate
|
||||||
|
imin, imax := hbmin.Floor().Addv(-1, -1, -1), hbmax.Ceiling().Addv(1, 1, 1)
|
||||||
|
|
||||||
|
finDelta = delta
|
||||||
|
finVelocity = e.speed
|
||||||
|
for x := imin[0]; x <= imax[0]; x++ {
|
||||||
|
for y := imin[1]; y <= imax[1]; y++ {
|
||||||
|
for z := imin[2]; z <= imax[2]; z++ {
|
||||||
|
blockDelta, blockVelocity, blockOnGround := e.moveBlock(hb, delta, itype.Vec3i{x, y, z}, w)
|
||||||
|
finDelta[0] = util.AbsMind(finDelta[0], blockDelta[0])
|
||||||
|
finDelta[1] = util.AbsMind(finDelta[1], blockDelta[1])
|
||||||
|
finDelta[2] = util.AbsMind(finDelta[2], blockDelta[2])
|
||||||
|
finVelocity[0] = util.AbsMind(finVelocity[0], blockVelocity[0])
|
||||||
|
finVelocity[1] = util.AbsMind(finVelocity[1], blockVelocity[1])
|
||||||
|
finVelocity[2] = util.AbsMind(finVelocity[2], blockVelocity[2])
|
||||||
|
onGround = onGround || blockOnGround
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Y-
|
||||||
|
if delta[1] < 0 {
|
||||||
|
onGround = onGround || e.onGround
|
||||||
|
} else {
|
||||||
|
onGround = false
|
||||||
|
}
|
||||||
|
|
||||||
func (e *Entity) moveX(delta float64, hitbox itype.Boxd, w *world.World) {
|
|
||||||
if math.Abs(delta) < MoveEps*10 {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var hit bool = false
|
// moveBlock simulates moving the entity by delta, and tests collision with the block hibbox.
|
||||||
var deltaMin float64 = 10000
|
func (e *Entity) moveBlock(worldHitbox []itype.Boxd, delta itype.Vec3d, blockCoord itype.Vec3i, w *world.World) (blockDelta itype.Vec3d, finVelocity itype.Vec3d, onGround bool) {
|
||||||
|
blockDelta = delta
|
||||||
|
finVelocity = e.speed
|
||||||
|
onGround = false
|
||||||
|
|
||||||
if delta > 1-MoveEps {
|
var blockHitbox []itype.Boxd
|
||||||
delta = 1 - MoveEps
|
if block := w.Block(blockCoord); block.Id != 0 {
|
||||||
|
blocka := block.Appearance(blockCoord)
|
||||||
|
if !blocka.NotSolid {
|
||||||
|
blockHitbox = w.Block(blockCoord).Appearance(blockCoord).Hitbox
|
||||||
|
for i := range blockHitbox {
|
||||||
|
blockHitbox[i] = blockHitbox[i].Offset(blockCoord.ToFloat64())
|
||||||
}
|
}
|
||||||
if delta < -1+MoveEps {
|
|
||||||
delta = -1 + MoveEps
|
|
||||||
}
|
|
||||||
|
|
||||||
// X+ / X-
|
|
||||||
for _, p := range e.hp {
|
|
||||||
if pointStuck(p, w) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
dest := p.Addv(delta, 0, 0)
|
|
||||||
blockid := dest.Floor()
|
|
||||||
block := w.Block(blockid)
|
|
||||||
|
|
||||||
var deltaDone float64
|
|
||||||
if block.Id == 0 {
|
|
||||||
deltaDone = delta
|
|
||||||
} else { // block.Id!=0
|
|
||||||
app := world.GetBlockAppearance(blockid, block.Id, block.Aux, block.Dataset, w)
|
|
||||||
blockBox := app.Hitbox.Offset(blockid.ToFloat64())
|
|
||||||
if !app.NotSolid && blockBox.Contains(dest) { // Hit!
|
|
||||||
hit = true
|
|
||||||
if delta > 0 { // moving X+, hit on the X- face
|
|
||||||
deltaDone = blockBox.OffX - (e.pos[0] + hitbox.SizeX/2) - MoveEps
|
|
||||||
//log.Print("Hit X+: On Block ", blockid, ", delta=", delta, ", coord=", e.pos, ", p=", p, ", dest=", dest, ", deltaDone=", deltaDone)
|
|
||||||
} else { // moving X-, hit on the X+ face
|
|
||||||
deltaDone = blockBox.OffX + blockBox.SizeX - (e.pos[0] - hitbox.SizeX/2) + MoveEps
|
|
||||||
//log.Print("Hit X-: On Block ", blockid, ", delta=", delta, ", coord=", e.pos, ", p=", p, ", dest=", dest, ", deltaDone=", deltaDone)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
deltaDone = delta
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deltaMin = util.AbsMind(deltaMin, deltaDone)
|
if len(blockHitbox) == 0 {
|
||||||
}
|
|
||||||
|
|
||||||
if hit {
|
|
||||||
e.speed[0] = 0
|
|
||||||
}
|
|
||||||
e.pos[0] += deltaMin
|
|
||||||
}
|
|
||||||
func (e *Entity) moveY(delta float64, hitbox itype.Boxd, w *world.World) {
|
|
||||||
if math.Abs(delta) < MoveEps*10 {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var hit bool = false
|
for _, eb := range worldHitbox {
|
||||||
var deltaMin float64 = 10000
|
for _, bb := range blockHitbox {
|
||||||
|
// Already intersecting: return
|
||||||
if delta > 1-MoveEps {
|
if ok, _ := eb.Intersect(bb); ok {
|
||||||
delta = 1 - MoveEps
|
|
||||||
}
|
|
||||||
if delta < -1+MoveEps {
|
|
||||||
delta = -1 + MoveEps
|
|
||||||
}
|
|
||||||
|
|
||||||
// Y+ / Y-
|
|
||||||
for _, p := range e.hp {
|
|
||||||
if pointStuck(p, w) {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
dest := p.Addv(0, delta, 0)
|
// X
|
||||||
blockid := dest.Floor()
|
if ok, _ := eb.Offsetv(blockDelta[0], 0, 0).Intersect(bb); ok {
|
||||||
block := w.Block(blockid)
|
if blockDelta[0] > 0 {
|
||||||
|
blockDelta[0] = bb.OffX - (eb.OffX + eb.SizeX) - MoveEps
|
||||||
var deltaDone float64
|
//log.Printf("Hit(X+): On (X%d,Y%d,Z%d), delta=%v\n", blockCoord[0], blockCoord[1], blockCoord[2], blockDelta)
|
||||||
if block.Id == 0 {
|
|
||||||
deltaDone = delta
|
|
||||||
} else { // block.Id!=0
|
|
||||||
app := world.GetBlockAppearance(blockid, block.Id, block.Aux, block.Dataset, w)
|
|
||||||
blockBox := app.Hitbox.Offset(blockid.ToFloat64())
|
|
||||||
if !app.NotSolid && blockBox.Contains(dest) { // Hit!
|
|
||||||
hit = true
|
|
||||||
if delta > 0 { // moving Y+, hit on the Y- face
|
|
||||||
deltaDone = blockBox.OffY - (e.pos[1] + hitbox.SizeY) - MoveEps
|
|
||||||
//log.Print("Hit Y+: On Block ", blockid, ", delta=", delta, ", coord=", e.pos, ", p=", p, ", dest=", dest,", deltaDone=",deltaDone)
|
|
||||||
} else { // moving Y-, hit on the Y+ face (on the ground)
|
|
||||||
deltaDone = blockBox.OffY + blockBox.SizeY - e.pos[1] + MoveEps
|
|
||||||
//log.Print("Hit Y-: On Block ", blockid, ", delta=", delta, ", coord=", e.pos, ", p=", p, ", dest=", dest,", deltaDone=",deltaDone)
|
|
||||||
/*if !e.onGround {
|
|
||||||
log.Print("onGround = true")
|
|
||||||
}*/
|
|
||||||
e.onGround = true
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
deltaDone = delta
|
blockDelta[0] = (bb.OffX + bb.SizeX) - eb.OffX + MoveEps
|
||||||
|
//log.Printf("Hit(X-): On (X%d,Y%d,Z%d), delta=%v\n", blockCoord[0], blockCoord[1], blockCoord[2], blockDelta)
|
||||||
|
}
|
||||||
|
finVelocity[0] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Y
|
||||||
|
if ok, _ := eb.Offsetv(0, blockDelta[1], 0).Intersect(bb); ok {
|
||||||
|
if blockDelta[1] > 0 {
|
||||||
|
blockDelta[1] = bb.OffY - (eb.OffY + eb.SizeY) - MoveEps
|
||||||
|
//log.Printf("Hit(Y+): On (X%d,Y%d,Z%d), delta=%v\n", blockCoord[0], blockCoord[1], blockCoord[2], blockDelta)
|
||||||
|
} else {
|
||||||
|
onGround = true
|
||||||
|
blockDelta[1] = (bb.OffY + bb.SizeY) - eb.OffY + MoveEps
|
||||||
|
//log.Printf("Hit(Y-): On (X%d,Y%d,Z%d), delta=%v\n", blockCoord[0], blockCoord[1], blockCoord[2], blockDelta)
|
||||||
|
}
|
||||||
|
finVelocity[1] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Z
|
||||||
|
if ok, _ := eb.Offsetv(0, 0, blockDelta[2]).Intersect(bb); ok {
|
||||||
|
if blockDelta[2] > 0 {
|
||||||
|
blockDelta[2] = bb.OffZ - (eb.OffZ + eb.SizeZ) - MoveEps
|
||||||
|
//log.Printf("Hit(Z+): On (X%d,Y%d,Z%d), delta=%v\n", blockCoord[0], blockCoord[1], blockCoord[2], blockDelta)
|
||||||
|
} else {
|
||||||
|
blockDelta[2] = (bb.OffZ + bb.SizeZ) - eb.OffZ + MoveEps
|
||||||
|
//log.Printf("Hit(Z-): On (X%d,Y%d,Z%d), delta=%v\n", blockCoord[0], blockCoord[1], blockCoord[2], blockDelta)
|
||||||
|
}
|
||||||
|
finVelocity[2] = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deltaMin = util.AbsMind(deltaMin, deltaDone)
|
|
||||||
}
|
|
||||||
|
|
||||||
if hit {
|
|
||||||
e.speed[1] = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if math.Abs(deltaMin) > MoveEps*10 {
|
|
||||||
/*if e.onGround {
|
|
||||||
log.Print("onGround = false")
|
|
||||||
}*/
|
|
||||||
e.onGround = false
|
|
||||||
}
|
|
||||||
e.pos[1] += deltaMin
|
|
||||||
}
|
|
||||||
func (e *Entity) moveZ(delta float64, hitbox itype.Boxd, w *world.World) {
|
|
||||||
if math.Abs(delta) < MoveEps*10 {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var hit bool = false
|
const gravity = 26
|
||||||
var deltaMin float64 = 10000
|
const deaclc = 28
|
||||||
|
const maxspeed = 8
|
||||||
if delta > 1-MoveEps {
|
|
||||||
delta = 1 - MoveEps
|
|
||||||
}
|
|
||||||
if delta < -1+MoveEps {
|
|
||||||
delta = -1 + MoveEps
|
|
||||||
}
|
|
||||||
|
|
||||||
// Z+ / Z-
|
|
||||||
for _, p := range e.hp {
|
|
||||||
if pointStuck(p, w) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
dest := p.Addv(0, 0, delta)
|
|
||||||
blockid := dest.Floor()
|
|
||||||
block := w.Block(blockid)
|
|
||||||
|
|
||||||
var deltaDone float64
|
|
||||||
if block.Id == 0 {
|
|
||||||
deltaDone = delta
|
|
||||||
} else { // block.Id!=0
|
|
||||||
app := world.GetBlockAppearance(blockid, block.Id, block.Aux, block.Dataset, w)
|
|
||||||
blockBox := app.Hitbox.Offset(blockid.ToFloat64())
|
|
||||||
if !app.NotSolid && blockBox.Contains(dest) { // Hit!
|
|
||||||
hit = true
|
|
||||||
if delta > 0 { // moving Z+, hit on the Z- face
|
|
||||||
deltaDone = util.Maxd(blockBox.OffZ-(e.pos[2]+hitbox.SizeZ/2)-MoveEps, 0)
|
|
||||||
//log.Print("Hit Z+: On Block ", blockid, ", delta=", delta, ", coord=", e.pos, ", p=", p, ", dest=", dest, ", deltaDone=", deltaDone)
|
|
||||||
} else { // moving Z-, hit on the Z+ face
|
|
||||||
deltaDone = util.Mind(blockBox.OffZ+blockBox.SizeZ-(e.pos[2]-hitbox.SizeZ/2)+MoveEps, 0)
|
|
||||||
//log.Print("Hit Z-: On Block ", blockid, ", delta=", delta, ", coord=", e.pos, ", p=", p, ", dest=", dest, ", deltaDone=", deltaDone)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
deltaDone = delta
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deltaMin = util.AbsMind(deltaMin, deltaDone)
|
|
||||||
}
|
|
||||||
|
|
||||||
if hit {
|
|
||||||
e.speed[2] = 0
|
|
||||||
}
|
|
||||||
e.pos[2] += deltaMin
|
|
||||||
}
|
|
||||||
|
|
||||||
const gravity float64 = 26
|
|
||||||
const deaclc float64 = 28
|
|
||||||
|
|
||||||
func (e *Entity) Update(world *world.World, deltaTime time.Duration) {
|
func (e *Entity) Update(world *world.World, deltaTime time.Duration) {
|
||||||
|
|
||||||
hitbox := e.b.Hitbox(e.pos, e.ds)
|
/*
|
||||||
box := e.worldHitbox(hitbox)
|
delta, vec, onGround := e.move(itype.Vec3d{e.speed[0] * deltaTime.Seconds()}, world)
|
||||||
|
e.pos = e.pos.Add(delta)
|
||||||
|
e.speed = vec
|
||||||
|
delta, vec, onGround = e.move(e.speed.Multiply(deltaTime.Seconds()), world)
|
||||||
|
e.pos = e.pos.Add(delta)
|
||||||
|
e.speed = vec
|
||||||
|
delta, vec, onGround = e.move(e.speed.Multiply(deltaTime.Seconds()), world)
|
||||||
|
e.pos = e.pos.Add(delta)
|
||||||
|
e.speed = vec
|
||||||
|
|
||||||
e.hp = e.hp[0:0]
|
e.onGround = onGround
|
||||||
e.hp = e.boxHitpoints(e.hp, box)
|
*/
|
||||||
|
|
||||||
e.moveX(e.speed[0]*deltaTime.Seconds(), box, world)
|
|
||||||
e.moveY(e.speed[1]*deltaTime.Seconds(), box, world)
|
|
||||||
e.moveZ(e.speed[2]*deltaTime.Seconds(), box, world)
|
|
||||||
|
|
||||||
|
var deltaSpeed itype.Vec3d
|
||||||
|
if e.onGround {
|
||||||
speed := math.Sqrt(e.speed[0]*e.speed[0] + e.speed[2]*e.speed[2])
|
speed := math.Sqrt(e.speed[0]*e.speed[0] + e.speed[2]*e.speed[2])
|
||||||
if speed > MoveEps {
|
if speed > MoveEps {
|
||||||
decrease := deaclc * deltaTime.Seconds()
|
decrease := deaclc * deltaTime.Seconds()
|
||||||
|
factor := util.Maxd(util.Mind(speed-decrease, 6), 0) / speed
|
||||||
|
|
||||||
|
deltaSpeed[0] = -e.speed[0] * (1 - factor)
|
||||||
|
deltaSpeed[2] = -e.speed[2] * (1 - factor)
|
||||||
|
} else {
|
||||||
|
e.speed[0] = 0
|
||||||
|
e.speed[2] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deltaSpeed[1] = -gravity * deltaTime.Seconds()
|
||||||
|
|
||||||
|
delta := e.speed.Multiply(deltaTime.Seconds()).Add(deltaSpeed.Multiply(deltaTime.Seconds() / 2))
|
||||||
|
e.speed = e.speed.Add(deltaSpeed)
|
||||||
|
|
||||||
|
findelta, vec, onGround := e.move(delta, world)
|
||||||
|
e.pos = e.pos.Add(findelta)
|
||||||
|
e.speed = vec
|
||||||
|
e.onGround = onGround
|
||||||
|
|
||||||
if !e.onGround {
|
if !e.onGround {
|
||||||
decrease /= 10
|
vecXZ := itype.Vec2d{e.speed[0], e.speed[2]}
|
||||||
|
if vecXZ.Length() > maxspeed {
|
||||||
|
vecXZ = vecXZ.Normalize().Multiply(maxspeed)
|
||||||
}
|
}
|
||||||
factor := util.Maxd(util.Mind(speed-decrease, 9), 0) / speed
|
e.speed[0] = vecXZ[0]
|
||||||
|
e.speed[2] = vecXZ[1]
|
||||||
e.speed[0] *= factor
|
|
||||||
e.speed[2] *= factor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e.speed[1] -= gravity * deltaTime.Seconds()
|
|
||||||
|
|
||||||
e.b.Update(e.pos, e.ds, world, deltaTime)
|
e.b.Update(e.pos, e.ds, world, deltaTime)
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package game
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
@ -52,7 +53,8 @@ func (g *Game) imgui() {
|
|||||||
if imgui.BeginV("Player", nil, imgui.WindowFlagsAlwaysAutoResize) {
|
if imgui.BeginV("Player", nil, imgui.WindowFlagsAlwaysAutoResize) {
|
||||||
pos := g.player.Position()
|
pos := g.player.Position()
|
||||||
vel := g.player.Speed()
|
vel := g.player.Speed()
|
||||||
imgui.Text(fmt.Sprintf("Pos: (%.5f, %.5f, %.5f), Vel: (%.5f, %.5f, %.5f)", pos[0], pos[1], pos[2], vel[0], vel[1], vel[2]))
|
igwrap.Text("Pos: (%.5f, %.5f, %.5f), Vel: (%.5f, %.5f, %.5f)", pos[0], pos[1], pos[2], vel[0], vel[1], vel[2])
|
||||||
|
igwrap.Text("VelXZ=%.5f, VelXYZ=%.5f", math.Sqrt(vel[0]*vel[0]+vel[2]*vel[2]), vel.Length())
|
||||||
}
|
}
|
||||||
imgui.End()
|
imgui.End()
|
||||||
|
|
||||||
|
@ -166,6 +166,7 @@ func (g *Game) Init(win *glfw.Window) {
|
|||||||
igwrap.MouseScrollCallback(xpos, ypos)
|
igwrap.MouseScrollCallback(xpos, ypos)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const airAccel = 0.1
|
const airAccel = 0.1
|
||||||
@ -234,7 +235,7 @@ func (g *Game) Update(win *glfw.Window, delta time.Duration) {
|
|||||||
io.ViewPos = g.player.EyePosition()
|
io.ViewPos = g.player.EyePosition()
|
||||||
io.ViewDir = itype.Vec3d(mgl64.Rotate3DY(float64(g.rotY.Radians())).Mul3(mgl64.Rotate3DZ(float64(itype.Degrees(g.rotZ)))).Mul3x1(mgl64.Vec3{1, 0, 0}))
|
io.ViewDir = itype.Vec3d(mgl64.Rotate3DY(float64(g.rotY.Radians())).Mul3(mgl64.Rotate3DZ(float64(itype.Degrees(g.rotZ)))).Mul3x1(mgl64.Vec3{1, 0, 0}))
|
||||||
|
|
||||||
render.Framewire.PushBox(g.player.WorldHitbox().ToFloat32(), color.White)
|
render.Framewire.PushBox(g.player.WorldHitbox()[0].ToFloat32(), color.White)
|
||||||
|
|
||||||
if g.player.Position()[1] < -100 {
|
if g.player.Position()[1] < -100 {
|
||||||
g.player.SetPosition(itype.Vec3d{18, 80, 18})
|
g.player.SetPosition(itype.Vec3d{18, 80, 18})
|
||||||
|
@ -137,15 +137,15 @@ func pointIntersect(n, m, p, q float64) (min, len float64) {
|
|||||||
return arr[1], arr[2] - arr[1]
|
return arr[1], arr[2] - arr[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (box1 Boxd) Intersects(box2 Boxd) (result Boxd) {
|
func (box1 Boxd) Intersect(box2 Boxd) (ok bool, intersect Boxd) {
|
||||||
a, b := pointIntersect(box1.OffX, box1.OffX+box1.SizeX, box2.OffX, box2.OffX+box2.SizeX)
|
a, b := pointIntersect(box1.OffX, box1.OffX+box1.SizeX, box2.OffX, box2.OffX+box2.SizeX)
|
||||||
c, d := pointIntersect(box1.OffY, box1.OffY+box1.SizeY, box2.OffY, box2.OffY+box2.SizeY)
|
c, d := pointIntersect(box1.OffY, box1.OffY+box1.SizeY, box2.OffY, box2.OffY+box2.SizeY)
|
||||||
e, f := pointIntersect(box1.OffZ, box1.OffZ+box1.SizeZ, box2.OffZ, box2.OffZ+box2.SizeZ)
|
e, f := pointIntersect(box1.OffZ, box1.OffZ+box1.SizeZ, box2.OffZ, box2.OffZ+box2.SizeZ)
|
||||||
|
|
||||||
if b == 0 || d == 0 || f == 0 {
|
if b == 0 || d == 0 || f == 0 {
|
||||||
return Boxd{}
|
return false, Boxd{}
|
||||||
} else {
|
} else {
|
||||||
return Boxd{
|
return true, Boxd{
|
||||||
OffX: a,
|
OffX: a,
|
||||||
SizeX: b,
|
SizeX: b,
|
||||||
OffY: c,
|
OffY: c,
|
||||||
|
@ -205,6 +205,14 @@ func (v Vec3d) Floor() Vec3i {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v Vec3d) Ceiling() Vec3i {
|
||||||
|
return Vec3i{
|
||||||
|
int(math.Ceil(v[0])),
|
||||||
|
int(math.Ceil(v[1])),
|
||||||
|
int(math.Ceil(v[2])),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (v Vec3d) ToFloat32() Vec3f {
|
func (v Vec3d) ToFloat32() Vec3f {
|
||||||
return Vec3f{float32(v[0]), float32(v[1]), float32(v[2])}
|
return Vec3f{float32(v[0]), float32(v[1]), float32(v[2])}
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,10 @@ const (
|
|||||||
type BlockAppearance struct {
|
type BlockAppearance struct {
|
||||||
Name string // A short name, like "stone" or "dirt", used for texture lookups
|
Name string // A short name, like "stone" or "dirt", used for texture lookups
|
||||||
Transparent bool // Is block transparent?
|
Transparent bool // Is block transparent?
|
||||||
NotSolid bool // Is block not solid, i.e., has no solid hitbox? (this makes the zero value reasonable)
|
NotSolid bool // Is block not solid, i.e., has no hitbox at all? (this makes the zero value reasonable)
|
||||||
Light int // The light level it emits, 0 is none
|
Light int // The light level it emits, 0 is none
|
||||||
|
|
||||||
Hitbox itype.Boxd // Hitbox, in block-local coordinates; empty slice means a default hitbox of 1x1x1
|
Hitbox []itype.Boxd // Hitbox, in block-local coordinates; empty slice means a default hitbox of 1x1x1
|
||||||
|
|
||||||
RenderType BlockRenderType // Rendering type, defaults to OneTexture (zero value)
|
RenderType BlockRenderType // Rendering type, defaults to OneTexture (zero value)
|
||||||
|
|
||||||
@ -124,11 +124,11 @@ func DoneRegisteringBlockBehaviour() {
|
|||||||
// GetBlockAppearance gets the block appearance of the given block in the fastest way possible.
|
// GetBlockAppearance gets the block appearance of the given block in the fastest way possible.
|
||||||
func GetBlockAppearance(position itype.Vec3i, id, aux int, data itype.Dataset, world *World) BlockAppearance {
|
func GetBlockAppearance(position itype.Vec3i, id, aux int, data itype.Dataset, world *World) BlockAppearance {
|
||||||
if app, ok := appearance[id]; ok { // Cache
|
if app, ok := appearance[id]; ok { // Cache
|
||||||
if app.Hitbox == (itype.Boxd{}) {
|
if len(app.Hitbox) == 0 {
|
||||||
app.Hitbox = itype.Boxd{
|
app.Hitbox = []itype.Boxd{{
|
||||||
OffX: 0, OffY: 0, OffZ: 0,
|
OffX: 0, OffY: 0, OffZ: 0,
|
||||||
SizeX: 1, SizeY: 1, SizeZ: 1,
|
SizeX: 1, SizeY: 1, SizeZ: 1,
|
||||||
}
|
}}
|
||||||
}
|
}
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
@ -140,11 +140,11 @@ func GetBlockAppearance(position itype.Vec3i, id, aux int, data itype.Dataset, w
|
|||||||
}
|
}
|
||||||
|
|
||||||
app := b.Appearance(position, aux, data, world)
|
app := b.Appearance(position, aux, data, world)
|
||||||
if app.Hitbox == (itype.Boxd{}) {
|
if len(app.Hitbox) == 0 {
|
||||||
app.Hitbox = itype.Boxd{
|
app.Hitbox = []itype.Boxd{{
|
||||||
OffX: 0, OffY: 0, OffZ: 0,
|
OffX: 0, OffY: 0, OffZ: 0,
|
||||||
SizeX: 1, SizeY: 1, SizeZ: 1,
|
SizeX: 1, SizeY: 1, SizeZ: 1,
|
||||||
}
|
}}
|
||||||
}
|
}
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
@ -165,7 +165,14 @@ type Block struct {
|
|||||||
// Appearance is a shortcut for Behaviour.Appearance().
|
// Appearance is a shortcut for Behaviour.Appearance().
|
||||||
// It returns the Appearance of the block with the given parameters.
|
// It returns the Appearance of the block with the given parameters.
|
||||||
func (b Block) Appearance(position itype.Vec3i) BlockAppearance {
|
func (b Block) Appearance(position itype.Vec3i) BlockAppearance {
|
||||||
return b.Behaviour.Appearance(position, b.Aux, b.Dataset, b.World)
|
app := b.Behaviour.Appearance(position, b.Aux, b.Dataset, b.World)
|
||||||
|
if !app.NotSolid && len(app.Hitbox) == 0 {
|
||||||
|
app.Hitbox = []itype.Boxd{{
|
||||||
|
OffX: 0, OffY: 0, OffZ: 0,
|
||||||
|
SizeX: 1, SizeY: 1, SizeZ: 1,
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockUpdate is a shortcut for Behaviour.BlockUpdate().
|
// BlockUpdate is a shortcut for Behaviour.BlockUpdate().
|
||||||
|
Loading…
Reference in New Issue
Block a user