gohud

HUD

← วิดเจ็ต

เรื่องเล็ก ๆ ต่างหากที่ตัดสินว่าหน้าจอดูดีหรือไม่

จะขัดเกลาพาเนลใหญ่ ๆ แค่ไหนก็ตาม สิ่งที่สะดุดตาเสมอคือเรื่องเล็ก ๆ: คำที่ถูกหักเป็นสองท่อน แสงเรืองที่ถูกตัดขาด สล็อตที่แน่นจนอึดอัด มีสี่เรื่องแบบนี้ถูกชี้ให้เห็นเมื่อ 2026-09-13 และถูกแก้ที่ตัววิดเจ็ตกับธีม ไม่ใช่แก้ที่หน้าจอเดโม ทุกหน้าจอจึงได้ผลลัพธ์เดียวกัน

อาการที่เห็นสาเหตุวิธีแก้
ปุ่ม Done ของโค้ชมาร์กกลายเป็น Don/e ปุ่มที่เปิดการตัดบรรทัดจะหักความกว้างของข้อความออกจากความกว้างขั้นต่ำของมัน พอถูกบีบ มันจึงหักกลางคำ GoStyle.fit_words(): คำเดียวไม่มีวันถูกตัดบรรทัด ถ้ามีหลายคำก็ตัดบรรทัดได้ แต่คำที่ยาวที่สุดต้องพอดีเสมอ โดยตัดสินจากข้อความที่แสดงจริง ไม่ใช่จากคีย์คำแปล และฟอร์มจะคำนวณใหม่ให้เมื่อเปลี่ยนภาษา
แสงเรืองของปุ่มเต็มความกว้างถูกตัดหายไปในแนวตั้งทางด้านซ้าย คอนเทนเนอร์ที่เลื่อนได้จะตัดทุกอย่างที่ขอบของมันโดยไม่มีข้อยกเว้น เหลือรอดแค่ด้านขวาเพราะมีร่องของรางเลื่อนช่วยไว้ GoScroll ขอยืมระยะขอบของพาเรนต์มาดันขอบของมันออกไป 12dp แล้วคืนกลับเข้ามาข้างใน — เนื้อหาอยู่ที่เดิม
เวลา ไอคอน และจำนวน ซ้อนกันเป็นแนวตั้งในสล็อต สามแถวอัดอยู่ใน 48dp ไอคอนขนาดใหญ่อยู่กลาง ปุ่มลัดอยู่มุมบนซ้าย จำนวนเป็นแบดจ์มุมล่างขวา และเวลาที่เหลือเป็นแบดจ์ทับบนไอคอน — พาเนลของแบดจ์มาจาก badge_box() ของสกิน
ดรอปดาวน์ที่แบนราบจนมองไม่ออกว่าเลือกอะไรอยู่ การชี้ที่รายการใช้พาเนลของปุ่ม ส่วนเครื่องหมายเรดิโอเป็นของเอนจินที่จางมาก พาเนลชี้เฉพาะของมันเอง (ย้อมสีเน้นอ่อน ๆ) เครื่องหมายเรดิโอชุดเดียวกับเช็กบ็อกซ์ และความสูงของรายการที่พอดีกับการกดด้วยนิ้ว
ดรอปดาวน์ที่เปิดอยู่ — พาเนลชี้ที่ย้อมสีเน้นอ่อน ๆ และเครื่องหมายเรดิโอของรายการที่เลือก
ดรอปดาวน์ — พาเนลชี้และเครื่องหมายเรดิโอ
ควิกสล็อตสี่ช่อง — ปุ่มลัดมุมบนซ้าย แบดจ์จำนวนมุมล่างขวา และช่องแรกมีแบดจ์เวลาที่เหลือ
สล็อต — แบดจ์ที่มุมและเวลาที่เหลือ (ไซไฟ)

ใส่คำอธิบายให้ปุ่มที่มีแต่ไอคอนด้วย GoStyle.icon_button(icon, action, -1, tooltip_key) — ทั้งทูลทิปสำหรับคนใช้เมาส์และชื่อเชิงการเข้าถึงสำหรับโปรแกรมอ่านหน้าจอ มาจากค่าเดียวกันนี้ gohud วาดทูลทิปเอง เพราะของเอนจินจะฉีกข้อความเป็นบรรทัดละตัวอักษรเมื่อการคำนวณความกว้าง ของมันผิดพลาด (วัดได้ว่ากว้างแค่ 1dp)

การ์ดโค้ชมาร์กหลบสิ่งที่ตรึงอยู่กับที่

