everything I got
This commit is contained in:
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch Package",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "auto",
|
||||
"program": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,71 @@
|
||||
package assets
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"embed"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/audio"
|
||||
"github.com/hajimehoshi/ebiten/v2/audio/wav"
|
||||
)
|
||||
|
||||
//go:embed *
|
||||
//go:embed */*
|
||||
var embeddedFiles embed.FS
|
||||
var sampleRate = 44100
|
||||
var audioContext = audio.NewContext(sampleRate)
|
||||
var songChoice = 2
|
||||
var SongTracks = loadTracksForSong(songChoice)
|
||||
|
||||
func loadTracksForSong(sng int) map[int]*audio.Player {
|
||||
tempMap := make(map[int]*audio.Player)
|
||||
for i := 1; i <= 10; i++ {
|
||||
tempMap[i] = LoadWavAudioFile(fmt.Sprintf("audio/song0%d/track%02d.wav", sng, i), true)
|
||||
}
|
||||
|
||||
return tempMap
|
||||
}
|
||||
|
||||
var SFXLibrary = map[string]*audio.Player{
|
||||
"newLevel": LoadWavAudioFile("audio/portal2.wav", false),
|
||||
"colourMatch": LoadWavAudioFile("audio/portal.wav", false),
|
||||
"gameOver": LoadWavAudioFile("audio/gameOver.wav", false),
|
||||
}
|
||||
|
||||
func LoadWavAudioFile(filePath string, loop bool) *audio.Player {
|
||||
|
||||
audioData, err := fs.ReadFile(embeddedFiles, filePath)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
stream, err := wav.DecodeWithSampleRate(sampleRate, bytes.NewReader(audioData))
|
||||
if err != nil {
|
||||
log.Fatalf("failed to decode audio: %v", err)
|
||||
}
|
||||
|
||||
var player *audio.Player
|
||||
|
||||
if loop {
|
||||
lengthOfAudioData := int64(len(audioData))
|
||||
loopingStream := audio.NewInfiniteLoop(stream, lengthOfAudioData)
|
||||
player, err = audioContext.NewPlayer(loopingStream)
|
||||
|
||||
} else {
|
||||
player, err = audioContext.NewPlayer(stream)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return player
|
||||
|
||||
}
|
||||
|
||||
func SilenceSongTracks() {
|
||||
for _, song := range SongTracks {
|
||||
song.SetVolume(0)
|
||||
}
|
||||
}
|
||||
Vendored
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Vendored
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,37 @@
|
||||
package assets
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"log"
|
||||
|
||||
"golang.org/x/image/font"
|
||||
"golang.org/x/image/font/opentype"
|
||||
)
|
||||
|
||||
//go:embed *
|
||||
var FontFiles embed.FS
|
||||
var fontFace font.Face
|
||||
|
||||
func LoadFontFace(fileName string, size float64) font.Face {
|
||||
fontBytes, err := FontFiles.ReadFile(fileName)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
tt, err := opentype.Parse(fontBytes)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
const dpi = 144
|
||||
fontFace, err = opentype.NewFace(tt, &opentype.FaceOptions{
|
||||
Size: size,
|
||||
DPI: dpi,
|
||||
Hinting: font.HintingNone,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return fontFace
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,182 @@
|
||||
package geom
|
||||
|
||||
import (
|
||||
//"fmt"
|
||||
"image/color"
|
||||
"math/rand"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
var defaultSquareSpacing = 5
|
||||
var minBorder = 20
|
||||
var ScoreOffset = 50
|
||||
var HighScoreOffset = 10
|
||||
var GameGrid Grid
|
||||
var MaxGridDimension = 20
|
||||
|
||||
type Grid struct {
|
||||
squareSpacing int
|
||||
squares [][]Square
|
||||
startX int
|
||||
startY int
|
||||
squareSize int
|
||||
coloredSquaresRemaining int
|
||||
}
|
||||
|
||||
// used for comparing two squares positions
|
||||
type Pair struct {
|
||||
rowNum int
|
||||
colNum int
|
||||
}
|
||||
|
||||
func (pr Pair) equal(pr2 Pair) bool {
|
||||
return pr.rowNum == pr2.rowNum && pr.colNum == pr2.colNum
|
||||
|
||||
}
|
||||
|
||||
func pairAlreadyExists(pr Pair, pairs []Pair) bool {
|
||||
result := false
|
||||
for _, nextPair := range pairs {
|
||||
if pr.equal(nextPair) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (grd *Grid) NumSquares() int {
|
||||
size := -1
|
||||
if len(grd.squares[0]) != 0 {
|
||||
size = len(grd.squares) * len(grd.squares[0])
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
// returns num rows by num columns
|
||||
func (grd *Grid) Size() (int, int) {
|
||||
if len(grd.squares[0]) != 0 {
|
||||
return len(grd.squares), len(grd.squares[0])
|
||||
}
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
func BuildGrid(numRows int, numColumns int) {
|
||||
grd := Grid{squareSpacing: defaultSquareSpacing}
|
||||
|
||||
winWidth, winHeight := ebiten.WindowSize()
|
||||
sqSize := min((winWidth-2*minBorder-defaultSquareSpacing*numColumns)/numColumns, (winHeight-2*minBorder-ScoreOffset-3*HighScoreOffset-defaultSquareSpacing*numRows)/numRows)
|
||||
sqSize = max(sqSize, 1) //ensure a nonzero, nonnegative square size
|
||||
gridWidth := numColumns*(sqSize+grd.squareSpacing) - grd.squareSpacing
|
||||
gridHeight := numRows*(sqSize+grd.squareSpacing) - grd.squareSpacing
|
||||
|
||||
currentX := (winWidth - gridWidth) / 2
|
||||
currentY := ScoreOffset + (winHeight-gridHeight-ScoreOffset-HighScoreOffset)/2
|
||||
grd.startX = currentX
|
||||
grd.startY = currentY
|
||||
grd.squareSize = sqSize
|
||||
|
||||
table := make([][]Square, numRows)
|
||||
|
||||
for i := 0; i < numRows; i++ {
|
||||
row := make([]Square, numColumns)
|
||||
for j := 0; j < numColumns; j++ {
|
||||
sq := MakeSquare(sqSize)
|
||||
sq.SetPosition(currentX, currentY)
|
||||
row[j] = sq
|
||||
currentX += sqSize + grd.squareSpacing
|
||||
}
|
||||
table[i] = row
|
||||
currentY += sqSize + grd.squareSpacing
|
||||
currentX = grd.startX
|
||||
}
|
||||
|
||||
grd.squares = table
|
||||
|
||||
//assign random colours to a subset of all squares
|
||||
squaresToColour := min(numColumns, numRows)
|
||||
|
||||
usedPositions := make([]Pair, squaresToColour)
|
||||
coloredSoFar := 0
|
||||
for i := 0; i < squaresToColour; i++ {
|
||||
colourIndex := rand.Intn(len(LightRGBMap))
|
||||
row := rand.Intn(numRows) + 1
|
||||
col := rand.Intn(numColumns) + 1
|
||||
//prevent a colour on the starting square
|
||||
if row == numRows && col == 1 {
|
||||
col = 2
|
||||
}
|
||||
|
||||
//make sure we don't colour the same square twice
|
||||
nextPair := Pair{rowNum: row, colNum: col}
|
||||
if coloredSoFar == 0 {
|
||||
usedPositions[0] = nextPair
|
||||
coloredSoFar = 1
|
||||
} else {
|
||||
for pairAlreadyExists(nextPair, usedPositions) {
|
||||
row = rand.Intn(numRows) + 1
|
||||
col = rand.Intn(numColumns) + 1
|
||||
//prevent a colour on the starting square
|
||||
if row == numRows && col == 1 {
|
||||
col = 2
|
||||
}
|
||||
nextPair = Pair{rowNum: row, colNum: col}
|
||||
}
|
||||
usedPositions[coloredSoFar] = nextPair
|
||||
coloredSoFar += 1
|
||||
|
||||
}
|
||||
|
||||
grd.ChangeColour(row, col, LightRGBMap[colourIndex])
|
||||
grd.GetSquareAt(row, col).RGBColourIndex = colourIndex
|
||||
}
|
||||
grd.coloredSquaresRemaining = squaresToColour
|
||||
|
||||
GameGrid = grd
|
||||
}
|
||||
|
||||
func (grd *Grid) Draw(screen *ebiten.Image) {
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
|
||||
for _, rowOfSquares := range grd.squares {
|
||||
for _, sq := range rowOfSquares {
|
||||
xPos := float64(sq.X())
|
||||
yPos := float64(sq.Y())
|
||||
opts.GeoM.Translate(xPos, yPos)
|
||||
screen.DrawImage(sq.Img, opts)
|
||||
opts.GeoM.Reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (grd *Grid) DrawUpTo(finalSquareCount int, screen *ebiten.Image) {
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
curr := 1
|
||||
for _, rowOfSquares := range grd.squares {
|
||||
for _, sq := range rowOfSquares {
|
||||
xPos := float64(sq.X())
|
||||
yPos := float64(sq.Y())
|
||||
opts.GeoM.Translate(xPos, yPos)
|
||||
screen.DrawImage(sq.Img, opts)
|
||||
opts.GeoM.Reset()
|
||||
if curr == finalSquareCount {
|
||||
return
|
||||
}
|
||||
curr++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (grd *Grid) ChangeColour(row int, column int, clr color.Color) {
|
||||
sq := grd.squares[row-1][column-1]
|
||||
sq.ChangeColour(clr)
|
||||
}
|
||||
|
||||
func (grd *Grid) GetSquareAt(row int, column int) *Square {
|
||||
return &grd.squares[row-1][column-1]
|
||||
}
|
||||
|
||||
func (grd *Grid) ColouredSquaresRemaining() int {
|
||||
return grd.coloredSquaresRemaining
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package geom
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
||||
"src.robn.tv/MrDonuts/RGB/assets"
|
||||
)
|
||||
|
||||
var MainPlayer *Player
|
||||
var totalColors = 3
|
||||
var colorMap = map[int]color.Color{
|
||||
0: RedFill,
|
||||
1: GreenFill,
|
||||
2: BlueFill,
|
||||
}
|
||||
var defaultStartingEnergy = 50
|
||||
var nextLevelEnergyJump = 30
|
||||
var CurrentEnergy = defaultStartingEnergy
|
||||
var CurrentLevel = 1
|
||||
|
||||
type Player struct {
|
||||
square Square
|
||||
row int
|
||||
col int
|
||||
currColorIndex int
|
||||
}
|
||||
|
||||
func SetupPlayer() {
|
||||
rows, _ := GameGrid.Size()
|
||||
|
||||
//build default square
|
||||
sq := MakeSquare(GameGrid.squareSize)
|
||||
|
||||
//adjust to red as starting value
|
||||
sq.ChangeColour(RedFill)
|
||||
|
||||
//position on bottom left
|
||||
gridSq := GameGrid.GetSquareAt(rows, 1)
|
||||
sq.SetPosition(gridSq.x, gridSq.y)
|
||||
|
||||
//setup struct for passing around
|
||||
ply := Player{square: sq, row: rows, col: 1, currColorIndex: 0}
|
||||
MainPlayer = &ply
|
||||
}
|
||||
|
||||
func (p *Player) Update() {
|
||||
|
||||
moveOccurs := false
|
||||
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyArrowDown) {
|
||||
rows, _ := GameGrid.Size()
|
||||
if p.row < rows {
|
||||
p.row += 1
|
||||
p.square.moveDownOnGrid()
|
||||
moveOccurs = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyArrowRight) {
|
||||
_, cols := GameGrid.Size()
|
||||
if p.col < cols {
|
||||
p.col += 1
|
||||
p.square.moveRightOnGrid()
|
||||
moveOccurs = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyArrowLeft) {
|
||||
if p.col > 1 {
|
||||
p.col -= 1
|
||||
p.square.moveLeftOnGrid()
|
||||
moveOccurs = true
|
||||
}
|
||||
}
|
||||
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyArrowUp) {
|
||||
if p.row > 1 {
|
||||
p.row -= 1
|
||||
p.square.moveUpOnGrid()
|
||||
moveOccurs = true
|
||||
}
|
||||
}
|
||||
|
||||
if moveOccurs {
|
||||
moveOccurs = false
|
||||
|
||||
p.NextColor()
|
||||
|
||||
// check if player is on same colour square
|
||||
gridSquare := GameGrid.GetSquareAt(p.row, p.col)
|
||||
if p.currColorIndex == gridSquare.RGBColourIndex {
|
||||
GameGrid.coloredSquaresRemaining -= 1
|
||||
gridSquare.RGBColourIndex = -1
|
||||
gridSquare.ChangeColour(GrayFill)
|
||||
if GameGrid.coloredSquaresRemaining != 0 {
|
||||
assets.SFXLibrary["colourMatch"].Rewind()
|
||||
assets.SFXLibrary["colourMatch"].Play()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// reduce energy
|
||||
CurrentEnergy -= 1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (p *Player) Draw(screen *ebiten.Image) {
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
opts.GeoM.Translate(float64(p.square.x), float64(p.square.y))
|
||||
screen.DrawImage(p.square.Img, opts)
|
||||
}
|
||||
|
||||
func (p *Player) NextColor() {
|
||||
p.currColorIndex = (p.currColorIndex + 1) % totalColors
|
||||
p.square.ChangeColour(colorMap[p.currColorIndex])
|
||||
}
|
||||
|
||||
func ResetPlayerValues() {
|
||||
CurrentEnergy = defaultStartingEnergy
|
||||
CurrentLevel = 1
|
||||
}
|
||||
|
||||
func PrepareForNextLevel() {
|
||||
CurrentEnergy += nextLevelEnergyJump
|
||||
CurrentLevel += 1
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package geom
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
var GrayFill = color.RGBA{R: 128, G: 128, B: 128, A: 255}
|
||||
var RedFill = color.RGBA{R: 200, G: 0, B: 0, A: 255}
|
||||
var GreenFill = color.RGBA{R: 0, G: 200, B: 0, A: 255}
|
||||
var BlueFill = color.RGBA{R: 0, G: 0, B: 200, A: 255}
|
||||
var LightRedFill = color.RGBA{R: 255, G: 104, B: 103, A: 255}
|
||||
var LightGreenFill = color.RGBA{R: 144, G: 255, B: 143, A: 255}
|
||||
var LightBlueFill = color.RGBA{R: 150, G: 150, B: 255, A: 255}
|
||||
|
||||
var RGBColourMap = map[int]color.Color{
|
||||
0: RedFill,
|
||||
1: GreenFill,
|
||||
2: BlueFill,
|
||||
}
|
||||
|
||||
var AllColourMap = map[int]color.Color{
|
||||
0: GrayFill,
|
||||
1: RedFill,
|
||||
2: GreenFill,
|
||||
3: BlueFill,
|
||||
4: LightRedFill,
|
||||
5: LightBlueFill,
|
||||
6: LightGreenFill,
|
||||
}
|
||||
|
||||
var LightRGBMap = map[int]color.Color{
|
||||
0: LightRedFill,
|
||||
1: LightGreenFill,
|
||||
2: LightBlueFill,
|
||||
}
|
||||
|
||||
type Square struct {
|
||||
x int
|
||||
y int
|
||||
clr color.Color
|
||||
width int
|
||||
height int
|
||||
Img *ebiten.Image
|
||||
RGBColourIndex int
|
||||
}
|
||||
|
||||
func MakeSquare(size int) Square {
|
||||
image := ebiten.NewImage(size, size)
|
||||
defaultColor := color.RGBA{R: 128, G: 128, B: 128, A: 255}
|
||||
image.Fill(defaultColor)
|
||||
sq := Square{clr: defaultColor, Img: image, width: size, height: size, x: 0, y: 0, RGBColourIndex: -1}
|
||||
return sq
|
||||
}
|
||||
|
||||
func (sq *Square) ChangeColour(newColor color.Color) {
|
||||
sq.clr = newColor
|
||||
sq.Img.Fill(newColor)
|
||||
}
|
||||
|
||||
func (sq *Square) SetPosition(x int, y int) {
|
||||
sq.x = x
|
||||
sq.y = y
|
||||
}
|
||||
|
||||
func (sq *Square) X() int {
|
||||
return sq.x
|
||||
}
|
||||
|
||||
func (sq *Square) Y() int {
|
||||
return sq.y
|
||||
}
|
||||
|
||||
func (sq *Square) moveRightOnGrid() {
|
||||
newX := sq.x + GameGrid.squareSize + GameGrid.squareSpacing
|
||||
sq.x = newX
|
||||
}
|
||||
|
||||
func (sq *Square) moveLeftOnGrid() {
|
||||
newX := sq.x - GameGrid.squareSize - GameGrid.squareSpacing
|
||||
sq.x = newX
|
||||
}
|
||||
|
||||
func (sq *Square) moveDownOnGrid() {
|
||||
newY := sq.y + GameGrid.squareSize + GameGrid.squareSpacing
|
||||
sq.y = newY
|
||||
}
|
||||
|
||||
func (sq *Square) moveUpOnGrid() {
|
||||
newY := sq.y - GameGrid.squareSize - GameGrid.squareSpacing
|
||||
sq.y = newY
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
module src.robn.tv/MrDonuts/RGB
|
||||
|
||||
go 1.21.3
|
||||
|
||||
require github.com/hajimehoshi/ebiten/v2 v2.6.2
|
||||
|
||||
require (
|
||||
github.com/ebitengine/oto/v3 v3.1.0 // indirect
|
||||
github.com/ebitengine/purego v0.5.0 // indirect
|
||||
github.com/jezek/xgb v1.1.0 // indirect
|
||||
golang.org/x/exp/shiny v0.0.0-20230817173708-d852ddb80c63 // indirect
|
||||
golang.org/x/image v0.14.0
|
||||
golang.org/x/mobile v0.0.0-20230922142353-e2f452493d57 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/sys v0.12.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
)
|
||||
@@ -0,0 +1,22 @@
|
||||
github.com/ebitengine/oto/v3 v3.1.0 h1:9tChG6rizyeR2w3vsygTTTVVJ9QMMyu00m2yBOCch6U=
|
||||
github.com/ebitengine/oto/v3 v3.1.0/go.mod h1:IK1QTnlfZK2GIB6ziyECm433hAdTaPpOsGMLhEyEGTg=
|
||||
github.com/ebitengine/purego v0.5.0 h1:JrMGKfRIAM4/QVKaesIIT7m/UVjTj5GYhRSQYwfVdpo=
|
||||
github.com/ebitengine/purego v0.5.0/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
|
||||
github.com/hajimehoshi/bitmapfont/v3 v3.0.0 h1:r2+6gYK38nfztS/et50gHAswb9hXgxXECYgE8Nczmi4=
|
||||
github.com/hajimehoshi/bitmapfont/v3 v3.0.0/go.mod h1:+CxxG+uMmgU4mI2poq944i3uZ6UYFfAkj9V6WqmuvZA=
|
||||
github.com/hajimehoshi/ebiten/v2 v2.6.2 h1:tVa3ZJbp4Uz/VSjmpgtQIOvwd7aQH290XehHBLr2iWk=
|
||||
github.com/hajimehoshi/ebiten/v2 v2.6.2/go.mod h1:TZtorL713an00UW4LyvMeKD8uXWnuIuCPtlH11b0pgI=
|
||||
github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk=
|
||||
github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
|
||||
golang.org/x/exp/shiny v0.0.0-20230817173708-d852ddb80c63 h1:3AGKexOYqL+ztdWdkB1bDwXgPBuTS/S8A4WzuTvJ8Cg=
|
||||
golang.org/x/exp/shiny v0.0.0-20230817173708-d852ddb80c63/go.mod h1:UH99kUObWAZkDnWqppdQe5ZhPYESUw8I0zVV1uWBR+0=
|
||||
golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=
|
||||
golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
||||
golang.org/x/mobile v0.0.0-20230922142353-e2f452493d57 h1:Q6NT8ckDYNcwmi/bmxe+XbiDMXqMRW1xFBtJ+bIpie4=
|
||||
golang.org/x/mobile v0.0.0-20230922142353-e2f452493d57/go.mod h1:wEyOn6VvNW7tcf+bW/wBz1sehi2s2BZ4TimyR7qZen4=
|
||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
@@ -0,0 +1,60 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
|
||||
"src.robn.tv/MrDonuts/RGB/assets"
|
||||
geom "src.robn.tv/MrDonuts/RGB/geometry"
|
||||
"src.robn.tv/MrDonuts/RGB/states"
|
||||
score "src.robn.tv/MrDonuts/RGB/tools"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
numRows := 3
|
||||
numColumns := 6
|
||||
geom.BuildGrid(numRows, numColumns)
|
||||
|
||||
states.SetupStateMachine()
|
||||
|
||||
//some audio testing
|
||||
for i, song := range assets.SongTracks {
|
||||
song.Play()
|
||||
if i != 1 {
|
||||
song.SetVolume(0)
|
||||
} else {
|
||||
song.SetVolume(0.7)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type Game struct{}
|
||||
|
||||
func (g *Game) Update() error {
|
||||
|
||||
states.SM.Update()
|
||||
score.ScoreMngr.Update()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Game) Draw(screen *ebiten.Image) {
|
||||
|
||||
states.SM.Draw(screen)
|
||||
|
||||
}
|
||||
|
||||
func (g *Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
|
||||
return 640, 480
|
||||
}
|
||||
|
||||
func main() {
|
||||
ebiten.SetWindowSize(640, 480)
|
||||
ebiten.SetWindowTitle("RGB")
|
||||
if err := ebiten.RunGame(&Game{}); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package states
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"math/rand"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
||||
"github.com/hajimehoshi/ebiten/v2/text"
|
||||
"golang.org/x/image/font"
|
||||
"src.robn.tv/MrDonuts/RGB/assets"
|
||||
geom "src.robn.tv/MrDonuts/RGB/geometry"
|
||||
)
|
||||
|
||||
type GameOverState struct {
|
||||
}
|
||||
|
||||
func (st *GameOverState) Enter() {
|
||||
fmt.Println("Entering Game Over State")
|
||||
assets.SilenceSongTracks()
|
||||
assets.SFXLibrary["gameOver"].Rewind()
|
||||
assets.SFXLibrary["gameOver"].Play()
|
||||
|
||||
}
|
||||
|
||||
func (st *GameOverState) Exit() {
|
||||
fmt.Println("Exiting Game OverState")
|
||||
|
||||
}
|
||||
|
||||
func (st *GameOverState) Update() {
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyN) {
|
||||
geom.ResetPlayerValues()
|
||||
geom.BuildGrid(rand.Intn(5+geom.CurrentLevel)+2, rand.Intn(5+geom.CurrentLevel)+2)
|
||||
CurrTrack = 1
|
||||
assets.SongTracks[CurrTrack].SetVolume(0.7) //turn up track 1
|
||||
SM.Transition("load")
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (st *GameOverState) Draw(screen *ebiten.Image) {
|
||||
w, h := ebiten.WindowSize()
|
||||
|
||||
gameOverStr := "Game Over"
|
||||
face := assets.LoadFontFace("fonts/robot.otf", 30)
|
||||
stringWidth := font.MeasureString(face, gameOverStr).Ceil()
|
||||
text.Draw(screen, gameOverStr, face, w/2-stringWidth/2, h/2, color.White)
|
||||
|
||||
newGameStr := "(press N for new game)"
|
||||
face = assets.LoadFontFace("fonts/robot.otf", 12)
|
||||
stringWidth = font.MeasureString(face, newGameStr).Ceil()
|
||||
text.Draw(screen, newGameStr, face, w/2-stringWidth/2, h-int(0.1*float64(h)), color.White)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package states
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
geom "src.robn.tv/MrDonuts/RGB/geometry"
|
||||
score "src.robn.tv/MrDonuts/RGB/tools"
|
||||
)
|
||||
|
||||
var currentEnd = 1 //used for animating squares
|
||||
var secondsPerUpdate = 0.02
|
||||
var ticksPerSecond = 60.0
|
||||
var deltaSeconds = 1.0 / ticksPerSecond
|
||||
var secondsCounter = 0.0
|
||||
|
||||
type LoadLevelState struct {
|
||||
}
|
||||
|
||||
func (s *LoadLevelState) Enter() {
|
||||
fmt.Println("Entering Loading State")
|
||||
currentEnd = 1
|
||||
}
|
||||
|
||||
func (s *LoadLevelState) Exit() {
|
||||
fmt.Println("Exiting Loading State")
|
||||
}
|
||||
|
||||
func (s *LoadLevelState) Update() {
|
||||
secondsCounter += deltaSeconds
|
||||
|
||||
//determine how much to jump by on each draw
|
||||
totalSquares := geom.GameGrid.NumSquares()
|
||||
jumpAmount := math.Ceil(float64(totalSquares) / ticksPerSecond)
|
||||
if secondsCounter >= float64(secondsPerUpdate) {
|
||||
secondsCounter = 0
|
||||
currentEnd += int(jumpAmount)
|
||||
}
|
||||
|
||||
if currentEnd > geom.GameGrid.NumSquares() {
|
||||
SM.Transition("play")
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *LoadLevelState) Draw(screen *ebiten.Image) {
|
||||
|
||||
geom.GameGrid.DrawUpTo(currentEnd, screen)
|
||||
score.ScoreMngr.Draw(screen)
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package states
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
||||
"src.robn.tv/MrDonuts/RGB/assets"
|
||||
geom "src.robn.tv/MrDonuts/RGB/geometry"
|
||||
score "src.robn.tv/MrDonuts/RGB/tools"
|
||||
)
|
||||
|
||||
var CurrTrack = 1
|
||||
|
||||
type PlayLevelState struct {
|
||||
}
|
||||
|
||||
func (s *PlayLevelState) Enter() {
|
||||
fmt.Println("Entering Play State")
|
||||
geom.SetupPlayer()
|
||||
fmt.Println(geom.GameGrid.ColouredSquaresRemaining())
|
||||
|
||||
}
|
||||
|
||||
func (s *PlayLevelState) Exit() {
|
||||
fmt.Println("Exiting Play State")
|
||||
|
||||
geom.PrepareForNextLevel()
|
||||
|
||||
if CurrTrack < len(assets.SongTracks) {
|
||||
if geom.CurrentLevel%3 == 0 {
|
||||
CurrTrack++
|
||||
assets.SongTracks[CurrTrack].SetVolume(0.7)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *PlayLevelState) Update() {
|
||||
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyN) {
|
||||
newRowSize := min(rand.Intn(5+geom.CurrentLevel)+2, geom.MaxGridDimension)
|
||||
newColSize := min(rand.Intn(5+geom.CurrentLevel)+2, geom.MaxGridDimension)
|
||||
geom.BuildGrid(newRowSize, newColSize)
|
||||
SM.Transition("load")
|
||||
assets.SFXLibrary["newLevel"].Rewind()
|
||||
assets.SFXLibrary["newLevel"].Play()
|
||||
}
|
||||
|
||||
geom.MainPlayer.Update()
|
||||
if geom.CurrentEnergy == 0 {
|
||||
SM.Transition("game over")
|
||||
}
|
||||
if geom.GameGrid.ColouredSquaresRemaining() == 0 {
|
||||
//go to next level
|
||||
newRowSize := min(rand.Intn(5+geom.CurrentLevel)+2, geom.MaxGridDimension)
|
||||
newColSize := min(rand.Intn(5+geom.CurrentLevel)+2, geom.MaxGridDimension)
|
||||
geom.BuildGrid(newRowSize, newColSize)
|
||||
SM.Transition("load")
|
||||
assets.SFXLibrary["newLevel"].Rewind()
|
||||
assets.SFXLibrary["newLevel"].Play()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *PlayLevelState) Draw(screen *ebiten.Image) {
|
||||
geom.GameGrid.Draw(screen)
|
||||
geom.MainPlayer.Draw(screen)
|
||||
score.ScoreMngr.Draw(screen)
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package states
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
var SM StateMachine
|
||||
var StateMap map[string]State
|
||||
|
||||
type State interface {
|
||||
Enter()
|
||||
Exit()
|
||||
Update()
|
||||
Draw(screen *ebiten.Image)
|
||||
}
|
||||
|
||||
type StateMachine struct {
|
||||
CurrentState State
|
||||
}
|
||||
|
||||
func NewStateMachine(initialState State) *StateMachine {
|
||||
sm := &StateMachine{CurrentState: initialState}
|
||||
sm.CurrentState.Enter()
|
||||
return sm
|
||||
}
|
||||
|
||||
func (sm *StateMachine) Transition(newState string) {
|
||||
sm.CurrentState.Exit()
|
||||
sm.CurrentState = StateMap[newState]
|
||||
sm.CurrentState.Enter()
|
||||
}
|
||||
|
||||
func (sm *StateMachine) Update() {
|
||||
sm.CurrentState.Update()
|
||||
}
|
||||
|
||||
func (sm *StateMachine) Draw(screen *ebiten.Image) {
|
||||
sm.CurrentState.Draw(screen)
|
||||
}
|
||||
|
||||
func SetupStateMachine() {
|
||||
|
||||
loadState := &LoadLevelState{}
|
||||
playState := &PlayLevelState{}
|
||||
gameOverState := &GameOverState{}
|
||||
|
||||
StateMap = make(map[string]State)
|
||||
StateMap["load"] = loadState
|
||||
StateMap["play"] = playState
|
||||
StateMap["game over"] = gameOverState
|
||||
|
||||
SM = *NewStateMachine(loadState)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package score
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/text"
|
||||
"golang.org/x/image/font"
|
||||
|
||||
//"golang.org/x/image/font/gofont/gobold"
|
||||
"src.robn.tv/MrDonuts/RGB/assets"
|
||||
geom "src.robn.tv/MrDonuts/RGB/geometry"
|
||||
)
|
||||
|
||||
var ScoreMngr ScoreManager
|
||||
|
||||
type ScoreManager struct{}
|
||||
|
||||
func (sm *ScoreManager) Update() {
|
||||
}
|
||||
|
||||
func (sm *ScoreManager) Draw(screen *ebiten.Image) {
|
||||
|
||||
w, h := ebiten.WindowSize()
|
||||
|
||||
//highScoreStr := fmt.Sprintf("High Score: %v", highScore)
|
||||
levelStr := fmt.Sprintf("Level: %v", geom.CurrentLevel)
|
||||
face := assets.LoadFontFace("fonts/robot.otf", 12)
|
||||
|
||||
//draw high score (i.e. best level)
|
||||
//stringWidth := font.MeasureString(face, highScoreStr).Ceil()
|
||||
//text.Draw(screen, highScoreStr, face, w-stringWidth-geom.HighScoreOffset, h-geom.HighScoreOffset, color.White)
|
||||
|
||||
//draw current level
|
||||
//stringWidth = font.MeasureString(face, levelStr).Ceil()
|
||||
text.Draw(screen, levelStr, face, geom.HighScoreOffset, h-geom.HighScoreOffset, color.White)
|
||||
|
||||
//draw energy at the top
|
||||
energyStr := fmt.Sprintf("Energy: %v", geom.CurrentEnergy)
|
||||
face = assets.LoadFontFace("fonts/robot.otf", 20)
|
||||
stringWidth := font.MeasureString(face, energyStr).Ceil()
|
||||
text.Draw(screen, energyStr, face, w/2-stringWidth/2, geom.ScoreOffset, color.White)
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user