Initial commit.
This commit is contained in:
15
.vscode/launch.json
vendored
Normal file
15
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "ducky",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "auto",
|
||||||
|
"program": "main.go"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
assets/duck_idle.png
Normal file
BIN
assets/duck_idle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
45
assets/imagebank.go
Normal file
45
assets/imagebank.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package assets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
_ "embed"
|
||||||
|
"image"
|
||||||
|
_ "image/png"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ImgAssetName string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Ducky ImgAssetName = "Ducky"
|
||||||
|
ReDucky ImgAssetName = "ReDucky"
|
||||||
|
Orb ImgAssetName = "Orb"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ImageBank map[ImgAssetName]*ebiten.Image
|
||||||
|
|
||||||
|
//go:embed duck_idle.png
|
||||||
|
duckidle_img []byte
|
||||||
|
//go:embed reducky_idle.png
|
||||||
|
reduckidle_img []byte
|
||||||
|
//go:embed orb.png
|
||||||
|
orb_img []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadImages() {
|
||||||
|
ImageBank = make(map[ImgAssetName]*ebiten.Image)
|
||||||
|
ImageBank[Ducky] = LoadImagesFatal(duckidle_img)
|
||||||
|
ImageBank[ReDucky] = LoadImagesFatal(reduckidle_img)
|
||||||
|
ImageBank[Orb] = LoadImagesFatal(orb_img)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadImagesFatal(b []byte) *ebiten.Image {
|
||||||
|
img, _, err := image.Decode(bytes.NewReader(b))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
return ebiten.NewImageFromImage(img)
|
||||||
|
}
|
||||||
BIN
assets/mainloop.ogg
Normal file
BIN
assets/mainloop.ogg
Normal file
Binary file not shown.
BIN
assets/orb.png
Normal file
BIN
assets/orb.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/reducky_idle.png
Normal file
BIN
assets/reducky_idle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
74
assets/soundbank.go
Normal file
74
assets/soundbank.go
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
package assets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
_ "embed"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/audio/mp3"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/audio/vorbis"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/audio/wav"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SndAssetName string
|
||||||
|
|
||||||
|
const (
|
||||||
|
MainLoop SndAssetName = "MainLoop"
|
||||||
|
MainLoopMp3 SndAssetName = "MainLoopMp3"
|
||||||
|
MainLoopOgg SndAssetName = "MainLoopOgg"
|
||||||
|
SampleRate = 44100
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
//SoundBank map[SndAssetName]*wav.Stream
|
||||||
|
//SoundBankMp3 map[SndAssetName]*mp3.Stream
|
||||||
|
SoundBankOgg map[SndAssetName]*vorbis.Stream
|
||||||
|
//go:embed mainloop.ogg
|
||||||
|
mainloop_snd []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
LoadSounds()
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadSounds() {
|
||||||
|
//SoundBank = make(map[SndAssetName]*wav.Stream)
|
||||||
|
//SoundBankMp3 = make(map[SndAssetName]*mp3.Stream)
|
||||||
|
SoundBankOgg = make(map[SndAssetName]*vorbis.Stream)
|
||||||
|
|
||||||
|
//SoundBank[MainLoop] = LoadSoundFatal(SampleRate, hyper_snd)
|
||||||
|
//SoundBankMp3[MainLoopMp3] = LoadSoundFatalMp3(SampleRate, mainloop_snd)
|
||||||
|
SoundBankOgg[MainLoopOgg] = LoadSoundFatalOgg(SampleRate, mainloop_snd)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadSoundFatal(rate int, obj []byte) *wav.Stream {
|
||||||
|
|
||||||
|
stream, err := wav.DecodeWithSampleRate(rate, bytes.NewReader(obj))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("dead, jim")
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadSoundFatalMp3(rate int, obj []byte) *mp3.Stream {
|
||||||
|
|
||||||
|
stream, err := mp3.DecodeWithSampleRate(rate, bytes.NewReader(obj))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("dead, jim")
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadSoundFatalOgg(rate int, obj []byte) *vorbis.Stream {
|
||||||
|
|
||||||
|
stream, err := vorbis.DecodeWithSampleRate(rate, bytes.NewReader(obj))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("dead, jim")
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream
|
||||||
|
}
|
||||||
54
elements/duck.go
Normal file
54
elements/duck.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package elements
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ducky/gamedata"
|
||||||
|
"image"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
"golang.org/x/exp/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DuckyWidth = 36
|
||||||
|
DuckyHeight = DuckyWidth
|
||||||
|
)
|
||||||
|
|
||||||
|
type Ducky struct {
|
||||||
|
Sprite *ebiten.Image
|
||||||
|
asset *ebiten.Image
|
||||||
|
cycle int
|
||||||
|
position gamedata.Coordinates
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDucky(asset *ebiten.Image) *Ducky {
|
||||||
|
d := &Ducky{
|
||||||
|
Sprite: ebiten.NewImage(DuckyWidth, DuckyHeight),
|
||||||
|
asset: asset,
|
||||||
|
cycle: rand.Intn(11),
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Ducky) Update() {
|
||||||
|
d.cycle++
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Ducky) Draw() {
|
||||||
|
d.Sprite.Clear()
|
||||||
|
|
||||||
|
idx := d.cycle / 4 % 10
|
||||||
|
x0 := idx * DuckyWidth
|
||||||
|
y0 := 0
|
||||||
|
x1 := x0 + DuckyWidth
|
||||||
|
y1 := DuckyHeight
|
||||||
|
|
||||||
|
d.Sprite.DrawImage(d.asset.SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Ducky) SetPosition(pos gamedata.Coordinates) {
|
||||||
|
d.position = pos
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Ducky) GetPosition() gamedata.Coordinates {
|
||||||
|
return d.position
|
||||||
|
}
|
||||||
87
elements/slider.go
Normal file
87
elements/slider.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package elements
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ducky/gamedata"
|
||||||
|
"image/color"
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
"golang.org/x/exp/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sliderWidth = 640 / 5
|
||||||
|
sliderHeight = 480
|
||||||
|
easeValue = 16
|
||||||
|
)
|
||||||
|
|
||||||
|
type Slider struct {
|
||||||
|
Sprite *ebiten.Image
|
||||||
|
position gamedata.Coordinates
|
||||||
|
targetposition gamedata.Coordinates
|
||||||
|
cycle int
|
||||||
|
callback func()
|
||||||
|
called bool
|
||||||
|
color color.Color
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSlider() *Slider {
|
||||||
|
slider := &Slider{
|
||||||
|
Sprite: ebiten.NewImage(sliderWidth, sliderHeight),
|
||||||
|
called: false,
|
||||||
|
color: color.RGBA{
|
||||||
|
R: uint8(rand.Intn(256)) & 0xff,
|
||||||
|
G: uint8(rand.Intn(256)) & 0xff,
|
||||||
|
B: uint8(rand.Intn(256)) & 0xff,
|
||||||
|
A: 0xff,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return slider
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Slider) Update() {
|
||||||
|
|
||||||
|
dx := s.targetposition.X - s.position.X
|
||||||
|
dy := s.targetposition.Y - s.position.Y
|
||||||
|
|
||||||
|
deltapos := math.Sqrt(dx*dx + dy*dy)
|
||||||
|
|
||||||
|
if deltapos > 0.5 {
|
||||||
|
s.position.X = s.position.X + dx/easeValue
|
||||||
|
s.position.Y = s.position.Y + dy/easeValue
|
||||||
|
} else {
|
||||||
|
if s.callback != nil && !s.called {
|
||||||
|
s.callback()
|
||||||
|
s.called = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.cycle++
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Slider) Draw() {
|
||||||
|
s.Sprite.Clear()
|
||||||
|
s.Sprite.Fill(s.color)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Slider) GetPosition() gamedata.Coordinates {
|
||||||
|
return s.position
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Slider) SetPosition(pos gamedata.Coordinates) {
|
||||||
|
s.position = pos
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Slider) SetTargetPosition(pos gamedata.Coordinates) {
|
||||||
|
s.targetposition = pos
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Slider) SetCallback(f func()) {
|
||||||
|
if f != nil {
|
||||||
|
s.callback = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Slider) Reset() {
|
||||||
|
s.called = false
|
||||||
|
}
|
||||||
33
elements/spotlight.go
Normal file
33
elements/spotlight.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package elements
|
||||||
|
|
||||||
|
import "github.com/hajimehoshi/ebiten/v2"
|
||||||
|
|
||||||
|
type Spotlight struct {
|
||||||
|
Sprite *ebiten.Image
|
||||||
|
asset *ebiten.Image
|
||||||
|
cycle int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSpotlight(asset *ebiten.Image) *Spotlight {
|
||||||
|
sl := &Spotlight{
|
||||||
|
Sprite: ebiten.NewImage(100, 100),
|
||||||
|
asset: asset,
|
||||||
|
}
|
||||||
|
|
||||||
|
return sl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Spotlight) Update() {
|
||||||
|
s.cycle++
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Spotlight) Draw() {
|
||||||
|
s.Sprite.Clear()
|
||||||
|
|
||||||
|
op := &ebiten.DrawImageOptions{}
|
||||||
|
op.GeoM.Translate(-16, -16)
|
||||||
|
op.GeoM.Scale(3, 3)
|
||||||
|
op.GeoM.Translate(50, 50)
|
||||||
|
s.Sprite.DrawImage(s.asset, op)
|
||||||
|
|
||||||
|
}
|
||||||
BIN
fonts/bitbybit.ttf
Normal file
BIN
fonts/bitbybit.ttf
Normal file
Binary file not shown.
41
fonts/fonts.go
Normal file
41
fonts/fonts.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package fonts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
_ "embed"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/text/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FontStruct struct {
|
||||||
|
Ducky *text.GoTextFaceSource
|
||||||
|
Karen *text.GoTextFaceSource
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
//go:embed bitbybit.ttf
|
||||||
|
bitbybit_ttf []byte
|
||||||
|
//go:embed karenfat.ttf
|
||||||
|
karen_ttf []byte
|
||||||
|
|
||||||
|
DuckyFont FontStruct
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
DuckyFont = FontStruct{}
|
||||||
|
|
||||||
|
s, err := text.NewGoTextFaceSource(bytes.NewReader(bitbybit_ttf))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
DuckyFont.Ducky = s
|
||||||
|
|
||||||
|
s, err = text.NewGoTextFaceSource(bytes.NewReader(karen_ttf))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
DuckyFont.Karen = s
|
||||||
|
|
||||||
|
}
|
||||||
BIN
fonts/karenfat.ttf
Normal file
BIN
fonts/karenfat.ttf
Normal file
Binary file not shown.
267
game/game.go
Normal file
267
game/game.go
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
package game
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ducky/assets"
|
||||||
|
"ducky/elements"
|
||||||
|
"ducky/fonts"
|
||||||
|
"ducky/gamedata"
|
||||||
|
"fmt"
|
||||||
|
"image/color"
|
||||||
|
"math"
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/audio"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/text/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
screenWidth = 640
|
||||||
|
screenHeight = 480
|
||||||
|
|
||||||
|
duckyWidth = 32
|
||||||
|
duckyHeight = duckyWidth
|
||||||
|
|
||||||
|
spotResetDuration = 120
|
||||||
|
duckySpottedTextOffsetX = 120
|
||||||
|
duckySpottedTextOffsetY = 32
|
||||||
|
duckySpottedTextSize = 30
|
||||||
|
toastCount = 120
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
audioContext = audio.NewContext(assets.SampleRate)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Game struct {
|
||||||
|
initialized bool
|
||||||
|
reducky *elements.Ducky
|
||||||
|
ducky *elements.Ducky
|
||||||
|
spotlight *elements.Spotlight
|
||||||
|
cycle int
|
||||||
|
mousepos gamedata.Coordinates
|
||||||
|
|
||||||
|
darkness *ebiten.Image
|
||||||
|
offscreen *ebiten.Image
|
||||||
|
|
||||||
|
reduckycol int
|
||||||
|
reduckyrow int
|
||||||
|
|
||||||
|
spottedticks int
|
||||||
|
spotted bool
|
||||||
|
toast bool
|
||||||
|
toastcounter int
|
||||||
|
disabledarkness bool
|
||||||
|
|
||||||
|
sliders []*elements.Slider
|
||||||
|
|
||||||
|
reachcount int
|
||||||
|
|
||||||
|
musicInitialized bool
|
||||||
|
audioplayer *audio.Player
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) Update() error {
|
||||||
|
|
||||||
|
g.HandleInput()
|
||||||
|
|
||||||
|
if !g.initialized {
|
||||||
|
g.Initialize()
|
||||||
|
}
|
||||||
|
|
||||||
|
g.UpdateDuck()
|
||||||
|
g.UpdateDetection()
|
||||||
|
//g.UpdateSliders()
|
||||||
|
|
||||||
|
g.cycle++
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) Draw(screen *ebiten.Image) {
|
||||||
|
screen.Clear()
|
||||||
|
g.darkness.Clear()
|
||||||
|
|
||||||
|
if g.initialized {
|
||||||
|
|
||||||
|
//g.darkness.Fill(color.RGBA{R: 0xff, G: 0x00, B: 0x00, A: 0xff})
|
||||||
|
g.darkness.Fill(color.Black)
|
||||||
|
g.ducky.Draw()
|
||||||
|
g.reducky.Draw()
|
||||||
|
|
||||||
|
op := &ebiten.DrawImageOptions{}
|
||||||
|
for x := 0; x < screenWidth/duckyWidth; x++ {
|
||||||
|
for y := 0; y < screenHeight/duckyWidth; y++ {
|
||||||
|
op.GeoM.Reset()
|
||||||
|
op.GeoM.Translate(float64(x)*duckyWidth, float64(y)*duckyHeight)
|
||||||
|
if !(x == g.reduckycol && y == g.reduckyrow) {
|
||||||
|
screen.DrawImage(g.ducky.Sprite, op)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
op = &ebiten.DrawImageOptions{}
|
||||||
|
op.GeoM.Translate(float64(g.reduckycol)*duckyWidth, float64(g.reduckyrow)*duckyHeight)
|
||||||
|
screen.DrawImage(g.reducky.Sprite, op)
|
||||||
|
|
||||||
|
op = &ebiten.DrawImageOptions{}
|
||||||
|
op.GeoM.Translate(-duckyWidth/2, -duckyHeight/2)
|
||||||
|
op.GeoM.Translate(g.mousepos.X, g.mousepos.Y)
|
||||||
|
//screen.DrawImage(assets.ImageBank[assets.Orb], op)
|
||||||
|
|
||||||
|
g.spotlight.Draw()
|
||||||
|
|
||||||
|
g.offscreen.Clear()
|
||||||
|
op = &ebiten.DrawImageOptions{}
|
||||||
|
|
||||||
|
spotlight_w := float64(g.spotlight.Sprite.Bounds().Dx())
|
||||||
|
spotlight_h := float64(g.spotlight.Sprite.Bounds().Dy())
|
||||||
|
|
||||||
|
op.GeoM.Translate(-spotlight_w/2, -spotlight_h/2)
|
||||||
|
op.GeoM.Translate(g.mousepos.X, g.mousepos.Y)
|
||||||
|
//g.offscreen.DrawImage(assets.ImageBank[assets.Orb], op)
|
||||||
|
g.offscreen.DrawImage(g.spotlight.Sprite, op)
|
||||||
|
|
||||||
|
op.GeoM.Reset()
|
||||||
|
op.Blend = ebiten.BlendXor
|
||||||
|
g.offscreen.DrawImage(g.darkness, op)
|
||||||
|
|
||||||
|
if !g.disabledarkness {
|
||||||
|
op = &ebiten.DrawImageOptions{}
|
||||||
|
if g.toast {
|
||||||
|
op.GeoM.Translate(-screenWidth/2, -screenHeight/2)
|
||||||
|
op.GeoM.Rotate(float64(g.toastcounter) / (math.Pi * 2))
|
||||||
|
op.GeoM.Translate(screenWidth/2, screenHeight/2)
|
||||||
|
}
|
||||||
|
screen.DrawImage(g.offscreen, op)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.spotted && !g.toast {
|
||||||
|
font := &text.GoTextFace{
|
||||||
|
Source: fonts.DuckyFont.Karen,
|
||||||
|
Size: duckySpottedTextSize,
|
||||||
|
}
|
||||||
|
top := &text.DrawOptions{}
|
||||||
|
top.GeoM.Translate(screenWidth/2-duckySpottedTextOffsetX, screenHeight/2-duckySpottedTextOffsetY)
|
||||||
|
if g.cycle%30 < 15 {
|
||||||
|
text.Draw(screen, "DUCKY SPOTTED", font, top)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range g.sliders {
|
||||||
|
s.Draw()
|
||||||
|
op = &ebiten.DrawImageOptions{}
|
||||||
|
op.GeoM.Translate(s.GetPosition().X, s.GetPosition().Y)
|
||||||
|
screen.DrawImage(s.Sprite, op)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) Layout(outsideWidth, outsideHeight int) (screenwidth, screenheight int) {
|
||||||
|
return screenWidth, screenHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) Initialize() {
|
||||||
|
assets.LoadImages()
|
||||||
|
|
||||||
|
g.offscreen = ebiten.NewImage(screenWidth, screenHeight)
|
||||||
|
g.darkness = ebiten.NewImage(screenWidth, screenHeight)
|
||||||
|
|
||||||
|
g.spotlight = elements.NewSpotlight(assets.ImageBank[assets.Orb])
|
||||||
|
g.ducky = elements.NewDucky(assets.ImageBank[assets.Ducky])
|
||||||
|
g.reducky = elements.NewDucky(assets.ImageBank[assets.ReDucky])
|
||||||
|
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
slider := elements.NewSlider()
|
||||||
|
g.sliders = append(g.sliders, slider)
|
||||||
|
}
|
||||||
|
|
||||||
|
g.initialized = true
|
||||||
|
|
||||||
|
if !g.musicInitialized {
|
||||||
|
//s := audio.NewInfiniteLoop(assets.SoundBank[assets.MainLoop], assets.SoundBank[assets.MainLoop].Length())
|
||||||
|
s := audio.NewInfiniteLoop(assets.SoundBankOgg[assets.MainLoopOgg], assets.SoundBankOgg[assets.MainLoopOgg].Length())
|
||||||
|
g.audioplayer, _ = audioContext.NewPlayer(s)
|
||||||
|
g.audioplayer.Play()
|
||||||
|
g.musicInitialized = true
|
||||||
|
}
|
||||||
|
|
||||||
|
g.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) UpdateDuck() {
|
||||||
|
g.ducky.Update()
|
||||||
|
g.reducky.Update()
|
||||||
|
|
||||||
|
x, y := ebiten.CursorPosition()
|
||||||
|
g.mousepos.X = float64(x)
|
||||||
|
g.mousepos.Y = float64(y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) Reset() {
|
||||||
|
g.reduckycol = rand.Intn(screenWidth / duckyHeight)
|
||||||
|
g.reduckyrow = rand.Intn(screenHeight / duckyWidth)
|
||||||
|
|
||||||
|
for i, slider := range g.sliders {
|
||||||
|
var yoffset float64
|
||||||
|
|
||||||
|
if i%2 == 0 {
|
||||||
|
yoffset = screenHeight
|
||||||
|
} else {
|
||||||
|
yoffset = -screenHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
slider.SetPosition(gamedata.Coordinates{X: float64(i) * screenWidth / 5, Y: yoffset})
|
||||||
|
slider.SetTargetPosition(gamedata.Coordinates{X: float64(i) * screenWidth / 5, Y: 0})
|
||||||
|
slider.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
//fmt.Printf("Ducky Position: %d, %d\n", g.reduckycol, g.reduckyrow)
|
||||||
|
g.spottedticks = 0
|
||||||
|
g.toast = false
|
||||||
|
g.reachcount = 0
|
||||||
|
g.toastcounter = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) HandleInput() {
|
||||||
|
if inpututil.IsKeyJustPressed(ebiten.KeyR) {
|
||||||
|
g.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
g.disabledarkness = ebiten.IsKeyPressed(ebiten.KeySpace)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) UpdateDetection() {
|
||||||
|
x, y := ebiten.CursorPosition()
|
||||||
|
|
||||||
|
if g.reduckycol*duckyWidth <= x && x <= (g.reduckycol+1)*duckyWidth &&
|
||||||
|
g.reduckyrow*duckyHeight <= y && y <= (g.reduckyrow+1)*duckyHeight && !g.toast {
|
||||||
|
g.spottedticks++
|
||||||
|
g.spotted = true
|
||||||
|
fmt.Println("ducky spotted!")
|
||||||
|
} else {
|
||||||
|
g.spotted = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.spottedticks > spotResetDuration {
|
||||||
|
g.toast = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.toast {
|
||||||
|
g.UpdateSliders()
|
||||||
|
g.toastcounter++
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.toastcounter > toastCount {
|
||||||
|
g.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) UpdateSliders() {
|
||||||
|
for _, s := range g.sliders {
|
||||||
|
s.Update()
|
||||||
|
}
|
||||||
|
}
|
||||||
6
gamedata/gamedata.go
Normal file
6
gamedata/gamedata.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package gamedata
|
||||||
|
|
||||||
|
type Coordinates struct {
|
||||||
|
X float64
|
||||||
|
Y float64
|
||||||
|
}
|
||||||
26
go.mod
Normal file
26
go.mod
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
module ducky
|
||||||
|
|
||||||
|
go 1.22.0
|
||||||
|
|
||||||
|
toolchain go1.22.10
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/hajimehoshi/ebiten/v2 v2.8.5
|
||||||
|
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/ebitengine/gomobile v0.0.0-20240911145611-4856209ac325 // indirect
|
||||||
|
github.com/ebitengine/hideconsole v1.0.0 // indirect
|
||||||
|
github.com/ebitengine/oto/v3 v3.3.1 // indirect
|
||||||
|
github.com/ebitengine/purego v0.8.0 // indirect
|
||||||
|
github.com/go-text/typesetting v0.2.0 // indirect
|
||||||
|
github.com/hajimehoshi/go-mp3 v0.3.4 // indirect
|
||||||
|
github.com/jezek/xgb v1.1.1 // indirect
|
||||||
|
github.com/jfreymuth/oggvorbis v1.0.5 // indirect
|
||||||
|
github.com/jfreymuth/vorbis v1.0.2 // indirect
|
||||||
|
golang.org/x/image v0.20.0 // indirect
|
||||||
|
golang.org/x/sync v0.10.0 // indirect
|
||||||
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
|
golang.org/x/text v0.18.0 // indirect
|
||||||
|
)
|
||||||
23
main.go
Normal file
23
main.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ducky/game"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ver := 0.04
|
||||||
|
verstring := fmt.Sprintf("ducky v%.2f", ver)
|
||||||
|
|
||||||
|
game := &game.Game{}
|
||||||
|
|
||||||
|
ebiten.SetWindowSize(640*1.5, 480*1.5)
|
||||||
|
ebiten.SetWindowTitle(verstring)
|
||||||
|
|
||||||
|
if err := ebiten.RunGame(game); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user