kisekinopureya 4520f2b9f7
All checks were successful
commit-lint / commit-lint (push) Successful in 33s
feat(tools): toggleable fps counter
2025-07-23 17:57:43 +03:00

100 lines
2.2 KiB
Go

package tools
import (
"fmt"
"log"
"time"
"github.com/veandco/go-sdl2/sdl"
"github.com/veandco/go-sdl2/ttf"
)
var (
oldTime = time.Now()
font *ttf.Font
)
// Initialize font once (call this in setup)
func InitFont(fontPath string, fontSize int) {
var err error
if err := ttf.Init(); err != nil {
log.Fatal(err)
}
font, err = ttf.OpenFont(fontPath, fontSize)
if err != nil {
log.Fatalf("Failed to load font: %v", err)
}
}
// Converts text to raw []uint32 pixels
func textToPixels(text string, color sdl.Color) ([]uint32, int, int) {
surface, err := font.RenderUTF8Blended(text, color)
if err != nil {
log.Fatalf("Render failed: %v", err)
}
defer surface.Free()
w := int(surface.W)
h := int(surface.H)
if err := surface.Lock(); err != nil {
log.Fatalf("Failed to lock surface: %v", err)
}
defer surface.Unlock()
converted, err := surface.ConvertFormat(sdl.PIXELFORMAT_ARGB8888, 0)
if err != nil {
log.Fatal(err)
}
defer converted.Free()
pixelBytes := converted.Pixels()
pixels := make([]uint32, w*h)
for i := 0; i < w*h; i++ {
b := pixelBytes[i*4 : i*4+4]
pixels[i] = uint32(b[3])<<24 | uint32(b[2])<<16 | uint32(b[1])<<8 | uint32(b[0])
}
dst := make([]uint32, w*h)
copy(dst, pixels)
return dst, w, h
}
// Draws text pixels onto your screen framebuffer
func blitTextToBuffer(dst []uint32, dstW, dstH, dstPitch int, src []uint32, srcW, srcH, posX, posY int) {
for y := 0; y < srcH; y++ {
for x := 0; x < srcW; x++ {
dx := posX + x
dy := posY + y
if dx < 0 || dx >= dstW || dy < 0 || dy >= dstH {
continue
}
srcPixel := src[y*srcW+x]
// Only draw non-transparent pixels
if (srcPixel>>24)&0xFF > 0 {
dst[dy*dstPitch+dx] = srcPixel
}
}
}
}
func FpsCounter(pixels []uint32, screenWidth, screenHeight int) {
now := time.Now()
frameTime := now.Sub(oldTime).Seconds()
oldTime = now
if frameTime == 0 {
return
}
fps := 1.0 / frameTime
fpsText := fmt.Sprintf("FPS: %.0f", fps)
color := sdl.Color{R: 255, G: 255, B: 255, A: 255}
textPixels, textW, textH := textToPixels(fpsText, color)
// Draw text at top-left (10,10)
blitTextToBuffer(pixels, screenWidth, screenHeight, screenWidth, textPixels, textW, textH, 10, 10)
}