2023-07-23 07:57:28 +01:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
// Image-related packages
|
|
|
|
img "image"
|
|
|
|
"image/color"
|
|
|
|
|
2023-07-23 15:27:31 +01:00
|
|
|
// String convert
|
2023-07-23 21:37:24 +01:00
|
|
|
//"strconv"
|
2023-07-23 15:27:31 +01:00
|
|
|
|
2023-07-23 07:57:28 +01:00
|
|
|
// EbitenUI
|
|
|
|
"github.com/ebitenui/ebitenui"
|
|
|
|
"github.com/ebitenui/ebitenui/image"
|
|
|
|
"github.com/ebitenui/ebitenui/widget"
|
2023-07-23 15:27:31 +01:00
|
|
|
|
|
|
|
// Fonts
|
|
|
|
"github.com/devraza/ambition/assets/fonts"
|
|
|
|
"github.com/golang/freetype/truetype"
|
|
|
|
"golang.org/x/image/font"
|
2023-07-23 07:57:28 +01:00
|
|
|
)
|
|
|
|
|
2023-07-23 17:07:39 +01:00
|
|
|
// The UI struct
|
2023-07-23 07:57:28 +01:00
|
|
|
type UI struct {
|
2023-07-23 15:27:31 +01:00
|
|
|
base ebitenui.UI
|
|
|
|
colors map[string]color.RGBA
|
2023-07-23 07:57:28 +01:00
|
|
|
width, height int
|
|
|
|
}
|
|
|
|
|
2023-07-23 15:27:31 +01:00
|
|
|
// The `hazakura` colorscheme (default)
|
|
|
|
var hazakura = map[string]color.RGBA{
|
|
|
|
// The monotone colors
|
|
|
|
"dark_black": color.RGBA{0x0f, 0x0f, 0x0d, 0xff},
|
|
|
|
"black": color.RGBA{0x15, 0x15, 0x17, 0xff},
|
|
|
|
"dark_gray": color.RGBA{0x24, 0x24, 0x26, 0xff},
|
|
|
|
"gray": color.RGBA{0x27, 0x27, 0x2b, 0xff},
|
|
|
|
"light_gray": color.RGBA{0x45, 0x44, 0x49, 0xff},
|
|
|
|
"overlay": color.RGBA{0x5c, 0x5c, 0x61, 0xff},
|
2023-07-23 21:37:24 +01:00
|
|
|
"subwhite": color.RGBA{0xd9, 0x0, 0xd7, 0xff},
|
|
|
|
"white": color.RGBA{0xec, 0xe5, 0xea, 0xff},
|
2023-07-23 15:27:31 +01:00
|
|
|
|
|
|
|
// Actual* colors
|
|
|
|
"red": color.RGBA{0xf0, 0x69, 0x69, 0xff},
|
|
|
|
"magenta": color.RGBA{0xe8, 0x87, 0xbb, 0xff},
|
|
|
|
"purple": color.RGBA{0xa2, 0x92, 0xe8, 0xff},
|
|
|
|
"blue": color.RGBA{0x78, 0xb9, 0xc4, 0xff},
|
|
|
|
"cyan": color.RGBA{0x7e, 0xe6, 0xae, 0xff},
|
|
|
|
"green": color.RGBA{0x91, 0xd6, 0x5c, 0xff},
|
|
|
|
"yellow": color.RGBA{0xd9, 0xd5, 0x64, 0xff},
|
|
|
|
}
|
|
|
|
|
2023-07-23 07:57:28 +01:00
|
|
|
// Function for UI initialization
|
|
|
|
func uiInit(width, height int) UI {
|
|
|
|
var ui UI
|
2023-07-23 15:27:31 +01:00
|
|
|
|
|
|
|
// Define the UI colors
|
|
|
|
ui.colors = hazakura
|
|
|
|
|
|
|
|
// Load the images for the button states
|
|
|
|
buttonImage, _ := loadButtonImage()
|
2023-07-23 07:57:28 +01:00
|
|
|
|
|
|
|
// Get the window width/height
|
|
|
|
ui.width = width
|
|
|
|
ui.height = height
|
|
|
|
|
|
|
|
// Define the root container
|
|
|
|
root := widget.NewContainer(
|
|
|
|
// Define the plain color to be used as a default background
|
|
|
|
widget.ContainerOpts.BackgroundImage(image.NewNineSliceColor(ui.colors["dark_black"])),
|
|
|
|
)
|
|
|
|
|
2023-07-23 21:37:24 +01:00
|
|
|
// Make the different faces
|
|
|
|
headingFace, _ := makeFace(18, fonts.IosevkaBold_ttf)
|
|
|
|
defaultFace, _ := makeFace(14, fonts.IosevkaRegular_ttf)
|
2023-07-23 15:27:31 +01:00
|
|
|
|
|
|
|
tabProfile := widget.NewTabBookTab("Profile",
|
|
|
|
widget.ContainerOpts.BackgroundImage(image.NewNineSliceColor(ui.colors["gray"])),
|
|
|
|
widget.ContainerOpts.Layout(widget.NewGridLayout(
|
|
|
|
//Define number of columns in the grid
|
|
|
|
widget.GridLayoutOpts.Columns(2),
|
2023-07-23 21:37:24 +01:00
|
|
|
// Specify the Stretch for each row and column.
|
2023-07-23 15:27:31 +01:00
|
|
|
widget.GridLayoutOpts.Stretch([]bool{false, true}, nil),
|
2023-07-23 21:37:24 +01:00
|
|
|
// Define the spacing between items in the grid
|
|
|
|
widget.GridLayoutOpts.Spacing(20, 15),
|
|
|
|
// Define the padding in the grid
|
|
|
|
widget.GridLayoutOpts.Padding(widget.NewInsetsSimple(20)),
|
2023-07-23 15:27:31 +01:00
|
|
|
)),
|
|
|
|
)
|
2023-07-23 21:37:24 +01:00
|
|
|
makeStatsBars(tabProfile, ui, defaultFace)
|
2023-07-23 15:27:31 +01:00
|
|
|
|
|
|
|
tabInventory := widget.NewTabBookTab("Inventory",
|
|
|
|
widget.ContainerOpts.BackgroundImage(image.NewNineSliceColor(color.NRGBA{0, 255, 0, 0xff})),
|
|
|
|
widget.ContainerOpts.Layout(widget.NewAnchorLayout()),
|
|
|
|
)
|
|
|
|
inventoryButton := widget.NewText(
|
2023-07-23 21:37:24 +01:00
|
|
|
widget.TextOpts.Text("Inventory content", headingFace, color.Black),
|
2023-07-23 15:27:31 +01:00
|
|
|
widget.TextOpts.Position(widget.TextPositionCenter, widget.TextPositionCenter),
|
|
|
|
widget.TextOpts.WidgetOpts(widget.WidgetOpts.LayoutData(widget.AnchorLayoutData{
|
|
|
|
HorizontalPosition: widget.AnchorLayoutPositionCenter,
|
|
|
|
VerticalPosition: widget.AnchorLayoutPositionCenter,
|
|
|
|
})),
|
|
|
|
)
|
|
|
|
tabInventory.AddChild(inventoryButton)
|
|
|
|
|
|
|
|
tabOther := widget.NewTabBookTab("Other",
|
|
|
|
widget.ContainerOpts.BackgroundImage(image.NewNineSliceColor(color.NRGBA{0, 255, 0, 0xff})),
|
|
|
|
widget.ContainerOpts.Layout(widget.NewAnchorLayout()),
|
|
|
|
)
|
|
|
|
otherButton := widget.NewText(
|
2023-07-23 21:37:24 +01:00
|
|
|
widget.TextOpts.Text("Other content", headingFace, color.Black),
|
2023-07-23 15:27:31 +01:00
|
|
|
widget.TextOpts.Position(widget.TextPositionCenter, widget.TextPositionCenter),
|
|
|
|
widget.TextOpts.WidgetOpts(widget.WidgetOpts.LayoutData(widget.AnchorLayoutData{
|
|
|
|
HorizontalPosition: widget.AnchorLayoutPositionCenter,
|
|
|
|
VerticalPosition: widget.AnchorLayoutPositionCenter,
|
|
|
|
})),
|
|
|
|
)
|
|
|
|
tabOther.AddChild(otherButton)
|
|
|
|
|
|
|
|
// Create the tabbook widget
|
|
|
|
leftTabs := widget.NewTabBook(
|
|
|
|
widget.TabBookOpts.TabButtonImage(buttonImage),
|
2023-07-23 21:37:24 +01:00
|
|
|
widget.TabBookOpts.TabButtonText(headingFace, &widget.ButtonTextColor{Idle: color.White}),
|
2023-07-23 15:27:31 +01:00
|
|
|
widget.TabBookOpts.TabButtonSpacing(0),
|
|
|
|
widget.TabBookOpts.ContainerOpts(
|
|
|
|
widget.ContainerOpts.WidgetOpts(widget.WidgetOpts.LayoutData(widget.AnchorLayoutData{
|
|
|
|
StretchHorizontal: true,
|
|
|
|
StretchVertical: true,
|
|
|
|
HorizontalPosition: widget.AnchorLayoutPositionCenter,
|
|
|
|
VerticalPosition: widget.AnchorLayoutPositionCenter,
|
|
|
|
}),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
widget.TabBookOpts.TabButtonOpts(
|
|
|
|
widget.ButtonOpts.TextPadding(widget.NewInsetsSimple(5)),
|
|
|
|
widget.ButtonOpts.WidgetOpts(widget.WidgetOpts.MinSize(int(float32(width)/(3.5*3)), 0)),
|
|
|
|
),
|
|
|
|
widget.TabBookOpts.Tabs(tabProfile, tabInventory, tabOther),
|
|
|
|
)
|
2023-07-23 07:57:28 +01:00
|
|
|
// Define the left bar container
|
|
|
|
leftBar := widget.NewContainer(
|
|
|
|
widget.ContainerOpts.BackgroundImage(image.NewNineSliceColor(ui.colors["gray"])),
|
2023-07-23 21:37:24 +01:00
|
|
|
widget.ContainerOpts.Layout(widget.NewAnchorLayout()),
|
2023-07-23 07:57:28 +01:00
|
|
|
)
|
2023-07-23 15:27:31 +01:00
|
|
|
// Add the tabbook to the left bar
|
|
|
|
leftBar.AddChild(leftTabs)
|
|
|
|
|
2023-07-23 07:57:28 +01:00
|
|
|
// Set the position and size of the left bar
|
2023-07-23 15:27:31 +01:00
|
|
|
leftBar.SetLocation(img.Rect(0, 0, int(float32(width)/3.5), height))
|
2023-07-23 07:57:28 +01:00
|
|
|
// Add the left bar to the root container
|
|
|
|
root.AddChild(leftBar)
|
|
|
|
|
|
|
|
ui.base.Container = root
|
|
|
|
|
|
|
|
return ui
|
|
|
|
}
|
2023-07-23 15:27:31 +01:00
|
|
|
|
2023-07-23 21:37:24 +01:00
|
|
|
// Create progressbars for all the player stats
|
|
|
|
func makeStatsBars(parent *widget.TabBookTab, ui UI, face font.Face) {
|
|
|
|
// Health
|
|
|
|
health := widget.NewText(
|
|
|
|
widget.TextOpts.Text("Health", face, ui.colors["white"]),
|
|
|
|
widget.TextOpts.WidgetOpts(widget.WidgetOpts.LayoutData(widget.GridLayoutData{
|
|
|
|
HorizontalPosition: widget.GridLayoutPositionStart,
|
|
|
|
})),
|
|
|
|
)
|
|
|
|
health_progressbar := widget.NewProgressBar(
|
|
|
|
widget.ProgressBarOpts.WidgetOpts(
|
|
|
|
// Set the required anchor layout data to determine where in the container to place the progressbar
|
|
|
|
widget.WidgetOpts.LayoutData(widget.AnchorLayoutData{
|
|
|
|
HorizontalPosition: widget.AnchorLayoutPositionCenter,
|
|
|
|
VerticalPosition: widget.AnchorLayoutPositionCenter,
|
|
|
|
}),
|
|
|
|
// Set the minimum size for the progressbar.
|
|
|
|
widget.WidgetOpts.MinSize(200, 20),
|
|
|
|
),
|
|
|
|
widget.ProgressBarOpts.Images(
|
|
|
|
// Set the track colors
|
|
|
|
&widget.ProgressBarImage{
|
|
|
|
Idle: image.NewNineSliceColor(ui.colors["black"]),
|
|
|
|
Hover: image.NewNineSliceColor(ui.colors["black"]),
|
|
|
|
},
|
|
|
|
// Set the progress colors
|
|
|
|
&widget.ProgressBarImage{
|
|
|
|
Idle: image.NewNineSliceColor(ui.colors["red"]),
|
|
|
|
Hover: image.NewNineSliceColor(ui.colors["red"]),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
// Set the min, max, and current values for each progressbar
|
|
|
|
widget.ProgressBarOpts.Values(0, testPlayer.health, testPlayer.health),
|
|
|
|
)
|
|
|
|
parent.AddChild(health)
|
|
|
|
parent.AddChild(health_progressbar)
|
|
|
|
|
|
|
|
// Defence
|
|
|
|
defence := widget.NewText(
|
|
|
|
widget.TextOpts.Text("Defence", face, ui.colors["white"]),
|
|
|
|
widget.TextOpts.WidgetOpts(widget.WidgetOpts.LayoutData(widget.GridLayoutData{
|
|
|
|
HorizontalPosition: widget.GridLayoutPositionStart,
|
|
|
|
})),
|
|
|
|
)
|
|
|
|
defence_progressbar := widget.NewProgressBar(
|
|
|
|
widget.ProgressBarOpts.WidgetOpts(
|
|
|
|
// Set the required anchor layout data to determine where in the container to place the progressbar
|
|
|
|
widget.WidgetOpts.LayoutData(widget.AnchorLayoutData{
|
|
|
|
HorizontalPosition: widget.AnchorLayoutPositionCenter,
|
|
|
|
VerticalPosition: widget.AnchorLayoutPositionCenter,
|
|
|
|
}),
|
|
|
|
// Set the minimum size for the progressbar.
|
|
|
|
widget.WidgetOpts.MinSize(200, 20),
|
|
|
|
),
|
|
|
|
widget.ProgressBarOpts.Images(
|
|
|
|
// Set the track colors
|
|
|
|
&widget.ProgressBarImage{
|
|
|
|
Idle: image.NewNineSliceColor(ui.colors["black"]),
|
|
|
|
Hover: image.NewNineSliceColor(ui.colors["black"]),
|
|
|
|
},
|
|
|
|
// Set the progress colors
|
|
|
|
&widget.ProgressBarImage{
|
|
|
|
Idle: image.NewNineSliceColor(ui.colors["yellow"]),
|
|
|
|
Hover: image.NewNineSliceColor(ui.colors["yellow"]),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
// Set the min, max, and current values for each progressbar
|
|
|
|
widget.ProgressBarOpts.Values(0, testPlayer.health, testPlayer.health),
|
|
|
|
)
|
|
|
|
parent.AddChild(defence)
|
|
|
|
parent.AddChild(defence_progressbar)
|
|
|
|
|
|
|
|
// XP/Level
|
|
|
|
level := widget.NewText(
|
|
|
|
widget.TextOpts.Text("Level", face, ui.colors["white"]),
|
|
|
|
widget.TextOpts.WidgetOpts(widget.WidgetOpts.LayoutData(widget.GridLayoutData{
|
|
|
|
HorizontalPosition: widget.GridLayoutPositionStart,
|
|
|
|
})),
|
|
|
|
)
|
|
|
|
level_progressbar := widget.NewProgressBar(
|
|
|
|
widget.ProgressBarOpts.WidgetOpts(
|
|
|
|
// Set the required anchor layout data to determine where in the container to place the progressbar
|
|
|
|
widget.WidgetOpts.LayoutData(widget.AnchorLayoutData{
|
|
|
|
HorizontalPosition: widget.AnchorLayoutPositionCenter,
|
|
|
|
VerticalPosition: widget.AnchorLayoutPositionCenter,
|
|
|
|
}),
|
|
|
|
// Set the minimum size for the progressbar.
|
|
|
|
widget.WidgetOpts.MinSize(200, 20),
|
|
|
|
),
|
|
|
|
widget.ProgressBarOpts.Images(
|
|
|
|
// Set the track colors
|
|
|
|
&widget.ProgressBarImage{
|
|
|
|
Idle: image.NewNineSliceColor(ui.colors["black"]),
|
|
|
|
Hover: image.NewNineSliceColor(ui.colors["black"]),
|
|
|
|
},
|
|
|
|
// Set the progress colors
|
|
|
|
&widget.ProgressBarImage{
|
|
|
|
Idle: image.NewNineSliceColor(ui.colors["cyan"]),
|
|
|
|
Hover: image.NewNineSliceColor(ui.colors["cyan"]),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
// Set the min, max, and current values for each progressbar
|
|
|
|
widget.ProgressBarOpts.Values(0, testPlayer.health, testPlayer.health_max),
|
|
|
|
)
|
|
|
|
parent.AddChild(level)
|
|
|
|
parent.AddChild(level_progressbar)
|
|
|
|
|
|
|
|
// Ambition
|
|
|
|
ambition := widget.NewText(
|
|
|
|
widget.TextOpts.Text("Ambition", face, ui.colors["white"]),
|
|
|
|
widget.TextOpts.WidgetOpts(widget.WidgetOpts.LayoutData(widget.GridLayoutData{
|
|
|
|
HorizontalPosition: widget.GridLayoutPositionStart,
|
|
|
|
})),
|
|
|
|
)
|
|
|
|
ambition_progressbar := widget.NewProgressBar(
|
|
|
|
widget.ProgressBarOpts.WidgetOpts(
|
|
|
|
// Set the required anchor layout data to determine where in the container to place the progressbar
|
|
|
|
widget.WidgetOpts.LayoutData(widget.AnchorLayoutData{
|
|
|
|
HorizontalPosition: widget.AnchorLayoutPositionCenter,
|
|
|
|
VerticalPosition: widget.AnchorLayoutPositionCenter,
|
|
|
|
}),
|
|
|
|
// Set the minimum size for the progressbar.
|
|
|
|
widget.WidgetOpts.MinSize(200, 20),
|
|
|
|
),
|
|
|
|
widget.ProgressBarOpts.Images(
|
|
|
|
// Set the track colors
|
|
|
|
&widget.ProgressBarImage{
|
|
|
|
Idle: image.NewNineSliceColor(ui.colors["black"]),
|
|
|
|
Hover: image.NewNineSliceColor(ui.colors["black"]),
|
|
|
|
},
|
|
|
|
// Set the progress colors
|
|
|
|
&widget.ProgressBarImage{
|
|
|
|
Idle: image.NewNineSliceColor(ui.colors["purple"]),
|
|
|
|
Hover: image.NewNineSliceColor(ui.colors["purple"]),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
// Set the min, max, and current values for each progressbar
|
|
|
|
widget.ProgressBarOpts.Values(0, testPlayer.health, testPlayer.health),
|
|
|
|
)
|
|
|
|
parent.AddChild(ambition)
|
|
|
|
parent.AddChild(ambition_progressbar)
|
|
|
|
}
|
|
|
|
|
2023-07-23 17:07:39 +01:00
|
|
|
// Load a button image
|
2023-07-23 15:27:31 +01:00
|
|
|
func loadButtonImage() (*widget.ButtonImage, error) {
|
|
|
|
idle := image.NewNineSliceColor(hazakura["black"])
|
|
|
|
hover := image.NewNineSliceColor(hazakura["light_gray"])
|
|
|
|
pressed := image.NewNineSliceColor(hazakura["gray"])
|
|
|
|
pressedHover := image.NewNineSliceColor(hazakura["gray"])
|
|
|
|
disabled := image.NewNineSliceColor(hazakura["overlay"])
|
|
|
|
|
|
|
|
return &widget.ButtonImage{
|
|
|
|
Idle: idle,
|
|
|
|
Hover: hover,
|
|
|
|
Pressed: pressed,
|
|
|
|
PressedHover: pressedHover,
|
|
|
|
Disabled: disabled,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2023-07-23 17:07:39 +01:00
|
|
|
// Function to create a face providing font size and file (from assets)
|
|
|
|
func makeFace(size float64, fontfile []byte) (font.Face, error) {
|
|
|
|
ttfFont, err := truetype.Parse(fontfile)
|
2023-07-23 15:27:31 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return truetype.NewFace(ttfFont, &truetype.Options{
|
|
|
|
Size: size,
|
|
|
|
DPI: 72,
|
|
|
|
Hinting: font.HintingFull,
|
|
|
|
}), nil
|
|
|
|
}
|