Skip to content
This repository has been archived by the owner on May 31, 2024. It is now read-only.

Commit

Permalink
working on a physics example
Browse files Browse the repository at this point in the history
  • Loading branch information
GaryBrownEEngr committed Dec 1, 2023
1 parent f696d5b commit a064744
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 0 deletions.
203 changes: 203 additions & 0 deletions examples/marblemachine/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
package main

import (
"fmt"
"image"
"image/color"
"math"
"math/rand"
"time"

"github.com/GaryBrownEEngr/scratch"
"github.com/GaryBrownEEngr/scratch/models"
"github.com/GaryBrownEEngr/scratch/tools"
"github.com/fogleman/gg"
"github.com/jakecoffman/cp"
)

func main() {
params := scratch.ScratchParams{Width: 1000, Height: 1000, ShowFPS: true}
scratch.Start(params, simStartFunc)
}

type object struct {
sprite models.Sprite
physicsShape *cp.Shape
}

func simStartFunc(sim models.Scratch) {
oList := []*object{}

space := cp.NewSpace()
space.SetGravity(cp.Vector{X: 0, Y: -600})

container := space.AddBody(cp.NewKinematicBody())
container.SetAngularVelocity(0.4)
container.SetPosition(cp.Vector{0, 0})

Check failure on line 36 in examples/marblemachine/main.go

View workflow job for this annotation

GitHub Actions / Go CI

github.com/jakecoffman/cp.Vector struct literal uses unkeyed fields

a := cp.Vector{-200, -200}

Check failure on line 38 in examples/marblemachine/main.go

View workflow job for this annotation

GitHub Actions / Go CI

github.com/jakecoffman/cp.Vector struct literal uses unkeyed fields
b := cp.Vector{-200, 200}

Check failure on line 39 in examples/marblemachine/main.go

View workflow job for this annotation

GitHub Actions / Go CI

github.com/jakecoffman/cp.Vector struct literal uses unkeyed fields
c := cp.Vector{200, 200}

Check failure on line 40 in examples/marblemachine/main.go

View workflow job for this annotation

GitHub Actions / Go CI

github.com/jakecoffman/cp.Vector struct literal uses unkeyed fields
d := cp.Vector{200, -200}

Check failure on line 41 in examples/marblemachine/main.go

View workflow job for this annotation

GitHub Actions / Go CI

github.com/jakecoffman/cp.Vector struct literal uses unkeyed fields

AddWall(space, container, a, b, 1)
AddWall(space, container, b, c, 1)
AddWall(space, container, c, d, 1)
AddWall(space, container, d, a, 1)

mass := 1.0
width := 30.0
height := width * 2

for i := 0; i < 7; i++ {
for j := 0; j < 3; j++ {
pos := cp.Vector{X: float64(i) * width, Y: float64(j) * height}

typ := rand.Intn(3)
if typ == 0 {
// AddBox(space, pos, mass, width, height)
} else if typ == 1 {
// AddSegment(space, pos, mass, width, height)
} else {
a := AddCircle(sim, space, pos.Add(cp.Vector{X: 0, Y: (height - width) / 2}), mass, width/2)
b := AddCircle(sim, space, pos.Add(cp.Vector{X: 0, Y: (width - height) / 2}), mass, width/2)
oList = append(oList, a, b)

}
}
}

for {
time.Sleep(time.Millisecond)
space.Step(.010)

for _, o := range oList {
b := o.physicsShape.Body()
p := b.Position()
o.sprite.Pos(p.X, p.Y)
o.sprite.Angle(180.0 / math.Pi * b.Angle())

}
}

}

func createCircleImage(radius float64, c color.Color) image.Image {
dc := gg.NewContext(int(radius*3), int(radius*3))
dc.DrawCircle(radius*1.5, radius*1.5, radius)
dc.SetColor(c)
dc.Fill()
dc.SetColor(tools.White)
dc.SetLineWidth(3)
dc.DrawLine(radius*1.5, radius*1.5, radius*2.0, radius*1.5)
dc.Stroke()

return dc.Image()
}

func createRectangleImage(width, height float64, c color.Color) image.Image {
dc := gg.NewContext(int(width), int(height))
dc.DrawRectangle(0, 0, width, height)
dc.SetColor(c)
dc.Fill()
return dc.Image()
}

// func createContainer(sim models.Scratch, space *cp.Space) []*object {
// container := space.AddBody(cp.NewKinematicBody())
// container.SetAngularVelocity(0.4)
// container.SetPosition(cp.Vector{X: 0, Y: 0})

// container
// shape := space.AddShape(circle.Shape)

// a := cp.Vector{X: -200, Y: -200}
// b := cp.Vector{X: -200, Y: 200}
// c := cp.Vector{X: 200, Y: 200}
// d := cp.Vector{X: 200, Y: -200}