เมื่อวางแนวนอน การ์ดเคยถูกส่งไปที่ขอบบนสุดหรือล่างสุด — ซึ่งเป็นที่อยู่ของแถบหัวและชิ้นส่วน HUD พอดี ในเดโมมันไปนั่งทับ → × ของแถบหัว ตอนนี้มันอยู่ระดับเดียวกับเป้าหมาย เดินอ้อม GoHudAnchor ทุกอันที่จองพื้นที่ไว้ และรับสิ่งอื่นที่ต้องหลบผ่าน keep_clear มันขยับด้วยระยะที่สั้นที่สุดที่พ้นสิ่งกีดขวางโดยไม่บังเป้าหมาย และจะอยู่นิ่งถ้าหน้าจอเล็กเกินกว่าจะหลบได้ครบ — ทับกันยังดีกว่าหายไปเลย ความลึกของมัน — ที่ทำให้มันอ่านว่าลอยอยู่เหนือหน้าเนื้อหา — มาจากค่าปรับของสกิน (float_shadow_size, float_shadow_lift, float_shadow_alpha; สกินมุมตัดเฉียงใช้ float_glow_size)

tour.keep_clear = [header_bar, toolbar]   # สิ่งที่ตรึงอยู่กับที่แต่ไม่ใช่แองเคอร์

หน้าจอที่มีเมาส์และคีย์บอร์ด

นิ้วไม่มีสถานะ hover ถ้าพัฒนาโดยคิดถึงแต่มือถือ จะมีสองสถานะที่มีเฉพาะบนเดสก์ท็อปหลุดการตรวจไป — และหนึ่งในนั้นก็พังจริง ๆ: วงแหวนโฟกัสของ gohud มองไม่เห็นเลยบนปุ่มหลัก เพราะพาเนลใช้สีเน้น และวงแหวนก็ใช้สีเน้นเหมือนกัน: 1.00:1 คือสีเดียวกันวาดทับตัวเอง เมื่อไล่ด้วยคีย์บอร์ด จึงไม่มีทางรู้เลยว่าตอนนี้อยู่ตรงไหน

แถวปุ่มชุดเดียวกันในสามสถานะ — ปกติ เมาส์ชี้ และโฟกัสจากคีย์บอร์ด
จากบนลงล่าง: ปกติ · เมาส์ชี้ · โฟกัส ปุ่มแบบทึบได้วงแหวนที่ตัดกับพาเนลของมันเอง

ปุ่มแบบทึบ (GoPrimaryButton, GoDangerSolidButton) ใช้วงแหวนที่ ตัดกับพาเนลของตัวเอง — สีเข้มบนธีมมืด สีขาวบนธีมสว่าง และวงเล็บเล็งเป้าสีเข้มในธีมไซไฟ ตัวตรวจคอนทราสต์วัดวงแหวนโฟกัสเทียบกับพาเนลที่มันวางอยู่ กฎนี้จึงอยู่รอดแม้เปลี่ยนจานสี (WCAG 2.4.11 กำหนดไว้ที่ 3:1 สำหรับตัวบอกโฟกัส)

วิดเจ็ต HUD

GoHudAnchor — เก้าตำแหน่ง

เคารพเซฟแอเรียและระยะขอบจอ ใส่ landscape_spot ให้มันแล้วมันจะย้ายที่เมื่อวางแนวนอน — ปุ่มควบคุมที่อยู่กลางล่างในแนวตั้งจึงไปอยู่มุมล่างขวาแทนได้

ทำไมต้องมีมัน ถ้าเขียนแองเคอร์และออฟเซ็ตด้วยมือทีละชิ้น HUD ค่าจะเพี้ยนไปเรื่อย ๆ: แถบพลังชีวิตไปโผล่ใต้รอยบากกล้องบนเครื่องที่มีนอตช์ และปุ่มควบคุมไปตกบนแถบท่าทางเมื่อวางแนวนอน เลขคณิตพวกนั้นถูกรวมไว้ที่เดียว

กันเนื้อหาไม่ให้มุดเข้าไปใต้ HUD

เมื่อหน้าจอที่เลื่อนได้ต้องแบ่งพื้นที่กับ HUD เนื้อหาจะเลื่อนลอดเข้าไปข้างใต้ แล้วข้อความสองชุด จะทับกันจนอ่านไม่ออกทั้งคู่ เรื่องนี้เกิดขึ้นสองครั้งในแอดออนนี้: ข้อความตัวอย่างในช่องกรอกถูกบีบ โผล่ออกมาระหว่างควิกสล็อต และปุ่มสวิตช์ในหน้าตั้งค่าไปตกบนแถบพลังชีวิต

form.avoid_hud = true                  # หลบทุก GoHudAnchor ที่มองเห็นอยู่
joystick_anchor.reserve_space = false  # …ยกเว้นอันที่โผล่มาเฉพาะตอนมีนิ้วแตะ

