|
|
@ -14,10 +14,12 @@ import ( |
|
|
|
"time" |
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
|
|
"github.com/hajimehoshi/ebiten/v2" |
|
|
|
"github.com/hajimehoshi/ebiten/v2" |
|
|
|
|
|
|
|
"github.com/hajimehoshi/ebiten/v2/audio" |
|
|
|
"github.com/hajimehoshi/ebiten/v2/inpututil" |
|
|
|
"github.com/hajimehoshi/ebiten/v2/inpututil" |
|
|
|
"github.com/hajimehoshi/ebiten/v2/text" |
|
|
|
"github.com/hajimehoshi/ebiten/v2/text" |
|
|
|
"golang.org/x/image/font" |
|
|
|
"golang.org/x/image/font" |
|
|
|
"golang.org/x/image/font/opentype" |
|
|
|
"golang.org/x/image/font/opentype" |
|
|
|
|
|
|
|
"golang.org/x/image/font/sfnt" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
const Version string = "v0.1" |
|
|
|
const Version string = "v0.1" |
|
|
@ -33,36 +35,40 @@ const ( |
|
|
|
SaveFileName string = "capyclickSave.json" |
|
|
|
SaveFileName string = "capyclickSave.json" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
var WorkingDir string = "." |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type Game struct { |
|
|
|
type Game struct { |
|
|
|
|
|
|
|
WorkingDir string |
|
|
|
Config conf.Configuration |
|
|
|
Config conf.Configuration |
|
|
|
Save save.Save |
|
|
|
Save save.Save |
|
|
|
|
|
|
|
AudioContext *audio.Context |
|
|
|
|
|
|
|
ImageResources map[string]*ebiten.Image |
|
|
|
|
|
|
|
Font *sfnt.Font |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Resource images
|
|
|
|
func NewGame() *Game { |
|
|
|
var ( |
|
|
|
return &Game{ |
|
|
|
ImgCapybara1 = ebiten.NewImageFromImage(ImageFromFile("capybara_1.png")) |
|
|
|
WorkingDir: ".", |
|
|
|
ImgCapybara2 = ebiten.NewImageFromImage(ImageFromFile("capybara_2.png")) |
|
|
|
Config: conf.Default(), |
|
|
|
ImgCapybara3 = ebiten.NewImageFromImage(ImageFromFile("capybara_3.png")) |
|
|
|
Save: save.Default(), |
|
|
|
|
|
|
|
AudioContext: audio.NewContext(48000), |
|
|
|
GameFont = util.NewFont(ResourceGetFont("PixeloidSans-Bold.otf"), &opentype.FaceOptions{ |
|
|
|
ImageResources: map[string]*ebiten.Image{ |
|
|
|
Size: 10, |
|
|
|
"capybara1": ebiten.NewImageFromImage(ImageFromFile("capybara_1.png")), |
|
|
|
DPI: 72, |
|
|
|
"capybara2": ebiten.NewImageFromImage(ImageFromFile("capybara_2.png")), |
|
|
|
Hinting: font.HintingVertical, |
|
|
|
"capybara3": ebiten.NewImageFromImage(ImageFromFile("capybara_3.png")), |
|
|
|
}) |
|
|
|
}, |
|
|
|
) |
|
|
|
Font: ResourceGetFont("PixeloidSans-Bold.otf"), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Saves configuration information and game data
|
|
|
|
// Saves configuration information and game data
|
|
|
|
func SaveData(game *Game) error { |
|
|
|
func SaveData(game *Game) error { |
|
|
|
// Save configuration information and game data
|
|
|
|
// Save configuration information and game data
|
|
|
|
err := save.Create(filepath.Join(WorkingDir, SaveFileName), game.Save) |
|
|
|
err := save.Create(filepath.Join(game.WorkingDir, SaveFileName), game.Save) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
logger.Error("[SaveData] Failed to save game data before closing: %s!", err) |
|
|
|
logger.Error("[SaveData] Failed to save game data before closing: %s!", err) |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
err = conf.Create(filepath.Join(WorkingDir, ConfigurationFileName), game.Config) |
|
|
|
err = conf.Create(filepath.Join(game.WorkingDir, ConfigurationFileName), game.Config) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
logger.Error("[SaveData] Failed to save game configuration before closing: %s!", err) |
|
|
|
logger.Error("[SaveData] Failed to save game configuration before closing: %s!", err) |
|
|
|
return err |
|
|
|
return err |
|
|
@ -112,19 +118,29 @@ func (g *Game) Draw(screen *ebiten.Image) { |
|
|
|
screen.Fill(color.Black) |
|
|
|
screen.Fill(color.Black) |
|
|
|
|
|
|
|
|
|
|
|
// Capybara
|
|
|
|
// Capybara
|
|
|
|
|
|
|
|
scale := 15.0 |
|
|
|
op := &ebiten.DrawImageOptions{} |
|
|
|
op := &ebiten.DrawImageOptions{} |
|
|
|
op.GeoM.Scale(15, 15) |
|
|
|
op.GeoM.Scale(scale, scale) |
|
|
|
op.GeoM.Translate(float64(screen.Bounds().Dx()/3), float64(screen.Bounds().Dy()/3)) |
|
|
|
width := g.ImageResources["capybara1"].Bounds().Dx() * int(scale) |
|
|
|
screen.DrawImage(ImgCapybara1, op) |
|
|
|
height := g.ImageResources["capybara1"].Bounds().Dy() * int(scale) |
|
|
|
|
|
|
|
op.GeoM.Translate( |
|
|
|
|
|
|
|
float64(screen.Bounds().Dx()/2)-float64(width/2), |
|
|
|
|
|
|
|
float64(screen.Bounds().Dy()/2)-float64(height/2), |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
screen.DrawImage(g.ImageResources["capybara1"], op) |
|
|
|
|
|
|
|
|
|
|
|
// Points
|
|
|
|
// Points
|
|
|
|
msg := fmt.Sprintf("Points: %d", g.Save.Points) |
|
|
|
msg := fmt.Sprintf("Points: %d", g.Save.Points) |
|
|
|
text.Draw( |
|
|
|
text.Draw( |
|
|
|
screen, |
|
|
|
screen, |
|
|
|
msg, |
|
|
|
msg, |
|
|
|
GameFont, |
|
|
|
util.NewFont(g.Font, &opentype.FaceOptions{ |
|
|
|
|
|
|
|
Size: 24, |
|
|
|
|
|
|
|
DPI: 72, |
|
|
|
|
|
|
|
Hinting: font.HintingVertical, |
|
|
|
|
|
|
|
}), |
|
|
|
10, |
|
|
|
10, |
|
|
|
20, |
|
|
|
30, |
|
|
|
color.White, |
|
|
|
color.White, |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
@ -133,9 +149,13 @@ func (g *Game) Draw(screen *ebiten.Image) { |
|
|
|
text.Draw( |
|
|
|
text.Draw( |
|
|
|
screen, |
|
|
|
screen, |
|
|
|
msg, |
|
|
|
msg, |
|
|
|
GameFont, |
|
|
|
util.NewFont(g.Font, &opentype.FaceOptions{ |
|
|
|
screen.Bounds().Dx()-len(msg)*10, |
|
|
|
Size: 24, |
|
|
|
20, |
|
|
|
DPI: 72, |
|
|
|
|
|
|
|
Hinting: font.HintingVertical, |
|
|
|
|
|
|
|
}), |
|
|
|
|
|
|
|
screen.Bounds().Dx()-len(msg)*24, |
|
|
|
|
|
|
|
30, |
|
|
|
color.White, |
|
|
|
color.White, |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
@ -144,9 +164,13 @@ func (g *Game) Draw(screen *ebiten.Image) { |
|
|
|
text.Draw( |
|
|
|
text.Draw( |
|
|
|
screen, |
|
|
|
screen, |
|
|
|
msg, |
|
|
|
msg, |
|
|
|
GameFont, |
|
|
|
util.NewFont(g.Font, &opentype.FaceOptions{ |
|
|
|
|
|
|
|
Size: 24, |
|
|
|
|
|
|
|
DPI: 72, |
|
|
|
|
|
|
|
Hinting: font.HintingVertical, |
|
|
|
|
|
|
|
}), |
|
|
|
10, |
|
|
|
10, |
|
|
|
screen.Bounds().Dy()-10, |
|
|
|
screen.Bounds().Dy()-30, |
|
|
|
color.White, |
|
|
|
color.White, |
|
|
|
) |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
@ -174,10 +198,7 @@ func main() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Create a game instance
|
|
|
|
// Create a game instance
|
|
|
|
var game *Game = &Game{ |
|
|
|
var game *Game = NewGame() |
|
|
|
Config: conf.Default(), |
|
|
|
|
|
|
|
Save: save.Default(), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !*noFiles { |
|
|
|
if !*noFiles { |
|
|
|
// Work out working directory
|
|
|
|
// Work out working directory
|
|
|
@ -186,17 +207,17 @@ func main() { |
|
|
|
logger.Error("[Init] Failed to get executable's path: %s", err) |
|
|
|
logger.Error("[Init] Failed to get executable's path: %s", err) |
|
|
|
os.Exit(1) |
|
|
|
os.Exit(1) |
|
|
|
} |
|
|
|
} |
|
|
|
WorkingDir = filepath.Dir(exeDir) |
|
|
|
game.WorkingDir = filepath.Dir(exeDir) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
WorkingDir = "" |
|
|
|
game.WorkingDir = "" |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if !*noFiles { |
|
|
|
if !*noFiles { |
|
|
|
// Open/Create configuration file
|
|
|
|
// Open/Create configuration file
|
|
|
|
var config *conf.Configuration |
|
|
|
var config *conf.Configuration |
|
|
|
config, err := conf.FromFile(filepath.Join(WorkingDir, ConfigurationFileName)) |
|
|
|
config, err := conf.FromFile(filepath.Join(game.WorkingDir, ConfigurationFileName)) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
err = conf.Create(filepath.Join(WorkingDir, ConfigurationFileName), game.Config) |
|
|
|
err = conf.Create(filepath.Join(game.WorkingDir, ConfigurationFileName), game.Config) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
logger.Error("[Init] Failed to create a new configuration file: %s", err) |
|
|
|
logger.Error("[Init] Failed to create a new configuration file: %s", err) |
|
|
|
os.Exit(1) |
|
|
|
os.Exit(1) |
|
|
@ -226,9 +247,9 @@ func main() { |
|
|
|
|
|
|
|
|
|
|
|
if !*noFiles { |
|
|
|
if !*noFiles { |
|
|
|
// Open/Create save file
|
|
|
|
// Open/Create save file
|
|
|
|
gameSave, err := save.FromFile(filepath.Join(WorkingDir, SaveFileName)) |
|
|
|
gameSave, err := save.FromFile(filepath.Join(game.WorkingDir, SaveFileName)) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
err = save.Create(filepath.Join(WorkingDir, SaveFileName), game.Save) |
|
|
|
err = save.Create(filepath.Join(game.WorkingDir, SaveFileName), game.Save) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
logger.Error("[Init] Failed to create a new save file \"%s\": %s", SaveFileName, err) |
|
|
|
logger.Error("[Init] Failed to create a new save file \"%s\": %s", SaveFileName, err) |
|
|
|
os.Exit(1) |
|
|
|
os.Exit(1) |
|
|
|