// AddWall(space, container, a, b, 1)
// AddWall(space, container, b, c, 1)
// AddWall(space, container, c, d, 1)
// AddWall(space, container, d, a, 1)

// ret := &object{
// sprite: sprite,
// physicsShape: shape,
// }

// return ret
// }

func AddWall(space *cp.Space, body *cp.Body, a, b cp.Vector, radius float64) {
// swap so we always draw the same direction horizontally
if a.X < b.X {
a, b = b, a
}

seg := cp.NewSegment(body, a, b, radius).Class.(*cp.Segment)
shape := space.AddShape(seg.Shape)
shape.SetElasticity(1)
shape.SetFriction(1)

}

func AddSegment(space *cp.Space, pos cp.Vector, mass, width, height float64) *cp.Shape {
body := space.AddBody(cp.NewBody(mass, cp.MomentForBox(mass, width, height)))
body.SetPosition(pos)

a, b := cp.Vector{X: 0, Y: (height - width) / 2.0}, cp.Vector{X: 0, Y: (width - height) / 2.0}
seg := cp.NewSegment(body, a, b, width/2.0).Class.(*cp.Segment)
shape := space.AddShape(seg.Shape)
shape.SetElasticity(0)
shape.SetFriction(0.7)

return shape
}

func AddBox(sim models.Scratch, space *cp.Space, pos cp.Vector, mass, width, height float64) *object {
body := space.AddBody(cp.NewBody(mass, cp.MomentForBox(mass, width, height)))
body.SetPosition(pos)

shape := space.AddShape(cp.NewBox(body, width, height, 0))
shape.SetElasticity(0)
shape.SetFriction(0.7)

c := color.RGBA{R: uint8(rand.Intn(256)), G: uint8(rand.Intn(256)), B: uint8(rand.Intn(256)), A: 0xFF}
costumeName := fmt.Sprintf("%X", rand.Uint64())
sim.AddCostume(createRectangleImage(width, height, c), costumeName)
sprite := sim.AddSprite("")
sprite.Costume(costumeName)
sprite.Pos(pos.X, pos.Y)
sprite.Visible(true)

ret := &object{
sprite: sprite,
physicsShape: shape,
}
return ret
}

func AddCircle(sim models.Scratch, space *cp.Space, pos cp.Vector, mass, radius float64) *object {
body := space.AddBody(cp.NewBody(mass, cp.MomentForCircle(mass, 0, radius, cp.Vector{})))
body.SetPosition(pos)

circle := cp.NewCircle(body, radius, cp.Vector{}).Class.(*cp.Circle)
shape := space.AddShape(circle.Shape)
shape.SetElasticity(0)
shape.SetFriction(0.7)

c := color.RGBA{R: uint8(rand.Intn(256)), G: uint8(rand.Intn(256)), B: uint8(rand.Intn(256)), A: 0xFF}
costumeName := fmt.Sprintf("%X", rand.Uint64())
sim.AddCostume(createCircleImage(radius, c), costumeName)
sprite := sim.AddSprite("")
sprite.Costume(costumeName)
sprite.Pos(pos.X, pos.Y)
sprite.Visible(true)

ret := &object{
sprite: sprite,
physicsShape: shape,
}
return ret
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/fogleman/gg v1.3.0
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/hajimehoshi/ebiten/v2 v2.6.3
github.com/jakecoffman/cp v1.2.1
github.com/stretchr/testify v1.8.4
golang.org/x/image v0.14.0
)
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ github.com/hajimehoshi/ebiten/v2 v2.6.3/go.mod h1:TZtorL713an00UW4LyvMeKD8uXWnuI
github.com/hajimehoshi/go-mp3 v0.3.4 h1:NUP7pBYH8OguP4diaTZ9wJbUbk3tC0KlfzsEpWmYj68=
github.com/hajimehoshi/go-mp3 v0.3.4/go.mod h1:fRtZraRFcWb0pu7ok0LqyFhCUrPeMsGRSVop0eemFmo=
github.com/hajimehoshi/oto/v2 v2.3.1/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo=
github.com/jakecoffman/cp v1.2.1 h1:zkhc2Gpo9l4NLUZfeG3j33+3bQD7MkqPa+n5PdX+5mI=
github.com/jakecoffman/cp v1.2.1/go.mod h1:JjY/Fp6d8E1CHnu74gWNnU0+b9VzEdUVPoJxg2PsTQg=
github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk=
github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
github.com/jfreymuth/oggvorbis v1.0.5 h1:u+Ck+R0eLSRhgq8WTmffYnrVtSztJcYrl588DM4e3kQ=
Expand Down

0 comments on commit a064744

Please sign in to comment.