remove demo game

This commit is contained in:
2026-05-25 21:28:17 +02:00
parent b1ea3447a8
commit 76f910ab36
75 changed files with 115 additions and 815 deletions

148
ui.inventory.go Normal file
View File

@@ -0,0 +1,148 @@
package pncdsl
import (
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/vector"
)
// InventoryBar shows the player's items as clickable slots. Left-click on
// a slot under the "look" verb prints the item's description; under any
// other verb, it toggles selection (the cursor "picks up" the item).
type InventoryBar struct {
Name string
Origin Point
Slots int
Cols int
SlotSize int
Gap int
PanelBG bool
}
func (b *InventoryBar) GetName() string { return b.Name }
func (b *InventoryBar) slotRect(idx int) Rectangle {
cols := b.Cols
if cols <= 0 {
cols = b.Slots
}
step := b.SlotSize + b.Gap
col := idx % cols
row := idx / cols
x := b.Origin.X + float64(col*step)
y := b.Origin.Y + float64(row*step)
return Rect(x, y, float64(b.SlotSize), float64(b.SlotSize))
}
func (b *InventoryBar) Tick(ctx *UICtx) {
g := ctx.Game
mp := g.Input.Point()
items := g.Inventory.Items()
// hover label: when over a slot with an item, show its description
for i := 0; i < min(b.Slots, len(items)); i++ {
if b.slotRect(i).Contains(mp) {
if it, ok := g.ItemManager.Get(items[i]); ok && it.Description != "" {
g.SetHoverLabel(it.Description)
} else {
g.SetHoverLabel(items[i])
}
break
}
}
if !g.Input.LeftClicked() {
return
}
for i := 0; i < min(b.Slots, len(items)); i++ {
if b.slotRect(i).Contains(mp) {
g.Input.ConsumeLeft()
name := items[i]
if g.SelectedVerb() == "look" {
if it, ok := g.ItemManager.Get(name); ok && it.Description != "" {
g.queueAction(Say("player", it.Description), "inv-look")
return
}
}
if g.Inventory.Selected() == name {
g.Inventory.Select("")
} else {
g.Inventory.Select(name)
}
return
}
}
}
func (b *InventoryBar) Draw(dst *ebiten.Image, ctx *UICtx) {
g := ctx.Game
th := g.Theme()
items := g.Inventory.Items()
if b.PanelBG {
last := b.slotRect(b.Slots - 1)
first := b.slotRect(0)
x := first.X - 2
y := first.Y - 2
w := (last.X + last.W) - first.X + 4
h := (last.Y + last.H) - first.Y + 4
vector.DrawFilledRect(dst, float32(x), float32(y), float32(w), float32(h), th.PanelBG, false)
}
for i := 0; i < b.Slots; i++ {
r := b.slotRect(i)
bg := th.InventorySlotBG
if i < len(items) && items[i] == g.Inventory.Selected() {
bg = th.InventorySlotSelectedBG
}
vector.DrawFilledRect(dst, float32(r.X), float32(r.Y), float32(r.W), float32(r.H), bg, false)
if i < len(items) {
it, ok := g.ItemManager.Get(items[i])
if !ok {
continue
}
img := g.loaded.image(g.AssetManager, it.Sprite)
sw, sh := img.Bounds().Dx(), img.Bounds().Dy()
if sw == 0 || sh == 0 {
continue
}
if g.loaded.isPlaceholder(it.Sprite) {
// draw a small colored square as a stand-in
inset := float32(2)
vector.DrawFilledRect(dst,
float32(r.X)+inset, float32(r.Y)+inset,
float32(r.W)-2*inset, float32(r.H)-2*inset,
th.VerbButtonSelectedBG, false)
continue
}
op := &ebiten.DrawImageOptions{}
inset := 1.0
tgtW := r.W - 2*inset
tgtH := r.H - 2*inset
op.GeoM.Scale(tgtW/float64(sw), tgtH/float64(sh))
op.GeoM.Translate(r.X+inset, r.Y+inset)
dst.DrawImage(img, op)
}
}
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
// BlocksClickAt — clickBlocker contract for the RadialVerbs widget.
func (b *InventoryBar) BlocksClickAt(p Point) bool {
if b.Slots <= 0 {
return false
}
first := b.slotRect(0)
last := b.slotRect(b.Slots - 1)
x := first.X
y := first.Y
w := last.X + last.W - first.X
h := last.Y + last.H - first.Y
return Rect(x, y, w, h).Contains(p)
}