Skip to content
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Video game console operating system that displays on a 16*9 RGB LED matrix.
| <img src="./docs/device.png" width="60"/> | Device | The Device software allows you to change the luminosity of the LEDs. | <img src="./docs/device.gif" width="150"/> |
| <img src="./docs/blocks.png" width="60"/> | Blocks | A puzzle game, score a maximum of points by clearing complete lines. | <img src="./docs/blocks.gif" width="150"/> |
| <img src="./docs/getout.png" width="60"/> | Getout | A labyrinth game, try to get out if you can. | <img src="./docs/getout.gif" width="150"/> |
| <img src="./docs/rollup-dice.png" width="60"/> | Rollup dice | Random dice generator (https://github.com/gwenker/matrix-rollup-dice). | <img src="./docs/rollup-dice.gif" width="150"/> |
| <img src="./docs/rollup-dice.png" width="60"/> | Rollup dice | Roll two dice, press A for a new throw. | <img src="./docs/rollup-dice.gif" width="150"/> |
| <img src="./docs/animate.png" width="60"/> | Animate | Player for animations generated with Glediator (http://www.solderlab.de/index.php/software/glediator). | <img src="./docs/animate.gif" width="150"/> |
| <img src="./docs/light.png" width="60"/> | Light | Simple software to generate mood light. | <img src="./docs/light.gif" width="150"/> |

Expand Down
2 changes: 1 addition & 1 deletion docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ That puts a static ARMv7 binary at `/usr/bin/matrix`, the data it renders from u
Choose what it runs in `/etc/default/matrix`:

```sh
MATRIX_COMPONENTS="core device gamepad emulator demo zigzag yumyum clock draw blocks getout animate light"
MATRIX_COMPONENTS="core device gamepad emulator demo zigzag yumyum clock draw blocks getout animate light rollupdice"
MATRIX_GAMEPAD_PORT=80
MATRIX_LOG_LEVEL=info
```
Expand Down
12 changes: 12 additions & 0 deletions fonts/diceValues.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "DiceValues",
"height": 5,
"caracters": {
"1": {"width": 5, "mask": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]},
"2": {"width": 5, "mask": [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]},
"3": {"width": 5, "mask": [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]},
"4": {"width": 5, "mask": [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1]},
"5": {"width": 5, "mask": [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1]},
"6": {"width": 5, "mask": [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1]}
}
}
19 changes: 19 additions & 0 deletions images/rollupdice.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "rollupdice",
"height": 7,
"width": 12,
"colors": [
{ "r": 0, "g": 0, "b": 0, "a": 0 },
{ "r": 255, "g": 255, "b": 255, "a": 1 },
{ "r": 0, "g": 0, "b": 0, "a": 1 }
],
"mask": [
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
1, 2, 1, 1, 1, 0, 0, 1, 2, 1, 2, 1,
1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1
]
}
5 changes: 4 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/richardlt/matrix/getout"
"github.com/richardlt/matrix/internal/errors"
"github.com/richardlt/matrix/light"
"github.com/richardlt/matrix/rollupdice"
"github.com/richardlt/matrix/yumyum"
"github.com/richardlt/matrix/zigzag"
)
Expand Down Expand Up @@ -51,7 +52,7 @@ func main() {
Usage: "[panic fatal error warning info debug]",
},
},
ArgsUsage: "[core emulator gamepad device zigzag yumyum demo clock draw blocks]",
ArgsUsage: "[core emulator gamepad device zigzag yumyum demo clock draw blocks getout animate light rollupdice]",
Action: startAction,
}},
}
Expand Down Expand Up @@ -112,6 +113,8 @@ func startAction(ctx context.Context, cmd *cli.Command) error {
cs = append(cs, component(func() error { return animate.Start(cmd.String("core-uri")) }))
case "light":
cs = append(cs, component(func() error { return light.Start(cmd.String("core-uri")) }))
case "rollupdice":
cs = append(cs, component(func() error { return rollupdice.Start(cmd.String("core-uri")) }))
default:
return errors.Errorf("invalid component name %q, expected one of %s", arg, cmd.ArgsUsage)
}
Expand Down
2 changes: 1 addition & 1 deletion packaging/deb/default
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#
# Every component is a separate process-worth of goroutines and one gRPC connection, so
# on a small board it is worth trimming this to what you actually play.
MATRIX_COMPONENTS="core device gamepad emulator demo zigzag yumyum clock draw blocks getout animate light"
MATRIX_COMPONENTS="core device gamepad emulator demo zigzag yumyum clock draw blocks getout animate light rollupdice"

# Port for the gamepad web app, the virtual controller played from a phone.
MATRIX_GAMEPAD_PORT=80
Expand Down
57 changes: 57 additions & 0 deletions rollupdice/daemon.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package rollupdice

import (
"github.com/sirupsen/logrus"

"github.com/richardlt/matrix/sdk-go/common"
"github.com/richardlt/matrix/sdk-go/software"
)

