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

Commit

Permalink
2D GUI (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
tsukinoko-kun authored Jan 7, 2024
1 parent 0edc370 commit 5193dc5
Show file tree
Hide file tree
Showing 28 changed files with 1,416 additions and 313 deletions.
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

0 comments on commit 5193dc5

Please sign in to comment.