doodle/render/point.go
Noah Petherbridge e25869644c Fix Play Mode, Level Handover & Collision Detection
* Edit Mode now uses the Level object itself to keep the drawing data
  rather than pull its Palette and Chunks out, so it can hang on to more
  information. The Canvas widget is given references to the
  Level.Palette and Level.Chunker via Canvas.LoadLevel()
* Fix the handoff between Edit Mode and Play Mode. They pass the Level
  object back and forth and the Filename, because it's not part of the
  Level. You can save the map with its original settings after returning
  from Play Mode.
* Fix the collision detection in Play Mode. It broke previously when
  palettes were added because of the difference between a render.Point
  and a level.Pixel and it couldn't easily look up coordinates. The new
  Chunker system provides a render.Point lookup API.
* All pixels are solid for collision right now, TODO is to return Swatch
  information from the pixels touching the player character and react
  accordingly (non-solid, fire flag, etc.)
* Remove the level.Grid type as it has been replaced by the Chunker.
* Clean up some unused variables and functions.
2018-09-25 09:40:34 -07:00

100 lines
2.0 KiB
Go

package render
import (
"fmt"
"strconv"
"strings"
)
// Point holds an X,Y coordinate value.
type Point struct {
X int32
Y int32
}
// Common points.
var (
Origin Point
)
// NewPoint makes a new Point at an X,Y coordinate.
func NewPoint(x, y int32) Point {
return Point{
X: x,
Y: y,
}
}
func (p Point) String() string {
return fmt.Sprintf("%d,%d", p.X, p.Y)
}
// ParsePoint to parse a point from its string representation.
func ParsePoint(v string) (Point, error) {
halves := strings.Split(v, ",")
if len(halves) != 2 {
return Point{}, fmt.Errorf("'%s': not a valid coordinate string", v)
}
x, errX := strconv.Atoi(halves[0])
y, errY := strconv.Atoi(halves[1])
if errX != nil || errY != nil {
return Point{}, fmt.Errorf("invalid coordinate string (X: %v; Y: %v)",
errX,
errY,
)
}
return Point{
X: int32(x),
Y: int32(y),
}, nil
}
// IsZero returns if the point is the zero value.
func (p Point) IsZero() bool {
return p.X == 0 && p.Y == 0
}
// Inside returns whether the Point falls inside the rect.
func (p Point) Inside(r Rect) bool {
var (
x1 = r.X
y1 = r.Y
x2 = r.X + r.W
y2 = r.Y + r.H
)
return p.X >= x1 && p.X <= x2 && p.Y >= y1 && p.Y <= y2
}
// Add (or subtract) the other point to your current point.
func (p *Point) Add(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
// as a map key and serialized to JSON.
func (p *Point) MarshalText() ([]byte, error) {
return []byte(fmt.Sprintf("%d,%d", p.X, p.Y)), nil
}
// UnmarshalText to restore it from text.
func (p *Point) UnmarshalText(b []byte) error {
halves := strings.Split(strings.Trim(string(b), `"`), ",")
if len(halves) != 2 {
return fmt.Errorf("'%s': not a valid coordinate string", b)
}
x, errX := strconv.Atoi(halves[0])
y, errY := strconv.Atoi(halves[1])
if errX != nil || errY != nil {
return fmt.Errorf("Point.UnmarshalJSON: Atoi errors (X=%s Y=%s)",
errX,
errY,
)
}
p.X = int32(x)
p.Y = int32(y)
return nil
}