Skip to content
This repository has been archived by the owner on Feb 2, 2024. It is now read-only.

2D GUI #20

Merged
merged 6 commits into from
Jan 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/fonts/GlassAntiqua-Regular.ttf
Binary file not shown.
Binary file modified assets/textures/charmap.bmp
Binary file not shown.
9 changes: 9 additions & 0 deletions assets/ui/helloworld.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<List xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="schema.xsd"
orientation="vertical">
<Text id="counter" color="#ff1493">0</Text>
<Button id="btn">
<Text>Click me!</Text>
</Button>
</List>
61 changes: 61 additions & 0 deletions assets/ui/schema.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="Image">
<xs:complexType>
<xs:attribute name="src" type="xs:string" use="required" />
<xs:attribute name="width" type="xs:string" use="required" />
<xs:attribute name="height" type="xs:string" use="required" />
<xs:attribute name="id" type="xs:string" />
</xs:complexType>
</xs:element>

<xs:element name="Text">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="id" type="xs:string" />
<xs:attribute name="font" type="xs:string" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>

<!-- -->

<xs:element name="List">
<xs:complexType>
<xs:sequence>
<xs:any minOccurs="1" maxOccurs="unbounded" processContents="strict" />
</xs:sequence>
<xs:attribute name="orientation" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="vertical" />
<xs:enumeration value="horizontal" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>

<xs:element name="Button">
<xs:complexType>
<xs:sequence>
<xs:any minOccurs="1" maxOccurs="1" processContents="strict" />
</xs:sequence>
<xs:attribute name="id" use="required" />
</xs:complexType>
</xs:element>

<!-- Document / Root needs at least ParentElement or ChildElement-->

