Added a shatter function to subtract rectangles from a rectangle
This commit is contained in:
parent
7f1c3ae870
commit
a893831a21
@ -5,6 +5,7 @@ import "time"
|
|||||||
import "image"
|
import "image"
|
||||||
import "image/color"
|
import "image/color"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/shatter"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/defaultfont"
|
import "git.tebibyte.media/sashakoshka/tomo/defaultfont"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||||
|
|
||||||
@ -118,6 +119,30 @@ func (element *Artist) draw () {
|
|||||||
x, element.cellAt(x, 3))
|
x, element.cellAt(x, 3))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4, 3
|
||||||
|
shatterPos := element.cellAt(4, 3).Min
|
||||||
|
rocks := []image.Rectangle {
|
||||||
|
image.Rect(3, 12, 13, 23).Add(shatterPos),
|
||||||
|
// image.Rect(30, 10, 40, 23).Add(shatterPos),
|
||||||
|
image.Rect(55, 40, 70, 49).Add(shatterPos),
|
||||||
|
image.Rect(30, -10, 40, 43).Add(shatterPos),
|
||||||
|
image.Rect(80, 30, 90, 45).Add(shatterPos),
|
||||||
|
}
|
||||||
|
tiles := shatter.Shatter(element.cellAt(4, 3), rocks...)
|
||||||
|
for index, tile := range tiles {
|
||||||
|
artist.FillRectangle (
|
||||||
|
element, []artist.Pattern {
|
||||||
|
uhex(0xFF0000FF),
|
||||||
|
uhex(0x00FF00FF),
|
||||||
|
uhex(0x0000FFFF),
|
||||||
|
uhex(0xFF00FFFF),
|
||||||
|
uhex(0xFFF00FFF),
|
||||||
|
uhex(0xAAAAAAFF),
|
||||||
|
uhex(0x699669FF),
|
||||||
|
uhex(0x077777FF),
|
||||||
|
} [index % 8], tile)
|
||||||
|
}
|
||||||
|
|
||||||
// 0, 4 - 3, 4
|
// 0, 4 - 3, 4
|
||||||
for x := 0; x < 4; x ++ {
|
for x := 0; x < 4; x ++ {
|
||||||
artist.FillEllipse (
|
artist.FillEllipse (
|
||||||
|
96
shatter/shatter.go
Normal file
96
shatter/shatter.go
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package shatter
|
||||||
|
|
||||||
|
import "image"
|
||||||
|
|
||||||
|
// Shatter takes in a bounding rectangle, and several rectangles to be
|
||||||
|
// subtracted from it. It returns a slice of rectangles that tile together to
|
||||||
|
// make up the difference between them. This is intended to be used for figuring
|
||||||
|
// out which areas of a container element's background are covered by other
|
||||||
|
// elements so it doesn't waste CPU cycles drawing to those areas.
|
||||||
|
func Shatter (
|
||||||
|
glass image.Rectangle,
|
||||||
|
rocks ...image.Rectangle,
|
||||||
|
) (
|
||||||
|
tiles []image.Rectangle,
|
||||||
|
) {
|
||||||
|
// in this function, the metaphor of throwing several rocks at a sheet
|
||||||
|
// of glass is used to illustrate the concept.
|
||||||
|
|
||||||
|
tiles = []image.Rectangle { glass }
|
||||||
|
for _, rock := range rocks {
|
||||||
|
|
||||||
|
// check each tile to see if the rock has collided with it
|
||||||
|
tileLen := len(tiles)
|
||||||
|
for tileIndex := 0; tileIndex < tileLen; tileIndex ++ {
|
||||||
|
tile := tiles[tileIndex]
|
||||||
|
if !rock.Overlaps(tile) { continue }
|
||||||
|
newTiles, n := shatterOnce(tile, rock)
|
||||||
|
if n > 0 {
|
||||||
|
// the tile was shattered into one or more sub
|
||||||
|
// tiles
|
||||||
|
tiles[tileIndex] = newTiles[0]
|
||||||
|
tiles = append(tiles, newTiles[1:n]...)
|
||||||
|
} else {
|
||||||
|
// the tile was entirely obscured by the rock
|
||||||
|
// and must be wholly removed
|
||||||
|
tiles = remove(tiles, tileIndex)
|
||||||
|
tileIndex --
|
||||||
|
tileLen --
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func shatterOnce (glass, rock image.Rectangle) (tiles [4]image.Rectangle, n int) {
|
||||||
|
rock = rock.Intersect(glass)
|
||||||
|
|
||||||
|
// |'''''''''''|
|
||||||
|
// | |
|
||||||
|
// |###|'''| |
|
||||||
|
// |###|___| |
|
||||||
|
// | |
|
||||||
|
// |___________|
|
||||||
|
if rock.Min.X > glass.Min.X { tiles[n] = image.Rect (
|
||||||
|
glass.Min.X, rock.Min.Y,
|
||||||
|
rock.Min.X, rock.Max.Y,
|
||||||
|
); n ++ }
|
||||||
|
|
||||||
|
// |'''''''''''|
|
||||||
|
// | |
|
||||||
|
// | |'''|###|
|
||||||
|
// | |___|###|
|
||||||
|
// | |
|
||||||
|
// |___________|
|
||||||
|
if rock.Max.X < glass.Max.X { tiles[n] = image.Rect (
|
||||||
|
rock.Max.X, rock.Min.Y,
|
||||||
|
glass.Max.X, rock.Max.Y,
|
||||||
|
); n ++ }
|
||||||
|
|
||||||
|
// |###########|
|
||||||
|
// |###########|
|
||||||
|
// | |'''| |
|
||||||
|
// | |___| |
|
||||||
|
// | |
|
||||||
|
// |___________|
|
||||||
|
if rock.Min.Y > glass.Min.Y { tiles[n] = image.Rect (
|
||||||
|
glass.Min.X, glass.Min.Y,
|
||||||
|
glass.Max.X, rock.Min.Y,
|
||||||
|
); n ++ }
|
||||||
|
|
||||||
|
// |'''''''''''|
|
||||||
|
// | |
|
||||||
|
// | |'''| |
|
||||||
|
// | |___| |
|
||||||
|
// |###########|
|
||||||
|
// |###########|
|
||||||
|
if rock.Max.Y < glass.Max.Y { tiles[n] = image.Rect (
|
||||||
|
glass.Min.X, rock.Max.Y,
|
||||||
|
glass.Max.X, glass.Max.Y,
|
||||||
|
); n ++ }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func remove[ELEMENT any] (slice []ELEMENT, s int) []ELEMENT {
|
||||||
|
return append(slice[:s], slice[s + 1:]...)
|
||||||
|
}
|
Reference in New Issue
Block a user