Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,22 @@ const (
GroundY = 600
)

type Resolution struct {
Width int
Height int
Label string
}

var Resolutions = []Resolution{
{640, 480, "640 x 480"},
{800, 600, "800 x 600"},
{1024, 768, "1024 x 768"},
{1280, 960, "1280 x 960"},
{1600, 1200, "1600 x 1200"},
}

const DefaultResolutionIdx = 1

var (
BaseWidth = float32(ScreenWidth) / 10.0
BaseHeight = float32(ScreenHeight) / 10.0
Expand Down
35 changes: 30 additions & 5 deletions internal/game/game.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
"github.com/hajimehoshi/ebiten/v2/inpututil"
"github.com/hajimehoshi/ebiten/v2/vector"
"github.com/ystepanoff/paragopher/internal/audio"
"github.com/ystepanoff/paragopher/internal/config"
Expand All @@ -24,6 +25,11 @@ type Game struct {

showExitDialog bool
showGameOverDialog bool
showResolutionMenu bool

resolutionMenuIdx int
currentResolutionIdx int
fullscreen bool

barrelAngle float64
barrelImage *ebiten.Image
Expand All @@ -47,11 +53,13 @@ func NewGame() *Game {
gameData = &utils.GameData{}
}
game := &Game{
bullets: make([]*Bullet, 0),
lastShot: time.Now(),
gameData: gameData,
soundProfile: audio.NewSoundProfile(),
showIntro: true,
bullets: make([]*Bullet, 0),
lastShot: time.Now(),
gameData: gameData,
soundProfile: audio.NewSoundProfile(),
showIntro: true,
resolutionMenuIdx: config.DefaultResolutionIdx,
currentResolutionIdx: config.DefaultResolutionIdx,
}
game.initTurretImage()
game.initBarrelImage()
Expand All @@ -69,6 +77,9 @@ func NewGame() *Game {
func (g *Game) Draw(screen *ebiten.Image) {
if g.showIntro {
g.drawIntro(screen)
if g.showResolutionMenu {
g.drawResolutionMenu(screen)
}
return
}
g.drawTurret(screen)
Expand All @@ -89,9 +100,23 @@ func (g *Game) Draw(screen *ebiten.Image) {
if g.showGameOverDialog {
showYesNoDialog(screen, "GAME OVER!\nWould you like to start again?")
}

if g.showResolutionMenu {
g.drawResolutionMenu(screen)
}
}

func (g *Game) Update() error {
if g.showResolutionMenu {
g.updateResolutionMenu()
return nil
}
if inpututil.IsKeyJustPressed(ebiten.KeyR) &&
!g.showExitDialog && !g.showGameOverDialog {
g.resolutionMenuIdx = g.currentResolutionIdx
g.showResolutionMenu = true
return nil
}
if g.showIntro {
return nil
}
Expand Down
12 changes: 7 additions & 5 deletions internal/game/intro.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import (
const (
introText = "P A R A G O P H E R"

introSkipText = "ENTER: skip intro"
rotateText = "LEFT (←), RIGHT (→): rotate barrel"
shootText = "SPACE: shoot bullets"
exitText = "ESCAPE: exit the game"
introSkipText = "ENTER: skip intro"
rotateText = "LEFT (←), RIGHT (→): rotate barrel"
shootText = "SPACE: shoot bullets"
resolutionText = "R: change resolution"
exitText = "ESCAPE: exit the game"

scaleFactor = 4
)
Expand Down Expand Up @@ -67,6 +68,7 @@ func (g *Game) drawIntro(screen *ebiten.Image) {
introSkipText,
rotateText,
shootText,
resolutionText,
exitText,
}

Expand Down Expand Up @@ -99,7 +101,7 @@ func (g *Game) drawIntro(screen *ebiten.Image) {
g.lastIntroStep = time.Now()
}

if ebiten.IsKeyPressed(ebiten.KeyEnter) || g.isIntroFinished() {
if !g.showResolutionMenu && (ebiten.IsKeyPressed(ebiten.KeyEnter) || g.isIntroFinished()) {
g.soundProfile.IntroPlayer.Close()
g.showIntro = false
}
Expand Down
96 changes: 96 additions & 0 deletions internal/game/menu.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package game

import (
"fmt"

"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
"github.com/hajimehoshi/ebiten/v2/inpututil"
"github.com/hajimehoshi/ebiten/v2/vector"
"github.com/ystepanoff/paragopher/internal/config"
)

func (g *Game) updateResolutionMenu() {
if inpututil.IsKeyJustPressed(ebiten.KeyUp) {
if g.resolutionMenuIdx > 0 {
g.resolutionMenuIdx--
}
}
if inpututil.IsKeyJustPressed(ebiten.KeyDown) {
if g.resolutionMenuIdx < len(config.Resolutions)-1 {
g.resolutionMenuIdx++
}
}
if inpututil.IsKeyJustPressed(ebiten.KeyEnter) {
res := config.Resolutions[g.resolutionMenuIdx]
ebiten.SetWindowSize(res.Width, res.Height)
g.currentResolutionIdx = g.resolutionMenuIdx
if g.fullscreen {
g.fullscreen = false
ebiten.SetFullscreen(false)
ebiten.SetCursorMode(ebiten.CursorModeVisible)
}
g.showResolutionMenu = false
}
if inpututil.IsKeyJustPressed(ebiten.KeyF) {
g.fullscreen = !g.fullscreen
ebiten.SetFullscreen(g.fullscreen)
if g.fullscreen {
ebiten.SetCursorMode(ebiten.CursorModeHidden)
} else {
ebiten.SetCursorMode(ebiten.CursorModeVisible)
}
g.showResolutionMenu = false
}
if inpututil.IsKeyJustPressed(ebiten.KeyEscape) ||
inpututil.IsKeyJustPressed(ebiten.KeyR) {
g.showResolutionMenu = false
}
}

func (g *Game) drawResolutionMenu(screen *ebiten.Image) {
overlay := ebiten.NewImage(screen.Bounds().Dx(), screen.Bounds().Dy())
overlay.Fill(config.SemiTransparentBlack)
screen.DrawImage(overlay, nil)

dialogWidth := 300
dialogHeight := 50 + len(config.Resolutions)*20 + 60
dialogX := (screen.Bounds().Dx() - dialogWidth) / 2
dialogY := (screen.Bounds().Dy() - dialogHeight) / 2

dialog := ebiten.NewImage(dialogWidth, dialogHeight)
dialog.Fill(config.ColourDarkGrey)

borderSize := float32(5)
vector.DrawFilledRect(dialog, 0, 0, float32(dialogWidth), borderSize, config.ColourBlack, false)
vector.DrawFilledRect(dialog, 0, float32(dialogHeight)-borderSize, float32(dialogWidth), borderSize, config.ColourBlack, false)
vector.DrawFilledRect(dialog, 0, 0, borderSize, float32(dialogHeight), config.ColourBlack, false)
vector.DrawFilledRect(dialog, float32(dialogWidth)-borderSize, 0, borderSize, float32(dialogHeight), config.ColourBlack, false)

op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(float64(dialogX), float64(dialogY))
screen.DrawImage(dialog, op)

ebitenutil.DebugPrintAt(screen, "RESOLUTION", dialogX+105, dialogY+15)

for i, res := range config.Resolutions {
cursor := " "
if i == g.resolutionMenuIdx {
cursor = "> "
}
active := ""
if i == g.currentResolutionIdx && !g.fullscreen {
active = " *"
}
label := fmt.Sprintf("%s%s%s", cursor, res.Label, active)
ebitenutil.DebugPrintAt(screen, label, dialogX+70, dialogY+45+i*20)
}

fullscreenLabel := "F: Toggle Fullscreen"
if g.fullscreen {
fullscreenLabel = "F: Toggle Fullscreen *"
}
footerY := dialogY + 45 + len(config.Resolutions)*20 + 10
ebitenutil.DebugPrintAt(screen, fullscreenLabel, dialogX+55, footerY)
ebitenutil.DebugPrintAt(screen, "ENTER: Select ESC: Back", dialogX+40, footerY+20)
}