Working prototype with dev dashboard
- Created core Engine that coordinates all subsystems - Extended API with comprehensive endpoints for dev dashboard - Implemented pure Go vision processing (no GoCV dependency) - Built full-featured dev dashboard with live capture viewer, region overlays, pixel inspector - Added D2R detector with actual health/mana reading from orb regions - Fixed resolution profile registration and region validation - Generated synthetic test data for development - Added dev mode support with file backend for testing - Fixed build tag issues for cross-platform compilation Prototype features: ✅ Live capture viewer with region overlays ✅ Real-time state detection (game state, health %, mana %) ✅ Pixel inspector (hover for RGB/HSV values) ✅ Capture stats monitoring (FPS, frame count) ✅ Region management with toggle visibility ✅ File upload for testing screenshots ✅ Dark theme dev-focused UI ✅ CORS enabled for dev convenience Ready for: go run ./cmd/iso-bot --dev --api :8080
This commit is contained in:
parent
80ba9b1b90
commit
6a9562c406
10 changed files with 1884 additions and 62 deletions
|
|
@ -5,12 +5,14 @@ import (
|
|||
"image"
|
||||
|
||||
"git.cloonar.com/openclawd/iso-bot/pkg/plugin"
|
||||
"git.cloonar.com/openclawd/iso-bot/pkg/engine/vision"
|
||||
)
|
||||
|
||||
// Detector implements plugin.GameDetector for D2R.
|
||||
type Detector struct {
|
||||
config Config
|
||||
services plugin.EngineServices
|
||||
vision *vision.Pipeline
|
||||
}
|
||||
|
||||
// NewDetector creates a D2R state detector.
|
||||
|
|
@ -18,6 +20,7 @@ func NewDetector(config Config, services plugin.EngineServices) *Detector {
|
|||
return &Detector{
|
||||
config: config,
|
||||
services: services,
|
||||
vision: vision.NewPipeline(0.8), // 80% confidence threshold
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +44,7 @@ func (d *Detector) DetectState(frame image.Image) plugin.GameState {
|
|||
}
|
||||
if d.isInGame(frame) {
|
||||
vitals := d.ReadVitals(frame)
|
||||
if vitals.HealthPct == 0 {
|
||||
if vitals.HealthPct <= 0.01 { // Consider very low health as dead
|
||||
return plugin.StateDead
|
||||
}
|
||||
return plugin.StateInGame
|
||||
|
|
@ -51,15 +54,42 @@ func (d *Detector) DetectState(frame image.Image) plugin.GameState {
|
|||
|
||||
// ReadVitals reads health and mana from the orbs.
|
||||
func (d *Detector) ReadVitals(frame image.Image) plugin.VitalStats {
|
||||
// TODO: Analyze health/mana orb regions using color detection
|
||||
// Get region coordinates from the engine services
|
||||
healthRegion := d.services.Region("health_orb")
|
||||
manaRegion := d.services.Region("mana_orb")
|
||||
|
||||
_ = healthRegion // Use these regions for color analysis
|
||||
_ = manaRegion
|
||||
var healthPct, manaPct float64
|
||||
|
||||
return plugin.VitalStats{}
|
||||
// Read health percentage from red-filled pixels in health orb
|
||||
if !healthRegion.Empty() {
|
||||
healthColor := vision.ColorRange{
|
||||
LowerH: d.config.Colors.HealthFilled.LowerH,
|
||||
UpperH: d.config.Colors.HealthFilled.UpperH,
|
||||
LowerS: d.config.Colors.HealthFilled.LowerS,
|
||||
UpperS: d.config.Colors.HealthFilled.UpperS,
|
||||
LowerV: d.config.Colors.HealthFilled.LowerV,
|
||||
UpperV: d.config.Colors.HealthFilled.UpperV,
|
||||
}
|
||||
healthPct = d.vision.ReadBarPercentage(frame, healthRegion, healthColor)
|
||||
}
|
||||
|
||||
// Read mana percentage from blue-filled pixels in mana orb
|
||||
if !manaRegion.Empty() {
|
||||
manaColor := vision.ColorRange{
|
||||
LowerH: d.config.Colors.ManaFilled.LowerH,
|
||||
UpperH: d.config.Colors.ManaFilled.UpperH,
|
||||
LowerS: d.config.Colors.ManaFilled.LowerS,
|
||||
UpperS: d.config.Colors.ManaFilled.UpperS,
|
||||
LowerV: d.config.Colors.ManaFilled.LowerV,
|
||||
UpperV: d.config.Colors.ManaFilled.UpperV,
|
||||
}
|
||||
manaPct = d.vision.ReadBarPercentage(frame, manaRegion, manaColor)
|
||||
}
|
||||
|
||||
return plugin.VitalStats{
|
||||
HealthPct: healthPct,
|
||||
ManaPct: manaPct,
|
||||
XPPct: 0.0, // TODO: Implement XP bar reading
|
||||
}
|
||||
}
|
||||
|
||||
// IsInGame returns true if health orb is visible.
|
||||
|
|
@ -68,21 +98,64 @@ func (d *Detector) IsInGame(frame image.Image) bool {
|
|||
}
|
||||
|
||||
func (d *Detector) isLoading(frame image.Image) bool {
|
||||
// TODO: Check for loading screen (mostly black with loading bar)
|
||||
return false
|
||||
// Check for loading screen by looking for mostly black screen
|
||||
// This is a simple heuristic - could be improved
|
||||
bounds := frame.Bounds()
|
||||
totalPixels := 0
|
||||
darkPixels := 0
|
||||
|
||||
// Sample every 10 pixels for performance
|
||||
step := 10
|
||||
for y := bounds.Min.Y; y < bounds.Max.Y; y += step {
|
||||
for x := bounds.Min.X; x < bounds.Max.X; x += step {
|
||||
c := frame.At(x, y)
|
||||
r, g, b, _ := c.RGBA()
|
||||
// Convert to 8-bit
|
||||
r, g, b = r>>8, g>>8, b>>8
|
||||
|
||||
totalPixels++
|
||||
// Consider pixel dark if all channels are below 30
|
||||
if r < 30 && g < 30 && b < 30 {
|
||||
darkPixels++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if totalPixels == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// If more than 70% of screen is dark, likely loading
|
||||
return float64(darkPixels)/float64(totalPixels) > 0.7
|
||||
}
|
||||
|
||||
func (d *Detector) isMainMenu(frame image.Image) bool {
|
||||
// TODO: Template match main menu elements
|
||||
// TODO: Template match main menu elements or check for specific colors/text
|
||||
// For now, this is a placeholder
|
||||
return false
|
||||
}
|
||||
|
||||
func (d *Detector) isCharacterSelect(frame image.Image) bool {
|
||||
// TODO: Template match character select screen
|
||||
// For now, this is a placeholder
|
||||
return false
|
||||
}
|
||||
|
||||
func (d *Detector) isInGame(frame image.Image) bool {
|
||||
// TODO: Check if health orb region contains red pixels
|
||||
return false
|
||||
// Check if health orb region contains red pixels indicating health
|
||||
healthRegion := d.services.Region("health_orb")
|
||||
if healthRegion.Empty() {
|
||||
return false
|
||||
}
|
||||
|
||||
healthColor := vision.ColorRange{
|
||||
LowerH: d.config.Colors.HealthFilled.LowerH,
|
||||
UpperH: d.config.Colors.HealthFilled.UpperH,
|
||||
LowerS: d.config.Colors.HealthFilled.LowerS,
|
||||
UpperS: d.config.Colors.HealthFilled.UpperS,
|
||||
LowerV: d.config.Colors.HealthFilled.LowerV,
|
||||
UpperV: d.config.Colors.HealthFilled.UpperV,
|
||||
}
|
||||
|
||||
return d.vision.HasColorInRegion(frame, healthRegion, healthColor)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue