Updated README & added credits.
This commit is contained in:
parent
c82ce53433
commit
6f9191cbf9
28
README.md
28
README.md
@ -1,4 +1,4 @@
|
||||
# TINS 2020
|
||||
# TINS 2021
|
||||
|
||||
## Content
|
||||
|
||||
@ -24,11 +24,14 @@
|
||||
|
||||
**Welcome to Qbitter!**
|
||||
|
||||
TODO: description of the game.
|
||||
Qbitter is a game loosly based on a work "LW305 Kringloop" of M.C. Escher where a gnome runs down a stairs and morphs into its 2D abstract shape. The game also lends ideas from _Q*Bert_, a game from the eighties that was itself based on the works of M.C. Escher. In the game you (represented as a gnome) have to collect stars while trying to avoid enemies (hexagons). Every level has increasing difficulty.
|
||||
|
||||
**Controls:**
|
||||
|
||||
TODO: fill in.
|
||||
W: move up (left) cube
|
||||
A: move down (left) cube
|
||||
S: move down (right) cube
|
||||
D: move up (right) cube
|
||||
|
||||
## Additional Rules
|
||||
|
||||
@ -36,23 +39,28 @@ TODO: fill in.
|
||||
|
||||
**genre rule #143**
|
||||
|
||||
This rule has been omitted by applying the bonus rule.
|
||||
This rule has been omitted (too subjective) by applying the bonus rule. There is two elements that could be considered funny though:
|
||||
- The gnome (player) is an character that is absurdly placed in this world, both style (hand drawn vs geometric) and color (gray vs colorful) are opposites of each other.
|
||||
- In the credits my own libraries are blatantly mentioned first (yes I know, it could be considered arrogance or is it humorous as well?).
|
||||
|
||||
**artistical rule #60**
|
||||
|
||||
The least obvious and not finished within the time contraint: when researching you'll have to dial a phone number like you used to do with an old rotary dial (works by repeating the number on the keyboard an exact number of times).
|
||||
**artistical rule #147**
|
||||
The game is based on a work of M.C. Escher "LW305 Kringloop" and it shows in different ways:
|
||||
- The isometric cubes of the game try to mimic the style.
|
||||
- The gnome featured as player is a loose interpretation of the gnome drawn by M.C. Escher.
|
||||
- Geometric figures are used as game elements (stars, hearts, enemies).
|
||||
* They are all based on a formula applied on a polar coordinate system (also the heart but this one isn't repeated).
|
||||
|
||||
**artistical rule #94**
|
||||
|
||||
TODO: describe plug.
|
||||
In the credits some of the libraries I wrote (and used) are promoted (**Developed using** geom, zntg and allg5). To be sure that people notice this I put them on top of the list of credits.
|
||||
|
||||
**technical rule #113**
|
||||
|
||||
The main grid is made of cubes (faux 3D) that are regular hexagons in 2D.
|
||||
The main grid is made of cubes (faux 3D) that are regular hexagons in 2D. Additionaly the enemies of the player are made of wobbly hexagons.
|
||||
|
||||
**bonus rule #13**
|
||||
|
||||
TODO: describe tests.
|
||||
Some functionality of the root package (tins2021) is unit tested (coverage is at time of writing 17% of the statements). You can find the tests in the files ending on `_test.go` (e.g. `level_test.go`).
|
||||
|
||||
### Definition
|
||||
|
||||
|
@ -34,7 +34,6 @@ func (a *app) loadFonts(ctx ui.Context, descriptors ...fontDescriptor) error {
|
||||
const fpsOverlayName = `fps`
|
||||
|
||||
func (a *app) Init(ctx ui.Context) error {
|
||||
|
||||
if err := a.loadFonts(ctx,
|
||||
fontDescriptor{"debug", "fonts/FiraMono-Regular.ttf", 12},
|
||||
fontDescriptor{"default", "fonts/escheresk.ttf", 48},
|
||||
|
@ -22,7 +22,10 @@ func (app *appContext) show(control ui.Control) {
|
||||
app.setView(control)
|
||||
}
|
||||
|
||||
func (app *appContext) ShowCredits(ctx ui.Context) {}
|
||||
func (app *appContext) ShowCredits(ctx ui.Context) {
|
||||
app.setView(newCredits(app, ctx))
|
||||
}
|
||||
|
||||
func (app *appContext) ShowInfo(ctx ui.Context) {}
|
||||
|
||||
func (app *appContext) ShowMainMenu(ctx ui.Context) {
|
||||
|
185
cmd/tins2021/credits.go
Normal file
185
cmd/tins2021/credits.go
Normal file
@ -0,0 +1,185 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"opslag.de/schobers/geom"
|
||||
"opslag.de/schobers/zntg/ui"
|
||||
)
|
||||
|
||||
type credits struct {
|
||||
ui.ControlBase
|
||||
|
||||
app *appContext
|
||||
|
||||
content []string
|
||||
hovering int
|
||||
offset float32
|
||||
lastUpdate time.Time
|
||||
}
|
||||
|
||||
func newCredits(app *appContext, ctx ui.Context) *credits {
|
||||
return &credits{app: app, lastUpdate: time.Now(), content: []string{
|
||||
"# QBITTER",
|
||||
"",
|
||||
"a game by Tharro",
|
||||
"developed during the TINS 2021 game development competition",
|
||||
"",
|
||||
"**Developed using**",
|
||||
"geom: a Go package for mathematics and geometries",
|
||||
" - https://opslag.de/schobers/geom",
|
||||
"zntg: an abstraction for rendering (UIs)",
|
||||
" - https://opslag.de/schobers/zntg",
|
||||
"allg5: an Allegro abstraction for Go",
|
||||
" - https://opslag.de/schobers/allg5",
|
||||
"",
|
||||
"**... and also using**",
|
||||
"Allegro: cross-platform development library",
|
||||
" - https://liballeg.org",
|
||||
"SDL: another cross-platform development library",
|
||||
" - https://libsdl.org",
|
||||
"go-sdl2: an SDL abstraction for Go",
|
||||
" - https://github.com/veandco/go-sdl2",
|
||||
"Fira Mono: monotype font",
|
||||
"Escheresk: M.C. Escher themed font",
|
||||
"Escher: M.C. Escher themed font",
|
||||
"fauxgl: a software renderer for Go",
|
||||
" - https://github.com/fogleman/fauxgl",
|
||||
"draw2d: a 2D drawing library for Go",
|
||||
" - https://github.com/llgcode/draw2d",
|
||||
"go-colurful: a 2D drawing library for Go",
|
||||
" - https://github.com/lucasb-eyer/go-colorful",
|
||||
"resize: an image resizing library for Go",
|
||||
" - https://github.com/nfnt/resize",
|
||||
"testify: a testing library for Go",
|
||||
" - https://github.com/stretchr/testify",
|
||||
"",
|
||||
"# THANKS",
|
||||
"A big thank you to Amarillion for hosting this competition!",
|
||||
" - https://tins.amarillion.org/2021",
|
||||
}}
|
||||
}
|
||||
|
||||
func (c *credits) Handle(ctx ui.Context, e ui.Event) bool {
|
||||
if c.ControlBase.Handle(ctx, e) {
|
||||
return true
|
||||
}
|
||||
ctx.Animate()
|
||||
|
||||
switch e := e.(type) {
|
||||
case *ui.MouseButtonDownEvent:
|
||||
if c.hovering != -1 {
|
||||
s := c.content[c.hovering]
|
||||
if strings.HasPrefix(s, " - https://") {
|
||||
url := s[3:]
|
||||
c.openBrowser(url)
|
||||
}
|
||||
}
|
||||
case *ui.KeyDownEvent:
|
||||
if e.Key == ui.KeyEscape {
|
||||
c.app.ShowMainMenu(ctx)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
c.hovering = -1
|
||||
mouse := ctx.MousePosition()
|
||||
c.enumerateContent(ctx, func(s string, i int, top, height float32, font ui.Font) {
|
||||
if !strings.HasPrefix(s, " - https://") {
|
||||
return
|
||||
}
|
||||
if mouse.Y >= top && mouse.Y < top+height {
|
||||
c.hovering = i
|
||||
}
|
||||
ctx.Renderer().SetMouseCursor(ui.MouseCursorPointer)
|
||||
})
|
||||
|
||||
now := time.Now()
|
||||
// if c.hovering == -1 {
|
||||
delta := now.Sub(c.lastUpdate)
|
||||
c.offset += float32(delta/time.Millisecond) / float32(20_000)
|
||||
// }
|
||||
c.lastUpdate = now
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *credits) enumerateContent(ctx ui.Context, enum func(s string, i int, top, height float32, font ui.Font)) {
|
||||
bounds := c.Bounds()
|
||||
top := (1. - c.offset) * bounds.Max.Y
|
||||
for i, font := range c.fonts(ctx) {
|
||||
height := font.Height()
|
||||
if top+height > 0 && top < bounds.Max.Y {
|
||||
enum(c.content[i], i, top, height, font)
|
||||
}
|
||||
top += height
|
||||
}
|
||||
}
|
||||
|
||||
func (c *credits) fonts(ctx ui.Context) []ui.Font {
|
||||
titleFont := ctx.Fonts().Font("title")
|
||||
captionFont := ctx.Fonts().Font("default")
|
||||
defaultFont := ctx.Fonts().Font("score")
|
||||
|
||||
font := func(s string) ui.Font {
|
||||
if strings.HasPrefix(s, "# ") {
|
||||
return titleFont
|
||||
}
|
||||
if strings.HasPrefix(s, "**") && strings.HasSuffix(s, "**") {
|
||||
return captionFont
|
||||
}
|
||||
return defaultFont
|
||||
}
|
||||
|
||||
fonts := make([]ui.Font, 0, len(c.content))
|
||||
for _, line := range c.content {
|
||||
font := font(line)
|
||||
fonts = append(fonts, font)
|
||||
}
|
||||
return fonts
|
||||
}
|
||||
|
||||
func (c *credits) openBrowser(url string) {
|
||||
var err error
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
err = exec.Command("xdg-open", url).Start()
|
||||
case "windows":
|
||||
err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
|
||||
case "darwin":
|
||||
err = exec.Command("open", url).Start()
|
||||
default:
|
||||
err = fmt.Errorf("unsupported platform")
|
||||
}
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *credits) Render(ctx ui.Context) {
|
||||
renderer := ctx.Renderer()
|
||||
width := c.Bounds().Dx()
|
||||
defaultColor := ctx.Style().Palette.Text
|
||||
c.enumerateContent(ctx, func(s string, i int, top, height float32, font ui.Font) {
|
||||
color := defaultColor
|
||||
if i == c.hovering {
|
||||
color = ctx.Style().Palette.Secondary
|
||||
}
|
||||
|
||||
if strings.HasPrefix(s, "# ") {
|
||||
s = s[2:]
|
||||
} else if strings.HasPrefix(s, "**") && strings.HasSuffix(s, "**") {
|
||||
s = s[2 : len(s)-2]
|
||||
} else if strings.HasPrefix(s, " - https://") {
|
||||
s = s[3:]
|
||||
}
|
||||
|
||||
textWidth := font.WidthOf(s)
|
||||
renderer.Text(font, geom.PtF32(.5*(width-textWidth), top), color, s)
|
||||
})
|
||||
}
|
@ -100,6 +100,8 @@ func (r levelController) Handle(ctx ui.Context, e ui.Event) bool {
|
||||
r.Level.MovePlayer(tins2021.DirectionDownRight)
|
||||
case ui.KeyA:
|
||||
r.Level.MovePlayer(tins2021.DirectionDownLeft)
|
||||
case ui.KeyEscape:
|
||||
r.app.ShowMainMenu(ctx)
|
||||
}
|
||||
}
|
||||
for _, animations := range r.Animations {
|
||||
|
@ -82,7 +82,7 @@ func run() error {
|
||||
Primary: zntg.MustHexColor(tins2021.Orange),
|
||||
PrimaryDark: zntg.MustHexColor(`#15569F`),
|
||||
PrimaryLight: zntg.MustHexColor(`#ABCAED`),
|
||||
Secondary: zntg.MustHexColor(`#4AC69A`),
|
||||
Secondary: zntg.MustHexColor(tins2021.Blue),
|
||||
SecondaryDark: zntg.MustHexColor(`#0AA36D`),
|
||||
SecondaryLight: zntg.MustHexColor(`#A6EED4`),
|
||||
Text: zntg.MustHexColor(`#EFEFEF`),
|
||||
|
Loading…
Reference in New Issue
Block a user