Add game components 246-268; data.DrawSlot, Canvas.TextVeil
Health, mana and experience bars, quarter hearts, lives, a spinning coin counter, score board, stage timer, minimap with fog, compass, hotbar, paper-doll equipment, skill tree, skill buttons with cooldown wipes, status effects, a boss bar, damage numbers, quest log and tracker, party frames, character sheet, level-up screen and shop. data exports DrawSlot so every slot looks alike; pixel adds TextVeil for dissolving text. Messages the font cannot draw are fixed and TestMessagesHaveGlyphs holds every message to the font.
This commit is contained in:
42 files changed
+3260
-26
No files matched your search
@@ -268,3 +268,26 @@ func boolInt(b bool) int {
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func TestTextVeilKeepsDotsBelowTheLevel(t *testing.T) {
|
||||
plain := canvas(t, 40, 40, func(g pixel.Canvas) { g.Text(2, 2, "HM", pixel.Ink, 2) })
|
||||
for _, level := range []int{0, 8, 16} {
|
||||
veil := canvas(t, 40, 40, func(g pixel.Canvas) { g.TextVeil(2, 2, "HM", pixel.Ink, level, 2) })
|
||||
kept, all := 0, 0
|
||||
for y := range 40 {
|
||||
for x := range 40 {
|
||||
ink, got := plain.at(x, y) == pixel.Ink, veil.at(x, y) == pixel.Ink
|
||||
if got && (!ink || pixel.Bayer(x, y) >= level) {
|
||||
t.Fatalf("level %d: dot %d,%d drawn", level, x, y)
|
||||
}
|
||||
if ink && pixel.Bayer(x, y) < level && !got {
|
||||
t.Fatalf("level %d: dot %d,%d missing", level, x, y)
|
||||
}
|
||||
kept, all = kept+boolInt(got), all+boolInt(ink)
|
||||
}
|
||||
}
|
||||
if want := all * level / 16; kept < want-all/8 || kept > want+all/8 {
|
||||
t.Fatalf("level %d kept %d of %d dots", level, kept, all)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,3 +40,21 @@ func checkLevel(level int) {
|
||||
panic(fmt.Sprintf("pixel: dither level %d outside 0–16", level))
|
||||
}
|
||||
}
|
||||
|
||||
// TextVeil draws s, keeping glyph dots below the dither level.
|
||||
func (g Canvas) TextVeil(x, y int, s string, ink Slot, level, scale int) {
|
||||
checkLevel(level)
|
||||
checkScale(scale)
|
||||
for _, r := range s {
|
||||
gl := glyphOf(r)
|
||||
gx := x + gl.x*scale
|
||||
for j := range gl.h * scale {
|
||||
yy := y + gl.top()*scale + j
|
||||
row := bayer[(g.gy+yy)&3]
|
||||
runs(gl.w*scale, func(i int) bool {
|
||||
return gl.on(i/scale, j/scale) && row[(g.gx+gx+i)&3] < level
|
||||
}, func(a, b int) { g.Rect(gx+a, yy, b-a, 1, ink) })
|
||||
}
|
||||
x += gl.adv * scale
|
||||
}
|
||||
}
|
||||
+10
-2
@@ -24,14 +24,18 @@ var messages = map[Locale]map[string]string{
|
||||
"just_now": "JUST NOW", "min_ago": "%d MIN AGO", "hours_ago": "%d H AGO", "yesterday": "YESTERDAY", "days_ago": "%d DAYS AGO",
|
||||
"in_min": "IN %d MIN", "in_hours": "IN %d H", "tomorrow": "TOMORROW", "in_days": "IN %d DAYS",
|
||||
"spring": "SPRING", "summer": "SUMMER", "autumn": "AUTUMN", "winter": "WINTER", "minutes": "MIN", "seconds": "SEC",
|
||||
"level": "LV %d", "score": "SCORE", "hi_score": "HI-SCORE", "time": "TIME", "compass": "N E S W",
|
||||
"head": "HEAD", "body": "BODY", "weapon": "WEAPON", "shield": "SHIELD", "ring": "RING",
|
||||
"points": "POINTS %d", "learned": "LEARNED", "can_learn": "CAN LEARN", "locked": "LOCKED", "ready": "READY",
|
||||
"buy": "BUY", "sell": "SELL", "done": "DONE", "tracking": "TRACKING",
|
||||
},
|
||||
Zh: {
|
||||
"ok": "确定", "cancel": "取消", "yes": "是", "no": "否", "close": "关闭",
|
||||
"continue": "继续?", "game_over": "游戏结束", "loading": "读取中",
|
||||
"search": "搜索", "empty": "空空如也", "minimize": "最小化", "resize": "调整大小",
|
||||
"scroll_up": "向上滚动", "scroll_down": "向下滚动",
|
||||
"scroll_up": "向上翻动", "scroll_down": "向下翻动",
|
||||
"up": "上", "down": "下", "left": "左", "right": "右", "disabled": "已禁用",
|
||||
"remove": "移除", "online": "在线", "away": "离开", "busy": "忙碌", "offline": "离线",
|
||||
"remove": "移除", "online": "在线", "away": "离开", "busy": "繁忙", "offline": "离线",
|
||||
"gold": "金", "silver": "银", "bronze": "铜",
|
||||
"common": "普通", "uncommon": "优秀", "rare": "稀有", "epic": "史诗", "legendary": "传说",
|
||||
"hold": "长按确认", "del": "删", "end": "完", "lives": "命数 +30!",
|
||||
@@ -46,6 +50,10 @@ var messages = map[Locale]map[string]string{
|
||||
"just_now": "刚刚", "min_ago": "%d 分钟前", "hours_ago": "%d 小时前", "yesterday": "昨天", "days_ago": "%d 天前",
|
||||
"in_min": "%d 分钟后", "in_hours": "%d 小时后", "tomorrow": "明天", "in_days": "%d 天后",
|
||||
"spring": "春", "summer": "夏", "autumn": "秋", "winter": "冬", "minutes": "分", "seconds": "秒",
|
||||
"level": "等级 %d", "score": "得分", "hi_score": "最高分", "time": "时间", "compass": "北 东 南 西",
|
||||
"head": "头", "body": "身体", "weapon": "武器", "shield": "盾牌", "ring": "戒指",
|
||||
"points": "点数 %d", "learned": "已学会", "can_learn": "可学习", "locked": "未解锁", "ready": "就绪",
|
||||
"buy": "购买", "sell": "出售", "done": "完成", "tracking": "追踪中",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -26,3 +26,15 @@ func TestMessagesCoverBothLocales(t *testing.T) {
|
||||
}()
|
||||
Kit{locale: En}.Msg("no_such_key")
|
||||
}
|
||||
|
||||
func TestMessagesHaveGlyphs(t *testing.T) {
|
||||
for loc, m := range messages {
|
||||
for key, s := range m {
|
||||
for _, r := range s {
|
||||
if _, ok := font12.find(r); !ok && r != ' ' {
|
||||
t.Errorf("locale %d message %q: the font has no %q", loc, key, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user