// Start the rollup dice software.
func Start(uri string) error {
logrus.Infof("Start rollup dice for uri %s\n", uri)

r := &rollupDice{}

return software.Connect(uri, r, true)
}

type rollupDice struct {
engine *engine
renderer *renderer
}

func (r *rollupDice) Init(a software.API) (err error) {
logrus.Debug("Init rollup dice")

r.renderer, err = newRenderer(a)
if err != nil {
return err
}

if err := a.SetConfig(&software.ConnectRequest_SoftwareData_Config{
Logo: a.GetImageFromLocal("rollupdice"),
MinPlayerCount: 1,
MaxPlayerCount: 1,
}); err != nil {
return err
}

return a.Ready()
}

func (r *rollupDice) Start(uint64) {
r.engine = newEngine()
r.engine.roll()
r.renderer.print(r.engine.values)
}

func (r *rollupDice) Close() { r.renderer.clean() }

func (r *rollupDice) ActionReceived(slot uint64, cmd common.Command) {
if cmd != common.Command_A_UP {
return
}
r.engine.roll()
r.renderer.print(r.engine.values)
}
21 changes: 21 additions & 0 deletions rollupdice/engine.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package rollupdice

import "math/rand"

// diceCount dice are rolled together, one per half of the display.
const diceCount = 2

func newEngine() *engine { return &engine{} }

type engine struct {
values [diceCount]int
}

// roll draws a new face, one to six, for every die. The global source is used rather than
// one seeded from the clock: the board this runs on has no clock to seed from, and the
// runtime seeds the global source itself.
func (e *engine) roll() {
for i := range e.values {
e.values[i] = rand.Intn(6) + 1
}
}
27 changes: 27 additions & 0 deletions rollupdice/engine_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package rollupdice

import (
"testing"

"github.com/stretchr/testify/assert"
)

// Only the six faces of the DiceValues font can be rendered, so a value outside one to
// six would print an empty face rather than a die.
func TestRollStaysOnTheFaces(t *testing.T) {
assert := assert.New(t)

e := newEngine()
seen := map[int]bool{}

for i := 0; i < 1000; i++ {
e.roll()
for _, v := range e.values {
assert.GreaterOrEqual(v, 1)
assert.LessOrEqual(v, 6)
seen[v] = true
}
}

assert.Len(seen, 6)
}
71 changes: 71 additions & 0 deletions rollupdice/renderer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package rollupdice

import (
"github.com/richardlt/matrix/sdk-go/common"
"github.com/richardlt/matrix/sdk-go/software"
)

// A face is a square of this many pixels, which is what fits two dice on the 16x9
// display: a one pixel border all around and a two pixel gap down the middle.
const faceSize = 7

func newRenderer(a software.API) (*renderer, error) {
faceLayer, err := a.NewLayer()
if err != nil {
return nil, err
}

pipLayer, err := a.NewLayer()
if err != nil {
return nil, err
}

cd, err := pipLayer.NewCaracterDriver(a.GetFontFromLocal("DiceValues"))
if err != nil {
return nil, err
}

return &renderer{
api: a,
faceLayer: faceLayer,
pipLayer: pipLayer,
caracterDriver: cd,
faceColor: &common.Color{R: 255, G: 255, B: 255, A: 1},
pipColor: &common.Color{A: 1},
}, nil
}

type renderer struct {
api software.API
faceLayer, pipLayer software.Layer
caracterDriver *software.CaracterDriver
faceColor, pipColor *common.Color
}

func (r *renderer) clean() {
_ = r.faceLayer.Clean()
_ = r.pipLayer.Clean()
}

func (r *renderer) print(values [diceCount]int) {
r.clean()

for i, value := range values {
originX := i * (faceSize + 2)

for x := originX; x < originX+faceSize; x++ {
for y := 1; y <= faceSize; y++ {
_ = r.faceLayer.SetWithCoord(&common.Coord{X: int64(x), Y: int64(y)}, r.faceColor)
}
}

// The pips of a value are one caracter of the DiceValues font, five by five, and
// the driver places it around its center. The background is left transparent so
// the face below shows through.
_ = r.caracterDriver.Render(rune('0'+value),
&common.Coord{X: int64(originX + faceSize/2), Y: int64(1 + faceSize/2)},
r.pipColor, &common.Color{})
}

_ = r.api.Print()
}
2 changes: 1 addition & 1 deletion scripts/prepare-alpine-card.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ DEBUG=0
# core and device, plus every game. gamepad and emulator are left out: gamepad is the web
# controller, unreachable without a network, and emulator is a development tool. Trim this
# with --components if memory gets tight.
COMPONENTS="core device demo zigzag yumyum clock draw blocks getout animate light"
COMPONENTS="core device demo zigzag yumyum clock draw blocks getout animate light rollupdice"
# Go's collector shares the single core with rendering, and the frame path allocates on
# every frame, so the default collection rate shows up as a periodic stutter. Trading
# memory for fewer collections is the right way round on a board that does nothing else.
Expand Down