feat: initial game screen and input window defs
This commit is contained in:
parent
331c625220
commit
024eb0c2bb
6 changed files with 156 additions and 74 deletions
60
main.go
60
main.go
|
@ -1,67 +1,22 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
|
|
||||||
. "github.com/gbin/goncurses"
|
. "github.com/gbin/goncurses"
|
||||||
"gitlab.com/stvnliu/ai_game/menu"
|
"gitlab.com/stvnliu/ai_game/menu"
|
||||||
|
"gitlab.com/stvnliu/ai_game/utils/windows"
|
||||||
. "gitlab.com/stvnliu/ai_game/utils/types"
|
. "gitlab.com/stvnliu/ai_game/utils/types"
|
||||||
// "gitlab.com/stvnliu/ai_game/utils/window_helper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
INPUT_PROMPT_LENGTH = 40
|
LEFT_PAD = 3
|
||||||
INPUT_PROMPT_HEIGHT = 10
|
RIGHT_PAD = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
func InputPrompt(scr *Window) string {
|
|
||||||
my, mx := scr.MaxYX()
|
|
||||||
w, err := NewWindow(INPUT_PROMPT_HEIGHT, INPUT_PROMPT_LENGTH, (my/2)-(INPUT_PROMPT_HEIGHT/2), (mx/2)-(INPUT_PROMPT_LENGTH/2))
|
|
||||||
if err != nil {
|
|
||||||
panic("Oh no sth went wrong in input!!")
|
|
||||||
}
|
|
||||||
w.Box(0, 0)
|
|
||||||
Echo(true)
|
|
||||||
msg := "Game name: "
|
|
||||||
w.MovePrint(0, 1, " New game information ")
|
|
||||||
w.MovePrint(2, 2, msg)
|
|
||||||
w.Move(2, 2+len(msg))
|
|
||||||
input, err := w.GetString(16) // character input box
|
|
||||||
if err != nil {
|
|
||||||
panic("Oh no sth went wrong in input 2!!")
|
|
||||||
}
|
|
||||||
w.MovePrint(3, 2, input)
|
|
||||||
w.Refresh()
|
|
||||||
Echo(false)
|
|
||||||
for {
|
|
||||||
ch := w.GetChar()
|
|
||||||
switch Key(ch) {
|
|
||||||
case 'q':
|
|
||||||
return input
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func NewGame(scr *Window) {
|
|
||||||
//_, _ := scr.MaxYX()
|
|
||||||
game_name := InputPrompt(scr)
|
|
||||||
// create new game state
|
|
||||||
// println("Creating new game %v...", game_name)
|
|
||||||
game := Game{
|
|
||||||
SaveGame: game_name,
|
|
||||||
LastSaved: time.Now(),
|
|
||||||
}
|
|
||||||
my_npcs := MakeNpcs()
|
|
||||||
game.DataStored.Npcs = my_npcs
|
|
||||||
scr.MovePrintf(1, 2, "Created new game \"%v\"!", game.SaveGame)
|
|
||||||
for i := 0; i < len(game.DataStored.Npcs); i++ {
|
|
||||||
scr.MovePrintf(2+i, 2, "Initialising \"%v\"...", game.DataStored.Npcs[i].Name)
|
|
||||||
scr.MovePrintf(3+i, 2, "Found NPC query string!")
|
|
||||||
scr.Refresh()
|
|
||||||
|
|
||||||
}
|
|
||||||
// println(game.DataStored.Npcs[0].Name)
|
|
||||||
}
|
|
||||||
func Continue(scr *Window) {
|
func Continue(scr *Window) {
|
||||||
|
response := windows.InputPrompt(scr, "Continue!!", "Your answer:", 20)
|
||||||
|
scr.MovePrintf(5, 2, "Resp: %v", response)
|
||||||
// recover state from last save?
|
// recover state from last save?
|
||||||
}
|
}
|
||||||
func Exit(scr *Window) {
|
func Exit(scr *Window) {
|
||||||
|
@ -77,6 +32,9 @@ func main() {
|
||||||
{Name: "New game!", Operation: NewGame},
|
{Name: "New game!", Operation: NewGame},
|
||||||
{Name: "Continue!", Operation: Continue},
|
{Name: "Continue!", Operation: Continue},
|
||||||
{Name: "Exit!", Operation: Exit},
|
{Name: "Exit!", Operation: Exit},
|
||||||
|
{Name: "Test function!", Operation: func(scr *Window) {
|
||||||
|
|
||||||
|
},},
|
||||||
}
|
}
|
||||||
menu.CreateMenu(scr, menu_items)
|
menu.CreateMenu(scr, menu_items)
|
||||||
}
|
}
|
||||||
|
|
20
menu/menu.go
20
menu/menu.go
|
@ -2,7 +2,7 @@ package menu
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "github.com/gbin/goncurses"
|
. "github.com/gbin/goncurses"
|
||||||
. "gitlab.com/stvnliu/ai_game/utils/types"
|
. "gitlab.com/stvnliu/ai_game/utils/types"
|
||||||
// "log"
|
// "log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,13 +21,13 @@ func CreateMenu(stdscr *Window, menu []GameMenuItem) {
|
||||||
stdscr.Clear()
|
stdscr.Clear()
|
||||||
stdscr.Keypad(true)
|
stdscr.Keypad(true)
|
||||||
|
|
||||||
my, mx := stdscr.MaxYX()
|
_, mx := stdscr.MaxYX()
|
||||||
y, x := 2, (mx/2)-(WIDTH/2)
|
y, x := 2, (mx/2)-(WIDTH/2)
|
||||||
|
|
||||||
win, _ := NewWindow(HEIGHT, WIDTH, y, x)
|
win, _ := NewWindow(HEIGHT, WIDTH, y, x)
|
||||||
win.Keypad(true)
|
win.Keypad(true)
|
||||||
|
|
||||||
stdscr.Print("Welcome to Rulmarc, the Role-playing game using LLMs")
|
stdscr.Print("Welcome to Rulmarc, the Role-playing game using LLMs (Use q to quit the current window)")
|
||||||
stdscr.Refresh()
|
stdscr.Refresh()
|
||||||
|
|
||||||
printmenu(win, menu, active)
|
printmenu(win, menu, active)
|
||||||
|
@ -36,6 +36,8 @@ func CreateMenu(stdscr *Window, menu []GameMenuItem) {
|
||||||
ch := stdscr.GetChar()
|
ch := stdscr.GetChar()
|
||||||
switch Key(ch) {
|
switch Key(ch) {
|
||||||
case 'q':
|
case 'q':
|
||||||
|
win.Erase()
|
||||||
|
win.Refresh()
|
||||||
return
|
return
|
||||||
case KEY_UP:
|
case KEY_UP:
|
||||||
if active == 0 {
|
if active == 0 {
|
||||||
|
@ -50,15 +52,13 @@ func CreateMenu(stdscr *Window, menu []GameMenuItem) {
|
||||||
active += 1
|
active += 1
|
||||||
}
|
}
|
||||||
case KEY_RETURN, KEY_ENTER, Key('\r'):
|
case KEY_RETURN, KEY_ENTER, Key('\r'):
|
||||||
stdscr.MovePrintf(my-2, 0, "Choice #%d: %s selected",
|
menu[active].Operation(stdscr)
|
||||||
active,
|
|
||||||
menu[active].Name)
|
|
||||||
menu[active].Operation(stdscr)
|
|
||||||
stdscr.ClearToEOL()
|
stdscr.ClearToEOL()
|
||||||
|
win.Erase()
|
||||||
|
win.Refresh()
|
||||||
stdscr.Refresh()
|
stdscr.Refresh()
|
||||||
|
return
|
||||||
default:
|
default:
|
||||||
stdscr.MovePrintf(my-2, 0, "Character pressed = %3d/%c",
|
|
||||||
ch, ch)
|
|
||||||
stdscr.ClearToEOL()
|
stdscr.ClearToEOL()
|
||||||
stdscr.Refresh()
|
stdscr.Refresh()
|
||||||
}
|
}
|
||||||
|
|
69
new_game.go
Normal file
69
new_game.go
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
. "github.com/gbin/goncurses"
|
||||||
|
. "gitlab.com/stvnliu/ai_game/utils/types"
|
||||||
|
"gitlab.com/stvnliu/ai_game/utils/windows"
|
||||||
|
"gitlab.com/stvnliu/ai_game/utils/helper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewGame(scr *Window) {
|
||||||
|
//_, _ := scr.MaxYX()
|
||||||
|
game_name := windows.InputPrompt(scr, " New game information ", "Game name: ", 20)
|
||||||
|
// create new game state
|
||||||
|
// println("Creating new game %v...", game_name)
|
||||||
|
game := Game{
|
||||||
|
SaveGame: game_name,
|
||||||
|
LastSaved: time.Now(),
|
||||||
|
}
|
||||||
|
my_npcs := MakeNpcs()
|
||||||
|
game.DataStored.Npcs = my_npcs
|
||||||
|
scr.MovePrintf(1, 2, "Created new game \"%v\"!", game.SaveGame)
|
||||||
|
for i := 0; i < len(game.DataStored.Npcs); i++ {
|
||||||
|
scr.MovePrintf(2+i, 2, "Initialising \"%v\"...", game.DataStored.Npcs[i].Name)
|
||||||
|
scr.MovePrintf(3+i, 2, "Found NPC query string!")
|
||||||
|
scr.Refresh()
|
||||||
|
|
||||||
|
}
|
||||||
|
my, mx := scr.MaxYX()
|
||||||
|
|
||||||
|
// Initialise container box for game content
|
||||||
|
w, err := NewWindow(my-1, mx-1, 1, 1)
|
||||||
|
if err != nil {
|
||||||
|
panic("Oh shit something happened that shouldn't")
|
||||||
|
}
|
||||||
|
w.Box(0, 0)
|
||||||
|
input_window, input_window_error := NewWindow(6,mx-3,my-7,2)
|
||||||
|
if input_window_error != nil {
|
||||||
|
panic("Oh no")
|
||||||
|
}
|
||||||
|
input_window.Box(1, 1)
|
||||||
|
input_window.MovePrint(1, 1, "> ")
|
||||||
|
input_window.Move(1, 3)
|
||||||
|
w.Refresh()
|
||||||
|
input_window.Refresh()
|
||||||
|
texts := []string {
|
||||||
|
"Hello world!!",
|
||||||
|
"Welcome to R.U.L.M.A.R.C.",
|
||||||
|
"This is an experimental game project that uses Large Language Models to power realistically rendered characters.",
|
||||||
|
"============ Copyright 2024 @ Zhongheng Liu & Zhiyong He =============",
|
||||||
|
"Try it! Put in some characters in the input box below!",
|
||||||
|
"Please wait while we boot some Artificial Intelligencce models for the first part of the game...",
|
||||||
|
}
|
||||||
|
for i := 0; i < len(texts); i++ {
|
||||||
|
helper.IncrementalPrint(w, texts[i], 1+i, 1, 500)
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
ch := w.GetChar()
|
||||||
|
switch Key(ch) {
|
||||||
|
case 'q':
|
||||||
|
w.Erase()
|
||||||
|
w.Refresh()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Refresh()
|
||||||
|
}
|
||||||
|
// println(game.DataStored.Npcs[0].Name)
|
||||||
|
}
|
19
utils/helper/incremental_print.go
Normal file
19
utils/helper/incremental_print.go
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
package helper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
. "github.com/gbin/goncurses"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IncrementalPrint(scr *Window, text string, from_y int, from_x int, interval_millis int) {
|
||||||
|
for i:=0; i < len(text); i++ {
|
||||||
|
ch := string([]rune(text)[i])
|
||||||
|
_, mx := scr.MaxYX()
|
||||||
|
cy := i / mx + 2 + from_y
|
||||||
|
cx := i % mx + 2
|
||||||
|
scr.MovePrint(cy, cx, ch)
|
||||||
|
time.Sleep( time.Duration(1000 / len(text)) * time.Millisecond)
|
||||||
|
scr.Refresh()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +0,0 @@
|
||||||
package window_helper
|
|
||||||
import (
|
|
||||||
. "github.com/gbin/goncurses"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CreateMenu(win *Window, menu_string []string) {
|
|
||||||
x, y := 2, 2
|
|
||||||
win.Clear()
|
|
||||||
win.Box(0, 0)
|
|
||||||
for i, str := range menu_string {
|
|
||||||
win.MovePrint(y+i, x, str)
|
|
||||||
}
|
|
||||||
}
|
|
49
utils/windows/windows.go
Normal file
49
utils/windows/windows.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package windows
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/gbin/goncurses"
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
LEFT_PAD = 2
|
||||||
|
RIGHT_PAD = 2
|
||||||
|
)
|
||||||
|
func InputPrompt(
|
||||||
|
scr *Window,
|
||||||
|
title string,
|
||||||
|
prompt string,
|
||||||
|
input_length int,
|
||||||
|
) string {
|
||||||
|
height, length := 8, len(prompt)+input_length+LEFT_PAD+RIGHT_PAD
|
||||||
|
my, mx := scr.MaxYX()
|
||||||
|
w, err := NewWindow(
|
||||||
|
height,
|
||||||
|
length,
|
||||||
|
(my/2)-(height/2),
|
||||||
|
(mx/2)-(length/2),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
panic("Oh no sth went wrong in input!!")
|
||||||
|
}
|
||||||
|
w.Box(0, 0)
|
||||||
|
Echo(true)
|
||||||
|
w.MovePrint(0, 1, title)
|
||||||
|
w.MovePrint(2, 2, prompt)
|
||||||
|
w.Move(2, 2+len(prompt))
|
||||||
|
input, err := w.GetString(input_length) // character input box
|
||||||
|
if err != nil {
|
||||||
|
panic("Oh no sth went wrong in input 2!!")
|
||||||
|
}
|
||||||
|
w.MovePrintf(height-2, 2, "Press q to continue...")
|
||||||
|
w.Refresh()
|
||||||
|
Echo(false)
|
||||||
|
for {
|
||||||
|
ch := w.GetChar()
|
||||||
|
switch Key(ch) {
|
||||||
|
case 'q':
|
||||||
|
w.Erase()
|
||||||
|
w.Refresh()
|
||||||
|
w.Delete()
|
||||||
|
return input
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue