feat: implemented the basic collider system.
This commit is contained in:
parent
f910d4f99b
commit
31940fa899
6 changed files with 128 additions and 34 deletions
|
@ -2,7 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
//"math/rand"
|
//"math/rand"
|
||||||
//"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,12 +28,24 @@ func NewPlayer() *Player {
|
||||||
ret.Visible = true
|
ret.Visible = true
|
||||||
ret.Layer = PlayerL
|
ret.Layer = PlayerL
|
||||||
|
|
||||||
|
ret.Collidable = true
|
||||||
|
ret.Resolvable = true
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) Start(c *Context) {
|
func (p *Player) Start(c *Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Player) Draw(c *Context) []gg.EVertex {
|
||||||
|
return p.AnimatedSprite.Draw(c)
|
||||||
|
prect := &gg.DrawableRectangle{
|
||||||
|
Rectangle: p.Rectangle(),
|
||||||
|
}
|
||||||
|
prect.Color = gg.Rgba(1, 1, 1, 1)
|
||||||
|
return prect.Draw(c)
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Player) Update(c *Context) {
|
func (p *Player) Update(c *Context) {
|
||||||
if p.Spawned {
|
if p.Spawned {
|
||||||
return
|
return
|
||||||
|
@ -58,7 +70,7 @@ func (p *Player) Update(c *Context) {
|
||||||
case gg.KeyArrowRight:
|
case gg.KeyArrowRight:
|
||||||
cam.Position.X += p.MoveSpeed * dt
|
cam.Position.X += p.MoveSpeed * dt
|
||||||
case gg.KeyW:
|
case gg.KeyW:
|
||||||
p.Position.Y += p.MoveSpeed * dt
|
p.Position.Y -= p.MoveSpeed * dt*10
|
||||||
walking = true
|
walking = true
|
||||||
p.Animate(Walk)
|
p.Animate(Walk)
|
||||||
case gg.KeyA:
|
case gg.KeyA:
|
||||||
|
@ -140,5 +152,26 @@ func (p *Player) Update(c *Context) {
|
||||||
ec.Offset.Y * dt * p.ScaleSpeed * 40,
|
ec.Offset.Y * dt * p.ScaleSpeed * 40,
|
||||||
))
|
))
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
p.Position.Y += 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Player) Resolve(c *Context) {
|
||||||
|
|
||||||
|
col := c.Collisions[0]
|
||||||
|
fmt.Printf("frame[%d]: the col[0] len(%d): %T, %T\n", c.Frame(), len(c.Collisions), col.What, col.With)
|
||||||
|
switch col.Type{
|
||||||
|
case gg.PhysCollision :
|
||||||
|
LOOP:
|
||||||
|
for {
|
||||||
|
p.Position.Y -= 0.2
|
||||||
|
shit, collides := gg.Collide(p, col.With)
|
||||||
|
fmt.Println("shit:", shit)
|
||||||
|
fmt.Println("do:", collides)
|
||||||
|
if !collides {
|
||||||
|
break LOOP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,9 @@ func NewRect() *Rect {
|
||||||
}
|
}
|
||||||
ret.Layer = RectL
|
ret.Layer = RectL
|
||||||
ret.Visible = true
|
ret.Visible = true
|
||||||
|
ret.Collidable = true
|
||||||
|
ret.Width = 100
|
||||||
|
ret.Height = 200
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
23
collider.go
23
collider.go
|
@ -12,14 +12,14 @@ package gg
|
||||||
|
|
||||||
type CollisionType int
|
type CollisionType int
|
||||||
const (
|
const (
|
||||||
CollisionTypePhys CollisionType = iota
|
PhysCollision CollisionType = iota
|
||||||
CollisionTypeTrigger
|
TriggerCollision
|
||||||
)
|
)
|
||||||
|
|
||||||
// The structure contains collision information.
|
// The structure contains collision information.
|
||||||
type Collision struct {
|
type Collision struct {
|
||||||
Type CollisionType
|
Type CollisionType
|
||||||
What, With Objecter
|
What, With Collider
|
||||||
// Points of Self contained in
|
// Points of Self contained in
|
||||||
Points Points
|
Points Points
|
||||||
Crosses []LineCross
|
Crosses []LineCross
|
||||||
|
@ -28,19 +28,21 @@ type Collision struct {
|
||||||
|
|
||||||
// Implementing the interface lets the engine
|
// Implementing the interface lets the engine
|
||||||
// to determine if the object collides with anything.
|
// to determine if the object collides with anything.
|
||||||
// Mostly will use the Collide function with some
|
|
||||||
// inner structure field as first argument.
|
|
||||||
// The Collide method will be called on collisions.
|
|
||||||
type Collider interface {
|
type Collider interface {
|
||||||
// Checks whether the object is collidable
|
// Checks whether the object is collidable
|
||||||
|
CollisionType() CollisionType
|
||||||
IsCollidable() bool
|
IsCollidable() bool
|
||||||
Verticer
|
Verticer
|
||||||
Edger
|
Edger
|
||||||
PointContainer
|
PointContainer
|
||||||
}
|
}
|
||||||
type Collidability struct {
|
type Collidability struct {
|
||||||
|
Type CollisionType
|
||||||
Collidable bool
|
Collidable bool
|
||||||
}
|
}
|
||||||
|
func (c Collidability) CollisionType() CollisionType {
|
||||||
|
return c.Type
|
||||||
|
}
|
||||||
func (c Collidability) IsCollidable() bool {
|
func (c Collidability) IsCollidable() bool {
|
||||||
return c.Collidable
|
return c.Collidable
|
||||||
}
|
}
|
||||||
|
@ -75,6 +77,9 @@ func Collide(c1, c2 Collider) (Collision, bool) {
|
||||||
crosses, doCross := es1.LineCrossWith(es2)
|
crosses, doCross := es1.LineCrossWith(es2)
|
||||||
pts := c2.ContainedPoints(vertices)
|
pts := c2.ContainedPoints(vertices)
|
||||||
return Collision{
|
return Collision{
|
||||||
|
Type: c2.CollisionType(),
|
||||||
|
What: c1,
|
||||||
|
With: c2,
|
||||||
Points: pts,
|
Points: pts,
|
||||||
Crosses: crosses,
|
Crosses: crosses,
|
||||||
}, len(pts) != 0 || doCross
|
}, len(pts) != 0 || doCross
|
||||||
|
@ -83,9 +88,13 @@ func Collide(c1, c2 Collider) (Collision, bool) {
|
||||||
func GetCollisions(c Collider, cs []Collider) []Collision {
|
func GetCollisions(c Collider, cs []Collider) []Collision {
|
||||||
ret := []Collision{}
|
ret := []Collision{}
|
||||||
for _, ic := range cs {
|
for _, ic := range cs {
|
||||||
if !ic.IsCollidable() || ic == c {
|
if ic == c {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
col, has := Collide(c, ic)
|
||||||
|
if has {
|
||||||
|
ret = append(ret, col)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
38
engine.go
38
engine.go
|
@ -4,7 +4,7 @@ import (
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
||||||
"vultras.su/core/gods/maps"
|
"vultras.su/core/gods/maps"
|
||||||
"fmt"
|
//"fmt"
|
||||||
"time"
|
"time"
|
||||||
"slices"
|
"slices"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -164,7 +164,12 @@ func (e *Engine) Spawn(b Objecter) error {
|
||||||
obj.input = make(chan *Context)
|
obj.input = make(chan *Context)
|
||||||
go func() {
|
go func() {
|
||||||
for c := range obj.input {
|
for c := range obj.input {
|
||||||
b.Update(c)
|
switch c.typ{
|
||||||
|
case updateContext :
|
||||||
|
b.Update(c)
|
||||||
|
case resolveContext :
|
||||||
|
b.Resolve(c)
|
||||||
|
}
|
||||||
e.wg.Done()
|
e.wg.Done()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -300,7 +305,7 @@ func (e *engine) Update() error {
|
||||||
e.dt = time.Since(e.lastTime)
|
e.dt = time.Since(e.lastTime)
|
||||||
|
|
||||||
e.runes = ebiten.AppendInputChars(e.runes[:0])
|
e.runes = ebiten.AppendInputChars(e.runes[:0])
|
||||||
fmt.Println("runes:", e.runes)
|
//fmt.Println("runes:", e.runes)
|
||||||
// Buffering the context for faster.
|
// Buffering the context for faster.
|
||||||
// Providing the events to the objects.
|
// Providing the events to the objects.
|
||||||
// Maybe should think of the better way,
|
// Maybe should think of the better way,
|
||||||
|
@ -325,16 +330,39 @@ func (e *engine) Update() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *engine) Resolve() {
|
func (e *engine) Resolve() {
|
||||||
|
eng := (*Engine)(e)
|
||||||
|
type resHold struct{
|
||||||
|
Resolver Resolver
|
||||||
|
input chan *Context
|
||||||
|
}
|
||||||
colliders := []Collider{}
|
colliders := []Collider{}
|
||||||
resolvers := []Resolver{}
|
|
||||||
|
resolvers := []resHold{}
|
||||||
for _, object := range e.Objects.store {
|
for _, object := range e.Objects.store {
|
||||||
if object.IsCollidable() {
|
if object.IsCollidable() {
|
||||||
colliders = append(colliders, object)
|
colliders = append(colliders, object)
|
||||||
}
|
}
|
||||||
if object.IsResolvable() {
|
if object.IsResolvable() {
|
||||||
resolvers = append(resolvers, object)
|
resolvers = append(resolvers, resHold{
|
||||||
|
object,
|
||||||
|
object.Input(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, resolver := range resolvers {
|
||||||
|
cols := GetCollisions(resolver.Resolver, colliders)
|
||||||
|
if len(cols) > 0 {
|
||||||
|
c := &Context{
|
||||||
|
typ: resolveContext,
|
||||||
|
Collisions: cols,
|
||||||
|
Engine: eng,
|
||||||
|
}
|
||||||
|
e.wg.Add(1)
|
||||||
|
resolver.input <- c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e.wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
22
rect.go
22
rect.go
|
@ -17,12 +17,15 @@ type Rectangle struct {
|
||||||
|
|
||||||
// Return points of vertices of the rectangle.
|
// Return points of vertices of the rectangle.
|
||||||
func (r Rectangle) Vertices() Vertices {
|
func (r Rectangle) Vertices() Vertices {
|
||||||
m := r.Matrix()
|
t := r.Transform
|
||||||
|
wh := V(r.Width, r.Height)
|
||||||
|
t.Around = t.Around.Scale(wh)
|
||||||
|
m := t.Matrix()
|
||||||
p1 := V(0, 0).Apply(m)
|
p1 := V(0, 0).Apply(m)
|
||||||
p2 := V(1, 0).Apply(m)
|
p2 := V(wh.X, 0).Apply(m)
|
||||||
p3 := V(1, 1).Apply(m)
|
p3 := V(wh.X, wh.Y).Apply(m)
|
||||||
p4 := V(0, 1).Apply(m)
|
p4 := V(0, wh.Y).Apply(m)
|
||||||
return Points{p1, p2, p3, p4}
|
return Vertices{p1, p2, p3, p4}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Rectangle) Edges() Edges {
|
func (r Rectangle) Edges() Edges {
|
||||||
|
@ -63,15 +66,6 @@ type DrawableRectangle struct {
|
||||||
// Will be ignored if the Shader
|
// Will be ignored if the Shader
|
||||||
// field is not nil.
|
// field is not nil.
|
||||||
Colority
|
Colority
|
||||||
|
|
||||||
// Should be draw or not.
|
|
||||||
Visibility
|
|
||||||
Collidability
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether the drawable rectangle should be drawn.
|
|
||||||
func (r *DrawableRectangle) IsVisible() bool {
|
|
||||||
return r.Visible
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DrawableRectangle) Draw(c *Context) []EVertex {
|
func (r *DrawableRectangle) Draw(c *Context) []EVertex {
|
||||||
|
|
39
sprite.go
39
sprite.go
|
@ -11,8 +11,6 @@ type Sprite struct {
|
||||||
ShaderOptions
|
ShaderOptions
|
||||||
Floating bool
|
Floating bool
|
||||||
Visibility
|
Visibility
|
||||||
Collidability
|
|
||||||
Resolvability
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -25,7 +23,7 @@ func (s *Sprite) Draw(c *Context) []EVertex {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
t := s.Rectangle().Transform
|
t := s.RectangleToDraw().Transform
|
||||||
m := t.Matrix()
|
m := t.Matrix()
|
||||||
if !s.Floating {
|
if !s.Floating {
|
||||||
m.Concat(c.Camera.RealMatrix())
|
m.Concat(c.Camera.RealMatrix())
|
||||||
|
@ -49,10 +47,10 @@ func (s *Sprite) Draw(c *Context) []EVertex {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the rectangle that contains the sprite.
|
// Return the rectangle that contains the sprite to draw.
|
||||||
func (s *Sprite) Rectangle() Rectangle {
|
func (s *Sprite) RectangleToDraw() Rectangle {
|
||||||
if s.Images[0] == nil {
|
if s.Images[0] == nil {
|
||||||
panic("trying to get rectangle for nil image pointer")
|
return Rectangle{}
|
||||||
}
|
}
|
||||||
|
|
||||||
w, h := s.Images[0].Size()
|
w, h := s.Images[0].Size()
|
||||||
|
@ -65,9 +63,38 @@ func (s *Sprite) Rectangle() Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the rectangle that contains the sprite in the engine.
|
||||||
|
func (s *Sprite) Rectangle() Rectangle {
|
||||||
|
if s.Images[0] == nil {
|
||||||
|
return Rectangle{
|
||||||
|
Transform: s.Transform,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w, h := s.Images[0].Size()
|
||||||
|
t := s.Transform
|
||||||
|
|
||||||
|
return Rectangle{
|
||||||
|
Transform: t,
|
||||||
|
Width: Float(w),
|
||||||
|
Height: Float(h),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get triangles of the rectangle that contains the sprite
|
// Get triangles of the rectangle that contains the sprite
|
||||||
// and has the same widght and height.
|
// and has the same widght and height.
|
||||||
func (s *Sprite) MakeTriangles() Triangles {
|
func (s *Sprite) MakeTriangles() Triangles {
|
||||||
return s.Rectangle().MakeTriangles()
|
return s.Rectangle().MakeTriangles()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Sprite) Vertices() Vertices {
|
||||||
|
return s.Rectangle().Vertices()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Sprite) Edges() Edges {
|
||||||
|
return s.Rectangle().Edges()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Sprite) ContainedPoints(pts Points) Points {
|
||||||
|
return s.Rectangle().ContainedPoints(pts)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue