Initial commit
This commit is contained in:
29
internal/entity/entities/player.go
Normal file
29
internal/entity/entities/player.go
Normal file
@ -0,0 +1,29 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"edgaru089.ml/go/gl01/internal/entity"
|
||||
"edgaru089.ml/go/gl01/internal/util/itype"
|
||||
"edgaru089.ml/go/gl01/internal/world"
|
||||
)
|
||||
|
||||
type PlayerBehaviour struct{}
|
||||
|
||||
func init() {
|
||||
entity.RegisterEntityBehaviour(PlayerBehaviour{})
|
||||
}
|
||||
|
||||
func (PlayerBehaviour) Name() string { return "player" }
|
||||
|
||||
func (PlayerBehaviour) Hitbox(pos itype.Vec3d, dataset itype.Dataset) itype.Vec3d {
|
||||
return itype.Vec3d{0.6, 1.8, 0.6}
|
||||
}
|
||||
|
||||
func (PlayerBehaviour) EyeHeight(pos itype.Vec3d, dataset itype.Dataset) float64 {
|
||||
return 1.65
|
||||
}
|
||||
|
||||
func (PlayerBehaviour) Update(pos itype.Vec3d, dataset itype.Dataset, world *world.World, deltaTime time.Duration) {
|
||||
|
||||
}
|
109
internal/entity/entity.go
Normal file
109
internal/entity/entity.go
Normal file
@ -0,0 +1,109 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"edgaru089.ml/go/gl01/internal/util"
|
||||
"edgaru089.ml/go/gl01/internal/util/itype"
|
||||
"edgaru089.ml/go/gl01/internal/world"
|
||||
)
|
||||
|
||||
// EntityBehaviour describes the behaviour of a type of entity with the same Name.
|
||||
type EntityBehaviour interface {
|
||||
// Name returns the type Name of the behaviour.
|
||||
Name() string
|
||||
|
||||
// Hitbox gets the size of the hitbox of the entity.
|
||||
//
|
||||
// The hitbox is positioned with the position coordinates pointing to
|
||||
// the center of the bottom of the box.
|
||||
Hitbox(pos itype.Vec3d, dataset itype.Dataset) itype.Vec3d
|
||||
|
||||
// EyeHeight gets the height of the eye of the entity.
|
||||
EyeHeight(pos itype.Vec3d, dataset itype.Dataset) float64
|
||||
|
||||
// Update is called on every frame.
|
||||
// It should be used to update physics.
|
||||
Update(pos itype.Vec3d, dataset itype.Dataset, world *world.World, deltaTime time.Duration)
|
||||
}
|
||||
|
||||
var behaviour = make(map[string]EntityBehaviour)
|
||||
|
||||
// RegisterEntityBehaviour registers behaviour with the name of b.Name().
|
||||
//
|
||||
// If the name is already taken, false is returned and nothing is done.
|
||||
// Otherwise, true is returned and the entity is registered.
|
||||
func RegisterEntityBehaviour(b EntityBehaviour) bool {
|
||||
if _, ok := behaviour[b.Name()]; ok {
|
||||
return false
|
||||
}
|
||||
|
||||
behaviour[b.Name()] = b
|
||||
return true
|
||||
}
|
||||
|
||||
// Entity is a struct holding a Behaviour, a Position and a Speed.
|
||||
type Entity struct {
|
||||
b EntityBehaviour
|
||||
pos, speed itype.Vec3d // pos has a origin of the **center of the bottom** of the hitbox
|
||||
ds itype.Dataset
|
||||
|
||||
name string // a shortcut to b.Name(), the typename
|
||||
|
||||
onGround bool
|
||||
worldbox []itype.Boxd
|
||||
hp []itype.Vec3d
|
||||
}
|
||||
|
||||
func NewEntity(typename string, pos itype.Vec3d) *Entity {
|
||||
var b EntityBehaviour
|
||||
var ok bool
|
||||
if b, ok = behaviour[typename]; !ok {
|
||||
return nil
|
||||
}
|
||||
return &Entity{
|
||||
b: b,
|
||||
pos: pos,
|
||||
name: typename,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Entity) Position() itype.Vec3d {
|
||||
return e.pos
|
||||
}
|
||||
|
||||
func (e *Entity) SetPosition(pos itype.Vec3d) {
|
||||
e.pos = pos
|
||||
}
|
||||
|
||||
func (e *Entity) Speed() itype.Vec3d {
|
||||
return e.speed
|
||||
}
|
||||
|
||||
func (e *Entity) SetSpeed(speed itype.Vec3d) {
|
||||
e.speed = speed
|
||||
}
|
||||
|
||||
func (e *Entity) Hitbox() itype.Vec3d {
|
||||
return e.b.Hitbox(e.pos, e.ds)
|
||||
}
|
||||
|
||||
func (e *Entity) Accelerate(x, y, z float64) {
|
||||
/*e.speed[0] += x
|
||||
e.speed[1] += y
|
||||
e.speed[2] += z*/
|
||||
vec := itype.Vec3d{x, y, z}
|
||||
e.speed = util.BunnyhopAccelerate(vec, e.speed, vec.Length(), 8)
|
||||
}
|
||||
|
||||
func (e *Entity) OnGround() bool {
|
||||
return e.onGround
|
||||
}
|
||||
|
||||
func (e *Entity) EyeHeight() float64 {
|
||||
return e.b.EyeHeight(e.pos, e.ds)
|
||||
}
|
||||
|
||||
func (e *Entity) EyePosition() itype.Vec3d {
|
||||
return e.pos.Addv(0, e.EyeHeight(), 0)
|
||||
}
|
1
internal/entity/manager.go
Normal file
1
internal/entity/manager.go
Normal file
@ -0,0 +1 @@
|
||||
package entity
|
298
internal/entity/physics.go
Normal file
298
internal/entity/physics.go
Normal file
@ -0,0 +1,298 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"edgaru089.ml/go/gl01/internal/util"
|
||||
"edgaru089.ml/go/gl01/internal/util/itype"
|
||||
"edgaru089.ml/go/gl01/internal/world"
|
||||
)
|
||||
|
||||
func (e *Entity) worldHitbox(hitbox itype.Vec3d) itype.Boxd {
|
||||
return itype.Boxd{
|
||||
OffX: e.pos[0] - hitbox[0]/2,
|
||||
OffY: e.pos[1],
|
||||
OffZ: e.pos[2] - hitbox[2]/2,
|
||||
SizeX: hitbox[0],
|
||||
SizeY: hitbox[1],
|
||||
SizeZ: hitbox[2],
|
||||
}
|
||||
}
|
||||
|
||||
// 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}),
|
||||
)
|
||||
/*
|
||||
// add the surface points
|
||||
// X+ and X-
|
||||
for y := base[1] + HitpointMeshLen; y < base[1]+hitbox[1]; y += HitpointMeshLen {
|
||||
for z := base[2] + HitpointMeshLen; z < base[2]+hitbox[2]; z += HitpointMeshLen {
|
||||
points = append(points,
|
||||
base.Addv(0, y, z),
|
||||
base.Addv(box.SizeX, y, z),
|
||||
)
|
||||
}
|
||||
}
|
||||
// Y+ and Y-
|
||||
for x := base[0] + HitpointMeshLen; x < base[0]+hitbox[0]; x += HitpointMeshLen {
|
||||
for z := base[2] + HitpointMeshLen; z < base[2]+hitbox[2]; z += HitpointMeshLen {
|
||||
points = append(points,
|
||||
base.Addv(x, 0, z),
|
||||
base.Addv(x, box.SizeY, z),
|
||||
)
|
||||
}
|
||||
}
|
||||
// Z+ and Z-
|
||||
for x := base[0] + HitpointMeshLen; x < base[0]+hitbox[0]; x += HitpointMeshLen {
|
||||
for y := base[1] + HitpointMeshLen; y < base[1]+hitbox[1]; y += HitpointMeshLen {
|
||||
points = append(points,
|
||||
base.Addv(x, y, 0),
|
||||
base.Addv(x, y, box.SizeZ),
|
||||
)
|
||||
}
|
||||
}*/
|
||||
return points
|
||||
}
|
||||
|
||||
// MoveEps is a small value used to indicate a tiny amount more than zero.
|
||||
const MoveEps = 1e-7
|
||||
|
||||
// tells if the point is already stuck inside a block hitbox
|
||||
func pointStuck(point itype.Vec3d, w *world.World) bool {
|
||||
blockid := point.Floor()
|
||||
block := w.Block(blockid)
|
||||
return block.Id != 0 &&
|
||||
block.Behaviour.Appearance(
|
||||
point.Floor(),
|
||||
block.Aux,
|
||||
block.Dataset,
|
||||
).Hitbox.Offset(blockid.ToFloat64()).Contains(point)
|
||||
}
|
||||
|
||||
// the move series functions should be called with e.hp already filled
|
||||
|
||||
func (e *Entity) moveX(delta float64, hitbox itype.Boxd, w *world.World) {
|
||||
if math.Abs(delta) < MoveEps*10 {
|
||||
return
|
||||
}
|
||||
|
||||
var hit bool = false
|
||||
var deltaMin float64 = 10000
|
||||
|
||||
if delta > 1-MoveEps {
|
||||
delta = 1 - MoveEps
|
||||
}
|
||||
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)
|
||||
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 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
|
||||
}
|
||||
|
||||
var hit bool = false
|
||||
var deltaMin float64 = 10000
|
||||
|
||||
if delta > 1-MoveEps {
|
||||
delta = 1 - MoveEps
|
||||
}
|
||||
if delta < -1+MoveEps {
|
||||
delta = -1 + MoveEps
|
||||
}
|
||||
|
||||
// Y+ / Y-
|
||||
for _, p := range e.hp {
|
||||
if pointStuck(p, w) {
|
||||
continue
|
||||
}
|
||||
|
||||
dest := p.Addv(0, delta, 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)
|
||||
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 {
|
||||
deltaDone = delta
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
var hit bool = false
|
||||
var deltaMin float64 = 10000
|
||||
|
||||
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)
|
||||
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) {
|
||||
|
||||
hitbox := e.b.Hitbox(e.pos, e.ds)
|
||||
box := e.worldHitbox(hitbox)
|
||||
|
||||
e.hp = e.hp[0:0]
|
||||
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)
|
||||
|
||||
speed := math.Sqrt(e.speed[0]*e.speed[0] + e.speed[2]*e.speed[2])
|
||||
if speed > MoveEps {
|
||||
decrease := deaclc * deltaTime.Seconds()
|
||||
if !e.onGround {
|
||||
decrease /= 10
|
||||
}
|
||||
factor := util.Maxd(util.Mind(speed-decrease, 9), 0) / speed
|
||||
|
||||
e.speed[0] *= factor
|
||||
e.speed[2] *= factor
|
||||
}
|
||||
|
||||
e.speed[1] -= gravity * deltaTime.Seconds()
|
||||
|
||||
e.b.Update(e.pos, e.ds, world, deltaTime)
|
||||
}
|
233
internal/entity/physics.go.new
Normal file
233
internal/entity/physics.go.new
Normal file
@ -0,0 +1,233 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"log"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/Edgaru089/gl01/internal/util"
|
||||
"github.com/Edgaru089/gl01/internal/util/itype"
|
||||
"github.com/Edgaru089/gl01/internal/world"
|
||||
)
|
||||
|
||||
func (e *Entity) worldHitbox(hitbox itype.Vec3d) itype.Boxd {
|
||||
return itype.Boxd{
|
||||
OffX: e.pos[0] - hitbox[0]/2,
|
||||
OffY: e.pos[1],
|
||||
OffZ: e.pos[2] - hitbox[2]/2,
|
||||
SizeX: hitbox[0],
|
||||
SizeY: hitbox[1],
|
||||
SizeZ: hitbox[2],
|
||||
}
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
// MoveEps is a small value used to indicate a tiny amount more than zero.
|
||||
const MoveEps = 1e-7
|
||||
|
||||
// the move series functions should be called with e.hp already filled
|
||||
|
||||
func (e *Entity) moveX(delta float64, hitbox itype.Boxd, w *world.World) {
|
||||
if math.Abs(delta) < MoveEps*10 {
|
||||
return
|
||||
}
|
||||
|
||||
var hit bool = false
|
||||
var deltaMin float64 = 10000
|
||||
|
||||
if delta > 1-MoveEps {
|
||||
delta = 1 - MoveEps
|
||||
}
|
||||
if delta < -1+MoveEps {
|
||||
delta = -1 + MoveEps
|
||||
}
|
||||
|
||||
// X+ / X-
|
||||
if pointStuck(p, w) {
|
||||
continue
|
||||
}
|
||||
|
||||
dest := hitbox.Offsetv(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)
|
||||
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 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
|
||||
}
|
||||
|
||||
var hit bool = false
|
||||
var deltaMin float64 = 10000
|
||||
|
||||
if delta > 1-MoveEps {
|
||||
delta = 1 - MoveEps
|
||||
}
|
||||
if delta < -1+MoveEps {
|
||||
delta = -1 + MoveEps
|
||||
}
|
||||
|
||||
// Y+ / Y-
|
||||
for _, p := range e.hp {
|
||||
if pointStuck(p, w) {
|
||||
continue
|
||||
}
|
||||
|
||||
dest := p.Addv(0, delta, 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)
|
||||
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 {
|
||||
deltaDone = delta
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
var hit bool = false
|
||||
var deltaMin float64 = 10000
|
||||
|
||||
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)
|
||||
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) {
|
||||
|
||||
hitbox := e.b.Hitbox(e.pos, e.ds)
|
||||
box := e.worldHitbox(hitbox)
|
||||
|
||||
e.hp = e.hp[0:0]
|
||||
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)
|
||||
|
||||
speed := math.Sqrt(e.speed[0]*e.speed[0] + e.speed[2]*e.speed[2])
|
||||
if speed > MoveEps {
|
||||
decrease := deaclc * deltaTime.Seconds()
|
||||
if !e.onGround {
|
||||
decrease /= 10
|
||||
}
|
||||
factor := util.Maxd(util.Mind(speed-decrease, 9), 0) / speed
|
||||
|
||||
e.speed[0] *= factor
|
||||
e.speed[2] *= factor
|
||||
}
|
||||
|
||||
e.speed[1] -= gravity * deltaTime.Seconds()
|
||||
|
||||
e.b.Update(e.pos, e.ds, world, deltaTime)
|
||||
}
|
Reference in New Issue
Block a user