Refactor grid to use level.Pixel and clean up collision between Edit and Play

This commit is contained in:
Noah 2018-07-24 17:44:32 -07:00
parent e141203c4b
commit c3fd2e63cb
5 changed files with 47 additions and 103 deletions

View File

@ -1,6 +1,7 @@
package doodads package doodads
import ( import (
"git.kirsle.net/apps/doodle/level"
"git.kirsle.net/apps/doodle/render" "git.kirsle.net/apps/doodle/render"
) )
@ -57,7 +58,7 @@ func CollidesWithGrid(d Doodad, grid *render.Grid) (Collide, bool) {
// Bottom edge. // Bottom edge.
for point := range render.IterLine2(bottomLeft, bottomRight) { for point := range render.IterLine2(bottomLeft, bottomRight) {
if grid.Exists(render.Pixel{ if grid.Exists(level.Pixel{
X: point.X, X: point.X,
Y: point.Y, Y: point.Y,
}) { }) {
@ -71,7 +72,7 @@ func CollidesWithGrid(d Doodad, grid *render.Grid) (Collide, bool) {
// Top edge. // Top edge.
for point := range render.IterLine2(topLeft, topRight) { for point := range render.IterLine2(topLeft, topRight) {
if grid.Exists(render.Pixel{ if grid.Exists(level.Pixel{
X: point.X, X: point.X,
Y: point.Y, Y: point.Y,
}) { }) {
@ -84,7 +85,7 @@ func CollidesWithGrid(d Doodad, grid *render.Grid) (Collide, bool) {
} }
for point := range render.IterLine2(topLeft, bottomLeft) { for point := range render.IterLine2(topLeft, bottomLeft) {
if grid.Exists(render.Pixel{ if grid.Exists(level.Pixel{
X: point.X, X: point.X,
Y: point.Y, Y: point.Y,
}) { }) {
@ -97,7 +98,7 @@ func CollidesWithGrid(d Doodad, grid *render.Grid) (Collide, bool) {
} }
for point := range render.IterLine2(topRight, bottomRight) { for point := range render.IterLine2(topRight, bottomRight) {
if grid.Exists(render.Pixel{ if grid.Exists(level.Pixel{
X: point.X, X: point.X,
Y: point.Y, Y: point.Y,
}) { }) {

View File

@ -8,7 +8,6 @@ import (
"os" "os"
"time" "time"
"git.kirsle.net/apps/doodle/draw"
"git.kirsle.net/apps/doodle/events" "git.kirsle.net/apps/doodle/events"
"git.kirsle.net/apps/doodle/level" "git.kirsle.net/apps/doodle/level"
"git.kirsle.net/apps/doodle/render" "git.kirsle.net/apps/doodle/render"
@ -22,7 +21,8 @@ type EditorScene struct {
Canvas render.Grid Canvas render.Grid
// History of all the pixels placed by the user. // History of all the pixels placed by the user.
pixelHistory []render.Pixel pixelHistory []level.Pixel
lastPixel *level.Pixel // last pixel placed while mouse down and dragging
canvas render.Grid canvas render.Grid
filename string // Last saved filename. filename string // Last saved filename.
@ -59,7 +59,7 @@ func (s *EditorScene) Setup(d *Doodle) error {
d.Flash("Editor Mode. Press 'P' to play this map.") d.Flash("Editor Mode. Press 'P' to play this map.")
if s.pixelHistory == nil { if s.pixelHistory == nil {
s.pixelHistory = []render.Pixel{} s.pixelHistory = []level.Pixel{}
} }
if s.canvas == nil { if s.canvas == nil {
log.Debug("EditorScene: Setting default canvas to an empty grid") log.Debug("EditorScene: Setting default canvas to an empty grid")
@ -92,33 +92,37 @@ func (s *EditorScene) Loop(d *Doodle, ev *events.State) error {
// Clicking? Log all the pixels while doing so. // Clicking? Log all the pixels while doing so.
if ev.Button1.Now { if ev.Button1.Now {
log.Warn("Button1: %+v", ev.Button1) // log.Warn("Button1: %+v", ev.Button1)
pixel := render.Pixel{ lastPixel := s.lastPixel
Start: ev.Button1.Pressed(), pixel := level.Pixel{
X: ev.CursorX.Now, X: ev.CursorX.Now,
Y: ev.CursorY.Now, Y: ev.CursorY.Now,
DX: ev.CursorX.Last,
DY: ev.CursorY.Last,
}
if pixel.Start {
log.Warn("START PIXEL %+v", pixel)
} }
// Append unique new pixels. // Append unique new pixels.
if len(s.pixelHistory) == 0 || s.pixelHistory[len(s.pixelHistory)-1] != pixel { if len(s.pixelHistory) == 0 || s.pixelHistory[len(s.pixelHistory)-1] != pixel {
// If not a start pixel, make the delta coord the previous one. if lastPixel != nil {
if !pixel.Start && len(s.pixelHistory) > 0 { // Draw the pixels in between.
prev := s.pixelHistory[len(s.pixelHistory)-1] if *lastPixel != pixel {
pixel.DY = prev.Y for point := range render.IterLine(lastPixel.X, lastPixel.Y, pixel.X, pixel.Y) {
pixel.DX = prev.X dot := level.Pixel{
X: point.X,
Y: point.Y,
Palette: lastPixel.Palette,
}
s.canvas[dot] = nil
}
}
} }
s.lastPixel = &pixel
s.pixelHistory = append(s.pixelHistory, pixel) s.pixelHistory = append(s.pixelHistory, pixel)
// Save in the pixel canvas map. // Save in the pixel canvas map.
fmt.Printf("%+v", pixel)
s.canvas[pixel] = nil s.canvas[pixel] = nil
} }
} else {
s.lastPixel = nil
} }
return nil return nil
@ -126,25 +130,6 @@ func (s *EditorScene) Loop(d *Doodle, ev *events.State) error {
// Draw the current frame. // Draw the current frame.
func (s *EditorScene) Draw(d *Doodle) error { func (s *EditorScene) Draw(d *Doodle) error {
// for i, pixel := range s.pixelHistory {
// if !pixel.Start && i > 0 {
// prev := s.pixelHistory[i-1]
// if prev.X == pixel.X && prev.Y == pixel.Y {
// d.Engine.DrawPoint(
// render.Black,
// render.Point{pixel.X, pixel.Y},
// )
// } else {
// d.Engine.DrawLine(
// render.Black,
// render.Point{pixel.X, pixel.Y},
// render.Point{prev.X, prev.Y},
// )
// }
// }
// d.Engine.DrawPoint(render.Black, render.Point{pixel.X, pixel.Y})
// }
s.canvas.Draw(d.Engine) s.canvas.Draw(d.Engine)
return nil return nil
@ -153,7 +138,7 @@ func (s *EditorScene) Draw(d *Doodle) error {
// LoadLevel loads a level from disk. // LoadLevel loads a level from disk.
func (s *EditorScene) LoadLevel(filename string) error { func (s *EditorScene) LoadLevel(filename string) error {
s.filename = filename s.filename = filename
s.pixelHistory = []render.Pixel{} s.pixelHistory = []level.Pixel{}
s.canvas = render.Grid{} s.canvas = render.Grid{}
m, err := level.LoadJSON(filename) m, err := level.LoadJSON(filename)
@ -162,12 +147,9 @@ func (s *EditorScene) LoadLevel(filename string) error {
} }
for _, point := range m.Pixels { for _, point := range m.Pixels {
pixel := render.Pixel{ pixel := level.Pixel{
Start: true,
X: point.X, X: point.X,
Y: point.Y, Y: point.Y,
DX: point.X,
DY: point.Y,
} }
s.pixelHistory = append(s.pixelHistory, pixel) s.pixelHistory = append(s.pixelHistory, pixel)
s.canvas[pixel] = nil s.canvas[pixel] = nil
@ -195,21 +177,11 @@ func (s *EditorScene) SaveLevel(filename string) {
} }
for pixel := range s.canvas { for pixel := range s.canvas {
if pixel.DX == 0 && pixel.DY == 0 {
m.Pixels = append(m.Pixels, level.Pixel{ m.Pixels = append(m.Pixels, level.Pixel{
X: pixel.X, X: pixel.X,
Y: pixel.Y, Y: pixel.Y,
Palette: 0, Palette: 0,
}) })
} else {
for point := range render.IterLine(pixel.X, pixel.Y, pixel.DX, pixel.DY) {
m.Pixels = append(m.Pixels, level.Pixel{
X: point.X,
Y: point.Y,
Palette: 0,
})
}
}
} }
json, err := m.ToJSON() json, err := m.ToJSON()
@ -238,14 +210,7 @@ func (s *EditorScene) Screenshot() {
// Fill in the dots we drew. // Fill in the dots we drew.
for pixel := range s.canvas { for pixel := range s.canvas {
// A line or a dot?
if pixel.DX == 0 && pixel.DY == 0 {
screenshot.Set(int(pixel.X), int(pixel.Y), image.Black) screenshot.Set(int(pixel.X), int(pixel.Y), image.Black)
} else {
for point := range draw.Line(pixel.X, pixel.Y, pixel.DX, pixel.DY) {
screenshot.Set(int(point.X), int(point.Y), image.Black)
}
}
} }
// Create the screenshot directory. // Create the screenshot directory.

View File

@ -131,7 +131,7 @@ func (s *PlayScene) LoadLevel(filename string) error {
} }
for _, point := range m.Pixels { for _, point := range m.Pixels {
pixel := render.Pixel{ pixel := level.Pixel{
X: point.X, X: point.X,
Y: point.Y, Y: point.Y,
} }

View File

@ -1,31 +1,14 @@
package render package render
import ( import (
"fmt" "git.kirsle.net/apps/doodle/level"
) )
// Pixel TODO: not a global
// TODO get rid of this ugly thing.
type Pixel struct {
Start bool
X int32
Y int32
DX int32
DY int32
}
func (p Pixel) String() string {
return fmt.Sprintf("(%d,%d) delta (%d,%d)",
p.X, p.Y,
p.DX, p.DY,
)
}
// Grid is a 2D grid of pixels in X,Y notation. // Grid is a 2D grid of pixels in X,Y notation.
type Grid map[Pixel]interface{} type Grid map[level.Pixel]interface{}
// Exists returns true if the point exists on the grid. // Exists returns true if the point exists on the grid.
func (g *Grid) Exists(p Pixel) bool { func (g *Grid) Exists(p level.Pixel) bool {
if _, ok := (*g)[p]; ok { if _, ok := (*g)[p]; ok {
return true return true
} }
@ -35,15 +18,9 @@ func (g *Grid) Exists(p Pixel) bool {
// Draw the grid efficiently. // Draw the grid efficiently.
func (g *Grid) Draw(e Engine) { func (g *Grid) Draw(e Engine) {
for pixel := range *g { for pixel := range *g {
if pixel.DX == 0 && pixel.DY == 0 {
e.DrawPoint(Black, Point{ e.DrawPoint(Black, Point{
X: pixel.X, X: pixel.X,
Y: pixel.Y, Y: pixel.Y,
}) })
} else {
for point := range IterLine(pixel.X, pixel.Y, pixel.DX, pixel.DY) {
e.DrawPoint(Black, point)
}
}
} }
} }

View File

@ -141,6 +141,7 @@ func IterLine(x1, y1, x2, y2 int32) chan Point {
return generator return generator
} }
// IterLine2 works with two Points rather than four coordinates.
func IterLine2(p1 Point, p2 Point) chan Point { func IterLine2(p1 Point, p2 Point) chan Point {
return IterLine(p1.X, p1.Y, p2.X, p2.Y) return IterLine(p1.X, p1.Y, p2.X, p2.Y)
} }