Added tool to color image.
Separated some image related methods. Added feedback for simulation speed (colored buttons).
This commit is contained in:
parent
b14f79a61a
commit
cd5ca3f04f
34
cmd/imadapt/color.go
Normal file
34
cmd/imadapt/color.go
Normal file
@ -0,0 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
|
||||
"opslag.de/schobers/tins2020/img"
|
||||
)
|
||||
|
||||
func colorImage(path string, col color.Color) error {
|
||||
src, err := img.DecodeImage(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
colNRGBA := color.NRGBAModel.Convert(col).(color.NRGBA)
|
||||
bounds := src.Bounds()
|
||||
dst := image.NewRGBA(bounds)
|
||||
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
|
||||
for x := bounds.Min.X; x < bounds.Max.X; x++ {
|
||||
c := src.At(x, y)
|
||||
srcCol := color.NRGBAModel.Convert(c).(color.NRGBA)
|
||||
if srcCol.A > 0 {
|
||||
dstCol := colNRGBA
|
||||
dstCol.A = srcCol.A
|
||||
dst.Set(x, y, dstCol)
|
||||
} else {
|
||||
dst.Set(x, y, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
return img.EncodePNG(path, dst)
|
||||
return nil
|
||||
}
|
@ -5,10 +5,11 @@ import (
|
||||
"image/draw"
|
||||
|
||||
"github.com/nfnt/resize"
|
||||
"opslag.de/schobers/tins2020/img"
|
||||
)
|
||||
|
||||
func crop(path string, crop rect, size *point) error {
|
||||
src, err := decodeImage(path)
|
||||
src, err := img.DecodeImage(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -17,9 +18,9 @@ func crop(path string, crop rect, size *point) error {
|
||||
dst := image.NewRGBA(dstRect)
|
||||
draw.Draw(dst, dstRect, src, srcRect.Min, draw.Src)
|
||||
if size == nil {
|
||||
return encodePNG(path, dst)
|
||||
return img.EncodePNG(path, dst)
|
||||
}
|
||||
|
||||
resized := resize.Resize(uint(size.x), uint(size.y), dst, resize.Bilinear)
|
||||
return encodePNG(path, resized)
|
||||
return img.EncodePNG(path, resized)
|
||||
}
|
||||
|
@ -3,10 +3,12 @@ package main
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
|
||||
"opslag.de/schobers/tins2020/img"
|
||||
)
|
||||
|
||||
func convertToGray(path string) error {
|
||||
src, err := decodeImage(path)
|
||||
src, err := img.DecodeImage(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -25,5 +27,5 @@ func convertToGray(path string) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
return encodePNG(path, dst)
|
||||
return img.EncodePNG(path, dst)
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"opslag.de/schobers/tins2020/img"
|
||||
)
|
||||
|
||||
func run() error {
|
||||
@ -73,6 +75,17 @@ func run() error {
|
||||
return fmt.Errorf("couldn't crop '%s'; error: %v", path, err)
|
||||
}
|
||||
}
|
||||
case "color":
|
||||
flags := flag.NewFlagSet("color", flag.ContinueOnError)
|
||||
var col string
|
||||
flags.StringVar(&col, "color", "#ff0000", "target color")
|
||||
flags.Parse(args[1:])
|
||||
for _, path := range flags.Args() {
|
||||
err := colorImage(path, img.MustHexColor(col))
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't convert to grayscale of '%s'; error: %v", path, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -3,10 +3,12 @@ package main
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
|
||||
"opslag.de/schobers/tins2020/img"
|
||||
)
|
||||
|
||||
func setAlpha(path string, alpha int) error {
|
||||
src, err := decodeImage(path)
|
||||
src, err := img.DecodeImage(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -21,5 +23,5 @@ func setAlpha(path string, alpha int) error {
|
||||
dst.Set(x, y, c)
|
||||
}
|
||||
}
|
||||
return encodePNG(path, dst)
|
||||
return img.EncodePNG(path, dst)
|
||||
}
|
||||
|
BIN
cmd/tins2020/res/images/fastForward_disabled.png
Normal file
BIN
cmd/tins2020/res/images/fastForward_disabled.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 373 B |
BIN
cmd/tins2020/res/images/forward_disabled.png
Normal file
BIN
cmd/tins2020/res/images/forward_disabled.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 346 B |
BIN
cmd/tins2020/res/images/pause_disabled.png
Normal file
BIN
cmd/tins2020/res/images/pause_disabled.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 246 B |
@ -8,8 +8,11 @@ control-load: images/basket.png
|
||||
control-quit: images/power.png
|
||||
|
||||
control-pause: images/pause.png
|
||||
control-pause-disabled: images/pause_disabled.png
|
||||
control-run: images/forward.png
|
||||
control-run-disabled: images/forward_disabled.png
|
||||
control-run-fast: images/fastForward.png
|
||||
control-run-fast-disabled: images/fastForward_disabled.png
|
||||
|
||||
tile-dirt: images/tile_dirt.png
|
||||
tile-grass: images/tile_grass.png
|
||||
|
58
color.go
58
color.go
@ -1,63 +1,9 @@
|
||||
package tins2020
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
"opslag.de/schobers/tins2020/img"
|
||||
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
)
|
||||
|
||||
var hexColorRE = regexp.MustCompile(`^#?([0-9A-Fa-f]{2})-?([0-9A-Fa-f]{2})-?([0-9A-Fa-f]{2})-?([0-9A-Fa-f]{2})?$`)
|
||||
|
||||
func HexColor(s string) (sdl.Color, error) {
|
||||
match := hexColorRE.FindStringSubmatch(s)
|
||||
if match == nil {
|
||||
return sdl.Color{}, errors.New("invalid color format")
|
||||
}
|
||||
values, err := HexToInts(match[1:]...)
|
||||
if err != nil {
|
||||
return sdl.Color{}, err
|
||||
}
|
||||
a := 255
|
||||
if len(match[4]) > 0 {
|
||||
a = values[3]
|
||||
}
|
||||
return sdl.Color{R: uint8(values[0]), G: uint8(values[1]), B: uint8(values[2]), A: uint8(a)}, nil
|
||||
}
|
||||
|
||||
func MustHexColor(s string) sdl.Color {
|
||||
color, err := HexColor(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return color
|
||||
}
|
||||
|
||||
func HexToInt(s string) (int, error) {
|
||||
var i int
|
||||
for _, c := range s {
|
||||
i *= 16
|
||||
if c >= '0' && c <= '9' {
|
||||
i += int(c - '0')
|
||||
} else if c >= 'A' && c <= 'F' {
|
||||
i += int(c - 'A' + 10)
|
||||
} else if c >= 'a' && c <= 'f' {
|
||||
i += int(c - 'a' + 10)
|
||||
} else {
|
||||
return 0, errors.New("hex digit not supported")
|
||||
}
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func HexToInts(s ...string) ([]int, error) {
|
||||
ints := make([]int, len(s))
|
||||
for i, s := range s {
|
||||
value, err := HexToInt(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ints[i] = value
|
||||
}
|
||||
return ints, nil
|
||||
}
|
||||
func MustHexColor(s string) sdl.Color { return sdl.Color(img.MustHexColor(s)) }
|
||||
|
1
game.go
1
game.go
@ -58,6 +58,7 @@ func NewGame() *Game {
|
||||
}
|
||||
terrain.AddFlower(Pt(0, 0), NewPoppyTraits())
|
||||
return &Game{
|
||||
Speed: GameSpeedNormal,
|
||||
Balance: 100,
|
||||
Terrain: terrain,
|
||||
|
||||
|
@ -19,6 +19,12 @@ func NewGameControls(game *Game) *GameControls {
|
||||
}
|
||||
|
||||
func (c *GameControls) updateSpeedControls() {
|
||||
disable := func(b *IconButton, speed GameSpeed) {
|
||||
b.IsDisabled = speed == c.game.Speed
|
||||
}
|
||||
disable(c.pause, GameSpeedPaused)
|
||||
disable(c.run, GameSpeedNormal)
|
||||
disable(c.runFast, GameSpeedFast)
|
||||
}
|
||||
|
||||
func (c *GameControls) Arrange(ctx *Context, bounds Rectangle) {
|
||||
@ -40,18 +46,25 @@ func (c *GameControls) Init(ctx *Context) error {
|
||||
}
|
||||
|
||||
c.top.Orientation = OrientationHorizontal
|
||||
c.pause = NewIconButton("control-pause", EmptyEvent(func() {
|
||||
c.pause = NewIconButtonConfig("control-pause", EmptyEvent(func() {
|
||||
c.game.Pause()
|
||||
c.updateSpeedControls()
|
||||
}))
|
||||
c.run = NewIconButton("control-run", EmptyEvent(func() {
|
||||
}), func(b *IconButton) {
|
||||
b.IconDisabled = "control-pause-disabled"
|
||||
})
|
||||
c.run = NewIconButtonConfig("control-run", EmptyEvent(func() {
|
||||
c.game.Run()
|
||||
c.updateSpeedControls()
|
||||
}))
|
||||
c.runFast = NewIconButton("control-run-fast", EmptyEvent(func() {
|
||||
}), func(b *IconButton) {
|
||||
b.IconDisabled = "control-run-disabled"
|
||||
})
|
||||
c.runFast = NewIconButtonConfig("control-run-fast", EmptyEvent(func() {
|
||||
c.game.RunFast()
|
||||
c.updateSpeedControls()
|
||||
}))
|
||||
}), func(b *IconButton) {
|
||||
b.IconDisabled = "control-run-fast-disabled"
|
||||
})
|
||||
c.updateSpeedControls()
|
||||
c.top.Buttons = []Control{c.pause, c.run, c.runFast}
|
||||
|
||||
c.menu.Background = MustHexColor("#356dad")
|
||||
@ -71,7 +84,7 @@ func (c *GameControls) Render(ctx *Context) {
|
||||
topBar := MustHexColor("#0000007f")
|
||||
ctx.Renderer.SetDrawColor(topBar.R, topBar.G, topBar.B, topBar.A)
|
||||
ctx.Renderer.FillRect(Rect(c.menu.Bounds.Right(), 0, c.flowers.Bounds.X, 64).SDLPtr())
|
||||
ctx.Fonts.Font("balance").RenderCopyAlign(ctx.Renderer, FmtMoney(c.game.Balance), Pt(c.top.Bounds.X-8, 58), MustHexColor("#79A6D9"), TextAlignmentRight)
|
||||
ctx.Fonts.Font("balance").RenderCopyAlign(ctx.Renderer, FmtMoney(c.game.Balance), Pt(c.top.Bounds.X-8, 58), MustHexColor("#4AC69A"), TextAlignmentRight)
|
||||
|
||||
c.Container.Render(ctx)
|
||||
}
|
||||
|
62
img/color.go
Normal file
62
img/color.go
Normal file
@ -0,0 +1,62 @@
|
||||
package img
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"image/color"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var hexColorRE = regexp.MustCompile(`^#?([0-9A-Fa-f]{2})-?([0-9A-Fa-f]{2})-?([0-9A-Fa-f]{2})-?([0-9A-Fa-f]{2})?$`)
|
||||
|
||||
func HexColor(s string) (color.RGBA, error) {
|
||||
match := hexColorRE.FindStringSubmatch(s)
|
||||
if match == nil {
|
||||
return color.RGBA{}, errors.New("invalid color format")
|
||||
}
|
||||
values, err := HexToInts(match[1:]...)
|
||||
if err != nil {
|
||||
return color.RGBA{}, err
|
||||
}
|
||||
a := 255
|
||||
if len(match[4]) > 0 {
|
||||
a = values[3]
|
||||
}
|
||||
return color.RGBA{R: uint8(values[0]), G: uint8(values[1]), B: uint8(values[2]), A: uint8(a)}, nil
|
||||
}
|
||||
|
||||
func MustHexColor(s string) color.RGBA {
|
||||
color, err := HexColor(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return color
|
||||
}
|
||||
|
||||
func HexToInt(s string) (int, error) {
|
||||
var i int
|
||||
for _, c := range s {
|
||||
i *= 16
|
||||
if c >= '0' && c <= '9' {
|
||||
i += int(c - '0')
|
||||
} else if c >= 'A' && c <= 'F' {
|
||||
i += int(c - 'A' + 10)
|
||||
} else if c >= 'a' && c <= 'f' {
|
||||
i += int(c - 'a' + 10)
|
||||
} else {
|
||||
return 0, errors.New("hex digit not supported")
|
||||
}
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func HexToInts(s ...string) ([]int, error) {
|
||||
ints := make([]int, len(s))
|
||||
for i, s := range s {
|
||||
value, err := HexToInt(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ints[i] = value
|
||||
}
|
||||
return ints, nil
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package img
|
||||
|
||||
import (
|
||||
"image"
|
||||
@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func encodePNG(path string, im image.Image) error {
|
||||
func EncodePNG(path string, im image.Image) error {
|
||||
dst, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -15,7 +15,7 @@ func encodePNG(path string, im image.Image) error {
|
||||
return png.Encode(dst, im)
|
||||
}
|
||||
|
||||
func decodeImage(path string) (image.Image, error) {
|
||||
func DecodeImage(path string) (image.Image, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
Loading…
Reference in New Issue
Block a user