FPS counter in settings
This commit is contained in:
@@ -78,8 +78,15 @@ func (m MeterLabel) Draw(screen *ebiten.Image, x, y int) (int, int) {
|
||||
if m.Color == nil {
|
||||
m.Color = color.White
|
||||
}
|
||||
txt := fmt.Sprintf("%s: %3.0f%%", m.Meter.Label, m.Meter.Level)
|
||||
drawHUDText(screen, txt, m.Color, x, y)
|
||||
var txt string
|
||||
if m.Meter.Base < 0 {
|
||||
// Text-only display without percentage.
|
||||
txt = m.Meter.Label
|
||||
} else {
|
||||
// Standard meter with percentage.
|
||||
txt = fmt.Sprintf("%s: %3.0f%%", m.Meter.Label, m.Meter.Level)
|
||||
}
|
||||
drawHUDText(screen, txt, m.Meter.Color, x, y)
|
||||
return len(txt) * 7, 13
|
||||
}
|
||||
|
||||
|
||||
@@ -34,13 +34,21 @@ func (o Overlay) Draw(screen *ebiten.Image, meters []status.Meter) {
|
||||
// Meter column
|
||||
meterElements := make([]Element, 0, len(meters))
|
||||
for _, meter := range meters {
|
||||
meterElements = append(meterElements, Column{
|
||||
Elements: []Element{
|
||||
if meter.Base < 0 {
|
||||
// Text-only display (no bar).
|
||||
meterElements = append(meterElements,
|
||||
MeterLabel{Meter: meter, Color: o.Color},
|
||||
Bar{Meter: meter, MaxWidth: 180, Height: 8, ShowBorder: false},
|
||||
},
|
||||
Spacing: 2,
|
||||
})
|
||||
)
|
||||
} else {
|
||||
// Full meter with bar.
|
||||
meterElements = append(meterElements, Column{
|
||||
Elements: []Element{
|
||||
MeterLabel{Meter: meter, Color: o.Color},
|
||||
Bar{Meter: meter, MaxWidth: 180, Height: 8, ShowBorder: false},
|
||||
},
|
||||
Spacing: 2,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
meterPanel := Column{
|
||||
|
||||
@@ -42,41 +42,67 @@ const (
|
||||
optionCount
|
||||
)
|
||||
|
||||
type menuScreen int
|
||||
|
||||
const (
|
||||
screenMain menuScreen = iota
|
||||
screenSettings
|
||||
)
|
||||
|
||||
type PauseMenu struct {
|
||||
selectedIndex int
|
||||
showWIP bool
|
||||
selectedIndex int
|
||||
currentScreen menuScreen
|
||||
fpsMonitorValue *bool
|
||||
fpsCapValue FPSCapSetting
|
||||
}
|
||||
|
||||
type FPSCapSetting interface {
|
||||
String() string
|
||||
Cycle()
|
||||
}
|
||||
|
||||
func NewPauseMenu() *PauseMenu {
|
||||
return &PauseMenu{
|
||||
selectedIndex: 0,
|
||||
showWIP: false,
|
||||
currentScreen: screenMain,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *PauseMenu) SetFPSMonitor(enabled *bool) {
|
||||
m.fpsMonitorValue = enabled
|
||||
}
|
||||
|
||||
func (m *PauseMenu) SetFPSCap(cap FPSCapSetting) {
|
||||
m.fpsCapValue = cap
|
||||
}
|
||||
|
||||
// Returns the selected option if one was chosen, nil otherwise
|
||||
func (m *PauseMenu) Update() *MenuOption {
|
||||
// Handle up/down navigation
|
||||
if m.currentScreen == screenSettings {
|
||||
return m.updateSettings()
|
||||
}
|
||||
return m.updateMain()
|
||||
}
|
||||
|
||||
func (m *PauseMenu) updateMain() *MenuOption {
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyArrowUp) || inpututil.IsKeyJustPressed(ebiten.KeyW) {
|
||||
m.selectedIndex--
|
||||
if m.selectedIndex < 0 {
|
||||
m.selectedIndex = int(optionCount) - 1
|
||||
}
|
||||
m.showWIP = false
|
||||
}
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyArrowDown) || inpututil.IsKeyJustPressed(ebiten.KeyS) {
|
||||
m.selectedIndex++
|
||||
if m.selectedIndex >= int(optionCount) {
|
||||
m.selectedIndex = 0
|
||||
}
|
||||
m.showWIP = false
|
||||
}
|
||||
|
||||
// Handle selection
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyEnter) || inpututil.IsKeyJustPressed(ebiten.KeySpace) {
|
||||
selected := MenuOption(m.selectedIndex)
|
||||
if selected == OptionSettings {
|
||||
m.showWIP = true
|
||||
m.currentScreen = screenSettings
|
||||
m.selectedIndex = 0
|
||||
return nil
|
||||
}
|
||||
return &selected
|
||||
@@ -85,19 +111,48 @@ func (m *PauseMenu) Update() *MenuOption {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PauseMenu) updateSettings() *MenuOption {
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyEscape) {
|
||||
m.currentScreen = screenMain
|
||||
m.selectedIndex = 0
|
||||
return nil
|
||||
}
|
||||
|
||||
settingsCount := 2
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyArrowUp) || inpututil.IsKeyJustPressed(ebiten.KeyW) {
|
||||
m.selectedIndex--
|
||||
if m.selectedIndex < 0 {
|
||||
m.selectedIndex = 0
|
||||
}
|
||||
}
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyArrowDown) || inpututil.IsKeyJustPressed(ebiten.KeyS) {
|
||||
m.selectedIndex++
|
||||
if m.selectedIndex >= settingsCount {
|
||||
m.selectedIndex = settingsCount - 1
|
||||
}
|
||||
}
|
||||
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyEnter) || inpututil.IsKeyJustPressed(ebiten.KeySpace) {
|
||||
if m.selectedIndex == 0 && m.fpsMonitorValue != nil {
|
||||
*m.fpsMonitorValue = !*m.fpsMonitorValue
|
||||
} else if m.selectedIndex == 1 && m.fpsCapValue != nil {
|
||||
m.fpsCapValue.Cycle()
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PauseMenu) Draw(screen *ebiten.Image, screenWidth, screenHeight int) {
|
||||
// Draw semi-transparent overlay
|
||||
if overlay := getOverlayImage(screenWidth, screenHeight); overlay != nil {
|
||||
screen.DrawImage(overlay, nil)
|
||||
}
|
||||
|
||||
// Menu dimensions
|
||||
menuWidth := 400
|
||||
menuHeight := 300
|
||||
menuX := (screenWidth - menuWidth) / 2
|
||||
menuY := (screenHeight - menuHeight) / 2
|
||||
|
||||
// Draw menu background
|
||||
vector.DrawFilledRect(screen,
|
||||
float32(menuX), float32(menuY),
|
||||
float32(menuWidth), float32(menuHeight),
|
||||
@@ -105,7 +160,6 @@ func (m *PauseMenu) Draw(screen *ebiten.Image, screenWidth, screenHeight int) {
|
||||
false,
|
||||
)
|
||||
|
||||
// Draw menu border
|
||||
vector.StrokeRect(screen,
|
||||
float32(menuX), float32(menuY),
|
||||
float32(menuWidth), float32(menuHeight),
|
||||
@@ -114,13 +168,19 @@ func (m *PauseMenu) Draw(screen *ebiten.Image, screenWidth, screenHeight int) {
|
||||
false,
|
||||
)
|
||||
|
||||
// Draw title
|
||||
if m.currentScreen == screenSettings {
|
||||
m.drawSettings(screen, menuX, menuY, menuWidth, menuHeight)
|
||||
} else {
|
||||
m.drawMain(screen, menuX, menuY, menuWidth, menuHeight)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *PauseMenu) drawMain(screen *ebiten.Image, menuX, menuY, menuWidth, menuHeight int) {
|
||||
titleText := "PAUSED"
|
||||
titleX := menuX + (menuWidth / 2) - (len(titleText) * 7 / 2)
|
||||
titleY := menuY + 50
|
||||
m.drawText(screen, titleText, color.White, titleX, titleY)
|
||||
|
||||
// Draw menu options
|
||||
options := []string{"Resume", "Settings", "Quit"}
|
||||
startY := menuY + 110
|
||||
|
||||
@@ -128,7 +188,6 @@ func (m *PauseMenu) Draw(screen *ebiten.Image, screenWidth, screenHeight int) {
|
||||
optionY := startY + (i * 40)
|
||||
optionX := menuX + (menuWidth / 2) - (len(option) * 7 / 2)
|
||||
|
||||
// Draw selection indicator
|
||||
if i == m.selectedIndex {
|
||||
indicatorX := optionX - 20
|
||||
m.drawText(screen, ">", color.RGBA{R: 255, G: 200, B: 0, A: 255}, indicatorX, optionY)
|
||||
@@ -138,16 +197,53 @@ func (m *PauseMenu) Draw(screen *ebiten.Image, screenWidth, screenHeight int) {
|
||||
}
|
||||
}
|
||||
|
||||
// Draw WIP message if settings was selected
|
||||
if m.showWIP {
|
||||
wipY := startY + 140
|
||||
wipText := "Work In Progress"
|
||||
wipX := menuX + (menuWidth / 2) - (len(wipText) * 7 / 2)
|
||||
m.drawText(screen, wipText, color.RGBA{R: 255, G: 150, B: 0, A: 255}, wipX, wipY)
|
||||
hintText := "Use Arrow Keys/WASD to navigate, Enter/Space to select"
|
||||
hintX := menuX + (menuWidth / 2) - (len(hintText) * 7 / 2)
|
||||
hintY := menuY + menuHeight - 30
|
||||
m.drawText(screen, hintText, color.RGBA{R: 150, G: 150, B: 150, A: 255}, hintX, hintY)
|
||||
}
|
||||
|
||||
func (m *PauseMenu) drawSettings(screen *ebiten.Image, menuX, menuY, menuWidth, menuHeight int) {
|
||||
titleText := "SETTINGS"
|
||||
titleX := menuX + (menuWidth / 2) - (len(titleText) * 7 / 2)
|
||||
titleY := menuY + 50
|
||||
m.drawText(screen, titleText, color.White, titleX, titleY)
|
||||
|
||||
startY := menuY + 110
|
||||
leftMargin := menuX + 40
|
||||
|
||||
fpsMonitorText := "FPS Monitor: "
|
||||
if m.fpsMonitorValue != nil && *m.fpsMonitorValue {
|
||||
fpsMonitorText += "ON"
|
||||
} else {
|
||||
fpsMonitorText += "OFF"
|
||||
}
|
||||
|
||||
// Draw controls hint at bottom
|
||||
hintText := "Use Arrow Keys/WASD to navigate, Enter/Space to select"
|
||||
if m.selectedIndex == 0 {
|
||||
indicatorX := leftMargin - 20
|
||||
m.drawText(screen, ">", color.RGBA{R: 255, G: 200, B: 0, A: 255}, indicatorX, startY)
|
||||
m.drawText(screen, fpsMonitorText, color.RGBA{R: 255, G: 255, B: 100, A: 255}, leftMargin, startY)
|
||||
} else {
|
||||
m.drawText(screen, fpsMonitorText, color.RGBA{R: 180, G: 180, B: 180, A: 255}, leftMargin, startY)
|
||||
}
|
||||
|
||||
fpsCapText := "FPS Cap: "
|
||||
if m.fpsCapValue != nil {
|
||||
fpsCapText += m.fpsCapValue.String()
|
||||
} else {
|
||||
fpsCapText += "60 FPS"
|
||||
}
|
||||
|
||||
capY := startY + 30
|
||||
if m.selectedIndex == 1 {
|
||||
indicatorX := leftMargin - 20
|
||||
m.drawText(screen, ">", color.RGBA{R: 255, G: 200, B: 0, A: 255}, indicatorX, capY)
|
||||
m.drawText(screen, fpsCapText, color.RGBA{R: 255, G: 255, B: 100, A: 255}, leftMargin, capY)
|
||||
} else {
|
||||
m.drawText(screen, fpsCapText, color.RGBA{R: 180, G: 180, B: 180, A: 255}, leftMargin, capY)
|
||||
}
|
||||
|
||||
hintText := "Enter/Space to toggle, ESC to go back"
|
||||
hintX := menuX + (menuWidth / 2) - (len(hintText) * 7 / 2)
|
||||
hintY := menuY + menuHeight - 30
|
||||
m.drawText(screen, hintText, color.RGBA{R: 150, G: 150, B: 150, A: 255}, hintX, hintY)
|
||||
@@ -162,5 +258,5 @@ func (m *PauseMenu) drawText(screen *ebiten.Image, txt string, clr color.Color,
|
||||
|
||||
func (m *PauseMenu) Reset() {
|
||||
m.selectedIndex = 0
|
||||
m.showWIP = false
|
||||
m.currentScreen = screenMain
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user