Skip to content

Instantly share code, notes, and snippets.

@peterhellberg
Last active October 23, 2018 15:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peterhellberg/c8b61e9efc73c2c9eeae26c7cef207e8 to your computer and use it in GitHub Desktop.
Save peterhellberg/c8b61e9efc73c2c9eeae26c7cef207e8 to your computer and use it in GitHub Desktop.
Resolv example rendered by Ebiten
package main
import (
"fmt"
"image"
"image/color"
"image/draw"
"math/rand"
"github.com/SolarLune/resolv/resolv"
"github.com/hajimehoshi/ebiten"
)
const width, height, scale = 320, 240, 2.0
const cell int32 = 4
var bg = &image.Uniform{color.RGBA{20, 30, 40, 255}}
var world = World{Buffer: image.NewNRGBA(image.Rect(0, 0, width, height))}
func main() {
world.Create()
ebiten.Run(func(screen *ebiten.Image) error {
if ebiten.IsRunningSlowly() {
return nil
}
world.Update()
world.Draw()
ebiten.SetWindowTitle(fmt.Sprintf("Resolv - FPS: %.0f", ebiten.CurrentFPS()))
return screen.ReplacePixels(world.Buffer.Pix)
}, width, height, scale, "")
}
type World struct {
Buffer *image.NRGBA
squares []*Bouncer
space resolv.Space
}
func (w *World) Create() {
wc, hc := width/cell, height/cell
w.squares = make([]*Bouncer, 0)
w.space = resolv.NewSpace()
w.space.AddShape(
resolv.NewRectangle(0, 0, width, cell),
resolv.NewRectangle(0, cell, cell, height-cell),
resolv.NewRectangle(width-cell, cell, cell, height-cell),
resolv.NewRectangle(cell, height-cell, width-(cell*2), cell),
)
for i := 0; i < 10; i++ {
w.space.AddShape(
resolv.NewRectangle(
cell+(rand.Int31n(wc-2)*cell),
cell+(rand.Int31n(hc-2)*cell),
cell*(1+rand.Int31n(16)), cell*(1+rand.Int31n(16)),
),
)
}
for _, shape := range w.space {
shape.SetTags("solid")
}
w.NewBouncer()
}
func (w *World) Update() {
solids := w.space.FilterByTags("solid")
for _, b := range w.squares {
b.SpeedY += 0.25
b.BounceFrame *= .9
if b.SpeedY > float32(cell) {
b.SpeedY = float32(cell)
} else if b.SpeedY < -float32(cell) {
b.SpeedY = -float32(cell)
}
if b.SpeedX > float32(cell) {
b.SpeedX = float32(cell)
} else if b.SpeedX < -float32(cell) {
b.SpeedX = -float32(cell)
}
if res := solids.Resolve(b.Rect, int32(b.SpeedX), 0); res.Colliding() && !res.Teleporting {
b.Rect.X += res.ResolveX
b.SpeedX *= -1
b.BounceFrame = 1
} else {
b.Rect.X += int32(b.SpeedX)
}
if res := solids.Resolve(b.Rect, 0, int32(b.SpeedY)); res.Colliding() && !res.Teleporting {
b.Rect.Y += res.ResolveY
b.SpeedY *= -1
b.BounceFrame = 1
} else {
b.Rect.Y += int32(b.SpeedY)
}
}
if ebiten.IsKeyPressed(ebiten.KeyR) {
w.Create()
}
if ebiten.IsKeyPressed(ebiten.KeyUp) {
w.NewBouncer()
fmt.Println(len(w.squares), "bouncers in the world now.")
}
if ebiten.IsKeyPressed(ebiten.KeyDown) {
bouncers := w.space.FilterByTags("bouncer")
if len(bouncers) > 0 {
w.space.RemoveShape(bouncers[0])
for i, b := range w.squares {
if b.Rect == bouncers[0] {
w.squares[i] = nil
w.squares = append(w.squares[:i], w.squares[i+1:]...)
}
}
fmt.Println(len(w.squares), "bouncers in the world now.")
}
}
}
func (w World) Draw() {
draw.Draw(w.Buffer, w.Buffer.Bounds(), bg, image.ZP, draw.Src)
for _, shape := range w.space {
if rect := shape.(*resolv.Rectangle); !rect.HasTags("bouncer") {
drawRect(w.Buffer, rect, color.White)
}
}
for _, s := range w.squares {
g := uint8(60) + uint8((255-60)*s.BounceFrame)
drawRect(w.Buffer, s.Rect, color.RGBA{60, g, 255, 255})
}
}
type Bouncer struct {
Rect *resolv.Rectangle
SpeedX float32
SpeedY float32
BounceFrame float32
}
func (w *World) NewBouncer() *Bouncer {
bouncer := &Bouncer{
Rect: resolv.NewRectangle(
cell*2+rand.Int31n(width-cell*4),
cell*2+rand.Int31n(height-cell*4),
cell, cell,
),
SpeedX: (0.5 - rand.Float32()) * 8,
SpeedY: (0.5 - rand.Float32()) * 8}
for i := 0; i < 100; i++ {
if w.space.IsColliding(bouncer.Rect) {
bouncer.Rect.X = cell*2 + rand.Int31n(width-cell*4)
bouncer.Rect.Y = cell*2 + rand.Int31n(height-cell*4)
}
}
bouncer.Rect.SetTags("bouncer", "solid")
w.squares = append(w.squares, bouncer)
w.space.AddShape(bouncer.Rect)
return bouncer
}
func drawRect(m *image.NRGBA, r *resolv.Rectangle, c color.Color) {
for x := r.X; x <= r.X+r.W; x++ {
m.Set(int(x), int(r.Y), c)
m.Set(int(x), int(r.Y+r.H), c)
}
for y := r.Y; y <= r.Y+r.H; y++ {
m.Set(int(r.X), int(y), c)
m.Set(int(r.X+r.W), int(y), c)
}
}
@peterhellberg
Copy link
Author

peterhellberg commented Oct 1, 2018

https://jsgo.io/9e575f464c9bdc76db833f4160b646dc007d25f6

⬆️ to add bouncers
⬇️ to remove
R to restart

@peterhellberg
Copy link
Author

peterhellberg commented Oct 1, 2018

resolv-example

@peterhellberg
Copy link
Author

@steelx
Copy link

steelx commented Oct 23, 2018

Thanks.
I got it working by updating line no. 49 to w.space = resolv.Space{}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment