Skip to content

Latest commit

 

History

History
265 lines (202 loc) · 9.55 KB

README.md

File metadata and controls

265 lines (202 loc) · 9.55 KB

Furex

Furex is a minimal GUI framework built on top of Ebitengine, a 2D game engine for Go. It provides support for the Flex Layout Algorithm, a powerful tool for laying out items of different sizes and dimensions. Furex is not a component library, but rather a framework for positioning and stacking virtual widgets, handling button and touch events for mobile, and more. How these widgets are rendered is up to the user.

Go Reference

Assets by Kenney. Fonts by 00ff.

Full source code of the example is here.

Contents

Motivation

Flexbox is a popular layout mechanism in web development, used for creating responsive and flexible user interfaces. With Furex, we can bring this same concept to game development using Go and Ebitengine. This library aims to make it easier for developers with experience in web or React projects to create dynamic, user-friendly game UI.

If you are not familiar with Flexbox Layout, you can learn about it at this website.

Features

Here are some of the key features of Furex:

  • Flexbox layout: The UI layout can be configured using the properties of View instances, which can be thought of as equivalent to DIV elements in HTML. These views can be stacked or nested to create complex layouts.

  • Custom widgets: View instances can receive a Handler which is responsible for drawing and updating the view. This allows users to create any type of UI component by implementing the appropriate handler interfaces, such as Drawer, Updater, and more.

  • Button support: To create a button, users can implement the ButtonHandler interface. This supports both touch and mouse input for button actions. See the Example Button for more details.

  • Touch and mouse events: Furex provides support for handling touch events and positions using the TouchHandler interface, and mouse click events using the MouseLeftButtonHandler interface. It also offers support for detecting mouse position events using the MouseHandler interface, and mouse enter/leave events using the MouseEnterLeaveHandler interface.

  • Swipe gestures: Users can detect swipe gestures by implementing the SwipeHandler interface.

These are just a few examples of the capabilities of Furex. For more information, be sure to check out the GoDoc documentation.

Getting Started

To get started with Furex, install Furex using the following command:

go get github.com/yohamta/furex/v2

Basic Usage

Here's a simple example of how to use Furex to create an UI in your game:

Full source code of the example

type Game struct {
  initOnce sync.Once
  screen   screen
  gameUI   *furex.View
}

func (g *Game) Update() error {
  g.initOnce.Do(func() {
    g.setupUI()
  })
  return nil
}

func (g *Game) Draw(screen *ebiten.Image) {
  g.gameUI.Draw(screen)
}

func (g *Game) setupUI() {
  screen.Fill(color.RGBA{0x3d, 0x55, 0x0c, 0xff})
  colors := []color.Color{
    color.RGBA{0x3d, 0x55, 0x0c, 0xff},
    color.RGBA{0x81, 0xb6, 0x22, 0xff},
    color.RGBA{0xec, 0xf8, 0x7f, 0xff},
  }

  g.gameUI = &furex.View{
    Width:        g.screen.Width,
    Height:       g.screen.Height,
    Direction:    furex.Row,
    Justify:      furex.JustifyCenter,
    AlignItems:   furex.AlignItemCenter,
    AlignContent: furex.AlignContentCenter,
    Wrap:         furex.Wrap,
  }

  for i := 0; i < 20; i++ {
    g.gameUI.AddChild(&furex.View{
      Width:  100,
      Height: 100,
      Handler: &Box{
        Color: colors[i%len(colors)],
      },
    })
  }
}

type Box struct {
  Color color.Color
}

var _ furex.Drawer = (*Box)(nil)

func (b *Box) Draw(screen *ebiten.Image, frame image.Rectangle, view *furex.View) {
  graphic.FillRect(screen, &graphic.FillRectOpts{
    Rect: frame, Color: b.Color,
  })
}

Building UI with HTML

Sometimes making a complex UI tree in Go can be cumbersome. You can use HTML to construct the UI tree more easily.

Here's how to create a view tree from HTML:

  • ui.html

    <html>
      <head>
        <style>
          container {
            align-items: center;
            justify-content: center;
          }
          .sprite {
            width: 64px;
            height: 64px;
          }
        </style>
      </head>
      <body>
        <container>
          <character class="sprite"></character>
        </container>
      </body>
    </html>
  • ui.go

    //go:embed assets/html/ui.html
    var html string
    
    view := furex.Parse(html, &furex.ParseOptions{
      Width: 480,
      Height: 600,
      Components: map[string]furex.Component{
        "character": &widgets.Sprite{SpriteID: "mario.png"},
      },
    })

    Note: The <body> tag itself won't be converted as a View, but its children will be converted to View instances.

This example is equivalent to the following Go code. By using HTML for styling the UI, the code becomes more maintainable.

view := (&furex.View{
  Width: 480,
  Height: 600,
  AlignItems: furex.AlignItemsCenter,
  Justify: furex.JustifyCenter,
}).AddChild(
  &furex.View{
    Width: 64,
    Height: 64,
    Handler: &widgets.Sprite{SpriteID: "mario.png"},
  },
)

For a more extensive example, check out the example here and the embedded HTML file.

CSS Properties

The following table lists the available CSS properties:

CSS Property Type Available Values
left int Any integer value
right int Any integer value
top int Any integer value
bottom int Any integer value
width int Any integer value or percentage
height int Any integer value or percentage
margin-left int Any integer value
margin-top int Any integer value
margin-right int Any integer value
margin-bottom int Any integer value
position Position static, absolute
flex-direction Direction row, column
flex-wrap FlexWrap no-wrap, wrap, wrap-reverse
justify-content Justify flex-start, flex-end, center, space-between, space-around
align-items AlignItem stretch, flex-start, flex-end, center
align-content AlignContent flex-start, flex-end, center, space-between, space-around, stretch
flex-grow float64 Any float64 value
flex-shrink float64 Any float64 value
display Display flex, none

HTML Attributes

The following table lists the available HTML attributes:

HTML Attribute Type Available Values
id string Any string value
hidden bool true, false

Component Types

There are three types of components you can create in Furex:

  • Handler Instance: A furex.Handler instance, such as Drawer or Updater.
  • Factory Function: A function that returns a furex.Handler instance. This is useful when you want to create separate handler instances for each HTML tag.
  • Function Component: A function that returns a *furex.View instance. This is an alternative way to create components that encapsulate their own behavior and styles.

Global Components

To register a custom component globally, use the furex.RegisterComponents function. For example:

  func init() {
  	furex.RegisterComponents(furex.ComponentsMap{
  		"button":  &widgets.Button{},
  		"sprite": &widgets.Sprite{},
  	})
  }

Debugging

You can enable Debug Mode by setting the variable below.

furex.Debug = true

Contributions

Contributions are welcome! If you find a bug or have an idea for a new feature, feel free to open an issue or submit a pull request.