added files
This commit is contained in:
parent
d2004f7cb7
commit
b5e08452b6
22 changed files with 2761 additions and 0 deletions
78
accel3d.go
Normal file
78
accel3d.go
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
//go:build gopher_badge
|
||||
// +build gopher_badge
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/tinydraw"
|
||||
"tinygo.org/x/tinyfont"
|
||||
"tinygo.org/x/tinyfont/freesans"
|
||||
)
|
||||
|
||||
func Accel3D() {
|
||||
display.FillScreen(colorWhite)
|
||||
tinydraw.Rectangle(&display, 50, 16, 260, 16, colorBlack)
|
||||
tinydraw.Rectangle(&display, 50, 56, 260, 16, colorBlack)
|
||||
tinydraw.Rectangle(&display, 50, 96, 260, 16, colorBlack)
|
||||
|
||||
tinyfont.WriteLine(&display, &freesans.Regular12pt7b, 20, 180, "MOVE the Gopher to see", colorBlack)
|
||||
tinyfont.WriteLine(&display, &freesans.Regular12pt7b, 32, 200, "the accelerometer in", colorBlack)
|
||||
tinyfont.WriteLine(&display, &freesans.Regular12pt7b, 90, 220, "action.", colorBlack)
|
||||
|
||||
tinyfont.WriteLine(&display, &freesans.Regular24pt7b, 4, 40, "X:", colorBlack)
|
||||
tinyfont.WriteLine(&display, &freesans.Regular24pt7b, 4, 80, "Y:", colorBlack)
|
||||
tinyfont.WriteLine(&display, &freesans.Regular24pt7b, 4, 120, "Z:", colorBlack)
|
||||
|
||||
x, y, z := accel.ReadRawAcceleration()
|
||||
for {
|
||||
if !btnA.Get() || !btnB.Get() {
|
||||
break
|
||||
}
|
||||
|
||||
x, y, z = accel.ReadRawAcceleration()
|
||||
x = x / 250
|
||||
y = y / 250
|
||||
z = z / 250
|
||||
if x > 128 {
|
||||
x = 128
|
||||
}
|
||||
if y > 128 {
|
||||
y = 128
|
||||
}
|
||||
if z > 128 {
|
||||
z = 128
|
||||
}
|
||||
if x < -128 {
|
||||
x = -128
|
||||
}
|
||||
if y < -128 {
|
||||
y = -128
|
||||
}
|
||||
if z < -128 {
|
||||
z = -128
|
||||
}
|
||||
display.FillRectangle(51, 22, 258, 6, colorWhite)
|
||||
display.FillRectangle(51, 62, 258, 6, colorWhite)
|
||||
display.FillRectangle(51, 102, 258, 6, colorWhite)
|
||||
if x < 0 {
|
||||
display.FillRectangle(179+x, 22, -x, 6, colorRed)
|
||||
} else {
|
||||
display.FillRectangle(179, 22, x, 6, colorRed)
|
||||
}
|
||||
if y < 0 {
|
||||
display.FillRectangle(179+y, 62, -y, 6, colorGreen)
|
||||
} else {
|
||||
display.FillRectangle(179, 62, y, 6, colorGreen)
|
||||
}
|
||||
if z < 0 {
|
||||
display.FillRectangle(179+z, 102, -z, 6, colorBlue)
|
||||
} else {
|
||||
display.FillRectangle(179, 102, z, 6, colorBlue)
|
||||
}
|
||||
|
||||
println("X:", x, "Y:", y, "Z:", z)
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
86
accel3d_pybadge.go
Normal file
86
accel3d_pybadge.go
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
//go:build pybadge
|
||||
// +build pybadge
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/tinydraw"
|
||||
"tinygo.org/x/tinyfont"
|
||||
"tinygo.org/x/tinyfont/proggy"
|
||||
)
|
||||
|
||||
func Accel3D() {
|
||||
white := color.RGBA{255, 255, 255, 255}
|
||||
red := color.RGBA{255, 0, 0, 255}
|
||||
green := color.RGBA{0, 255, 0, 255}
|
||||
blue := color.RGBA{0, 0, 255, 255}
|
||||
black := color.RGBA{0, 0, 0, 255}
|
||||
|
||||
display.FillScreen(white)
|
||||
tinydraw.Rectangle(&display, 26, 30, 132, 7, black)
|
||||
tinydraw.Rectangle(&display, 26, 40, 132, 7, black)
|
||||
tinydraw.Rectangle(&display, 26, 50, 132, 7, black)
|
||||
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 10, 80, "Move the PyBadge to see", black)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 14, 90, "the accelerometer in", black)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 60, 100, "action.", black)
|
||||
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 8, 36, "X:", black)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 8, 46, "Y:", black)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 8, 56, "Z:", black)
|
||||
|
||||
x, y, z := accel.ReadRawAcceleration()
|
||||
for {
|
||||
pressed, _ := buttons.Read8Input()
|
||||
if pressed&machine.BUTTON_SELECT_MASK > 0 {
|
||||
break
|
||||
}
|
||||
|
||||
x, y, z = accel.ReadRawAcceleration()
|
||||
x = x / 500
|
||||
y = y / 500
|
||||
z = z / 500
|
||||
if x > 64 {
|
||||
x = 64
|
||||
}
|
||||
if y > 64 {
|
||||
y = 64
|
||||
}
|
||||
if z > 64 {
|
||||
z = 64
|
||||
}
|
||||
if x < -64 {
|
||||
x = -64
|
||||
}
|
||||
if y < -64 {
|
||||
y = -64
|
||||
}
|
||||
if z < -64 {
|
||||
z = -64
|
||||
}
|
||||
display.FillRectangle(28, 32, 128, 2, white)
|
||||
display.FillRectangle(28, 42, 128, 2, white)
|
||||
display.FillRectangle(28, 52, 128, 2, white)
|
||||
if x < 0 {
|
||||
display.FillRectangle(92+x, 32, -x, 2, red)
|
||||
} else {
|
||||
display.FillRectangle(92, 32, x, 2, red)
|
||||
}
|
||||
if y < 0 {
|
||||
display.FillRectangle(92+y, 42, -y, 2, green)
|
||||
} else {
|
||||
display.FillRectangle(92, 42, y, 2, green)
|
||||
}
|
||||
if z < 0 {
|
||||
display.FillRectangle(92+z, 52, -z, 2, blue)
|
||||
} else {
|
||||
display.FillRectangle(92, 52, z, 2, blue)
|
||||
}
|
||||
|
||||
time.Sleep(150 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
242
adventure.go
Normal file
242
adventure.go
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/tinydraw"
|
||||
"tinygo.org/x/tinyfont"
|
||||
"tinygo.org/x/tinyfont/freemono"
|
||||
"tinygo.org/x/tinyfont/freesans"
|
||||
"tinygo.org/x/tinyfont/proggy"
|
||||
|
||||
qrcode "github.com/skip2/go-qrcode"
|
||||
)
|
||||
|
||||
func adventure() {
|
||||
quit := false
|
||||
s := 0
|
||||
score := 0
|
||||
money := 0
|
||||
costume := 0
|
||||
pancake := false
|
||||
talk := false
|
||||
opinion := 0
|
||||
selected := int16(0)
|
||||
//released := true
|
||||
for {
|
||||
println(s)
|
||||
scene(s)
|
||||
selected = 0
|
||||
score += s
|
||||
if s == 5 {
|
||||
costume = 1
|
||||
} else if s == 3 {
|
||||
talk = true
|
||||
} else if s == 6 {
|
||||
pancake = true
|
||||
} else if s == 8 {
|
||||
money += 689
|
||||
costume = 2
|
||||
} else if s == 17 {
|
||||
money += 5
|
||||
} else if s == 20 {
|
||||
opinion = 57
|
||||
} else if s == 21 {
|
||||
opinion = 37
|
||||
} else if s == 22 {
|
||||
opinion = 21
|
||||
} else if s == 25 {
|
||||
myNameIs(YourName)
|
||||
} else if s == 27 {
|
||||
if costume == 0 {
|
||||
s = 30
|
||||
} else if costume == 1 {
|
||||
s = 28
|
||||
} else {
|
||||
s = 29
|
||||
}
|
||||
continue
|
||||
} else if s == 32 {
|
||||
s = 34
|
||||
if talk {
|
||||
s = 33
|
||||
}
|
||||
continue
|
||||
} else if s == 41 {
|
||||
showGameStats(score, money, costume, opinion, pancake, talk)
|
||||
} else if s == 42 {
|
||||
showGameQR()
|
||||
} else if s == 44 {
|
||||
return
|
||||
}
|
||||
|
||||
tinydraw.FilledCircle(&display, 10, displayHeight-28+10*selected, 3, colorWhite)
|
||||
//released = true
|
||||
for {
|
||||
|
||||
/*if released && !btnUp.Get() && selected > 0 {
|
||||
tinydraw.FilledCircle(&display, 10, displayHeight-28+10*selected, 3, colorBlack)
|
||||
selected--
|
||||
tinydraw.FilledCircle(&display, 10, displayHeight-28+10*selected, 3, colorWhite)
|
||||
}
|
||||
|
||||
if released && !btnDown.Get() && selected < 2 {
|
||||
tinydraw.FilledCircle(&display, 10, displayHeight-28+10*selected, 3, colorBlack)
|
||||
selected++
|
||||
tinydraw.FilledCircle(&display, 10, displayHeight-28+10*selected, 3, colorWhite)
|
||||
}
|
||||
|
||||
if released && !btnA.Get() {
|
||||
if selected == 0 {
|
||||
s = sceneData[s].sceneA
|
||||
if s == 1 {
|
||||
money += 385
|
||||
} else if s == 2 {
|
||||
money += 335
|
||||
}
|
||||
break
|
||||
} else if selected == 1 {
|
||||
s = sceneData[s].sceneB
|
||||
if s == 1 {
|
||||
money += 600
|
||||
} else if s == 2 {
|
||||
money += 550
|
||||
}
|
||||
break
|
||||
} else {
|
||||
s = sceneData[s].sceneC
|
||||
if s == 1 {
|
||||
money += 1050
|
||||
} else if s == 2 {
|
||||
money += 970
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if btnA.Get() && btnUp.Get() && btnDown.Get() {
|
||||
released = true
|
||||
} else {
|
||||
released = false
|
||||
}
|
||||
|
||||
if !btnB.Get() {
|
||||
return
|
||||
}*/
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
|
||||
}
|
||||
if quit {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func scene(s int) {
|
||||
display.FillScreen(colorWhite)
|
||||
|
||||
ss := splitBefore(sceneData[s].description)
|
||||
for i := int16(0); i < int16(len(ss)); i++ {
|
||||
tinyfont.WriteLine(&display, &freemono.Regular9pt7b, 6, 6+i*16, ss[i], colorBlack)
|
||||
}
|
||||
|
||||
display.FillRectangle(0, displayHeight-33, displayWidth, 33, colorBlack)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 20, displayHeight-24, sceneData[s].optionA, colorWhite)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 20, displayHeight-14, sceneData[s].optionB, colorWhite)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 20, displayHeight-4, sceneData[s].optionC, colorWhite)
|
||||
|
||||
tinydraw.Circle(&display, 10, displayHeight-28, 4, colorWhite)
|
||||
tinydraw.Circle(&display, 10, displayHeight-18, 4, colorWhite)
|
||||
tinydraw.Circle(&display, 10, displayHeight-8, 4, colorWhite)
|
||||
|
||||
display.Display()
|
||||
}
|
||||
|
||||
func splitBefore(str string) []string {
|
||||
l := len(str)
|
||||
a := 0
|
||||
s := make([]string, 1)
|
||||
for {
|
||||
if l <= 28 {
|
||||
s = append(s, str[a:a+l])
|
||||
break
|
||||
} else {
|
||||
for i := 28; i > 0; i-- {
|
||||
if string(str[a+i]) == " " {
|
||||
s = append(s, str[a:a+i])
|
||||
a = a + i + 1
|
||||
l = l - i - 1
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func showGameStats(score, money, costume, opinion int, pancake, talk bool) {
|
||||
|
||||
c := "SCORE: " + strconv.Itoa(score)
|
||||
w32, _ := tinyfont.LineWidth(&freesans.Bold9pt7b, c)
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, (displayWidth-int16(w32))/2, 26, c, colorBlack)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 10, 50, "Money spent: "+strconv.Itoa(money)+" EUR", colorBlack)
|
||||
|
||||
c = "YOURSELF"
|
||||
if costume == 1 {
|
||||
c = "UNICORN PIJAMA"
|
||||
} else if costume == 2 {
|
||||
c = "DELUXE TUXEDO"
|
||||
}
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 10, 60, "You were dressed as: "+c, colorBlack)
|
||||
|
||||
c = "NO pancakes"
|
||||
if pancake {
|
||||
c = "37 pancakes"
|
||||
}
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 10, 70, "Your breakfast: "+c, colorBlack)
|
||||
|
||||
if talk {
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 10, 80, "You DID give a talk (and it was awesome)", colorBlack)
|
||||
} else {
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 10, 80, "You did NOT give a talk (sad noises)", colorBlack)
|
||||
}
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 10, 90, "Your opinion is "+strconv.Itoa(opinion)+"% popular", colorBlack)
|
||||
|
||||
display.Display()
|
||||
}
|
||||
|
||||
func showGameQR() {
|
||||
|
||||
// https://tinyurl.com/gceuADV
|
||||
qr, err := qrcode.New("https://tinyurl.com/gceuADV", qrcode.Medium)
|
||||
if err != nil {
|
||||
println(err, 123)
|
||||
}
|
||||
|
||||
qrbytes := qr.Bitmap()
|
||||
size := int16(len(qrbytes))
|
||||
|
||||
factor := int16(displayHeight / len(qrbytes))
|
||||
|
||||
bx := (displayWidth - size*factor)
|
||||
by := (displayHeight - size*factor) / 2
|
||||
display.FillScreen(colorWhite)
|
||||
for y := int16(0); y < size; y++ {
|
||||
for x := int16(0); x < size; x++ {
|
||||
if qrbytes[y][x] {
|
||||
display.FillRectangle(bx+x*factor, by+y*factor, factor, factor, colorBlack)
|
||||
} else {
|
||||
display.FillRectangle(bx+x*factor, by+y*factor, factor, factor, colorWhite)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, 10, 30, "SCAN &", colorBlack)
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, 10, 50, "SHARE", colorBlack)
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, 10, 70, "YOUR", colorBlack)
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, 10, 90, "SCORE", colorBlack)
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, 10, 110, "ONLINE", colorBlack)
|
||||
|
||||
display.Display()
|
||||
}
|
||||
358
badge.go
Normal file
358
badge.go
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"image/color"
|
||||
"strconv"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"tinygo.org/x/tinydraw"
|
||||
"tinygo.org/x/tinyfont"
|
||||
"tinygo.org/x/tinyfont/freesans"
|
||||
"tinygo.org/x/tinyfont/gophers"
|
||||
|
||||
qrcode "github.com/skip2/go-qrcode"
|
||||
)
|
||||
|
||||
const (
|
||||
logoDisplayTime = 10 * time.Second
|
||||
)
|
||||
|
||||
var rainbow []color.RGBA
|
||||
var quit bool
|
||||
var selectedScreen uint8
|
||||
|
||||
//go:embed logo.bin
|
||||
var badgeLogo string
|
||||
|
||||
func Badge() {
|
||||
quit = false
|
||||
selectedScreen = 0
|
||||
display.FillScreen(colorBlack)
|
||||
|
||||
rainbow = make([]color.RGBA, 256)
|
||||
for i := 0; i < 256; i++ {
|
||||
rainbow[i] = getRainbowRGB(uint8(i))
|
||||
}
|
||||
|
||||
for {
|
||||
switch selectedScreen {
|
||||
case 7: // last +1
|
||||
selectedScreen = 0
|
||||
fallthrough
|
||||
case 0:
|
||||
//showLogoBin()
|
||||
selectedScreen++
|
||||
if quit {
|
||||
break
|
||||
}
|
||||
case 1:
|
||||
//logopurpleHardware()
|
||||
selectedScreen++
|
||||
if quit {
|
||||
break
|
||||
}
|
||||
case 2:
|
||||
myNameIsRainbow(YourName)
|
||||
if quit {
|
||||
break
|
||||
}
|
||||
case 3:
|
||||
blinkyRainbow(YourTitleA1, YourTitleA2)
|
||||
if quit {
|
||||
break
|
||||
}
|
||||
case 4:
|
||||
scroll(YourMarqueeTop, YourMarqueeMiddle, YourMarqueeBottom)
|
||||
if quit {
|
||||
break
|
||||
}
|
||||
case 5:
|
||||
QR(YourQRText)
|
||||
if quit {
|
||||
break
|
||||
}
|
||||
case 255: // max
|
||||
selectedScreen = 6 // last one
|
||||
fallthrough
|
||||
case 6:
|
||||
blinkyRainbow(YourTitleB1, YourTitleB2)
|
||||
if quit {
|
||||
break
|
||||
}
|
||||
default:
|
||||
selectedScreen = 0
|
||||
}
|
||||
if quit {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func myNameIs(name string) {
|
||||
display.FillScreen(colorWhite)
|
||||
|
||||
// black corners detail
|
||||
display.FillRectangle(0, 0, cornerRadius, cornerRadius, colorBlack)
|
||||
display.FillRectangle(0, displayHeight-cornerRadius, cornerRadius, cornerRadius, colorBlack)
|
||||
display.FillRectangle(displayWidth-cornerRadius, 0, cornerRadius, cornerRadius, colorBlack)
|
||||
display.FillRectangle(displayWidth-cornerRadius, displayHeight-cornerRadius, cornerRadius, cornerRadius, colorBlack)
|
||||
|
||||
// round corners
|
||||
tinydraw.FilledCircle(&display, cornerRadius, cornerRadius, cornerRadius, colorRed)
|
||||
tinydraw.FilledCircle(&display, displayWidth-cornerRadius-1, cornerRadius, cornerRadius, colorRed)
|
||||
tinydraw.FilledCircle(&display, cornerRadius, displayHeight-cornerRadius-1, cornerRadius, colorRed)
|
||||
tinydraw.FilledCircle(&display, displayWidth-cornerRadius-1, displayHeight-cornerRadius-1, cornerRadius, colorRed)
|
||||
|
||||
// top band
|
||||
display.FillRectangle(cornerRadius, 0, displayWidth-2*cornerRadius-1, cornerRadius, colorRed)
|
||||
display.FillRectangle(0, cornerRadius, displayWidth, int16(TopBandHeight), colorRed)
|
||||
|
||||
// bottom band
|
||||
display.FillRectangle(cornerRadius, displayHeight-cornerRadius-1, displayWidth-2*cornerRadius-1, cornerRadius+1, colorRed)
|
||||
display.FillRectangle(0, displayHeight-int16(BottomBandHeight)-cornerRadius-1, displayWidth, int16(BottomBandHeight), colorRed)
|
||||
|
||||
// top text
|
||||
if displayWidth >= 320 {
|
||||
// gopherbadge: HELLO + my name is
|
||||
w32, _ := tinyfont.LineWidth(&freesans.Bold18pt7b, "HELLO")
|
||||
tinyfont.WriteLine(&display, &freesans.Bold18pt7b, (displayWidth-int16(w32))/2, int16(HelloY), "HELLO", colorWhite)
|
||||
w32, _ = tinyfont.LineWidth(&freesans.Oblique9pt7b, "my name is")
|
||||
tinyfont.WriteLine(&display, &freesans.Oblique9pt7b, (displayWidth-int16(w32))/2, int16(MyNameIsY), "my name is", colorWhite)
|
||||
} else {
|
||||
// pybadge: my NAME is
|
||||
w32, _ := tinyfont.LineWidth(&freesans.Regular12pt7b, "my NAME is")
|
||||
tinyfont.WriteLine(&display, &freesans.Regular12pt7b, (displayWidth-int16(w32))/2, int16(MyNameIsY), "my NAME is", colorWhite)
|
||||
}
|
||||
|
||||
writeLine(name, colorBlack, displayWidth/2, 6*displayHeight/10, displayWidth, true)
|
||||
|
||||
// gophers
|
||||
if displayWidth >= 320 {
|
||||
tinyfont.WriteLineColors(&display, &gophers.Regular58pt, displayWidth-int16(GophersX), int16(GophersY), "BE", []color.RGBA{getRainbowRGB(100), getRainbowRGB(200)})
|
||||
} else {
|
||||
tinyfont.WriteLineColors(&display, &gophers.Regular32pt, displayWidth-int16(GophersX), int16(GophersY), "BE", []color.RGBA{getRainbowRGB(100), getRainbowRGB(200)})
|
||||
}
|
||||
}
|
||||
|
||||
func myNameIsRainbow(name string) {
|
||||
myNameIs(name)
|
||||
|
||||
for i := 0; i < 230; i++ {
|
||||
writeLine(name, rainbow[i], displayWidth/2, 6*displayHeight/10, displayWidth, true)
|
||||
i += 2
|
||||
|
||||
getInput()
|
||||
if goBack() {
|
||||
quit = true
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
selectedScreen++
|
||||
}
|
||||
|
||||
func blinkyRainbow(topline, bottomline string) {
|
||||
display.FillScreen(colorWhite)
|
||||
|
||||
// calculate the width of the text so we could center them later
|
||||
for i := int16(0); i < 20; i++ {
|
||||
|
||||
writeLine(topline, getRainbowRGB(uint8(i*12)), displayWidth/2, 4*displayHeight/10, displayWidth, true)
|
||||
writeLine(bottomline, getRainbowRGB(uint8(i*12)), displayWidth/2, 8*displayHeight/10, displayWidth, true)
|
||||
|
||||
getInput()
|
||||
if goBack() {
|
||||
quit = true
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
selectedScreen++
|
||||
}
|
||||
|
||||
func scroll(topline, middleline, bottomline string) {
|
||||
display.FillScreen(colorWhite)
|
||||
|
||||
writeLine(topline, getRainbowRGB(200), displayWidth/2, 3*displayHeight/10, displayWidth, true)
|
||||
writeLine(middleline, getRainbowRGB(80), displayWidth/2, 55*displayHeight/100, displayWidth, true)
|
||||
writeLine(bottomline, getRainbowRGB(120), displayWidth/2, 8*displayHeight/10, displayWidth, true)
|
||||
|
||||
display.SetScrollArea(0, 0)
|
||||
defer func() {
|
||||
display.SetScroll(0)
|
||||
display.StopScroll()
|
||||
}()
|
||||
|
||||
for k := 0; k < 4; k++ {
|
||||
for i := int16(displayWidth - 1); i >= 0; i-- {
|
||||
getInput()
|
||||
if goBack() {
|
||||
quit = true
|
||||
return
|
||||
}
|
||||
|
||||
display.SetScroll(i)
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
selectedScreen++
|
||||
}
|
||||
|
||||
func logopurpleHardware() {
|
||||
bgColor := color.RGBA{109, 0, 140, 255}
|
||||
white := color.RGBA{255, 255, 255, 255}
|
||||
display.FillScreen(bgColor)
|
||||
|
||||
if displayWidth >= 320 {
|
||||
// Full logo for gopherbadge
|
||||
display.FillRectangle(6, 166, 308, 21, white)
|
||||
|
||||
tinydraw.FilledCircle(&display, 282, 130, 9, white)
|
||||
tinydraw.Line(&display, 259, 110, 298, 149, bgColor)
|
||||
tinydraw.Line(&display, 260, 110, 299, 149, bgColor)
|
||||
tinydraw.Line(&display, 261, 110, 300, 149, bgColor)
|
||||
tinydraw.Line(&display, 262, 110, 301, 149, bgColor)
|
||||
tinydraw.Line(&display, 263, 110, 302, 149, bgColor)
|
||||
tinydraw.Line(&display, 264, 110, 303, 149, bgColor)
|
||||
tinydraw.Line(&display, 265, 110, 304, 149, bgColor)
|
||||
|
||||
display.FillRectangle(250, 98, 11, 63, white)
|
||||
display.FillRectangle(250, 98, 44, 11, white)
|
||||
|
||||
display.FillRectangle(270, 150, 44, 11, white)
|
||||
display.FillRectangle(303, 98, 11, 63, white)
|
||||
|
||||
tinyfont.WriteLine(&display, &freesans.Regular18pt7b, 6, 109, "purple", white)
|
||||
tinyfont.WriteLine(&display, &freesans.Regular18pt7b, 6, 153, "Hardware by", white)
|
||||
} else {
|
||||
// Simplified logo for pybadge
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, 10, 60, "purple", white)
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, 10, 80, "Hardware", white)
|
||||
}
|
||||
|
||||
refreshIntervals := uint8(7)
|
||||
displayTime := logoDisplayTime / 3
|
||||
|
||||
for i := uint8(0); i < refreshIntervals; i++ {
|
||||
time.Sleep(displayTime / time.Duration(refreshIntervals))
|
||||
getInput()
|
||||
|
||||
if goBack() {
|
||||
quit = true
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
selectedScreen++
|
||||
}
|
||||
|
||||
func getRainbowRGB(i uint8) color.RGBA {
|
||||
if i < 85 {
|
||||
return color.RGBA{i * 3, 255 - i*3, 0, 255}
|
||||
} else if i < 170 {
|
||||
i -= 85
|
||||
return color.RGBA{255 - i*3, 0, i * 3, 255}
|
||||
}
|
||||
i -= 170
|
||||
return color.RGBA{0, i * 3, 255 - i*3, 255}
|
||||
}
|
||||
|
||||
func showLogoBin() {
|
||||
row := make([]color.RGBA, displayWidth)
|
||||
unsafeBadgeLogo := unsafe.Slice(unsafe.StringData(badgeLogo), len(badgeLogo))
|
||||
for i := 0; i < displayHeight; i++ {
|
||||
for j := 0; j < displayWidth; j++ {
|
||||
values, err := strconv.ParseUint(string(unsafeBadgeLogo[6*(displayWidth*i+j):6*(displayWidth*i+j+1)]), 16, 32)
|
||||
|
||||
if err != nil {
|
||||
println(err)
|
||||
}
|
||||
|
||||
row[j] = color.RGBA{
|
||||
R: uint8(values >> 16),
|
||||
G: uint8((values >> 8) & 0xFF),
|
||||
B: uint8(values & 0xFF),
|
||||
A: 255,
|
||||
}
|
||||
}
|
||||
display.FillRectangleWithBuffer(0, int16(i), displayWidth, 1, row)
|
||||
}
|
||||
|
||||
refreshIntervals := uint8(20)
|
||||
|
||||
for i := uint8(0); i < refreshIntervals; i++ {
|
||||
time.Sleep(logoDisplayTime / time.Duration(refreshIntervals))
|
||||
getInput()
|
||||
|
||||
if goBack() {
|
||||
quit = true
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
selectedScreen++
|
||||
}
|
||||
|
||||
func QR(msg string) {
|
||||
qr, err := qrcode.New(msg, qrcode.Medium)
|
||||
if err != nil {
|
||||
println(err, 123)
|
||||
}
|
||||
|
||||
qrbytes := qr.Bitmap()
|
||||
size := int16(len(qrbytes))
|
||||
|
||||
factor := int16(displayHeight / len(qrbytes))
|
||||
|
||||
bx := (displayWidth - size*factor) / 2
|
||||
by := (displayHeight - size*factor) / 2
|
||||
display.FillScreen(color.RGBA{109, 0, 140, 255})
|
||||
for y := int16(0); y < size; y++ {
|
||||
for x := int16(0); x < size; x++ {
|
||||
if qrbytes[y][x] {
|
||||
display.FillRectangle(bx+x*factor, by+y*factor, factor, factor, colorBlack)
|
||||
} else {
|
||||
display.FillRectangle(bx+x*factor, by+y*factor, factor, factor, colorWhite)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
refreshIntervals := uint8(20)
|
||||
|
||||
for i := uint8(0); i < refreshIntervals; i++ {
|
||||
time.Sleep(logoDisplayTime / time.Duration(refreshIntervals))
|
||||
getInput()
|
||||
|
||||
if goBack() {
|
||||
quit = true
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
selectedScreen++
|
||||
}
|
||||
|
||||
func getFontWidthSize(text string) (w32 uint32, size byte) {
|
||||
w32, _ = tinyfont.LineWidth(&freesans.Bold24pt7b, text)
|
||||
size = 24
|
||||
if w32 < uint32(FontWidthThreshold) {
|
||||
size = 24
|
||||
} else {
|
||||
w32, _ = tinyfont.LineWidth(&freesans.Bold18pt7b, text)
|
||||
if w32 < uint32(FontWidthThreshold) {
|
||||
size = 18
|
||||
} else {
|
||||
w32, _ = tinyfont.LineWidth(&freesans.Bold12pt7b, text)
|
||||
if w32 < uint32(FontWidthThreshold) {
|
||||
size = 12
|
||||
} else {
|
||||
w32, _ = tinyfont.LineWidth(&freesans.Bold9pt7b, text)
|
||||
size = 9
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
483
data.go
Normal file
483
data.go
Normal file
|
|
@ -0,0 +1,483 @@
|
|||
package main
|
||||
|
||||
// Replace with your data by using -ldflags like this:
|
||||
//
|
||||
// tinygo flash -target pybadge -ldflags="-X main.YourName=@myontwitter -X main.YourTitleA1='Amazing human' -X main.YourTitleA2='also kind'"
|
||||
//
|
||||
// See Makefile for more info.
|
||||
var (
|
||||
YourName, YourCompany, YourTitleA1, YourTitleA2, YourTitleB1, YourTitleB2 string
|
||||
YourMarqueeTop, YourMarqueeMiddle, YourMarqueeBottom, YourQRText string
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultName = "@TinyGolang"
|
||||
DefaultTitleA1 = "Go Compiler"
|
||||
DefaultTitleA2 = "Small Places"
|
||||
DefaultMarqueeTop = "This badge"
|
||||
DefaultMarqueeMiddle = "runs"
|
||||
DefaultMarqueeBottom = "TINYGO"
|
||||
DefaultQRText = "https://gopherbadge.com"
|
||||
DefaultTitleB1 = "I enjoy"
|
||||
DefaultTitleB2 = "TINYGO"
|
||||
)
|
||||
|
||||
func setCustomData() {
|
||||
if YourName == "" {
|
||||
YourName = DefaultName
|
||||
}
|
||||
|
||||
if YourTitleA1 == "" {
|
||||
YourTitleA1 = DefaultTitleA1
|
||||
}
|
||||
|
||||
if YourTitleA2 == "" {
|
||||
YourTitleA2 = DefaultTitleA2
|
||||
}
|
||||
|
||||
if YourTitleB1 == "" {
|
||||
YourTitleB1 = DefaultTitleB1
|
||||
}
|
||||
|
||||
if YourTitleB2 == "" {
|
||||
YourTitleB2 = DefaultTitleB2
|
||||
}
|
||||
|
||||
if YourMarqueeTop == "" {
|
||||
YourMarqueeTop = DefaultMarqueeTop
|
||||
}
|
||||
|
||||
if YourMarqueeMiddle == "" {
|
||||
YourMarqueeMiddle = DefaultMarqueeMiddle
|
||||
}
|
||||
|
||||
if YourMarqueeBottom == "" {
|
||||
YourMarqueeBottom = DefaultMarqueeBottom
|
||||
}
|
||||
|
||||
if YourQRText == "" {
|
||||
YourQRText = DefaultQRText
|
||||
}
|
||||
|
||||
if YourCompany == "" {
|
||||
YourCompany = "TinyGo"
|
||||
}
|
||||
}
|
||||
|
||||
type Talk struct {
|
||||
startHour, endHour, line1, line2, line3 string
|
||||
}
|
||||
|
||||
type Day struct {
|
||||
title string
|
||||
talks []Talk
|
||||
}
|
||||
|
||||
var scheduleData = []Day{
|
||||
{"Monday August 25 (TZ EDT)",
|
||||
[]Talk{
|
||||
{"18:00", "20:00", "WOMEN WHO GO MEETbuttonUp", "Angelica Hill, Cassie Coyle,", "Kate Pong & Samantha Coyle"},
|
||||
{"", "", "", "", ""},
|
||||
{"", "", "", "", ""},
|
||||
{"", "", "", "", ""},
|
||||
},
|
||||
},
|
||||
{"Tuesday August 26 (TZ EDT)",
|
||||
[]Talk{
|
||||
{"07:00", "11:00", "Morning Coffee Break", "Foyer, Level 4, North Javits", ""},
|
||||
{"07:00", "17:30", "Registration & Gopher Gear Shop", "Foyer, Level 5, North Javits", ""},
|
||||
{"08:30", "12:30", "WORKSHOP: Building and deployin AI", "agents with Go", "Johnny Boursiquot"},
|
||||
{"08:30", "12:30", "WORKSHOP: Profiling and optimizing", "Go programs", "Cory LaNou"},
|
||||
{"08:30", "17:30", "WORKSHOP: AI-powered systems in Go:", "RAG & tool calling", "Florin Patan"},
|
||||
{"08:30", "17:30", "WORKSHOP", "Ultimate Go", "Miki Tebeka"},
|
||||
{"08:30", "17:30", "WORKSHOP", "Ultimate software design and engineering", "William Kennedy"},
|
||||
{"08:30", "17:30", "", "HALLWAY TRACK", "Foyer, Level 4, North Javits"},
|
||||
{"09:00", "12:00", "Contributors summit", "Ian Cottrell, Michael Knyszek", "& Michael Pratt"},
|
||||
{"09:00", "17:00", "Challenge series: how deep", "does the code go?", "Neil Primmer & Benji Vesterby"},
|
||||
{"10:00", "16:00", "TINYGO HARDWARE HACK SESSION", "Ron Evans & Patricio Whittingslow", "Room 409/411, Level 4, North Javits"},
|
||||
{"10:00", "16:00", "Community Roundtables", "Room 404/405, Level 4, North Javits", ""},
|
||||
{"12:00", "13:30", "Grab & Go lunch", "Foyer, Level 4, North Javits", ""},
|
||||
{"13:30", "16:30", "Community day:", "Meet the Go team", "Room 413, Level 4, North Javits"},
|
||||
{"13:30", "17:30", "WORKSHOP: Advanced Go for", "experienced programmers", "Johnny Boursiquot"},
|
||||
{"13:30", "17:30", "WORKSHOP: Advanced testing", "in Go programs", "Cory LaNou"},
|
||||
{"13:30", "17:30", "WORKSHOP: Go concurrency: debugging", "goroutines and channels", "Derek Parker"},
|
||||
{"15:00", "17:00", "Afternoon break", "Foyer, Level 4, North Javits", ""},
|
||||
{"17:00", "19:00", "Meetup organizers (past, present & future)", "Benji Vesterby, Cassie Coyle", "& Samantha Coyle"},
|
||||
{"18:00", "20:00", "Neurospicy meetup", "Andy Haskell, Charles Pustejovsky,", "Kaylyn Gibilterra & Erik St. Martin"},
|
||||
{"20:00", "22:00", "RainGo Connection Meetup", "Angelica Hill, Kris Brandow", "& Zaq? Question"},
|
||||
},
|
||||
},
|
||||
{"Wednesday August 27 (TZ EDT)",
|
||||
[]Talk{
|
||||
{"08:00", "10:00", "Coffee with the exhibitors", "Room 503/504, Level 5, North Javits", ""},
|
||||
{"08:00", "17:00", "Challenge series: how deep", "does the code go?", "Neil Primmer & Benji Vesterby"},
|
||||
{"08:00", "17:45", "GopherCon exhibition", "Room 503/504, Level 5, North Javits", ""},
|
||||
{"08:00", "17:45", "", "HALLWAY TRACK", "Foyer, Level 5, North Javits"},
|
||||
{"09:05", "09:30", "Go's next frontier", "Cameron Balahan", ""},
|
||||
{"09:35", "10:00", "Demystifying AI agents:", "A new primitive for flow control", "Solomon Hykes"},
|
||||
{"10:05", "10:30", "Goroutines and cells:", "Lessons in goal-directed systems", "Carlisia Campos"},
|
||||
{"10:30", "11:15", "Morning beverage break", "Room 503/504, Level 5, North Javits", ""},
|
||||
{"10:45", "11:00", "Go: a taylor-made language", "for AWS lambda", "Capital One"},
|
||||
{"11:15", "11:40", "The code you reviewed is", "not the code you built", "Jess McClintock"},
|
||||
{"11:45", "12:10", "My protobuf module is faster", " than yours (I cheated)", "Tom Lyons"},
|
||||
{"12:15", "12:40", "Building a decentralize social", "media app with Go and ATProto", "Gautam Dey"},
|
||||
{"12:15", "12:40", "Building a decentralize social", "media app with Go and ATProto", "Gautam Dey"},
|
||||
{"12:40", "14:25", "Lunch service", "Room 503/504, Level 5, North Javits", "Bayer"},
|
||||
{"13:40", "14:25", "Lightning talks", "Angelica Hill, Kaylyn Gibilterra,", "James Heller & Sahid Velji"},
|
||||
{"14:25", "14:50", "Analysis and transformation tools", "for Go codebase modernization", "Alan A. Donovan"},
|
||||
{"14:55", "15:20", "Plowing through data:", "building flexible pipelines with Go", "Mindy Ratcliff"},
|
||||
{"15:20", "16:00", "Afternoon beverage break", "Room 503/504, Level 5, North Javits", ""},
|
||||
{"16:00", "16:25", "Understanding escape analysis", "to speed up your code", "PJ Malloy"},
|
||||
{"16:30", "16:55", "Scaling LLMs with Go: production patterns", "for handling millions of AI requests", "John Wang"},
|
||||
{"17:00", "17:45", "Porting the TypeScript compiler", "to Go for a 10x speedup", "Jake Bailey"},
|
||||
{"18:00", "21:00", "Rooftop reception with Skool", "Rooftop, 570 10th Avenue", ""},
|
||||
{"19:00", "21:00", "Asian alliance meetup", "Arjun Malhotra, Ellen Gao,", "Hannah Kim & Madhav Jovrajani"},
|
||||
{"19:00", "21:00", "United Fo meetup", "Edmondo Porcu, Johnny Boursiquot", "& Kris BRandow"},
|
||||
},
|
||||
},
|
||||
{"Thursday August 28 (TZ EDT)",
|
||||
[]Talk{
|
||||
{"08:00", "10:00", "Coffee with the exhibitors", "Room 503/504, Level 5, North Javits", ""},
|
||||
{"08:00", "16:00", "Challenge series: how deep", "does the code go?", "Neil Primmer & Benji Vesterby"},
|
||||
{"08:00", "16:00", "GopherCon exhibition", "Room 503/504, Level 5, North Javits", ""},
|
||||
{"08:00", "17:30", "", "HALLWAY TRACK", "Foyer, Level 5, North Javits"},
|
||||
{"08:00", "18:00", "Attendee services & Gopher Gear Shop", "Foyer, Level 5, North Javits", ""},
|
||||
{"08:40", "08:55", "From chaos to cohesion:", "a community of practive story", "Capital One"},
|
||||
{"09:00", "09:05", "", "WELCOME BACK, GOPHERS!", ""},
|
||||
{"09:05", "09:30", "An operating system in Go", "Patricio Whittingslow", ""},
|
||||
{"09:35", "10:05", "Go's trace tooling", "and concurrency", "William Kennedy"},
|
||||
{"10:10", "10:35", "Profiling request latency", "with critical path analysis", "Felix Geisendorfer"},
|
||||
{"10:35", "11:05", "Morning beverage break", "Room 503/504, Level 5, North Javits", ""},
|
||||
{"11:05", "11:30", "Invisible insight: strategies for", "auto-instrumenting go apps", "Hannah Kim"},
|
||||
{"11:35", "12:00", "Next-gen AI tooling", "with MCP servers in Go", "Katie Hockman"},
|
||||
{"12:05", "12:30", "Supercharging ML pipelines", "with Go", "Vaidehi Thete"},
|
||||
{"12:30", "14:15", "Lunch service", "Room 503/504, Level 5, North Javits", ""},
|
||||
{"13:30", "14:15", "Lightning talks", "Angelica Hill, Kaylyn Gibilterra,", "James Heller & Sahid Velji"},
|
||||
{"14:15", "14:45", "Go faster: integrating CUDA", "in Go for GPU acceleration", "Sam Burns"},
|
||||
{"14:45", "15:15", "Go plays nice with your computer", "race detection and freedom", "Reghav Roy"},
|
||||
{"15:15", "15:45", "Afternoon beverage break", "Room 503/504, Level 5, North Javits", ""},
|
||||
{"15:45", "16:10", "Advancing Go garbage collection", "with green Tea", "Michael Knyszek"},
|
||||
{"16:15", "16:40", "The Go cryptography state of the union", "Filippo Valsorda", ""},
|
||||
{"16:45", "17:30", "AI & Go: opportunities & challenges", "Johnny Boursiquote, David Soria, Gari Singh,", "Ian Cottrell, Jaana Dogan & Solomon Hykes"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
type Scene struct {
|
||||
description, optionA, optionB, optionC string
|
||||
sceneA, sceneB, sceneC int
|
||||
}
|
||||
|
||||
var sceneData = []Scene{
|
||||
{
|
||||
"As usually, you are reading Golang Weekly, among very useful information you notice the CFP for GopherCon is open! It will be in New York, 25-28th August. What do you want to do?",
|
||||
"Oh no! you don't have any idea for a talk.",
|
||||
"Let's talk about AI, it's the new pink!",
|
||||
"You already have the slides for a TinyGo talk.",
|
||||
1, 2, 3,
|
||||
},
|
||||
{
|
||||
"It's ok, you still take advantage of the date and got an early-bird ticket at a discounted price:",
|
||||
"Self-payin gopher (385$)",
|
||||
"Corporate gopher (500$)",
|
||||
"Premium gopher + workshops (850$)",
|
||||
4, 4, 4,
|
||||
},
|
||||
{
|
||||
"You worked hard on your slides and send your abstract in time. A few days passed and received the bad news that your talk wasn't accepted, " +
|
||||
"nobody is interested anymore in AI. But they offer you a discount price for the tickets:",
|
||||
"Self-payin gopher (335$)",
|
||||
"Corporate gopher (450$)",
|
||||
"Premium gopher + workshops (770$)",
|
||||
4, 4, 4,
|
||||
},
|
||||
{
|
||||
"Flying drones, hens, LEDs, lasers, music,... who will not like such a talk about TinyGo? Your talk of course was accepted and your trip is fully paid.",
|
||||
"YAY!",
|
||||
"Super yay!",
|
||||
"OMG!!1! a dream come true",
|
||||
4, 4, 4,
|
||||
},
|
||||
{
|
||||
"BEEP BEEP BEEP. It's your alarm clock. Today is the day, your need to prepare and go to the airport, New York and a bunch of gophers are waiting for you.",
|
||||
"Take a taxi to the airport. No time to waste!",
|
||||
"Have Liam's signature pancakes.",
|
||||
"Sleep a bit more",
|
||||
5, 6, 4,
|
||||
},
|
||||
{ // 5
|
||||
"You took a taxi, arrived at the airport with enough time, there was no need to rush that much. When you go to the check-in baggage desktop you realize you forgot your suitcase with everything. You are only wearing your unicorn-pijama.",
|
||||
"No time to go back, you board the plane.",
|
||||
"You shop something at the airport's shop.",
|
||||
"You don't care. YOLO! Go to your gate.",
|
||||
7, 8, 7,
|
||||
},
|
||||
{
|
||||
"You have the best breakfast ever and feel full of energy, so much you pick up your suitcase and RUN to the airport. You pass the security check without issues.",
|
||||
"Better not waste time, board the plane.",
|
||||
"You shop something at the airport's shop.",
|
||||
"A quick visit to the toilet before boarding.",
|
||||
7, 8, 7,
|
||||
},
|
||||
{
|
||||
"You are finally at the plane, go up to your seat: 27B. Your seat neighborg looks like a gopher too, who is holding a shark plushie and a network switch.",
|
||||
"Ask about the shark.",
|
||||
"Ask about the network switch.",
|
||||
"Goeiemorgen.",
|
||||
9, 10, 11,
|
||||
},
|
||||
{
|
||||
"You've bought the most expensive suit and bowtie of your life, but holy guacomole, what a nice and superb suit. You look awesome.",
|
||||
"Go to the gate and board the plane",
|
||||
"Go to the gate and board the plane",
|
||||
"Go to the gate and board the plane",
|
||||
7, 7, 7,
|
||||
},
|
||||
{
|
||||
"-\"This shark? It's name is Blahaj and is the administrator of our mastodon instance. This is probably the weirdest train I've ever been in, I've never seen a train with wings before!\"",
|
||||
"Yeah... sure... ",
|
||||
"Oh cool",
|
||||
"Me neither",
|
||||
12, 12, 12,
|
||||
},
|
||||
{ // 10
|
||||
"-\"This switch? I need it for the uplink of our mastodon instance. This is probably the weirdest train I've ever been in, I've never seen a train with wings before!\"",
|
||||
"Yeah... sure... ",
|
||||
"Oh cool",
|
||||
"Me neither",
|
||||
12, 12, 12,
|
||||
},
|
||||
{
|
||||
"-\"Dit is waarschijnlijk de vreemdste trein waar ik ooit in heb gezeten, ik heb nog nooit een trein met vleugels gezien!\"",
|
||||
"Yeah... sure... ",
|
||||
"Oh cool",
|
||||
"Ik ook niet",
|
||||
12, 12, 12,
|
||||
},
|
||||
{
|
||||
"The plane finally landed. You check in the hotel and have a few hours left to visit the city. New York is famous for:",
|
||||
"Hotdog is a matter of pride for New Yorkers",
|
||||
"You know the lyrics of all JAY-Z's songs",
|
||||
"The Statue of Liberty is a must",
|
||||
13, 14, 15,
|
||||
},
|
||||
{
|
||||
"You ask the concierge at the hotel about the best Hotdog in the city and go there. You make a mess of yourself, but it was delicious. When you start leaving the place, a weird looking person, too clean to be a bum, but with crazy person vibes and a tinfoil hat approaches. He tries to stop you.",
|
||||
"You run as fast as you can",
|
||||
"Try to ignore him",
|
||||
"Give him 5USD & proceed to listen to him",
|
||||
16, 16, 17,
|
||||
},
|
||||
{
|
||||
"Unfortunately there is no JAY-Z concert today so you decide to go for a walk around the city to make time. When walking through a dark alley a weird looking person, too clean to be a bum, but with crazy person vibes and a tinfoil hat approaches. He tries to stop you.",
|
||||
"You run as fast as you can",
|
||||
"Try to ignore him",
|
||||
"Give him 5USD & proceed to listen to him",
|
||||
|
||||
16, 16, 17,
|
||||
},
|
||||
{ // 15
|
||||
"You visit the Statue of Liberty, it's amazong. While walking back to the hotel, you go through a dark alley and a weird looking person, too clean to be a bum, but with crazy person vibes and a tinfoil hat approaches. He tries to stop you.",
|
||||
"You run as fast as you can",
|
||||
"Try to ignore him",
|
||||
"Give him 5USD & proceed to listen to him",
|
||||
16, 16, 17,
|
||||
},
|
||||
{
|
||||
"-\"Hey you... yeah " + YourName + "! " + YourName + " who works at " + YourCompany + " listen to me, I'm Ron Evans!, but the Ron Evans from the future!!, the year 2053, the last gopher. You need to listen carefully I have very little time, remember the code : <<IDKFA>> You are the only hope to save the planet and the humanity! (truust me)\" ... zooosh... and he disappeared",
|
||||
"Wait! What just happened?",
|
||||
"IDKFA... IDKFA... IDKFA... you try to remember",
|
||||
"....",
|
||||
18, 18, 18,
|
||||
},
|
||||
{
|
||||
"-\"Oh hello " + YourName + "! Thank you for listening to me, I'm Ron Evans, but the Ron Evans from the future!!, the year 2053, the last gopher. You need to listen carefully I have very little time, remember the code : <<IDKFA>> You are the only hope to save the planet and the humanity! (truust me)\" ... zooosh... and he disappeared",
|
||||
"Wait! What just happened?",
|
||||
"IDKFA... IDKFA... IDKFA... you try to remember",
|
||||
"....",
|
||||
18, 18, 18,
|
||||
},
|
||||
{
|
||||
"After this misterious encounter, you want to go back to the hotel as fast as you can. In front of you there is a group of friendly gophers. Thankfully they are going to the same hotel and can carry you. But each one has it's own method of transportation.",
|
||||
"You truust Francesc with his bicycle",
|
||||
"Takasago can carry you in his motocross bike",
|
||||
"Share an e-scooter with Manolo",
|
||||
19, 19, 19,
|
||||
},
|
||||
{
|
||||
"You all arrive at the hotel and decided to take a drink at the bar. There, you encounter Natalie and Mat recording a GoTime podcast, they ask you about your unpopular opinion:",
|
||||
"It's pronounced data, not data",
|
||||
"Rabbits are not rodent, they are lagomorphs",
|
||||
"Cheese cake is the best dessert",
|
||||
20, 21, 22,
|
||||
},
|
||||
{ // 20
|
||||
"-\"Hey wonderful listeners, we welcome " + YourName + " to our program, the gopher who states that data should be pronounced data instead of data. What do you think Natalie? I'm a bit socked myself. And with this we end our episode for today\"",
|
||||
"Time to go to bed",
|
||||
"Time to go to bed",
|
||||
"Time to go to bed",
|
||||
23, 23, 23,
|
||||
},
|
||||
{
|
||||
"-\"Hey wonderful listeners, we welcome " + YourName + " to our program, the gopher who states that rabbits are ... lagomorphs? Isn't that the Alien movie? That doesn't sound like an opinion but more like a fact. What do you think Mat? I'm a bit socked myself. And with this we end our episode for today\"",
|
||||
"Time to go to bed",
|
||||
"Time to go to bed",
|
||||
"Time to go to bed",
|
||||
23, 23, 23,
|
||||
},
|
||||
{
|
||||
"-\"Hey wonderful listeners, we welcome " + YourName + " to our program, the gopher who states that the best dessert is the cheesecake. I've to say I totally agree with that. What do you think Natalie? And with this we end our episode for today\"",
|
||||
"Time to go to bed",
|
||||
"Time to go to bed",
|
||||
"Time to go to bed",
|
||||
23, 23, 23,
|
||||
},
|
||||
{
|
||||
"After a long day, you arrive to your room, your bed for the next days is waiting for you. You close your eyes. Looks like it's just a second, but wake up fully rested and ready for the first day of GopherCon. You skip breakfast because I'm too tired of adding options.",
|
||||
"-----",
|
||||
"Go to North Javits",
|
||||
"(event location)",
|
||||
24, 24, 24,
|
||||
},
|
||||
{
|
||||
"You arrive at the door. A familiar face greets you, it's the wonderful Angelica. You pick up your new TinyGo powered e-ink badge and look at it.",
|
||||
"-----",
|
||||
"Look at your badge",
|
||||
"-----",
|
||||
25, 25, 25,
|
||||
},
|
||||
{ // 25
|
||||
"",
|
||||
"-----",
|
||||
"-----",
|
||||
"-----",
|
||||
26, 26, 26,
|
||||
},
|
||||
{
|
||||
"You notice there's a modeSchedule function in your badge, you could navigate today's schedule and pick your favourite talks you want to attend.",
|
||||
"An Operating System in Go - Patricio Whittingslow",
|
||||
"Goroutines and cells - Carlisia Campos",
|
||||
"Next-gen AI tooling - Katie Hockman",
|
||||
27, 27, 27,
|
||||
},
|
||||
{ // left empty, redirect to proper scene according the clothes.
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
28, 29, 30,
|
||||
},
|
||||
{
|
||||
"The talk was super fun and you learned a lot. You are preparing to go to the next talk but some people stops you. They hand you a book and ask you to sign it, they have confused you with someone else. Since you are sporting your unicorn pijama, they think you are Aurelie, the famous Go book author.",
|
||||
"Sign it!",
|
||||
"Try to explain you are not her",
|
||||
"Je ne parle pas français",
|
||||
31, 31, 31,
|
||||
},
|
||||
{
|
||||
"The talk was super fun and you learned a lot. You are preparing to go to the next talk but some people stops you. They hand you a martini and ask you for crypto investment advice, they have confused you with someone else. Since you are sporting the faboulous suit and bow tie, they think you are Tanguy Herman, the best dressed gopher in the world.",
|
||||
"Shaken, not stirred",
|
||||
"Buy high, sell low... or the other way around",
|
||||
"Try to explain you are not her",
|
||||
31, 31, 31,
|
||||
},
|
||||
{ // 30
|
||||
"The talk was super fun and you learned a lot. You are preparing to go to the next talk but you find some old friends and catch up with your lives. You talked so much you missed the next talk and it's lunch time already.",
|
||||
"Yay! Veggie sandwiches.",
|
||||
"This quinoa salad is top.",
|
||||
"Not sure what I'm eating but it's superb.",
|
||||
32, 32, 32,
|
||||
},
|
||||
{
|
||||
"You try to explain they are mistaken to no avail. Anyway you talked so much you missed the next talk and it's lunch time already.",
|
||||
"Yay! Veggie sandwiches.",
|
||||
"This quinoa salad is top.",
|
||||
"Not sure what I'm eating but it's superb.",
|
||||
32, 32, 32,
|
||||
},
|
||||
{ // redIRECT IN CASE YOU GAVE A TALK OR NOT
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
33, 34, 34,
|
||||
},
|
||||
{
|
||||
"After lunch it's time for your talk: flying drones, hens, LEDs, lasers, music,... you left the auditorium in awe, asking for more. Time for the grand finale, you only have one shot, one opportunity:",
|
||||
"FIREWORKS never fail.",
|
||||
"Launch a weather ballon.",
|
||||
"One word: Robot-laser-tag.",
|
||||
35, 36, 37,
|
||||
},
|
||||
{
|
||||
"After lunch it's time for another talk. The Ron Evans from your timeline is flying some drones inside the auditorium, one is going crazy and is going to attack some gophers. You could help him by rebooting the drone remotely, but need to introduce the reboot CODE:",
|
||||
"IDGAF",
|
||||
"IDKFA",
|
||||
"IDDQD",
|
||||
38, 39, 38,
|
||||
},
|
||||
{ // 35
|
||||
"Fireforks inside an auditorium? Yeah why not? Not sure who approved this but you need to introduce the launch CODE:",
|
||||
"IDGAF",
|
||||
"IDKFA",
|
||||
"IDDQD",
|
||||
38, 39, 38,
|
||||
},
|
||||
{
|
||||
"You all go outside, a big weather balloon is waiting on the ground. Introduce the launch CODE to initiate the countdown:",
|
||||
"IDGAF",
|
||||
"IDKFA",
|
||||
"IDDQD",
|
||||
38, 39, 38,
|
||||
},
|
||||
{
|
||||
"Autonomous robots armed with lasers? Yeah why not? Not sure who approved this but you need to introduce the login CODE for them to boot up:",
|
||||
"IDGAF",
|
||||
"IDKFA",
|
||||
"IDDQD",
|
||||
38, 39, 38,
|
||||
},
|
||||
{
|
||||
"Wrong code, rememmber what that crazy person yesterday was telling you. You have another opportunity:",
|
||||
"IDDQD",
|
||||
"IDKFA",
|
||||
"IDGAF",
|
||||
38, 39, 38,
|
||||
},
|
||||
{
|
||||
"Correct code, sequence initiated. YAY! The talk is a big success, #TinyGo is trending topic. GopherCon is coming to an end and only the social mixer is left to attend. You talked with many gopher there, laugh at bad tech jokes and make some friends.",
|
||||
"Click A to continue.",
|
||||
"Click B to continue.",
|
||||
"Click C to continue.",
|
||||
40, 40, 40,
|
||||
},
|
||||
{ // 40
|
||||
"This is the end of this adventure. Continue to the next screen to see some stats of your adventure.",
|
||||
"Click A to continue.",
|
||||
"Click B to continue.",
|
||||
"Click C to continue.",
|
||||
41, 41, 41,
|
||||
},
|
||||
{ // STATS PAGE
|
||||
"",
|
||||
"Click A to continue.",
|
||||
"Click B to continue.",
|
||||
"Click C to continue.",
|
||||
42, 42, 42,
|
||||
},
|
||||
{ // QR PAGE
|
||||
"", "", "", "",
|
||||
43, 43, 43,
|
||||
},
|
||||
{ // THE END
|
||||
"Thank you for playing this adventure. I hope you enjoyed playing it as much as I (CONEJO) did making it. I hid some easter eggs (not very well hidden) and references. Feel free to share your opinion about it in person or online at @conejo@social.tinygo.org",
|
||||
"Click A to continue.",
|
||||
"Click B to continue.",
|
||||
"Click C to continue.",
|
||||
44, 44, 44,
|
||||
},
|
||||
{ // THE REAL END
|
||||
"", "", "", "",
|
||||
45, 45, 45,
|
||||
},
|
||||
}
|
||||
26
defs_default.go
Normal file
26
defs_default.go
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
//go:build !gopher_badge && !pybadge
|
||||
// +build !gopher_badge,!pybadge
|
||||
|
||||
package main
|
||||
|
||||
// Default definitions for IDE support and testing
|
||||
// This file is not compiled when using a specific target
|
||||
|
||||
const (
|
||||
displayWidth = 320
|
||||
displayHeight = 240
|
||||
)
|
||||
|
||||
const (
|
||||
CornerRadius = 10
|
||||
TopBandHeight = 54
|
||||
BottomBandHeight = 20
|
||||
HelloY = 34
|
||||
MyNameIsY = 54
|
||||
GophersY = 208
|
||||
GophersX = 84
|
||||
|
||||
menuItemSpace = 20
|
||||
menuCircleR = 6
|
||||
|
||||
)
|
||||
133
defs_gopherbadge.go
Normal file
133
defs_gopherbadge.go
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
//go:build gopher_badge
|
||||
// +build gopher_badge
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"machine"
|
||||
|
||||
"tinygo.org/x/drivers/lis3dh"
|
||||
"tinygo.org/x/drivers/st7789"
|
||||
"tinygo.org/x/drivers/ws2812"
|
||||
)
|
||||
|
||||
const (
|
||||
displayWidth = 320
|
||||
displayHeight = 240
|
||||
)
|
||||
|
||||
// UI layout constants for gopherbadge (320x240)
|
||||
const (
|
||||
// myNameIs layout
|
||||
cornerRadius = 10
|
||||
TopBandHeight = 54
|
||||
BottomBandHeight = 20
|
||||
HelloY = 34
|
||||
MyNameIsY = 54
|
||||
GophersY = 208
|
||||
GophersX = 84
|
||||
|
||||
// menu layout
|
||||
menuItemSpace = 20
|
||||
menuCircleR = 6
|
||||
|
||||
numLEDs = 2
|
||||
|
||||
buttonBack = buttonB
|
||||
)
|
||||
|
||||
var menuOptions = []int8{
|
||||
modeBadge,
|
||||
modeSchedule,
|
||||
modeAdventure,
|
||||
modeLEDs,
|
||||
modeAccelerometer,
|
||||
modeMusic,
|
||||
modeGameSnake,
|
||||
modeGameLife,
|
||||
modeGameColors,
|
||||
modeInfo,
|
||||
}
|
||||
|
||||
// Font size thresholds for gopherbadge
|
||||
const (
|
||||
FontWidthThreshold = 300
|
||||
)
|
||||
|
||||
var (
|
||||
display st7789.Device
|
||||
btnA machine.Pin
|
||||
btnB machine.Pin
|
||||
btnUp machine.Pin
|
||||
btnLeft machine.Pin
|
||||
btnDown machine.Pin
|
||||
btnRight machine.Pin
|
||||
)
|
||||
|
||||
func initHardware() {
|
||||
machine.SPI0.Configure(machine.SPIConfig{
|
||||
Frequency: 8000000,
|
||||
Mode: 0,
|
||||
})
|
||||
|
||||
machine.I2C0.Configure(machine.I2CConfig{
|
||||
SCL: machine.I2C0_SCL_PIN,
|
||||
SDA: machine.I2C0_SDA_PIN,
|
||||
})
|
||||
accel = lis3dh.New(machine.I2C0)
|
||||
accel.Address = lis3dh.Address0
|
||||
accel.Configure()
|
||||
|
||||
display = st7789.New(machine.SPI0,
|
||||
machine.TFT_RST, // TFT_RESET
|
||||
machine.TFT_WRX, // TFT_DC
|
||||
machine.TFT_CS, // TFT_CS
|
||||
machine.TFT_BACKLIGHT) // TFT_LITE
|
||||
|
||||
display.Configure(st7789.Config{
|
||||
Rotation: st7789.ROTATION_270,
|
||||
Height: 320,
|
||||
})
|
||||
|
||||
neo := machine.NEOPIXELS
|
||||
neo.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
leds = ws2812.New(neo)
|
||||
|
||||
bzrPin = machine.SPEAKER
|
||||
bzrPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
|
||||
speaker := machine.SPEAKER_ENABLE
|
||||
speaker.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
speaker.High()
|
||||
|
||||
btnA = machine.BUTTON_A
|
||||
btnB = machine.BUTTON_B
|
||||
btnUp = machine.BUTTON_UP
|
||||
btnLeft = machine.BUTTON_LEFT
|
||||
btnDown = machine.BUTTON_DOWN
|
||||
btnRight = machine.BUTTON_RIGHT
|
||||
btnA.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||
btnB.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||
btnUp.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||
btnLeft.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||
btnDown.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||
btnRight.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||
|
||||
black := color.RGBA{0, 0, 0, 255}
|
||||
display.FillScreen(black)
|
||||
|
||||
}
|
||||
|
||||
func getInput() {
|
||||
for b := 0; b < 9; b++ {
|
||||
buttonsOldState[b] = buttonsState[b]
|
||||
}
|
||||
|
||||
buttonsState[buttonUp] = !btnUp.Get()
|
||||
buttonsState[buttonRight] = !btnRight.Get()
|
||||
buttonsState[buttonDown] = !btnDown.Get()
|
||||
buttonsState[buttonLeft] = !btnLeft.Get()
|
||||
buttonsState[buttonA] = !btnA.Get()
|
||||
buttonsState[buttonB] = !btnB.Get()
|
||||
}
|
||||
109
defs_pybadge.go
Normal file
109
defs_pybadge.go
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
//go:build pybadge
|
||||
// +build pybadge
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
|
||||
"tinygo.org/x/drivers/lis3dh"
|
||||
"tinygo.org/x/drivers/shifter"
|
||||
"tinygo.org/x/drivers/st7735"
|
||||
"tinygo.org/x/drivers/ws2812"
|
||||
)
|
||||
|
||||
const (
|
||||
displayWidth = 160
|
||||
displayHeight = 128
|
||||
)
|
||||
|
||||
// UI layout constants for pybadge/gobadge (160x128)
|
||||
const (
|
||||
// myNameIs layout
|
||||
cornerRadius = 8
|
||||
TopBandHeight = 26
|
||||
BottomBandHeight = 8
|
||||
HelloY = 24 // not used, uses "my NAME is" instead
|
||||
MyNameIsY = 24
|
||||
GophersY = 110
|
||||
GophersX = 48
|
||||
|
||||
// menu layout
|
||||
menuItemSpace = 10
|
||||
menuCircleR = 4
|
||||
|
||||
numLEDs = 5
|
||||
|
||||
buttonBack = buttonSelect
|
||||
)
|
||||
|
||||
var menuOptions = []int8{
|
||||
modeBadge,
|
||||
modeSchedule,
|
||||
modeAdventure,
|
||||
modeLEDs,
|
||||
modeAccelerometer,
|
||||
modeMusic,
|
||||
modeGameSnake,
|
||||
modeGameLife,
|
||||
modeGameColors,
|
||||
modeInfo,
|
||||
}
|
||||
|
||||
// Font size thresholds for pybadge (smaller screen, use smaller fonts)
|
||||
const (
|
||||
FontWidthThreshold = 150
|
||||
)
|
||||
|
||||
var display st7735.Device
|
||||
var buttons shifter.Device
|
||||
|
||||
func initHardware() {
|
||||
machine.SPI1.Configure(machine.SPIConfig{
|
||||
SCK: machine.SPI1_SCK_PIN,
|
||||
SDO: machine.SPI1_SDO_PIN,
|
||||
SDI: machine.SPI1_SDI_PIN,
|
||||
Frequency: 8000000,
|
||||
})
|
||||
machine.I2C0.Configure(machine.I2CConfig{SCL: machine.SCL_PIN, SDA: machine.SDA_PIN})
|
||||
|
||||
accel = lis3dh.New(machine.I2C0)
|
||||
accel.Address = lis3dh.Address0
|
||||
accel.Configure()
|
||||
|
||||
display = st7735.New(machine.SPI1, machine.TFT_RST, machine.TFT_DC, machine.TFT_CS, machine.TFT_LITE)
|
||||
display.Configure(st7735.Config{
|
||||
Rotation: st7735.ROTATION_90,
|
||||
})
|
||||
|
||||
buttons = shifter.NewButtons()
|
||||
buttons.Configure()
|
||||
|
||||
neo := machine.NEOPIXELS
|
||||
neo.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
leds = ws2812.New(neo)
|
||||
|
||||
bzrPin = machine.A0
|
||||
bzrPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
|
||||
speaker := machine.SPEAKER_ENABLE
|
||||
speaker.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
speaker.High()
|
||||
}
|
||||
|
||||
func getInput() {
|
||||
for b := 0; b < 9; b++ {
|
||||
buttonsOldState[b] = buttonsState[b]
|
||||
}
|
||||
|
||||
buttons.ReadInput()
|
||||
|
||||
buttonsState[buttonUp] = buttons.Pins[shifter.BUTTON_UP].Get()
|
||||
buttonsState[buttonRight] = buttons.Pins[shifter.BUTTON_RIGHT].Get()
|
||||
buttonsState[buttonDown] = buttons.Pins[shifter.BUTTON_DOWN].Get()
|
||||
buttonsState[buttonLeft] = buttons.Pins[shifter.BUTTON_LEFT].Get()
|
||||
buttonsState[buttonA] = buttons.Pins[shifter.BUTTON_A].Get()
|
||||
buttonsState[buttonB] = buttons.Pins[shifter.BUTTON_B].Get()
|
||||
buttonsState[buttonStart] = buttons.Pins[shifter.BUTTON_START].Get()
|
||||
buttonsState[buttonSelect] = buttons.Pins[shifter.BUTTON_SELECT].Get()
|
||||
}
|
||||
179
game_colors.go
Normal file
179
game_colors.go
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
gameColorsCellSize = 16
|
||||
gameColorsSpeed = 9
|
||||
gameColorsWidth = int16(displayWidth / gameColorsCellSize)
|
||||
gameColorsHeight = int16(displayHeight / gameColorsCellSize)
|
||||
)
|
||||
|
||||
var (
|
||||
colorgame [][]bool
|
||||
|
||||
p1x, p1y, p2x, p2y, tx int16
|
||||
v1x, v1y, v2x, v2y, ty int16
|
||||
)
|
||||
|
||||
func ColorGame() {
|
||||
display.FillScreen(colorOrange)
|
||||
|
||||
colorgame = make([][]bool, gameColorsWidth)
|
||||
|
||||
p1x = int16(rand.Int31n(int32(displayWidth/3))) + displayWidth/12
|
||||
p1y = int16(rand.Int31n(int32(4*gameColorsHeight/5))) + gameColorsHeight/10
|
||||
p2x = int16(rand.Int31n(int32(displayWidth/3))) + 7*displayWidth/12
|
||||
p2y = int16(rand.Int31n(int32(4*gameColorsHeight/5))) + gameColorsHeight/10
|
||||
|
||||
v1x = 2
|
||||
v1y = 3
|
||||
v2x = -3
|
||||
v2y = 2
|
||||
|
||||
for i := int16(0); i < gameColorsWidth; i++ {
|
||||
colorgame[i] = make([]bool, gameColorsHeight)
|
||||
if i >= gameColorsWidth/2 {
|
||||
for j := int16(0); j < gameColorsHeight; j++ {
|
||||
colorgame[i][j] = true
|
||||
display.FillRectangle(i*gameColorsCellSize, j*gameColorsCellSize, gameColorsCellSize, gameColorsCellSize, colorPurple)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
display.FillRectangle(p1x-gameColorsSpeed, p1y-gameColorsSpeed, gameColorsCellSize, gameColorsCellSize, colorPurple)
|
||||
display.FillRectangle(p2x-gameColorsSpeed, p2y-gameColorsSpeed, gameColorsCellSize, gameColorsCellSize, colorOrange)
|
||||
|
||||
for {
|
||||
display.FillRectangle(p1x-gameColorsSpeed, p1y-gameColorsSpeed, gameColorsCellSize, gameColorsCellSize, colorOrange)
|
||||
display.FillRectangle(p2x-gameColorsSpeed, p2y-gameColorsSpeed, gameColorsCellSize, gameColorsCellSize, colorPurple)
|
||||
|
||||
p1x += v1x
|
||||
p1y += v1y
|
||||
p2x += v2x
|
||||
p2y += v2y
|
||||
|
||||
if (p1x < gameColorsSpeed && v1x < 0) || (p1x > (displayWidth-gameColorsSpeed) && v1x > 0) {
|
||||
v1x = -v1x
|
||||
}
|
||||
if (p2x < gameColorsSpeed && v2x < 0) || (p2x > (displayWidth-gameColorsSpeed) && v2x > 0) {
|
||||
v2x = -v2x
|
||||
}
|
||||
if (p1y < gameColorsSpeed && v1y < 0) || (p1y > (displayHeight-gameColorsSpeed) && v1y > 0) {
|
||||
v1y = -v1y
|
||||
}
|
||||
if (p2y < gameColorsSpeed && v2y < 0) || (p2y > (displayHeight-gameColorsSpeed) && v2y > 0) {
|
||||
v2y = -v2y
|
||||
}
|
||||
|
||||
tx = (p1x - gameColorsSpeed) / gameColorsCellSize
|
||||
ty = p1y / gameColorsCellSize
|
||||
if tx < 0 {
|
||||
tx = 0
|
||||
}
|
||||
if colorgame[tx][ty] {
|
||||
colorgame[tx][ty] = false
|
||||
if v1x < 0 {
|
||||
v1x = -v1x
|
||||
}
|
||||
display.FillRectangle(tx*gameColorsCellSize, ty*gameColorsCellSize, gameColorsCellSize, gameColorsCellSize, colorOrange)
|
||||
}
|
||||
tx = (p1x + gameColorsSpeed) / gameColorsCellSize
|
||||
if tx >= gameColorsWidth {
|
||||
tx = gameColorsWidth - 1
|
||||
}
|
||||
if colorgame[tx][ty] {
|
||||
colorgame[tx][ty] = false
|
||||
if v1x > 0 {
|
||||
v1x = -v1x
|
||||
}
|
||||
display.FillRectangle(tx*gameColorsCellSize, ty*gameColorsCellSize, gameColorsCellSize, gameColorsCellSize, colorOrange)
|
||||
}
|
||||
tx = p1x / gameColorsCellSize
|
||||
ty = (p1y - gameColorsSpeed) / gameColorsCellSize
|
||||
if ty < 0 {
|
||||
ty = 0
|
||||
}
|
||||
if colorgame[tx][ty] {
|
||||
colorgame[tx][ty] = false
|
||||
if v1y < 0 {
|
||||
v1y = -v1y
|
||||
}
|
||||
display.FillRectangle(tx*gameColorsCellSize, ty*gameColorsCellSize, gameColorsCellSize, gameColorsCellSize, colorOrange)
|
||||
}
|
||||
ty = (p1y + gameColorsSpeed) / gameColorsCellSize
|
||||
if ty >= gameColorsHeight {
|
||||
ty = gameColorsHeight - 1
|
||||
}
|
||||
if colorgame[tx][ty] {
|
||||
colorgame[tx][ty] = false
|
||||
if v1y > 0 {
|
||||
v1y = -v1y
|
||||
}
|
||||
display.FillRectangle(tx*gameColorsCellSize, ty*gameColorsCellSize, gameColorsCellSize, gameColorsCellSize, colorOrange)
|
||||
}
|
||||
|
||||
// P2
|
||||
tx = (p2x - gameColorsSpeed) / gameColorsCellSize
|
||||
ty = p2y / gameColorsCellSize
|
||||
if tx < 0 {
|
||||
tx = 0
|
||||
}
|
||||
if !colorgame[tx][ty] {
|
||||
colorgame[tx][ty] = true
|
||||
if v2x < 0 {
|
||||
v2x = -v2x
|
||||
}
|
||||
display.FillRectangle(tx*gameColorsCellSize, ty*gameColorsCellSize, gameColorsCellSize, gameColorsCellSize, colorPurple)
|
||||
}
|
||||
tx = (p2x + gameColorsSpeed) / gameColorsCellSize
|
||||
if tx >= gameColorsWidth {
|
||||
tx = gameColorsWidth - 2
|
||||
}
|
||||
if !colorgame[tx][ty] {
|
||||
colorgame[tx][ty] = true
|
||||
if v2x > 0 {
|
||||
v2x = -v2x
|
||||
}
|
||||
display.FillRectangle(tx*gameColorsCellSize, ty*gameColorsCellSize, gameColorsCellSize, gameColorsCellSize, colorPurple)
|
||||
}
|
||||
tx = p2x / gameColorsCellSize
|
||||
ty = (p2y - gameColorsSpeed) / gameColorsCellSize
|
||||
if ty < 0 {
|
||||
ty = 0
|
||||
}
|
||||
if !colorgame[tx][ty] {
|
||||
colorgame[tx][ty] = true
|
||||
if v2y < 0 {
|
||||
v2y = -v2y
|
||||
}
|
||||
display.FillRectangle(tx*gameColorsCellSize, ty*gameColorsCellSize, gameColorsCellSize, gameColorsCellSize, colorPurple)
|
||||
}
|
||||
ty = (p2y + gameColorsSpeed) / gameColorsCellSize
|
||||
if ty >= gameColorsHeight {
|
||||
ty = gameColorsHeight - 2
|
||||
}
|
||||
if !colorgame[tx][ty] {
|
||||
colorgame[tx][ty] = true
|
||||
if v2y > 0 {
|
||||
v2y = -v2y
|
||||
}
|
||||
display.FillRectangle(tx*gameColorsCellSize, ty*gameColorsCellSize, gameColorsCellSize, gameColorsCellSize, colorPurple)
|
||||
}
|
||||
|
||||
display.FillRectangle(p1x-gameColorsSpeed, p1y-gameColorsSpeed, gameColorsCellSize, gameColorsCellSize, colorPurple)
|
||||
display.FillRectangle(p2x-gameColorsSpeed, p2y-gameColorsSpeed, gameColorsCellSize, gameColorsCellSize, colorOrange)
|
||||
|
||||
getInput()
|
||||
if goBack() {
|
||||
break
|
||||
}
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
94
gameoflife.go
Normal file
94
gameoflife.go
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"time"
|
||||
|
||||
"github.com/acifani/vita/lib/game"
|
||||
)
|
||||
|
||||
const (
|
||||
population = 20
|
||||
cellSize int16 = 6
|
||||
gameWidth uint32 = uint32(displayWidth / cellSize)
|
||||
gameHeight uint32 = uint32(displayHeight / cellSize)
|
||||
)
|
||||
|
||||
var (
|
||||
gamebuffer []byte
|
||||
|
||||
universe *game.Universe
|
||||
|
||||
cellBuf = []color.RGBA{
|
||||
colorWhite, colorWhite, colorWhite, colorWhite, colorWhite, colorWhite,
|
||||
colorWhite, colorWhite, colorBlack, colorBlack, colorWhite, colorWhite,
|
||||
colorWhite, colorBlack, colorBlack, colorBlack, colorBlack, colorWhite,
|
||||
colorWhite, colorBlack, colorBlack, colorBlack, colorBlack, colorWhite,
|
||||
colorWhite, colorWhite, colorBlack, colorBlack, colorWhite, colorWhite,
|
||||
colorWhite, colorWhite, colorWhite, colorWhite, colorWhite, colorWhite,
|
||||
}
|
||||
)
|
||||
|
||||
func GameOfLife() {
|
||||
display.FillScreen(colorWhite)
|
||||
|
||||
gamebuffer = make([]byte, gameHeight*gameWidth)
|
||||
universe = game.NewUniverse(gameHeight, gameWidth)
|
||||
universe.Randomize(population)
|
||||
universe.Read(gamebuffer)
|
||||
|
||||
x, y, z := accel.ReadRawAcceleration()
|
||||
speed := 10
|
||||
|
||||
for {
|
||||
drawGrid()
|
||||
display.Display()
|
||||
universe.Read(gamebuffer)
|
||||
|
||||
universe.Tick()
|
||||
|
||||
getInput()
|
||||
|
||||
x, y, z = accel.ReadRawAcceleration()
|
||||
if x < (-31000) || x > 31000 || y < (-31000) || y > 31000 || z < (-31000) || z > 31000 ||
|
||||
(!buttonsOldState[buttonA] && buttonsState[buttonA]) {
|
||||
universe.Reset()
|
||||
universe.Randomize(population)
|
||||
}
|
||||
|
||||
if buttonsState[buttonUp] && speed > 5 {
|
||||
speed -= 5
|
||||
}
|
||||
|
||||
if buttonsState[buttonDown] && speed < 250 {
|
||||
speed += 5
|
||||
}
|
||||
|
||||
if goBack() {
|
||||
break
|
||||
}
|
||||
|
||||
time.Sleep(time.Duration(speed) * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func drawGrid() {
|
||||
var rows, cols uint32
|
||||
|
||||
for rows = 0; rows < gameHeight; rows++ {
|
||||
for cols = 0; cols < gameWidth; cols++ {
|
||||
idx := universe.GetIndex(rows, cols)
|
||||
|
||||
switch {
|
||||
case universe.Cell(idx) == gamebuffer[idx]:
|
||||
// no change, so skip
|
||||
continue
|
||||
case universe.Cell(idx) == game.Alive:
|
||||
display.FillRectangleWithBuffer(1+cellSize*int16(cols), cellSize*int16(rows), cellSize, cellSize, cellBuf)
|
||||
default: // game.Dead
|
||||
display.FillRectangle(1+cellSize*int16(cols), cellSize*int16(rows), cellSize, cellSize, colorWhite)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
15
go.mod
Normal file
15
go.mod
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
module github.com/conejoninja/gopherbadge
|
||||
|
||||
go 1.22.1
|
||||
|
||||
require (
|
||||
github.com/acifani/vita v1.4.1
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||
golang.org/x/image v0.7.0
|
||||
tinygo.org/x/drivers v0.32.0
|
||||
tinygo.org/x/tinydraw v0.4.0
|
||||
tinygo.org/x/tinyfont v0.6.0
|
||||
tinygo.org/x/tinyterm v0.5.0
|
||||
)
|
||||
|
||||
require github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
47
go.sum
Normal file
47
go.sum
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
github.com/acifani/vita v1.4.1 h1:uzPxJQq86GtftsBqwghEOXXJO4iXPzsWlmfkHbci9LM=
|
||||
github.com/acifani/vita v1.4.1/go.mod h1:r5ldyqj9b7t2/sDrUcLOQbQ9g/I28JQ7nSUjvRtruyw=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/image v0.7.0 h1:gzS29xtG1J5ybQlv0PuyfE3nmc6R4qB73m6LUUmvFuw=
|
||||
golang.org/x/image v0.7.0/go.mod h1:nd/q4ef1AKKYl/4kft7g+6UyGbdiqWqTP1ZAbRoV7Rg=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCbuttonUpdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
tinygo.org/x/drivers v0.32.0 h1:qz7MRR1ZBIUhWC6kc4XuVNPr2+mUT8m7QJwA+Jji4IU=
|
||||
tinygo.org/x/drivers v0.32.0/go.mod h1:ZdErNrApSABdVXjA1RejD67R8SNRI6RKVfYgQDZtKtk=
|
||||
tinygo.org/x/tinydraw v0.4.0 h1:U9V0mHz8/jPShKjlh199vCfq1ARFyUOD1b+FfqIwV8c=
|
||||
tinygo.org/x/tinydraw v0.4.0/go.mod h1:WCV/EMljTv8w04iAxjv+fRD6/4ffx0afATYeJlN90Yo=
|
||||
tinygo.org/x/tinyfont v0.6.0 h1:GibXDSFz6xrWnEDkDRo6vsbOyRw0MVj/eza3zNHMSHs=
|
||||
tinygo.org/x/tinyfont v0.6.0/go.mod h1:onflMSkpWl7r7j4MIqhPEVV39pn7yL4N3MOePl3G+G8=
|
||||
tinygo.org/x/tinyterm v0.5.0 h1:HusDSiTM290KzYM4+2X+ZfNM6Ll1yu13LpvIszlQE9M=
|
||||
tinygo.org/x/tinyterm v0.5.0/go.mod h1:mTNhIZ3bNXjLmtyTreqh0tUJNdTTXyPZ7i0z8vpZgaI=
|
||||
77
info.go
Normal file
77
info.go
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
//go:build gopher_badge
|
||||
// +build gopher_badge
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"image/color"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/tinyfont"
|
||||
"tinygo.org/x/tinyfont/freesans"
|
||||
|
||||
qrcode "github.com/skip2/go-qrcode"
|
||||
)
|
||||
|
||||
const QR_modeInfo_SIZE = 180
|
||||
|
||||
func Info() {
|
||||
|
||||
qr, err := qrcode.New("https://gopherbadge.com/", qrcode.Medium)
|
||||
if err != nil {
|
||||
println(err, 123)
|
||||
}
|
||||
|
||||
qrbytes := qr.Bitmap()
|
||||
size := int16(len(qrbytes))
|
||||
|
||||
factor := int16(QR_modeInfo_SIZE / len(qrbytes))
|
||||
|
||||
bx := (QR_modeInfo_SIZE - size*factor) / 2
|
||||
by := (QR_modeInfo_SIZE - size*factor) / 2
|
||||
display.FillScreen(color.RGBA{109, 0, 140, 255})
|
||||
for y := int16(0); y < size; y++ {
|
||||
for x := int16(0); x < size; x++ {
|
||||
if qrbytes[y][x] {
|
||||
display.FillRectangle(bx+x*factor, by+y*factor, factor, factor, colorBlack)
|
||||
} else {
|
||||
display.FillRectangle(bx+x*factor, by+y*factor, factor, factor, colorWhite)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
w32, _ := tinyfont.LineWidth(&freesans.Bold18pt7b, "SCAN")
|
||||
tinyfont.WriteLine(&display, &freesans.Bold18pt7b, QR_modeInfo_SIZE+((displayWidth-QR_modeInfo_SIZE)-int16(w32))/2, 45, "SCAN", colorWhite)
|
||||
|
||||
w32, _ = tinyfont.LineWidth(&freesans.Bold18pt7b, "ME")
|
||||
tinyfont.WriteLine(&display, &freesans.Bold18pt7b, QR_modeInfo_SIZE+((displayWidth-QR_modeInfo_SIZE)-int16(w32))/2, 80, "ME", colorWhite)
|
||||
|
||||
w32, _ = tinyfont.LineWidth(&freesans.Bold9pt7b, "Press any")
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, QR_modeInfo_SIZE+((displayWidth-QR_modeInfo_SIZE)-int16(w32))/2, 120, "Press any", colorWhite)
|
||||
w32, _ = tinyfont.LineWidth(&freesans.Bold9pt7b, "button")
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, QR_modeInfo_SIZE+((displayWidth-QR_modeInfo_SIZE)-int16(w32))/2, 140, "button", colorWhite)
|
||||
w32, _ = tinyfont.LineWidth(&freesans.Bold9pt7b, "to continue")
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, QR_modeInfo_SIZE+((displayWidth-QR_modeInfo_SIZE)-int16(w32))/2, 160, "to continue", colorWhite)
|
||||
|
||||
w32, _ = tinyfont.LineWidth(&freesans.Bold9pt7b, "Visit https://gopherbadge.com/")
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, (displayWidth-int16(w32))/2, QR_modeInfo_SIZE+25, "Visit https://gopherbadge.com/", colorWhite)
|
||||
w32, _ = tinyfont.LineWidth(&freesans.Bold9pt7b, "for more information")
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, (displayWidth-int16(w32))/2, QR_modeInfo_SIZE+45, "for more information", colorWhite)
|
||||
|
||||
quit := false
|
||||
for {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
getInput()
|
||||
for b := 0; b < 9; b++ {
|
||||
if !buttonsOldState[b] && buttonsState[b] {
|
||||
quit = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if quit {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
50
info_pybadge.go
Normal file
50
info_pybadge.go
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
//go:build pybadge
|
||||
// +build pybadge
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/tinyfont"
|
||||
"tinygo.org/x/tinyfont/freesans"
|
||||
|
||||
qrcode "github.com/skip2/go-qrcode"
|
||||
)
|
||||
|
||||
func Info() {
|
||||
qr, err := qrcode.New("https://tinygo.org", qrcode.Medium)
|
||||
if err != nil {
|
||||
println(err, 123)
|
||||
}
|
||||
|
||||
qrbytes := qr.Bitmap()
|
||||
size := int16(len(qrbytes))
|
||||
|
||||
factor := int16(displayHeight / len(qrbytes))
|
||||
|
||||
bx := (displayWidth - size*factor) / 2
|
||||
by := (displayHeight - size*factor) / 2
|
||||
display.FillScreen(color.RGBA{109, 0, 140, 255})
|
||||
for y := int16(0); y < size; y++ {
|
||||
for x := int16(0); x < size; x++ {
|
||||
if qrbytes[y][x] {
|
||||
display.FillRectangle(bx+x*factor, by+y*factor, factor, factor, colorBlack)
|
||||
} else {
|
||||
display.FillRectangle(bx+x*factor, by+y*factor, factor, factor, colorWhite)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, 5, 12, "SCAN ME", colorWhite)
|
||||
|
||||
for {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
pressed, _ := buttons.Read8Input()
|
||||
if pressed&machine.BUTTON_SELECT_MASK > 0 || pressed&machine.BUTTON_START_MASK > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
35
leds.go
Normal file
35
leds.go
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Leds() {
|
||||
display.EnableBacklight(false)
|
||||
display.FillScreen(color.RGBA{0, 0, 0, 255})
|
||||
ledColors := make([]color.RGBA, numLEDs)
|
||||
var i uint8
|
||||
for {
|
||||
getInput()
|
||||
for l := uint8(0); l < numLEDs; l++ {
|
||||
ledColors[l] = getRainbowRGB(i + ((50 * l) / numLEDs))
|
||||
}
|
||||
leds.WriteColors(ledColors)
|
||||
|
||||
if goBack() {
|
||||
break
|
||||
}
|
||||
i += 2
|
||||
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
|
||||
for l := 0; l < numLEDs; l++ {
|
||||
ledColors[l] = colorBlack
|
||||
}
|
||||
leds.WriteColors(ledColors)
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
|
||||
display.EnableBacklight(true)
|
||||
}
|
||||
0
logo.bin
Normal file
0
logo.bin
Normal file
140
main.go
Normal file
140
main.go
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/lis3dh"
|
||||
"tinygo.org/x/drivers/ws2812"
|
||||
"tinygo.org/x/tinyfont"
|
||||
"tinygo.org/x/tinyfont/freemono"
|
||||
"tinygo.org/x/tinyfont/freesans"
|
||||
"tinygo.org/x/tinyfont/proggy"
|
||||
)
|
||||
|
||||
var (
|
||||
colorRed = color.RGBA{250, 0, 0, 255}
|
||||
colorMellonGreen = color.RGBA{0, 200, 0, 255}
|
||||
colorGreen = color.RGBA{0, 255, 0, 255}
|
||||
colorCyan = color.RGBA{0, 255, 255, 255}
|
||||
colorBlue = color.RGBA{0, 0, 255, 255}
|
||||
colorPurple = color.RGBA{153, 51, 255, 255}
|
||||
colorWhite = color.RGBA{255, 255, 255, 255}
|
||||
colorBlack = color.RGBA{0, 0, 0, 255}
|
||||
colorText = color.RGBA{160, 160, 160, 255}
|
||||
colorOrange = color.RGBA{255, 153, 51, 255}
|
||||
)
|
||||
|
||||
const (
|
||||
buttonUp = iota
|
||||
buttonRight
|
||||
buttonDown
|
||||
buttonLeft
|
||||
buttonA
|
||||
buttonB
|
||||
buttonC
|
||||
buttonStart
|
||||
buttonSelect
|
||||
)
|
||||
|
||||
const (
|
||||
modeBadge = iota
|
||||
modeInfo
|
||||
modeSchedule
|
||||
modeAdventure
|
||||
modeLEDs
|
||||
modeAccelerometer
|
||||
modeMusic
|
||||
modeGameSnake
|
||||
modeGameLife
|
||||
modeGameColors
|
||||
)
|
||||
|
||||
var buttonsState []bool
|
||||
var buttonsOldState []bool
|
||||
var options = []string{
|
||||
"Badge",
|
||||
"Info",
|
||||
"GopherCon Schedule",
|
||||
"GopherCon Adventure",
|
||||
"Rainbow LEDs",
|
||||
"Accelerometer",
|
||||
"Music!",
|
||||
"Snake",
|
||||
"Game of Life",
|
||||
"Color Game",
|
||||
}
|
||||
|
||||
var leds ws2812.Device
|
||||
var bzrPin machine.Pin
|
||||
var accel lis3dh.Device
|
||||
|
||||
var defaultFont tinyfont.Fonter
|
||||
|
||||
var snakeGame = NewSnakeGame()
|
||||
|
||||
func main() {
|
||||
|
||||
buttonsState = make([]bool, 9)
|
||||
buttonsOldState = make([]bool, 9)
|
||||
defaultFont = &freemono.Regular12pt7b
|
||||
if displayWidth <= 180 {
|
||||
defaultFont = &proggy.TinySZ8pt7b
|
||||
}
|
||||
|
||||
initHardware()
|
||||
display.FillScreen(colorBlack)
|
||||
setCustomData()
|
||||
|
||||
Info()
|
||||
|
||||
for {
|
||||
selected := menu()
|
||||
runMenuOption(selected)
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func writeLine(str string, c color.RGBA, x, y int16, maxWidth uint32, xCenter bool) bool {
|
||||
w32, _ := tinyfont.LineWidth(&freesans.Bold24pt7b, str)
|
||||
if w32 <= maxWidth {
|
||||
if xCenter {
|
||||
x = x - (int16(w32) / 2)
|
||||
}
|
||||
tinyfont.WriteLine(&display, &freesans.Bold24pt7b, x, y, str, c)
|
||||
return true
|
||||
}
|
||||
|
||||
w32, _ = tinyfont.LineWidth(&freesans.Bold18pt7b, str)
|
||||
if w32 <= maxWidth {
|
||||
if xCenter {
|
||||
x = x - (int16(w32) / 2)
|
||||
}
|
||||
tinyfont.WriteLine(&display, &freesans.Bold18pt7b, x, y, str, c)
|
||||
return true
|
||||
}
|
||||
|
||||
w32, _ = tinyfont.LineWidth(&freesans.Bold12pt7b, str)
|
||||
if w32 <= maxWidth {
|
||||
if xCenter {
|
||||
x = x - (int16(w32) / 2)
|
||||
}
|
||||
tinyfont.WriteLine(&display, &freesans.Bold12pt7b, x, y, str, c)
|
||||
return true
|
||||
}
|
||||
|
||||
w32, _ = tinyfont.LineWidth(&freesans.Bold9pt7b, str)
|
||||
if xCenter {
|
||||
x = x - (int16(w32) / 2)
|
||||
}
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, x, y, str, c)
|
||||
if w32 <= maxWidth {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func goBack() bool {
|
||||
return !buttonsOldState[buttonBack] && buttonsState[buttonBack]
|
||||
}
|
||||
87
menu.go
Normal file
87
menu.go
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/tinydraw"
|
||||
"tinygo.org/x/tinyfont"
|
||||
)
|
||||
|
||||
func runMenuOption(selected int16) {
|
||||
switch menuOptions[selected] {
|
||||
case modeBadge:
|
||||
Badge()
|
||||
case modeSchedule:
|
||||
schedule(0, 0)
|
||||
case modeAdventure:
|
||||
adventure()
|
||||
case modeLEDs:
|
||||
Leds()
|
||||
case modeAccelerometer:
|
||||
Accel3D()
|
||||
case modeMusic:
|
||||
Music()
|
||||
case modeGameSnake:
|
||||
snakeGame.Loop()
|
||||
case modeGameLife:
|
||||
GameOfLife()
|
||||
case modeGameColors:
|
||||
ColorGame()
|
||||
case modeInfo:
|
||||
Info()
|
||||
}
|
||||
}
|
||||
|
||||
func menu() int16 {
|
||||
display.FillScreen(color.RGBA{0, 0, 0, 255})
|
||||
bgColor := color.RGBA{109, 0, 140, 255}
|
||||
display.FillScreen(bgColor)
|
||||
|
||||
selected := int16(0)
|
||||
numOpts := int16(len(menuOptions))
|
||||
|
||||
menuX := int16(0)
|
||||
for i := int16(0); i < numOpts; i++ {
|
||||
w32, _ := tinyfont.LineWidth(defaultFont, options[menuOptions[i]])
|
||||
if int16(w32) > menuX && w32 <= displayWidth {
|
||||
menuX = int16(w32)
|
||||
}
|
||||
}
|
||||
menuX = (displayWidth - menuX) / 2
|
||||
menuY := int16((displayHeight - ((numOpts - 1) * menuItemSpace)) / 2)
|
||||
for i := int16(0); i < numOpts; i++ {
|
||||
tinydraw.Circle(&display, menuX-2*menuCircleR, menuY-menuCircleR/2+menuItemSpace*i, int16(menuCircleR), color.RGBA{0, 0, 0, 255})
|
||||
tinyfont.WriteLine(&display, defaultFont, menuX, menuY+menuItemSpace*i, options[menuOptions[i]], color.RGBA{0, 0, 0, 255})
|
||||
tinyfont.WriteLine(&display, defaultFont, menuX, menuY+1+menuItemSpace*i, options[menuOptions[i]], color.RGBA{0, 0, 0, 255})
|
||||
tinyfont.WriteLine(&display, defaultFont, menuX, menuY+2+menuItemSpace*i, options[menuOptions[i]], color.RGBA{0, 0, 0, 255})
|
||||
tinyfont.WriteLine(&display, defaultFont, menuX+1, menuY+2+menuItemSpace*i, options[menuOptions[i]], color.RGBA{0, 0, 0, 255})
|
||||
tinyfont.WriteLine(&display, defaultFont, menuX+2, menuY+2+menuItemSpace*i, options[menuOptions[i]], color.RGBA{0, 0, 0, 255})
|
||||
tinyfont.WriteLine(&display, defaultFont, menuX+2, menuY+1+menuItemSpace*i, options[menuOptions[i]], color.RGBA{0, 0, 0, 255})
|
||||
tinyfont.WriteLine(&display, defaultFont, menuX+2, menuY+menuItemSpace*i, options[menuOptions[i]], color.RGBA{0, 0, 0, 255})
|
||||
tinyfont.WriteLine(&display, defaultFont, menuX+1, menuY+menuItemSpace*i, options[menuOptions[i]], color.RGBA{0, 0, 0, 255})
|
||||
tinyfont.WriteLine(&display, defaultFont, menuX+1, menuY+1+menuItemSpace*i, options[menuOptions[i]], color.RGBA{250, 250, 0, 255})
|
||||
}
|
||||
|
||||
menuY = menuY - menuCircleR/2
|
||||
tinydraw.FilledCircle(&display, menuX-2*menuCircleR, menuY, menuCircleR-2, color.RGBA{200, 200, 0, 255})
|
||||
|
||||
for {
|
||||
getInput()
|
||||
if !buttonsOldState[buttonUp] && buttonsState[buttonUp] && selected > 0 {
|
||||
selected--
|
||||
tinydraw.FilledCircle(&display, menuX-2*menuCircleR, menuY+menuItemSpace*selected, menuCircleR-2, color.RGBA{200, 200, 0, 255})
|
||||
tinydraw.FilledCircle(&display, menuX-2*menuCircleR, menuY+menuItemSpace*(selected+1), menuCircleR-2, bgColor)
|
||||
}
|
||||
if !buttonsOldState[buttonDown] && buttonsState[buttonDown] && selected < (numOpts-1) {
|
||||
selected++
|
||||
tinydraw.FilledCircle(&display, menuX-2*menuCircleR, menuY+menuItemSpace*selected, menuCircleR-2, color.RGBA{200, 200, 0, 255})
|
||||
tinydraw.FilledCircle(&display, menuX-2*menuCircleR, menuY+menuItemSpace*(selected-1), menuCircleR-2, bgColor)
|
||||
}
|
||||
if !buttonsOldState[buttonA] && buttonsState[buttonA] {
|
||||
break
|
||||
}
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
return selected
|
||||
}
|
||||
53
music.go
Normal file
53
music.go
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func Music() {
|
||||
display.FillScreen(colorWhite)
|
||||
|
||||
writeLine("Music", colorCyan, displayWidth/2, displayHeight/3, displayHeight, true)
|
||||
writeLine("Press any key", colorRed, displayWidth/2, 2*displayHeight/3, displayHeight, true)
|
||||
|
||||
for {
|
||||
getInput()
|
||||
|
||||
if buttonsState[buttonBack] {
|
||||
break
|
||||
}
|
||||
|
||||
if buttonsState[buttonStart] {
|
||||
tone(5274)
|
||||
}
|
||||
if buttonsState[buttonA] {
|
||||
tone(1046)
|
||||
}
|
||||
if buttonsState[buttonB] {
|
||||
tone(1975)
|
||||
}
|
||||
|
||||
if buttonsState[buttonLeft] {
|
||||
tone(329)
|
||||
}
|
||||
if buttonsState[buttonRight] {
|
||||
tone(739)
|
||||
}
|
||||
if buttonsState[buttonUp] {
|
||||
tone(369)
|
||||
}
|
||||
if buttonsState[buttonDown] {
|
||||
tone(523)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func tone(tone int) {
|
||||
for i := 0; i < 10; i++ {
|
||||
bzrPin.High()
|
||||
time.Sleep(time.Duration(tone) * time.Microsecond)
|
||||
|
||||
bzrPin.Low()
|
||||
time.Sleep(time.Duration(tone) * time.Microsecond)
|
||||
}
|
||||
}
|
||||
37
rand.go
Normal file
37
rand.go
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// NOT true random number generation on RP2040 but good enough for quick demos.
|
||||
// Do not use in important production systems.
|
||||
// Seriously, don't.
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
|
||||
"crypto/rand"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rand.Reader = &reader{}
|
||||
}
|
||||
|
||||
type reader struct{}
|
||||
|
||||
func (r *reader) Read(b []byte) (n int, err error) {
|
||||
if len(b) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var randomByte uint32
|
||||
for i := range b {
|
||||
if i%4 == 0 {
|
||||
randomByte, err = machine.GetRNG()
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
} else {
|
||||
randomByte >>= 8
|
||||
}
|
||||
b[i] = byte(randomByte)
|
||||
}
|
||||
|
||||
return len(b), nil
|
||||
}
|
||||
105
schedule.go
Normal file
105
schedule.go
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/tinydraw"
|
||||
"tinygo.org/x/tinyfont"
|
||||
"tinygo.org/x/tinyfont/freesans"
|
||||
"tinygo.org/x/tinyfont/proggy"
|
||||
)
|
||||
|
||||
func schedule(day int, hour int) {
|
||||
quit := false
|
||||
for {
|
||||
scheduleShowDay(day, hour)
|
||||
for {
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
getInput()
|
||||
if !buttonsOldState[buttonDown] && buttonsState[buttonDown] {
|
||||
hour++
|
||||
if hour > len(scheduleData[day].talks)-4 {
|
||||
hour = len(scheduleData[day].talks) - 4
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !buttonsOldState[buttonUp] && buttonsState[buttonUp] {
|
||||
hour--
|
||||
if hour < 0 {
|
||||
hour = 0
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !buttonsOldState[buttonLeft] && buttonsState[buttonLeft] {
|
||||
day--
|
||||
if day < 0 {
|
||||
day = 0
|
||||
} else {
|
||||
hour = 0
|
||||
break
|
||||
}
|
||||
}
|
||||
if !buttonsOldState[buttonRight] && buttonsState[buttonRight] {
|
||||
day++
|
||||
if day > len(scheduleData)-1 {
|
||||
day = len(scheduleData) - 1
|
||||
} else {
|
||||
hour = 0
|
||||
break
|
||||
}
|
||||
}
|
||||
if goBack() {
|
||||
quit = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if quit {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func scheduleShowDay(day int, hour int) {
|
||||
display.FillScreen(colorWhite)
|
||||
|
||||
tinydraw.Line(&display, 0, 76, displayWidth, 76, colorBlack)
|
||||
tinydraw.Line(&display, 0, 126, displayWidth, 126, colorBlack)
|
||||
tinydraw.Line(&display, 0, 176, displayWidth, 176, colorBlack)
|
||||
tinydraw.Line(&display, 50, 0, 50, displayHeight, colorBlack)
|
||||
|
||||
display.FillRectangle(0, 0, displayWidth, 26, colorBlack)
|
||||
tinyfont.WriteLine(&display, &freesans.Bold9pt7b, 8, 18, scheduleData[day].title, colorWhite)
|
||||
|
||||
display.FillRectangle(0, displayHeight-14, displayWidth, 14, colorBlack)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 0, displayHeight-4, " [arrows] TO NAVIGATE [buttonB] TO EXIT", colorWhite)
|
||||
|
||||
tinyfont.WriteLine(&display, &freesans.Regular9pt7b, 2, 46, scheduleData[day].talks[hour].startHour, colorBlack)
|
||||
tinyfont.WriteLine(&display, &freesans.Regular9pt7b, 2, 69, scheduleData[day].talks[hour].endHour, colorBlack)
|
||||
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 56, 40, scheduleData[day].talks[hour].line1, colorBlack)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 56, 53, scheduleData[day].talks[hour].line2, colorBlack)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 56, 66, scheduleData[day].talks[hour].line3, colorBlack)
|
||||
|
||||
tinyfont.WriteLine(&display, &freesans.Regular9pt7b, 2, 96, scheduleData[day].talks[hour+1].startHour, colorBlack)
|
||||
tinyfont.WriteLine(&display, &freesans.Regular9pt7b, 2, 119, scheduleData[day].talks[hour+1].endHour, colorBlack)
|
||||
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 56, 90, scheduleData[day].talks[hour+1].line1, colorBlack)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 56, 103, scheduleData[day].talks[hour+1].line2, colorBlack)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 56, 116, scheduleData[day].talks[hour+1].line3, colorBlack)
|
||||
|
||||
tinyfont.WriteLine(&display, &freesans.Regular9pt7b, 2, 146, scheduleData[day].talks[hour+2].startHour, colorBlack)
|
||||
tinyfont.WriteLine(&display, &freesans.Regular9pt7b, 2, 169, scheduleData[day].talks[hour+2].endHour, colorBlack)
|
||||
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 56, 140, scheduleData[day].talks[hour+2].line1, colorBlack)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 56, 153, scheduleData[day].talks[hour+2].line2, colorBlack)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 56, 166, scheduleData[day].talks[hour+2].line3, colorBlack)
|
||||
|
||||
tinyfont.WriteLine(&display, &freesans.Regular9pt7b, 2, 196, scheduleData[day].talks[hour+3].startHour, colorBlack)
|
||||
tinyfont.WriteLine(&display, &freesans.Regular9pt7b, 2, 219, scheduleData[day].talks[hour+3].endHour, colorBlack)
|
||||
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 56, 190, scheduleData[day].talks[hour+3].line1, colorBlack)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 56, 203, scheduleData[day].talks[hour+3].line2, colorBlack)
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 56, 216, scheduleData[day].talks[hour+3].line3, colorBlack)
|
||||
}
|
||||
327
snake.go
Normal file
327
snake.go
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/tinyfont"
|
||||
"tinygo.org/x/tinyfont/freesans"
|
||||
"tinygo.org/x/tinyfont/proggy"
|
||||
)
|
||||
|
||||
const (
|
||||
GameSplash = iota
|
||||
GameStart
|
||||
GamePlay
|
||||
GameOver
|
||||
GameQuit
|
||||
)
|
||||
|
||||
const (
|
||||
SnakeUp = iota
|
||||
SnakeDown
|
||||
SnakeLeft
|
||||
SnakeRight
|
||||
)
|
||||
|
||||
const (
|
||||
displayWidthBLOCKS = 32
|
||||
displayHeightBLOCKS = 24
|
||||
)
|
||||
|
||||
var (
|
||||
// Those variable are there for a more easy reading of the apple shape.
|
||||
re = colorRed // red
|
||||
bk = colorBlack // background
|
||||
gr = colorMellonGreen // green
|
||||
|
||||
// The array is split for a visual purpose too.
|
||||
appleBuf = []color.RGBA{
|
||||
bk, bk, bk, bk, bk, gr, gr, gr, bk, bk,
|
||||
bk, bk, bk, bk, gr, gr, gr, bk, bk, bk,
|
||||
bk, bk, bk, re, gr, gr, re, bk, bk, bk,
|
||||
bk, bk, re, re, re, re, re, re, bk, bk,
|
||||
bk, re, re, re, re, re, re, re, re, bk,
|
||||
bk, re, re, re, re, re, re, re, re, bk,
|
||||
bk, re, re, re, re, re, re, re, re, bk,
|
||||
bk, bk, re, re, re, re, re, re, bk, bk,
|
||||
bk, bk, bk, re, re, re, re, bk, bk, bk,
|
||||
bk, bk, bk, bk, bk, bk, bk, bk, bk, bk,
|
||||
}
|
||||
)
|
||||
|
||||
type Snake struct {
|
||||
body [768][2]int16
|
||||
length int16
|
||||
direction int16
|
||||
}
|
||||
|
||||
type SnakeGame struct {
|
||||
snake Snake
|
||||
appleX, appleY int16
|
||||
status uint8
|
||||
score int
|
||||
frame, delay int
|
||||
}
|
||||
|
||||
var splashed = false
|
||||
var scoreStr string
|
||||
|
||||
func NewSnakeGame() *SnakeGame {
|
||||
return &SnakeGame{
|
||||
snake: Snake{
|
||||
body: [768][2]int16{
|
||||
{0, 3},
|
||||
{0, 2},
|
||||
{0, 1},
|
||||
},
|
||||
length: 3,
|
||||
direction: SnakeLeft,
|
||||
},
|
||||
appleX: 5,
|
||||
appleY: 5,
|
||||
status: GameSplash,
|
||||
delay: 120,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *SnakeGame) Splash() {
|
||||
if !splashed {
|
||||
g.splash()
|
||||
splashed = true
|
||||
}
|
||||
}
|
||||
|
||||
func (g *SnakeGame) Start() {
|
||||
display.FillScreen(bk)
|
||||
|
||||
g.initSnake()
|
||||
g.drawSnake()
|
||||
g.createApple()
|
||||
|
||||
g.status = GamePlay
|
||||
}
|
||||
|
||||
func (g *SnakeGame) Play(direction int) {
|
||||
if direction != -1 && ((g.snake.direction == SnakeUp && direction != SnakeDown) ||
|
||||
(g.snake.direction == SnakeDown && direction != SnakeUp) ||
|
||||
(g.snake.direction == SnakeLeft && direction != SnakeRight) ||
|
||||
(g.snake.direction == SnakeRight && direction != SnakeLeft)) {
|
||||
g.snake.direction = int16(direction)
|
||||
}
|
||||
|
||||
g.moveSnake()
|
||||
}
|
||||
|
||||
func (g *SnakeGame) Over() {
|
||||
display.FillScreen(bk)
|
||||
splashed = false
|
||||
|
||||
g.status = GameOver
|
||||
}
|
||||
|
||||
func (g *SnakeGame) splash() {
|
||||
display.FillScreen(bk)
|
||||
|
||||
logo := `
|
||||
___ ___ ___
|
||||
/ /\ / /\ / /\
|
||||
/ /::\ / /::| / /::\
|
||||
/__/:/\:\ / /:|:| / /:/\:\
|
||||
_\_ \:\ \:\ / /:/|:|__ / /::\ \:\
|
||||
/__/\ \:\ \:\ /__/:/ |:| /\ /__/:/\:\_\:\
|
||||
\ \:\ \:\_\/ \__\/ |:|/:/ \__\/ \:\/:/
|
||||
\ \:\_\:\ | |:/:/ \__\::/
|
||||
\ \:\/:/ |__|::/ / /:/
|
||||
\ \::/ /__/:/ /__/:/
|
||||
\__\/ \__\/ \__\/
|
||||
___ ___
|
||||
/ /\ / /\
|
||||
/ /:/ / /::\
|
||||
/ /:/ / /:/\:\
|
||||
/ /::\____ / /::\ \:\
|
||||
/__/:/\:::::\ /__/:/\:\ \:\
|
||||
\__\/~|:|~~~~ \ \:\ \:\_\/
|
||||
| |:| \ \:\ \:\
|
||||
| |:| \ \:\_\/
|
||||
|__|:| \ \:\
|
||||
\__\| \__\/
|
||||
`
|
||||
for i, line := range strings.Split(strings.TrimSuffix(logo, "\n"), "\n") {
|
||||
tinyfont.WriteLine(&display, &proggy.TinySZ8pt7b, 0, int16(-6+i*11), line+"\n", gr)
|
||||
}
|
||||
|
||||
tinyfont.WriteLine(&display, &freesans.Regular18pt7b, 30, 130, "Press A to start", colorRed)
|
||||
|
||||
if g.score > 0 {
|
||||
scoreStr = strconv.Itoa(g.score)
|
||||
tinyfont.WriteLineRotated(&display, &freesans.Regular12pt7b, 300, 200, "SCORE: "+scoreStr, colorText, tinyfont.ROTATION_270)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *SnakeGame) initSnake() {
|
||||
g.snake.body[0][0] = 0
|
||||
g.snake.body[0][1] = 3
|
||||
g.snake.body[1][0] = 0
|
||||
g.snake.body[1][1] = 2
|
||||
g.snake.body[2][0] = 0
|
||||
g.snake.body[2][1] = 1
|
||||
|
||||
g.snake.length = 3
|
||||
g.snake.direction = SnakeRight
|
||||
}
|
||||
|
||||
func (g *SnakeGame) collisionWithSnake(x, y int16) bool {
|
||||
for i := int16(0); i < g.snake.length; i++ {
|
||||
if x == g.snake.body[i][0] && y == g.snake.body[i][1] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *SnakeGame) createApple() {
|
||||
g.appleX = int16(rand.Int31n(displayWidthBLOCKS))
|
||||
g.appleY = int16(rand.Int31n(displayHeightBLOCKS))
|
||||
for g.collisionWithSnake(g.appleX, g.appleY) {
|
||||
g.appleX = int16(rand.Int31n(displayWidthBLOCKS))
|
||||
g.appleY = int16(rand.Int31n(displayHeightBLOCKS))
|
||||
}
|
||||
g.drawApple(g.appleX, g.appleY)
|
||||
}
|
||||
|
||||
func (g *SnakeGame) moveSnake() {
|
||||
x := g.snake.body[0][0]
|
||||
y := g.snake.body[0][1]
|
||||
|
||||
switch g.snake.direction {
|
||||
case SnakeLeft:
|
||||
x--
|
||||
break
|
||||
case SnakeUp:
|
||||
y--
|
||||
break
|
||||
case SnakeDown:
|
||||
y++
|
||||
break
|
||||
case SnakeRight:
|
||||
x++
|
||||
break
|
||||
}
|
||||
if x >= displayWidthBLOCKS {
|
||||
x = 0
|
||||
}
|
||||
if x < 0 {
|
||||
x = displayWidthBLOCKS - 1
|
||||
}
|
||||
if y >= displayHeightBLOCKS {
|
||||
y = 0
|
||||
}
|
||||
if y < 0 {
|
||||
y = displayHeightBLOCKS - 1
|
||||
}
|
||||
|
||||
if g.collisionWithSnake(x, y) {
|
||||
g.score = int(g.snake.length - 3)
|
||||
g.Over()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// draw head
|
||||
g.drawSnakePartial(x, y, colorMellonGreen)
|
||||
if x == g.appleX && y == g.appleY {
|
||||
g.snake.length++
|
||||
g.createApple()
|
||||
} else {
|
||||
// remove tail
|
||||
g.drawSnakePartial(g.snake.body[g.snake.length-1][0], g.snake.body[g.snake.length-1][1], colorBlack)
|
||||
}
|
||||
for i := g.snake.length - 1; i > 0; i-- {
|
||||
g.snake.body[i][0] = g.snake.body[i-1][0]
|
||||
g.snake.body[i][1] = g.snake.body[i-1][1]
|
||||
}
|
||||
g.snake.body[0][0] = x
|
||||
g.snake.body[0][1] = y
|
||||
}
|
||||
|
||||
func (g *SnakeGame) drawApple(x, y int16) {
|
||||
display.FillRectangleWithBuffer(10*x, 10*y, 10, 10, appleBuf)
|
||||
}
|
||||
|
||||
func (g *SnakeGame) drawSnake() {
|
||||
for i := int16(0); i < g.snake.length; i++ {
|
||||
g.drawSnakePartial(g.snake.body[i][0], g.snake.body[i][1], colorMellonGreen)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *SnakeGame) drawSnakePartial(x, y int16, c color.RGBA) {
|
||||
display.FillRectangle(10*x, 10*y, 9, 9, c)
|
||||
}
|
||||
|
||||
func (g *SnakeGame) Loop() {
|
||||
g.status = GameSplash
|
||||
splashed = false
|
||||
for {
|
||||
g.update()
|
||||
if g.status == GameQuit {
|
||||
break
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *SnakeGame) update() {
|
||||
getInput()
|
||||
switch g.status {
|
||||
case GameSplash:
|
||||
g.Splash()
|
||||
if !buttonsOldState[buttonA] && buttonsState[buttonA] {
|
||||
g.Start()
|
||||
}
|
||||
if goBack() {
|
||||
g.status = GameOver
|
||||
}
|
||||
break
|
||||
|
||||
case GamePlay:
|
||||
switch {
|
||||
case (goBack()):
|
||||
g.Over()
|
||||
break
|
||||
case (!buttonsOldState[buttonRight] && buttonsState[buttonRight]):
|
||||
g.Play(SnakeRight)
|
||||
break
|
||||
|
||||
case (!buttonsOldState[buttonLeft] && buttonsState[buttonLeft]):
|
||||
g.Play(SnakeLeft)
|
||||
break
|
||||
|
||||
case (!buttonsOldState[buttonDown] && buttonsState[buttonDown]):
|
||||
g.Play(SnakeDown)
|
||||
break
|
||||
|
||||
case (!buttonsOldState[buttonUp] && buttonsState[buttonUp]):
|
||||
g.Play(SnakeUp)
|
||||
break
|
||||
|
||||
default:
|
||||
g.Play(-1)
|
||||
break
|
||||
}
|
||||
break
|
||||
case GameQuit:
|
||||
case GameOver:
|
||||
g.Splash()
|
||||
|
||||
if !buttonsOldState[buttonA] && buttonsState[buttonA] {
|
||||
g.Start()
|
||||
}
|
||||
if goBack() {
|
||||
g.status = GameQuit
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue