Colliding Doodads #1
BIN
assets/wallpapers/test-128x128.png
Normal file
BIN
assets/wallpapers/test-128x128.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 375 B |
|
@ -16,11 +16,11 @@ var (
|
||||||
***************/
|
***************/
|
||||||
|
|
||||||
// Debug overlay (FPS etc.) settings.
|
// Debug overlay (FPS etc.) settings.
|
||||||
DebugFontFilename = "./fonts/DejaVuSans-Bold.ttf"
|
DebugFontFilename = "./fonts/DejaVuSans.ttf"
|
||||||
DebugFontSize = 15
|
DebugFontSize = 16
|
||||||
DebugLabelColor = render.MustHexColor("#FF9900")
|
DebugLabelColor = render.MustHexColor("#FF9900")
|
||||||
DebugValueColor = render.MustHexColor("#00CCFF")
|
DebugValueColor = render.MustHexColor("#00CCFF")
|
||||||
DebugStrokeDarken int32 = 80
|
DebugStrokeDarken = 80
|
||||||
|
|
||||||
// Background color to use when exporting a drawing Chunk as a bitmap image
|
// Background color to use when exporting a drawing Chunk as a bitmap image
|
||||||
// on disk. Default is white. Setting this to translucent yellow is a great
|
// on disk. Default is white. Setting this to translucent yellow is a great
|
||||||
|
|
|
@ -15,8 +15,9 @@ var (
|
||||||
ScrollMaxVelocity = 24
|
ScrollMaxVelocity = 24
|
||||||
|
|
||||||
// Player speeds
|
// Player speeds
|
||||||
PlayerMaxVelocity = 12
|
PlayerMaxVelocity = 12
|
||||||
Gravity = 2
|
PlayerAcceleration = 2 // pixels / second / second
|
||||||
|
Gravity = 2
|
||||||
|
|
||||||
// Default chunk size for canvases.
|
// Default chunk size for canvases.
|
||||||
ChunkSize = 128
|
ChunkSize = 128
|
||||||
|
|
11
commands.go
11
commands.go
|
@ -22,6 +22,17 @@ func (c Command) Run(d *Doodle) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cheats :P
|
||||||
|
if c.Raw == "unleash the beast" {
|
||||||
|
if fpsDoNotCap {
|
||||||
|
d.Flash("Reset frame rate throttle to factory default %d FPS", TargetFPS)
|
||||||
|
} else {
|
||||||
|
d.Flash("Unleashing as many frames as we can render!")
|
||||||
|
}
|
||||||
|
fpsDoNotCap = !fpsDoNotCap
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
switch c.Command {
|
switch c.Command {
|
||||||
case "echo":
|
case "echo":
|
||||||
d.Flash(c.ArgsLiteral)
|
d.Flash(c.ArgsLiteral)
|
||||||
|
|
|
@ -14,6 +14,8 @@ type Actor interface {
|
||||||
Position() render.Point
|
Position() render.Point
|
||||||
Velocity() render.Point
|
Velocity() render.Point
|
||||||
SetVelocity(render.Point)
|
SetVelocity(render.Point)
|
||||||
|
Acceleration() int
|
||||||
|
SetAcceleration(int)
|
||||||
Size() render.Rect
|
Size() render.Rect
|
||||||
Grounded() bool
|
Grounded() bool
|
||||||
SetGrounded(bool)
|
SetGrounded(bool)
|
||||||
|
|
|
@ -96,8 +96,15 @@ const (
|
||||||
Right
|
Right
|
||||||
)
|
)
|
||||||
|
|
||||||
// CollidesWithGrid checks if a Doodad collides with level geometry.
|
/*
|
||||||
func CollidesWithGrid(d Actor, grid *level.Chunker, target render.Point) (*Collide, bool) {
|
CollidesWithGrid checks if a Doodad collides with level geometry.
|
||||||
|
|
||||||
|
The `target` is the point the actor wants to move to this tick.
|
||||||
|
|
||||||
|
The `scroll` is the scroll offset of the canvas that is viewing the grid, so
|
||||||
|
that collision geometry can be offset properly on screen.
|
||||||
|
*/
|
||||||
|
func CollidesWithGrid(d Actor, grid *level.Chunker, target render.Point, scroll render.Point) (*Collide, bool) {
|
||||||
var (
|
var (
|
||||||
P = d.Position()
|
P = d.Position()
|
||||||
S = d.Size()
|
S = d.Size()
|
||||||
|
@ -109,14 +116,14 @@ func CollidesWithGrid(d Actor, grid *level.Chunker, target render.Point) (*Colli
|
||||||
capHeight int32 // Stop vertical movement thru a ceiling
|
capHeight int32 // Stop vertical movement thru a ceiling
|
||||||
capLeft int32 // Stop movement thru a wall
|
capLeft int32 // Stop movement thru a wall
|
||||||
capRight int32
|
capRight int32
|
||||||
hitLeft bool // Has hit an obstacle on the left
|
capFloor int32 // Stop movement thru the floor
|
||||||
hitRight bool // or right
|
hitLeft bool // Has hit an obstacle on the left
|
||||||
hitFloor bool
|
hitRight bool // or right
|
||||||
capFloor int32
|
hitFloor bool // or floor
|
||||||
)
|
)
|
||||||
|
|
||||||
// Test all of the bounding boxes for a collision with level geometry.
|
// Test all of the bounding boxes for a collision with level geometry.
|
||||||
if ok := result.ScanBoundingBox(GetBoundingRect(d), grid); ok {
|
if ok := result.ScanBoundingBox(GetBoundingRect(d).SubtractPoint(scroll), grid); ok {
|
||||||
// We've already collided! Try to wiggle free.
|
// We've already collided! Try to wiggle free.
|
||||||
if result.Bottom {
|
if result.Bottom {
|
||||||
if !d.Grounded() {
|
if !d.Grounded() {
|
||||||
|
@ -190,7 +197,7 @@ func CollidesWithGrid(d Actor, grid *level.Chunker, target render.Point) (*Colli
|
||||||
Y: point.Y,
|
Y: point.Y,
|
||||||
W: S.W,
|
W: S.W,
|
||||||
H: S.H,
|
H: S.H,
|
||||||
}, grid); has {
|
}.SubtractPoint(scroll), grid); has {
|
||||||
if result.Bottom {
|
if result.Bottom {
|
||||||
if !hitFloor {
|
if !hitFloor {
|
||||||
hitFloor = true
|
hitFloor = true
|
||||||
|
|
|
@ -12,6 +12,7 @@ type Drawing struct {
|
||||||
id string
|
id string
|
||||||
point render.Point
|
point render.Point
|
||||||
velocity render.Point
|
velocity render.Point
|
||||||
|
accel int
|
||||||
size render.Rect
|
size render.Rect
|
||||||
grounded bool
|
grounded bool
|
||||||
}
|
}
|
||||||
|
@ -49,6 +50,16 @@ func (d *Drawing) SetVelocity(v render.Point) {
|
||||||
d.velocity = v
|
d.velocity = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Acceleration returns the Drawing's acceleration.
|
||||||
|
func (d *Drawing) Acceleration() int {
|
||||||
|
return d.accel
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAcceleration to set the acceleration.
|
||||||
|
func (d *Drawing) SetAcceleration(v int) {
|
||||||
|
d.accel = v
|
||||||
|
}
|
||||||
|
|
||||||
// Size returns the Drawing's size.
|
// Size returns the Drawing's size.
|
||||||
func (d *Drawing) Size() render.Rect {
|
func (d *Drawing) Size() render.Rect {
|
||||||
return d.size
|
return d.size
|
||||||
|
|
14
doodle.go
14
doodle.go
|
@ -15,7 +15,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Version number.
|
// Version number.
|
||||||
Version = "0.0.1-alpha"
|
Version = "0.0.7-alpha"
|
||||||
|
|
||||||
// TargetFPS is the frame rate to cap the game to.
|
// TargetFPS is the frame rate to cap the game to.
|
||||||
TargetFPS = 1000 / 60 // 60 FPS
|
TargetFPS = 1000 / 60 // 60 FPS
|
||||||
|
@ -148,13 +148,15 @@ func (d *Doodle) Run() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delay to maintain the target frames per second.
|
// Delay to maintain the target frames per second.
|
||||||
elapsed := time.Now().Sub(start)
|
|
||||||
tmp := elapsed / time.Millisecond
|
|
||||||
var delay uint32
|
var delay uint32
|
||||||
if TargetFPS-int(tmp) > 0 { // make sure it won't roll under
|
if !fpsDoNotCap {
|
||||||
delay = uint32(TargetFPS - int(tmp))
|
elapsed := time.Now().Sub(start)
|
||||||
|
tmp := elapsed / time.Millisecond
|
||||||
|
if TargetFPS-int(tmp) > 0 { // make sure it won't roll under
|
||||||
|
delay = uint32(TargetFPS - int(tmp))
|
||||||
|
}
|
||||||
|
d.Engine.Delay(delay)
|
||||||
}
|
}
|
||||||
d.Engine.Delay(delay)
|
|
||||||
|
|
||||||
// Track how long this frame took to measure FPS over time.
|
// Track how long this frame took to measure FPS over time.
|
||||||
d.TrackFPS(delay)
|
d.TrackFPS(delay)
|
||||||
|
|
10
fps.go
10
fps.go
|
@ -33,6 +33,7 @@ var (
|
||||||
fpsFrames int
|
fpsFrames int
|
||||||
fpsSkipped uint32
|
fpsSkipped uint32
|
||||||
fpsInterval uint32 = 1000
|
fpsInterval uint32 = 1000
|
||||||
|
fpsDoNotCap bool // remove the FPS delay cap in Main Loop
|
||||||
|
|
||||||
// Custom labels for scenes to add to the debug overlay view.
|
// Custom labels for scenes to add to the debug overlay view.
|
||||||
customDebugLabels []debugLabel
|
customDebugLabels []debugLabel
|
||||||
|
@ -49,17 +50,22 @@ func (d *Doodle) DrawDebugOverlay() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var framesSkipped = fmt.Sprintf("(skip: %dms)", fpsSkipped)
|
||||||
|
if fpsDoNotCap {
|
||||||
|
framesSkipped = "uncapped"
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
darken = balance.DebugStrokeDarken
|
darken = balance.DebugStrokeDarken
|
||||||
Yoffset int32 = 20 // leave room for the menu bar
|
Yoffset int32 = 20 // leave room for the menu bar
|
||||||
Xoffset int32 = 5
|
Xoffset int32 = 20
|
||||||
keys = []string{
|
keys = []string{
|
||||||
"FPS:",
|
"FPS:",
|
||||||
"Scene:",
|
"Scene:",
|
||||||
"Mouse:",
|
"Mouse:",
|
||||||
}
|
}
|
||||||
values = []string{
|
values = []string{
|
||||||
fmt.Sprintf("%d (skip: %dms)", fpsCurrent, fpsSkipped),
|
fmt.Sprintf("%d %s", fpsCurrent, framesSkipped),
|
||||||
d.Scene.Name(),
|
d.Scene.Name(),
|
||||||
fmt.Sprintf("%d,%d", d.event.CursorX.Now, d.event.CursorY.Now),
|
fmt.Sprintf("%d,%d", d.event.CursorX.Now, d.event.CursorY.Now),
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestWallpaper(t *testing.T) {
|
||||||
img := image.NewRGBA(image.Rect(0, 0, width, height))
|
img := image.NewRGBA(image.Rect(0, 0, width, height))
|
||||||
draw.Draw(
|
draw.Draw(
|
||||||
// Corner: red
|
// Corner: red
|
||||||
img, // dst Image
|
img, // dst Image
|
||||||
image.Rect(0, 0, qWidth, qHeight), // r Rectangle
|
image.Rect(0, 0, qWidth, qHeight), // r Rectangle
|
||||||
image.NewUniform(red), // src Image
|
image.NewUniform(red), // src Image
|
||||||
image.Point{0, 0}, // sp Point
|
image.Point{0, 0}, // sp Point
|
||||||
|
|
|
@ -173,7 +173,7 @@ func (s *PlayScene) movePlayer(ev *events.State) {
|
||||||
// Apply gravity.
|
// Apply gravity.
|
||||||
// var onFloor bool
|
// var onFloor bool
|
||||||
|
|
||||||
info, ok := doodads.CollidesWithGrid(s.Player, s.Level.Chunker, delta)
|
info, ok := doodads.CollidesWithGrid(s.Player, s.Level.Chunker, delta, s.drawing.Scroll)
|
||||||
if ok {
|
if ok {
|
||||||
// Collision happened with world.
|
// Collision happened with world.
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,15 +156,15 @@ func (c *Color) UnmarshalJSON(b []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a relative color value to the color.
|
// Add a relative color value to the color.
|
||||||
func (c Color) Add(r, g, b, a int32) Color {
|
func (c Color) Add(r, g, b, a int) Color {
|
||||||
var (
|
var (
|
||||||
R = int32(c.Red) + r
|
R = int(c.Red) + r
|
||||||
G = int32(c.Green) + g
|
G = int(c.Green) + g
|
||||||
B = int32(c.Blue) + b
|
B = int(c.Blue) + b
|
||||||
A = int32(c.Alpha) + a
|
A = int(c.Alpha) + a
|
||||||
)
|
)
|
||||||
|
|
||||||
cap8 := func(v int32) uint8 {
|
cap8 := func(v int) uint8 {
|
||||||
if v > 255 {
|
if v > 255 {
|
||||||
v = 255
|
v = 255
|
||||||
} else if v < 0 {
|
} else if v < 0 {
|
||||||
|
@ -182,11 +182,22 @@ func (c Color) Add(r, g, b, a int32) Color {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lighten a color value.
|
// Lighten a color value.
|
||||||
func (c Color) Lighten(v int32) Color {
|
func (c Color) Lighten(v int) Color {
|
||||||
return c.Add(v, v, v, 0)
|
return c.Add(v, v, v, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Darken a color value.
|
// Darken a color value.
|
||||||
func (c Color) Darken(v int32) Color {
|
func (c Color) Darken(v int) Color {
|
||||||
return c.Add(-v, -v, -v, 0)
|
return c.Add(-v, -v, -v, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transparentize adjusts the alpha level of a color.
|
||||||
|
func (c Color) Transparentize(v int) Color {
|
||||||
|
return c.Add(0, 0, 0, int(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAlpha sets the alpha value to a specific setting.
|
||||||
|
func (c Color) SetAlpha(v uint8) Color {
|
||||||
|
c.Alpha = v
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
|
@ -125,7 +125,8 @@ func (r Rect) Add(other Rect) Rect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a point to move the rect.
|
// Add (or subtract) a point to move the rect. This is usually the method you
|
||||||
|
// want to use: negative Point values will subtract the rect's position.
|
||||||
func (r Rect) AddPoint(other Point) Rect {
|
func (r Rect) AddPoint(other Point) Rect {
|
||||||
return Rect{
|
return Rect{
|
||||||
X: r.X + other.X,
|
X: r.X + other.X,
|
||||||
|
@ -135,6 +136,17 @@ func (r Rect) AddPoint(other Point) Rect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SubtractPoint is the inverse of AddPoint. Use this only if you need to
|
||||||
|
// invert the Point being added.
|
||||||
|
func (r Rect) SubtractPoint(other Point) Rect {
|
||||||
|
return Rect{
|
||||||
|
X: r.X - other.X,
|
||||||
|
Y: r.Y - other.Y,
|
||||||
|
W: r.W,
|
||||||
|
H: r.H,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Text holds information for drawing text.
|
// Text holds information for drawing text.
|
||||||
type Text struct {
|
type Text struct {
|
||||||
Text string
|
Text string
|
||||||
|
|
|
@ -69,12 +69,21 @@ func (p Point) Inside(r Rect) bool {
|
||||||
(p.Y >= y1 && p.Y <= y2))
|
(p.Y >= y1 && p.Y <= y2))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add (or subtract) the other point to your current point.
|
// Add (or subtract) the other point to your current point. This is usually
|
||||||
|
// the one you want: if the other Point has negative values it will subtract
|
||||||
|
// them from this Point, or if they are positive it will add them.
|
||||||
func (p *Point) Add(other Point) {
|
func (p *Point) Add(other Point) {
|
||||||
p.X += other.X
|
p.X += other.X
|
||||||
p.Y += other.Y
|
p.Y += other.Y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Subtract is the inverse of Add. Use this if you want to force a subtraction
|
||||||
|
// operation (i.e. to invert a Point before adding it).
|
||||||
|
func (p *Point) Subtract(other Point) {
|
||||||
|
p.X -= other.X
|
||||||
|
p.Y -= other.Y
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalText to convert the point into text so that a render.Point may be used
|
// MarshalText to convert the point into text so that a render.Point may be used
|
||||||
// as a map key and serialized to JSON.
|
// as a map key and serialized to JSON.
|
||||||
func (p *Point) MarshalText() ([]byte, error) {
|
func (p *Point) MarshalText() ([]byte, error) {
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
package sdl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.kirsle.net/apps/doodle/level"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Frames to cache for FPS calculation.
|
|
||||||
const (
|
|
||||||
maxSamples = 100
|
|
||||||
TargetFPS = 1000 / 60
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
fpsCurrentTicks uint32 // current time we get sdl.GetTicks()
|
|
||||||
fpsLastTime uint32 // last time we printed the fpsCurrentTicks
|
|
||||||
fpsCurrent int
|
|
||||||
fpsFrames int
|
|
||||||
fpsSkipped uint32
|
|
||||||
fpsInterval uint32 = 1000
|
|
||||||
)
|
|
||||||
|
|
||||||
var pixelHistory []level.Pixel
|
|
|
@ -8,5 +8,5 @@ var (
|
||||||
ButtonHoverColor = render.RGBA(200, 255, 255, 255)
|
ButtonHoverColor = render.RGBA(200, 255, 255, 255)
|
||||||
ButtonOutlineColor = render.Black
|
ButtonOutlineColor = render.Black
|
||||||
|
|
||||||
BorderColorOffset int32 = 40
|
BorderColorOffset = 40
|
||||||
)
|
)
|
||||||
|
|
|
@ -127,7 +127,7 @@ func (w *Canvas) loopFollowActor(ev *events.State) error {
|
||||||
var (
|
var (
|
||||||
APosition = actor.Position() // relative to screen
|
APosition = actor.Position() // relative to screen
|
||||||
APoint = actor.Drawing.Position()
|
APoint = actor.Drawing.Position()
|
||||||
ASize = actor.Canvas.Size()
|
ASize = actor.Drawing.Size()
|
||||||
scrollBy render.Point
|
scrollBy render.Point
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user