Physics/Collisions — Linear

linear.go
  1package main
  2
  3import (
  4 "embed"
  5 "log"
  6
  7 "github.com/TheBitDrifter/bappa/blueprint"
  8 "github.com/TheBitDrifter/bappa/coldbrew"
  9 "github.com/TheBitDrifter/bappa/coldbrew/coldbrew_rendersystems"
 10 "github.com/TheBitDrifter/bappa/warehouse"
 11
 12 "github.com/TheBitDrifter/bappa/tteokbokki/motion"
 13 "github.com/TheBitDrifter/bappa/tteokbokki/spatial"
 14 "github.com/TheBitDrifter/bappa/tteokbokki/tteo_coresystems"
 15)
 16
 17var assets embed.FS
 18
 19var floorTag = warehouse.FactoryNewComponent[struct{}]()
 20
 21func main() {
 22 client := coldbrew.NewClient(
 23  640,
 24  360,
 25  10,
 26  10,
 27  10,
 28  assets,
 29 )
 30
 31 client.SetTitle("Simple Collision and Physics")
 32
 33 err := client.RegisterScene(
 34  "Example Scene",
 35  640,
 36  360,
 37  exampleScenePlan,
 38  []coldbrew.RenderSystem{},
 39  []coldbrew.ClientSystem{},
 40  []blueprint.CoreSystem{
 41   gravitySystem{},
 42   tteo_coresystems.IntegrationSystem{},
 43   tteo_coresystems.TransformSystem{},
 44   collisionBounceSystem{},
 45  },
 46 )
 47 if err != nil {
 48  log.Fatal(err)
 49 }
 50
 51 client.RegisterGlobalRenderSystem(
 52  coldbrew_rendersystems.GlobalRenderer{},
 53  &coldbrew_rendersystems.DebugRenderer{},
 54 )
 55
 56 client.ActivateCamera()
 57
 58 if err := client.Start(); err != nil {
 59  log.Fatal(err)
 60 }
 61}
 62
 63func exampleScenePlan(height, width int, sto warehouse.Storage) error {
 64 boxArchetype, err := sto.NewOrExistingArchetype(
 65  spatial.Components.Position,
 66  spatial.Components.Rotation,
 67  spatial.Components.Shape,
 68  motion.Components.Dynamics,
 69 )
 70 if err != nil {
 71  return err
 72 }
 73 for i := 0; i < 10; i++ {
 74  err = boxArchetype.Generate(1,
 75   spatial.NewPosition(float64(i*100), float64(20*i)),
 76   motion.NewDynamics(10),
 77   spatial.NewRectangle(30, 40),
 78  )
 79  if err != nil {
 80   return err
 81  }
 82 }
 83
 84 floorArchetype, err := sto.NewOrExistingArchetype(
 85  floorTag,
 86  spatial.Components.Position,
 87  spatial.Components.Rotation,
 88  spatial.Components.Shape,
 89  motion.Components.Dynamics,
 90 )
 91 if err != nil {
 92  return err
 93 }
 94
 95 err = floorArchetype.Generate(1,
 96  spatial.NewPosition(320, 300),
 97  motion.NewDynamics(0),
 98  spatial.NewRectangle(800, 40),
 99 )
100
101 return nil
102}
103
104type gravitySystem struct{}
105
106func (gravitySystem) Run(scene blueprint.Scene, _ float64) error {
107 const (
108  DEFAULT_GRAVITY  = 9.8
109  PIXELS_PER_METER = 50.0
110 )
111
112 cursor := scene.NewCursor(blueprint.Queries.Dynamics)
113 for range cursor.Next() {
114  dyn := motion.Components.Dynamics.GetFromCursor(cursor)
115  mass := 1 / dyn.InverseMass
116  gravity := motion.Forces.Generator.NewGravityForce(mass, DEFAULT_GRAVITY, PIXELS_PER_METER)
117  motion.Forces.AddForce(dyn, gravity)
118 }
119 return nil
120}
121
122type collisionBounceSystem struct{}
123
124func (collisionBounceSystem) Run(scene blueprint.Scene, _ float64) error {
125 boxQuery := warehouse.Factory.NewQuery().And(
126  spatial.Components.Shape,
127  warehouse.Factory.NewQuery().Not(floorTag),
128 )
129 floorQuery := warehouse.Factory.NewQuery().And(
130  spatial.Components.Shape,
131  floorTag,
132 )
133
134 boxCursor := scene.NewCursor(boxQuery)
135 floorCursor := scene.NewCursor(floorQuery)
136
137 for range boxCursor.Next() {
138  for range floorCursor.Next() {
139   boxPos := spatial.Components.Position.GetFromCursor(boxCursor)
140   boxShape := spatial.Components.Shape.GetFromCursor(boxCursor)
141   boxDyn := motion.Components.Dynamics.GetFromCursor(boxCursor)
142
143   // Get the block pos, shape, and dynamics
144   floorPos := spatial.Components.Position.GetFromCursor(floorCursor)
145   floorShape := spatial.Components.Shape.GetFromCursor(floorCursor)
146   floorDyn := motion.Components.Dynamics.GetFromCursor(floorCursor)
147
148   // Check for a collision
149   if ok, collisionResult := spatial.Detector.Check(
150    *boxShape, *floorShape, boxPos.Two, floorPos.Two,
151   ); ok {
152    motion.Resolver.Resolve(
153     &boxPos.Two,
154     &floorPos.Two,
155     boxDyn,
156     floorDyn,
157     collisionResult,
158    )
159
160    boxDyn.Vel.Y -= 500
161   }
162  }
163 }
164 return nil
165}