สี่เหลี่ยมแต่ละผืนจะถูกหลบไปในทิศที่เสียพื้นที่น้อยที่สุด แถบที่อยู่มุมบนขวาจะถูกหลบลงล่าง บนมือถือแนวตั้ง (คิดเป็น 13% ของความสูง) และหลบไปด้านข้างเมื่อวางแนวนอน (21% ของความกว้าง) — เพราะถ้าหลบในแนวตั้งตอนวางแนวนอนจะเสียพื้นที่ถึง 27% ของหน้าจอ พื้นที่ที่ยอมเสียไปแล้ว จะถูกหักออกก่อนวัดสี่เหลี่ยมผืนถัดไป

ชิ้นส่วน HUD ก็ชนกันเองได้เหมือนกัน

เก้าตำแหน่งนั้นแบ่งหน้าจอออกเป็นส่วน ๆ แต่ไม่ได้รับประกันว่าชิ้นส่วนแต่ละชิ้นจะไม่ชนกัน สแน็กบาร์กว้าง ๆ ที่กลางบนเคยไปลงเต็ม ๆ บนแถบพลังชีวิตที่มุมบนขวา จนบังตัวเลขไว้หมด — อ่านไม่ออกเลยว่าเหลือพลังชีวิตเท่าไร

notice_anchor.avoid_peers = true      # ไปลงใต้ HUD ที่อยู่กับที่
notice_anchor.reserve_space = false   # และไม่ดันหน้าเนื้อหาระหว่างที่มันโผล่อยู่

มันหลบในแนวตั้งเท่านั้น — ถ้าหลบด้านข้างด้วย toast ที่จัดกึ่งกลางจะไปโผล่คนละที่ทุกครั้งที่แสดง และมันหลบเฉพาะชิ้นส่วนที่ไม่ได้กำลังหลบอยู่เหมือนกัน: ถ้าต่างฝ่ายต่างยอมหลบ ทั้งคู่จะสลับที่กันไปไม่มีวันจบ

GoBar — พลังชีวิต มานา ค่าประสบการณ์

var hp := GoBar.new()
hp.label_text = "HP"
hp.ink = GoUi.color(GoTheme.DANGER_FILL)   # โทเคนที่ใช้เป็นสีเติมอย่างเดียว
hp.set_values(320, 500)                     # "320 / 500"

การเปลี่ยนค่าจะไหลนุ่มนวลใน 0.18 วินาที — แถบพลังชีวิตที่กระโดดพรวดไม่ได้บอกคุณว่าโดนหนักแค่ไหน ตั้ง reduce_motion แล้วมันจะเปลี่ยนทันที ตัวเลขใหญ่ ๆ จะถูกย่อเป็น 12.3k เพื่อไม่ให้ความกว้างของแถบกระตุกไปมาตามจำนวนหลักที่เพิ่มลด

GoSlot — ควิกสล็อตหนึ่งช่อง

ไอคอน จำนวน คูลดาวน์ และปุ่มลัด อยู่บนหน้าเดียวกัน การเอาแบดจ์ไปห้อยรอบวงกลมเล็ก ๆ จะทำให้แต่ละสล็อตกว้างไม่เท่ากัน แล้วทั้งแถวก็โยกเยก

ขนาดที่เห็นกับขนาดที่กดได้ไม่เท่ากัน สล็อตที่เรียงชิดกันมีกล่องสัมผัส 48dp ที่ซ้อนทับกัน พื้นที่ซ้อนนั้นจะตกเป็นของสล็อตที่จุดกึ่งกลางใกล้กว่า — บอกให้พวกมันรู้จักกันผ่าน touch_peers

keyboard_focus ปิดไว้เป็นค่าเริ่มต้น สล็อตแปดช่องเรียงกันจึงไม่ไปขวางระหว่างผู้ใช้คีย์บอร์ด กับคอนโทรลในหน้าตั้งค่าทุกตัวในลำดับ Tab เปิดมันเมื่อคีย์บอร์ดหรือเกมแพดเป็นอินพุตเดียวที่มี

GoJoystick — จอยสติ๊กเสมือน

โหมดพฤติกรรม
FIXEDอยู่ที่เดิมเสมอ — หาเจอง่ายโดยไม่ต้องมอง
FOLLOWโผล่ขึ้นตรงที่นิ้วโป้งลง
RELATIVEตามนิ้วต่อไปเรื่อย ๆ หลังโผล่ขึ้นมาแล้ว — สบายสำหรับการเคลื่อนที่นาน ๆ

Vector2 ที่ได้จาก moved มีความยาว 0–1 คุณจึงคูณเข้ากับความเร็วได้ตรง ๆ และค่านี้ไม่แปรตามขนาดหน้าจอหรือ DPI

GoIconButton — ดูเล็ก แต่กดง่าย

ปลอดภัยเฉพาะตอนที่เพื่อนบ้านของมันไม่รับอินพุต ถ้าพื้นที่ที่ขยายออกไปครอบปุ่มถัดไป ปุ่มนั้นจะหยุดตอบสนอง ปุ่มไอคอนที่วางเรียงชิดกันต้องใช้ touch_peers