This repository has been archived by the owner on May 31, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f696d5b
commit a064744
Showing
3 changed files
with
206 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}) | ||
|
||
a := cp.Vector{-200, -200} | ||
b := cp.Vector{-200, 200} | ||
c := cp.Vector{200, 200} | ||
d := cp.Vector{200, -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) | ||
|
||
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters