diff --git a/cmd/tins2020/tins2020.go b/cmd/tins2020/tins2020.go index a0083ab..e50d65e 100644 --- a/cmd/tins2020/tins2020.go +++ b/cmd/tins2020/tins2020.go @@ -42,16 +42,10 @@ func run() error { defer ctx.Destroy() if ctx.Settings.Window.Location == nil { - ctx.Settings.Window.Location = &tins2020.Point{ - X: sdl.WINDOWPOS_UNDEFINED, - Y: sdl.WINDOWPOS_UNDEFINED, - } + ctx.Settings.Window.Location = tins2020.PtPtr(sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED) } if ctx.Settings.Window.Size == nil { - ctx.Settings.Window.Size = &tins2020.Point{ - X: 800, - Y: 600, - } + ctx.Settings.Window.Size = tins2020.PtPtr(800, 600) } sdl.SetHint(sdl.HINT_RENDER_SCALE_QUALITY, "1") @@ -74,7 +68,8 @@ func run() error { err = ctx.Fonts.LoadDesc( tins2020.FontDescriptor{Name: "debug", Path: "fonts/OpenSans-Regular.ttf", Size: 12}, - tins2020.FontDescriptor{Name: "default", Path: "fonts/FiraMono-Regular.ttf", Size: 10}, + tins2020.FontDescriptor{Name: "default", Path: "fonts/FiraMono-Regular.ttf", Size: 16}, + tins2020.FontDescriptor{Name: "small", Path: "fonts/FiraMono-Regular.ttf", Size: 12}, ) if err != nil { return err @@ -113,10 +108,10 @@ func run() error { switch e.Event { case sdl.WINDOWEVENT_MOVED: x, y := window.GetPosition() - ctx.Settings.Window.Location = &tins2020.Point{X: x, Y: y} + ctx.Settings.Window.Location = tins2020.PtPtr(x, y) case sdl.WINDOWEVENT_SIZE_CHANGED: w, h := window.GetSize() - ctx.Settings.Window.Size = &tins2020.Point{X: w, Y: h} + ctx.Settings.Window.Size = tins2020.PtPtr(w, h) } case *sdl.KeyboardEvent: switch e.Keysym.Sym { diff --git a/control.go b/control.go index 1bd3646..9a9e66b 100644 --- a/control.go +++ b/control.go @@ -9,10 +9,18 @@ type Control interface { } type ControlBase struct { + Bounds Rectangle + + IsMouseOver bool } -func (b *ControlBase) Handle(*Context, sdl.Event) {} +func (b *ControlBase) Init(*Context) error { return nil } + +func (b *ControlBase) Handle(ctx *Context, event sdl.Event) { + switch e := event.(type) { + case *sdl.MouseMotionEvent: + b.IsMouseOver = b.Bounds.IsPointInside(e.X, e.Y) + } +} func (b *ControlBase) Render(*Context) {} - -func (b *ControlBase) Init(*Context) error { return nil } diff --git a/flower.go b/flower.go index 9baa89b..e37edca 100644 --- a/flower.go +++ b/flower.go @@ -34,13 +34,14 @@ type FlowerResistance struct { // NewPoppyTraits creates the traits of a poppy, a very generic flower that thrives in a moderate climate. func NewPoppyTraits() FlowerTraits { return FlowerTraits{ - Spread: 0.0007, - Life: 0.99991, + // Spread: 0.0011, + Spread: 0.0011, + Life: 0.99993, Resistance: FlowerResistance{ - Cold: 0.3, - Hot: 0.3, - Dry: 0.3, - Wet: 0.3, + Cold: 0.5, + Hot: 0.5, + Dry: 0.5, + Wet: 0.5, }, } } diff --git a/fonts.go b/fonts.go index 2174653..7a0e65c 100644 --- a/fonts.go +++ b/fonts.go @@ -42,11 +42,11 @@ func (f *Font) RenderCopyAlign(renderer *sdl.Renderer, text string, pos Point, c rect := texture.Rect() switch align { case TextAlignmentLeft: - texture.Copy(renderer, &sdl.Rect{X: pos.X, Y: pos.Y, W: rect.W, H: rect.H}) + texture.Copy(renderer, RectSize(pos.X, pos.Y, rect.W, rect.H).SDLPtr()) case TextAlignmentCenter: - texture.Copy(renderer, &sdl.Rect{X: pos.X - (rect.W / 2), Y: pos.Y, W: rect.W, H: rect.H}) + texture.Copy(renderer, RectSize(pos.X-(rect.W/2), pos.Y, rect.W, rect.H).SDLPtr()) case TextAlignmentRight: - texture.Copy(renderer, &sdl.Rect{X: pos.X - rect.W, Y: pos.Y, W: rect.W, H: rect.H}) + texture.Copy(renderer, RectSize(pos.X-rect.W, pos.Y, rect.W, rect.H).SDLPtr()) } return nil } diff --git a/gamecontrols.go b/gamecontrols.go index d2dceda..a27eabf 100644 --- a/gamecontrols.go +++ b/gamecontrols.go @@ -46,7 +46,7 @@ func (b *ButtonBar) Handle(ctx *Context, event sdl.Event) { } func (b *ButtonBar) Render(ctx *Context) { - ctx.Renderer.FillRect(&sdl.Rect{X: b.Left, Y: b.Top, W: b.Left + buttonBarWidth, H: b.Bottom}) + ctx.Renderer.FillRect(Rect(b.Left, b.Top, b.Left+buttonBarWidth, b.Bottom).SDLPtr()) texture := func(b Button) *Texture { if b.IsDisabled { texture := ctx.Textures.Texture(b.Disabled) @@ -97,7 +97,8 @@ func (c *GameControls) Handle(ctx *Context, event sdl.Event) { } func (c *GameControls) Render(ctx *Context) { - ctx.Renderer.SetDrawColor(74, 198, 154, 255) + // ctx.Renderer.SetDrawColor(74, 198, 154, 255) // #4ac69a + ctx.Renderer.SetDrawColor(53, 109, 173, 255) c.menu.Render(ctx) c.flowers.Render(ctx) } diff --git a/point.go b/point.go index 4eb3018..51696b0 100644 --- a/point.go +++ b/point.go @@ -1,18 +1,34 @@ package tins2020 +import "github.com/veandco/go-sdl2/sdl" + type Point struct { - X, Y int32 + sdl.Point } func (p Point) Add(q Point) Point { return Pt(p.X+q.X, p.Y+q.Y) } +func (p Point) In(r Rectangle) bool { return r.IsPointInsidePt(p) } + type PointF struct { - X, Y float32 + sdl.FPoint } -func (p PointF) Add(q PointF) PointF { return PtF(p.X+q.X, p.Y+q.Y) } +func (p PointF) Add(q PointF) PointF { + return PtF(p.X+q.X, p.Y+q.Y) +} func (p PointF) Sub(q PointF) PointF { return PtF(p.X-q.X, p.Y-q.Y) } -func Pt(x, y int32) Point { return Point{x, y} } -func PtF(x, y float32) PointF { return PointF{x, y} } +func Pt(x, y int32) Point { return Point{sdl.Point{X: x, Y: y}} } +func PtF(x, y float32) PointF { return PointF{sdl.FPoint{X: x, Y: y}} } + +func PtPtr(x, y int32) *Point { + p := Pt(x, y) + return &p +} + +func PtFPtr(x, y float32) *PointF { + p := PtF(x, y) + return &p +} diff --git a/projection.go b/projection.go index c58e057..ee6e382 100644 --- a/projection.go +++ b/projection.go @@ -11,7 +11,7 @@ type projection struct { zoom float32 zoomInv float32 - windowRect sdl.Rect + windowRect Rectangle tileScreenDelta PointF tileScreenDeltaInv PointF tileScreenOffset Point @@ -64,7 +64,7 @@ func (p *projection) update(renderer *sdl.Renderer) { log.Fatal(err) } p.windowCenter = Pt(windowW/2, windowH/2) - p.windowRect = sdl.Rect{X: buttonBarWidth, Y: 0, W: windowW - 2*buttonBarWidth, H: windowH - 0} + p.windowRect = RectSize(buttonBarWidth, 0, windowW-2*buttonBarWidth, windowH) } func (p *projection) visibleTiles(action func(int32, int32, Point)) { diff --git a/rect.go b/rect.go new file mode 100644 index 0000000..5eba166 --- /dev/null +++ b/rect.go @@ -0,0 +1,28 @@ +package tins2020 + +import "github.com/veandco/go-sdl2/sdl" + +type Rectangle struct { + sdl.Rect +} + +func (r Rectangle) IsPointInside(x, y int32) bool { + return x >= r.X && x < r.X+r.W && y >= r.Y && y < r.Y+r.H +} + +func (r Rectangle) IsPointInsidePt(p Point) bool { return r.IsPointInside(p.X, p.Y) } + +func Rect(x1, y1, x2, y2 int32) Rectangle { + if x1 > x2 { + x1, x2 = x2, x1 + } + if y1 > y2 { + y1, y2 = y2, y1 + } + return Rectangle{sdl.Rect{X: x1, Y: y1, W: x2 - x1, H: y2 - y1}} +} + +func RectSize(x, y, w, h int32) Rectangle { return Rectangle{sdl.Rect{X: x, Y: y, W: w, H: h}} } + +func (r Rectangle) SDL() sdl.Rect { return r.Rect } +func (r Rectangle) SDLPtr() *sdl.Rect { return &r.Rect } diff --git a/terrainrenderer.go b/terrainrenderer.go index e436dde..e9a305b 100644 --- a/terrainrenderer.go +++ b/terrainrenderer.go @@ -35,30 +35,32 @@ func (r *terrainRenderer) Handle(ctx *Context, event sdl.Event) { if e.Button == sdl.BUTTON_LEFT { r.interact.mouseLeftDown = e.Type == sdl.MOUSEBUTTONDOWN if r.interact.mouseLeftDown && r.interact.mouseDrag == nil { - r.interact.mouseDrag = &Point{e.X, e.Y} + r.interact.mouseDrag = PtPtr(e.X, e.Y) } else if !r.interact.mouseLeftDown && r.interact.mouseDrag != nil { r.interact.mouseDrag = nil } } case *sdl.MouseMotionEvent: - if insideRect(e.X, e.Y, &r.project.windowRect) { + if r.project.windowRect.IsPointInside(e.X, e.Y) { hover := r.project.screenToMap(e.X, e.Y) - r.hover = &Point{X: int32(Round32(hover.X)), Y: int32(Round32(hover.Y))} + r.hover = PtPtr(int32(Round32(hover.X)), int32(Round32(hover.Y))) } else { r.hover = nil } if r.interact.mouseDrag != nil { r.project.center = r.project.center.Sub(r.project.screenToMapRel(e.X-r.interact.mouseDrag.X, e.Y-r.interact.mouseDrag.Y)) r.project.update(ctx.Renderer) - r.interact.mouseDrag = &Point{e.X, e.Y} + r.interact.mouseDrag = PtPtr(e.X, e.Y) } case *sdl.MouseWheelEvent: - if e.Y > 0 && r.project.zoom > .5 { - r.project.zoom *= .5 - r.project.update(ctx.Renderer) - } else if e.Y < 0 && r.project.zoom < 4 { - r.project.zoom *= 2 - r.project.update(ctx.Renderer) + if r.project.windowRect.IsPointInside(e.X, e.Y) { + if e.Y > 0 && r.project.zoom > .5 { + r.project.zoom *= .5 + r.project.update(ctx.Renderer) + } else if e.Y < 0 && r.project.zoom < 4 { + r.project.zoom *= 2 + r.project.update(ctx.Renderer) + } } case *sdl.WindowEvent: if e.Event == sdl.WINDOWEVENT_RESIZED { @@ -67,12 +69,6 @@ func (r *terrainRenderer) Handle(ctx *Context, event sdl.Event) { } } -func insideRect(x, y int32, rect *sdl.Rect) bool { - return x >= rect.X && x < rect.X+rect.W && y >= rect.Y && y < rect.Y+rect.H -} - -func insideRectPt(p Point, rect *sdl.Rect) bool { return insideRect(p.X, p.Y, rect) } - func (r *terrainRenderer) Render(ctx *Context) { toTileTexture := func(x, y int32) *Texture { temp := r.terrain.Temp.Value(x, y)