<xs:element name="Document">
<xs:complexType>
<xs:sequence>
<xs:any minOccurs="1" maxOccurs="unbounded" processContents="strict" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
3 changes: 1 addition & 2 deletions cmd/game/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func main() {

l, err := level.Load("assets/levels/level1.bmlvl")
if err != nil {
panic(err)
log.Fatal(err)
}
level.Set(l)

Expand All @@ -25,7 +25,6 @@ func main() {

// game loop
for core.Running() {
firstperson.GetMouseInput()
firstperson.MovePlayer()
err = firstperson.RenderViewport()
if err != nil {
Expand Down
48 changes: 48 additions & 0 deletions engine/core/window.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package core

import (
"runtime"

"github.com/charmbracelet/log"
"github.com/veandco/go-sdl2/sdl"
)
Expand Down Expand Up @@ -143,6 +145,8 @@ func Start(t string) {
log.Fatal("window already started")
}

runtime.LockOSThread()

var err error

title = t
Expand Down Expand Up @@ -229,6 +233,7 @@ func Stop() {
_ = window.Destroy()
_ = renderer.Destroy()
sdl.Quit()
log.Print("Engine stopped")
}

// Running returns whether the game loop should continue or not.
Expand All @@ -242,7 +247,33 @@ func Running() bool {
return running
}

// Mouse states.
var (
// MouseX is the current X position of the mouse.
MouseX int32
// MouseY is the current Y position of the mouse.
MouseY int32
// MouseDeltaX is the change in X position of the mouse since the last frame.
MouseDeltaX int32
// MouseDeltaY is the change in Y position of the mouse since the last frame.
MouseDeltaY int32
// MouseState is the current state of the mouse.
MouseState uint32
)

func eventLoop() {
var mouseX, mouseY int32
mouseX, mouseY, MouseState = sdl.GetMouseState()
if cursorLocked {
MouseDeltaX = mouseX - MouseX
MouseDeltaY = mouseY - MouseY
} else {
MouseDeltaX = 0
MouseDeltaY = 0
}
MouseX = mouseX
MouseY = mouseY

keyStates = sdl.GetKeyboardState()
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
switch event.GetType() {
Expand All @@ -257,13 +288,30 @@ func eventLoop() {
// Present draws the frame to the screen.
// Call this at the very end of the game loop.
func Present() {
if cursorHover {
sdl.SetCursor(sdl.CreateSystemCursor(sdl.SYSTEM_CURSOR_HAND))
} else {
sdl.SetCursor(sdl.CreateSystemCursor(sdl.SYSTEM_CURSOR_ARROW))
}
renderer.Present()
frameTime := uint32(sdl.GetTicks64() - frameStartTime)
if frameTime < targetFrameTime {
sdl.Delay(targetFrameTime - frameTime)
}

cursorHover = false
}

func FPS() float32 {
return 1.0 / DeltaTime
}

func ScreenRect() *sdl.Rect {
return &sdl.Rect{W: width, H: height}
}

var cursorHover = false

func NotifyCursorHover() {
cursorHover = true
}
18 changes: 1 addition & 17 deletions engine/firstperson/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,12 @@ const (
turnSpeed float32 = 0.1
)

var (
MouseX int32
MouseDeltaX int32
MouseState uint32
)

func GetMouseInput() {
MouseX, _, MouseState = sdl.GetMouseState()
if core.IsCursorLocked() {
MouseDeltaX = MouseX - core.CenterX()
core.Window().WarpMouseInWindow(core.CenterX(), core.CenterY())
} else {
MouseDeltaX = 0
}
}

func KeyDown(key uint8) bool {
return core.KeyStates()[key] != 0
}

func MovePlayer() {
core.P.Angle += float32(MouseDeltaX) * turnSpeed * core.DeltaTime
core.P.Angle += float32(core.MouseDeltaX) * turnSpeed * core.DeltaTime

if KeyDown(KeyForward) {
core.P.Speed = 1
Expand Down
2 changes: 0 additions & 2 deletions engine/firstperson/window.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@ package firstperson

import (
"github.com/bloodmagesoftware/bloodmage-engine/engine/core"
"github.com/bloodmagesoftware/bloodmage-engine/engine/level"
"github.com/charmbracelet/log"
"github.com/chewxy/math32"
)

func Init() {
level.CollisionRound = 0.125
f := func() {
log.Debug("firstperson window resize")
screenDist = core.HalfWidthF() / math32.Tan(halfFov)
Expand Down
107 changes: 90 additions & 17 deletions engine/font/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,101 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://github.com/bloodmagesoftware/bloodmage-engine/blob/main/LICENSE.md>.

// Package font is for dealing with ttf fonts in the ui.
//
// Call font.Init() before using any other font function.
// Call font.Quit() at the end of your game.
package font

import (
"github.com/bloodmagesoftware/bloodmage-engine/engine/textures"
"fmt"
"os"

"github.com/veandco/go-sdl2/ttf"
)

var (
// fonts holds all registered fonts wether they are currently loaded or not.
fonts map[string]*font
// defaultFont is the font that is used when no other font is specified.
defaultFont *font
)

type font struct {
startChar uint32
endChar uint32
texture *textures.Texture
charWidth int32
charHeight int32
collumnCount int32
}

func Load(texturePath string, startChar uint32, endChar uint32, charWidth int32, charHeight int32, collumnCount int32) *font {
return &font{
startChar: startChar,
endChar: endChar,
texture: textures.Unregistered(texturePath),
charWidth: charWidth,
charHeight: charHeight,
collumnCount: collumnCount,
path string
ttf *ttf.Font
}

// Font ensures the font is loaded and returns it.
func (f *font) Font() (*ttf.Font, error) {
if f.ttf != nil {
return f.ttf, nil
}

font, err := ttf.OpenFont(f.path, 32)
if err != nil {
return nil, err
}
f.ttf = font

return font, nil
}

func Init() error {
return ttf.Init()
}

// Quit closes all loaded fonts.
// After calling this function you can no longer use any font functions before calling Init() again.
func Quit() {
for _, font := range fonts {
if font.ttf != nil {
font.ttf.Close()
font.ttf = nil
}
}
ttf.Quit()
}

func Register(fontPath string, name string) error {
if fonts == nil {
fonts = make(map[string]*font)
}
if _, ok := fonts[name]; ok {
return fmt.Errorf("font %s already registered", name)
}
// check if file exists with os.Stat()
if _, err := os.Stat(fontPath); err != nil {
if os.IsNotExist(err) {
return fmt.Errorf("font %s does not exist", fontPath)
} else {
return fmt.Errorf("error checking if font %s exists: %s", fontPath, err)
}
}
fonts[name] = &font{
path: fontPath,
}
return nil
}

func SetDefault(name string) error {
if _, ok := fonts[name]; !ok {
return fmt.Errorf("font %s not registered", name)
}
defaultFont = fonts[name]
return nil
}

func Default() (*ttf.Font, error) {
if defaultFont != nil {
return defaultFont.Font()
}
return nil, fmt.Errorf("no default font set")
}

func Get(name string) (*ttf.Font, error) {
if font, ok := fonts[name]; ok {
return font.Font()
}
return nil, fmt.Errorf("font %s not registered", name)
}
44 changes: 0 additions & 44 deletions engine/font/rune.go

This file was deleted.

Loading