Browse Source

Reposition interface

master
Trevor Slocum 1 month ago
parent
commit
4e849022ac
  1. BIN
      assets/ojas-dungeon/dungeon-tileset-1.png
  2. 2
      creep.go
  3. 151
      game.go
  4. 6
      go.mod
  5. 12
      go.sum
  6. 13
      level.go
  7. 2
      player.go

BIN
assets/ojas-dungeon/dungeon-tileset-1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 32 KiB

2
creep.go

@ -140,7 +140,7 @@ func (c *gameCreep) moveSpeed() float64 {
if c.creepType == TypeSoul {
return 0.5 / 4
}
return 0.1 + (float64(c.level.num) * 0.1)
return 0.29 + (float64(c.level.num) * 0.01)
}
func (c *gameCreep) seekPlayer() {

151
game.go

@ -34,15 +34,14 @@ const (
playerDieVolume = 1.6
munchVolume = 0.8
spawnVampire = 777
spawnGarlic = 6
spawnGarlic = 6
garlicActiveTime = 7 * time.Second
holyWaterActiveTime = time.Second
maxCreeps = 3333 // TODO optimize and raise
batSoundDelay = 250 * time.Millisecond
screenPadding = 33
)
var startButtons = []ebiten.StandardGamepadButton{
@ -270,7 +269,13 @@ func (g *game) generateLevel() error {
g.level.items = append(g.level.items, item)
// Spawn creeps.
for i := 0; i < spawnVampire; i++ {
spawnAmount := 66
if g.levelNum == 2 {
spawnAmount = 666
} else if g.levelNum == 3 {
spawnAmount = 1111
}
for i := 0; i < spawnAmount; i++ {
g.level.addCreep(TypeVampire)
}
return nil
@ -349,8 +354,6 @@ func (g *game) handlePlayerDeath() {
return
}
g.player.holyWaters = 0
g.gameOverTime = time.Now()
// Play die sound.
@ -468,29 +471,23 @@ func (g *game) Update() error {
}
g.checkLevelComplete()
} else if !g.godMode && !c.repelled() {
if g.player.holyWaters > 0 {
// TODO g.playSound(SoundItemUseHolyWater, useholyWaterVolume)
g.player.holyWaterUntil = time.Now().Add(holyWaterActiveTime)
g.player.holyWaters--
} else {
err := g.hurtCreep(c, -1)
if err != nil {
// TODO
panic(err)
}
err := g.hurtCreep(c, -1)
if err != nil {
// TODO
panic(err)
}
g.player.health--
g.player.health--
if g.player.health == 2 {
g.playSound(SoundPlayerHurt, playerHurtVolume/2)
} else if g.player.health == 1 {
g.playSound(SoundPlayerHurt, playerHurtVolume)
}
if g.player.health == 2 {
g.playSound(SoundPlayerHurt, playerHurtVolume/2)
} else if g.player.health == 1 {
g.playSound(SoundPlayerHurt, playerHurtVolume)
}
g.addBloodSplatter(g.player.x, g.player.y)
g.addBloodSplatter(g.player.x, g.player.y)
g.handlePlayerDeath()
}
g.handlePlayerDeath()
}
} else if c.creepType == TypeBat && (dx <= 12 && dy <= 7) && rand.Intn(166) == 6 && time.Since(g.lastBatSound) >= batSoundDelay {
g.playSound(SoundBat, batDieVolume)
@ -581,8 +578,8 @@ func (g *game) Update() error {
g.playSound(SoundMunch, munchVolume)
g.player.garlicUntil = time.Now().Add(garlicActiveTime)
} else if item.itemType == itemTypeHolyWater {
// TODO g.playSound(SoundItemPickup, munchVolume)
g.player.holyWaters++
// TODO g.playSound(SoundItemPickup, pickupVolume)
g.player.health++
}
}
}
@ -720,11 +717,23 @@ UPDATEPROJECTILES:
}
}
maxCreeps := 666
if g.levelNum == 2 {
maxCreeps = 1999
} else if g.levelNum == 3 {
maxCreeps = 3333
}
if len(g.level.creeps) < maxCreeps {
// Spawn vampires.
if g.tick%144 == 0 {
spawnAmount := rand.Intn(26 + (g.tick / (144 * 3)))
if len(g.level.creeps) < 500 {
minCreeps := 0
if g.levelNum == 2 {
minCreeps = 500
} else if g.levelNum == 3 {
minCreeps = 1000
}
if len(g.level.creeps) < minCreeps {
spawnAmount *= 4
}
if g.debugMode && spawnAmount > 0 {
@ -851,8 +860,8 @@ UPDATEPROJECTILES:
}
g.flashMessage(fmt.Sprintf("SPAWNED %d GHOSTS", spawnAmount))
case inpututil.IsKeyJustPressed(ebiten.Key7):
g.player.holyWaters++
g.flashMessage("SPAWNED HOLY WATER")
g.player.health++
g.flashMessage("INCREASED HEALTH")
case inpututil.IsKeyJustPressed(ebiten.Key8):
// TODO Add garlic to inventory
//g.flashMessage("+ GARLIC")
@ -872,7 +881,18 @@ UPDATEPROJECTILES:
return nil
}
func (g *game) drawText(target *ebiten.Image, offsetX float64, y float64, scale float64, alpha float64, text string) {
func (g *game) drawText(target *ebiten.Image, x float64, y float64, scale float64, alpha float64, text string) {
g.overlayImg.Clear()
ebitenutil.DebugPrint(g.overlayImg, text)
g.op.GeoM.Reset()
g.op.GeoM.Scale(scale, scale)
g.op.GeoM.Translate(x, y)
g.op.ColorM.Scale(1, 1, 1, alpha)
target.DrawImage(g.overlayImg, g.op)
g.op.ColorM.Reset()
}
func (g *game) drawCenteredText(target *ebiten.Image, offsetX float64, y float64, scale float64, alpha float64, text string) {
g.overlayImg.Clear()
ebitenutil.DebugPrint(g.overlayImg, text)
g.op.GeoM.Reset()
@ -891,14 +911,14 @@ func (g *game) Draw(screen *ebiten.Image) {
if g.gameStartTime.IsZero() {
screen.Fill(colorBlood)
g.drawText(screen, 0, float64(g.h/2)-350, 16, 1.0, "CAROTID")
g.drawText(screen, 0, float64(g.h/2)-100, 16, 1.0, "ARTILLERY")
g.drawCenteredText(screen, 0, float64(g.h/2)-350, 16, 1.0, "CAROTID")
g.drawCenteredText(screen, 0, float64(g.h/2)-100, 16, 1.0, "ARTILLERY")
g.drawText(screen, 0, float64(g.h-210), 4, 1.0, "WASD + MOUSE = OK")
g.drawText(screen, 0, float64(g.h-145), 4, 1.0, "FULLSCREEN + GAMEPAD = BEST")
g.drawCenteredText(screen, 0, float64(g.h-210), 4, 1.0, "WASD + MOUSE = OK")
g.drawCenteredText(screen, 0, float64(g.h-145), 4, 1.0, "FULLSCREEN + GAMEPAD = BEST")
if time.Now().UnixMilli()%2000 < 1500 {
g.drawText(screen, 0, float64(g.h-80), 4, 1.0, "PRESS ANY KEY OR BUTTON TO START")
g.drawCenteredText(screen, 0, float64(g.h-80), 4, 1.0, "PRESS ANY KEY OR BUTTON TO START")
}
return
@ -942,47 +962,46 @@ func (g *game) Draw(screen *ebiten.Image) {
screen.DrawImage(img, g.op)
g.op.ColorM.Reset()
g.drawText(screen, 0, float64(g.h/2)-150, 16, a, "GAME OVER")
g.drawCenteredText(screen, 0, float64(g.h/2)-150, 16, a, "GAME OVER")
if time.Since(g.gameOverTime).Milliseconds()%2000 < 1500 {
g.drawText(screen, 0, 8, 4, a, "PRESS ENTER OR START TO PLAY AGAIN")
g.drawCenteredText(screen, 0, 8, 4, a, "PRESS ENTER OR START TO PLAY AGAIN")
}
}
if g.gameOverTime.IsZero() {
// Draw health.
heartSpace := 32
heartX := (g.w / 2) - ((heartSpace * g.player.health) / 2)
healthScale := 1.3
heartSpace := int(32 * healthScale)
heartY := float64(g.h - screenPadding - heartSpace)
for i := 0; i < g.player.health; i++ {
g.op.GeoM.Reset()
g.op.GeoM.Translate(float64(heartX+(i*heartSpace)), 32)
g.op.GeoM.Scale(healthScale, healthScale)
g.op.GeoM.Translate(screenPadding+(float64((i)*heartSpace)), heartY)
screen.DrawImage(imageAtlas[ImageHeart], g.op)
}
// Draw holy waters.
holyWaterSpace := 16
holyWaterX := (g.w / 2) - ((holyWaterSpace * g.player.holyWaters) / 2) - 8
for i := 0; i < g.player.holyWaters; i++ {
g.op.GeoM.Reset()
g.op.GeoM.Translate(float64(holyWaterX+(i*holyWaterSpace)), 76)
screen.DrawImage(imageAtlas[ImageHolyWater], g.op)
}
scale := 3.0
soulsY := 104.0
scale := 4.0
soulsY := float64(g.h-int(scale*14)) - screenPadding
if g.level.exitOpenTime.IsZero() {
// Draw souls.
soulsLabel := fmt.Sprintf("%d", g.level.requiredSouls-g.player.soulsRescued)
soulImgSize := 50.0
soulsX := float64(g.w-screenPadding) - (float64((len(soulsLabel)) * 4 * 6)) - soulImgSize
soulImgScale := 1.5
g.op.GeoM.Reset()
g.op.GeoM.Translate(float64(g.w/2)-(float64(len(soulsLabel))*3*scale)-40, soulsY+8)
g.op.GeoM.Translate((soulsX+soulImgSize)/soulImgScale, (soulsY+9)/soulImgScale)
g.op.GeoM.Scale(soulImgScale, soulImgScale)
screen.DrawImage(ojasDungeonSS.Soul1, g.op)
g.drawText(screen, 0, soulsY, scale, 1.0, soulsLabel)
g.drawText(screen, soulsX, soulsY, scale, 1.0, soulsLabel)
} else {
// Draw exit message.
if time.Since(g.level.exitOpenTime).Milliseconds()%2000 < 1500 {
g.drawText(screen, 0, soulsY, scale, 1.0, "EXIT OPEN")
g.drawCenteredText(screen, 0, soulsY, scale, 1.0, "EXIT OPEN")
}
}
}
@ -993,16 +1012,17 @@ func (g *game) Draw(screen *ebiten.Image) {
if alpha > 1 {
alpha = 1
}
g.drawText(screen, 0, float64(g.h-40), 2, alpha, g.flashMessageText)
g.drawCenteredText(screen, 0, float64(g.h-screenPadding-32), 2, alpha, g.flashMessageText)
}
if !g.gameWon {
if !g.gameOverTime.IsZero() && !g.gameWon {
a := g.minLevelColorScale
if a == -1 {
a = 1
}
scale := 5
scoreLabel := numberPrinter.Sprintf("%d", g.player.score)
g.drawText(screen, 0, float64(g.h-150), 8, a, scoreLabel)
g.drawCenteredText(screen, 0, float64(g.h-(scale*14))-screenPadding, float64(scale), a, scoreLabel)
}
if !g.debugMode {
@ -1183,7 +1203,7 @@ func (g *game) renderLevel(screen *ebiten.Image) int {
a := 1.0
if c.creepType == TypeSoul {
a = 0.35
a = 0.3
}
drawn += g.renderSprite(c.x, c.y, 0, 0, c.angle, 1.0, g.levelColorScale(c.x, c.y), a, c.sprites[c.frame], screen)
@ -1571,15 +1591,12 @@ func (g *game) showWinScreen() {
}
}
if i > int(144*12) {
if i > 144*12 {
p.angle -= 0.0025 * (float64(i-(144*12)) / (144 * 3))
addStar()
addStar()
addStar()
addStar()
addStar()
addStar()
for j := 0; j < 6; j++ {
addStar()
}
}
p.x += 0.05

6
go.mod

@ -13,8 +13,8 @@ require (
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211024062804-40e447a793be // indirect
github.com/hajimehoshi/oto/v2 v2.1.0-alpha.3 // indirect
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 // indirect
golang.org/x/exp v0.0.0-20211029153326-98a2daa683e3 // indirect
golang.org/x/mobile v0.0.0-20211029123140-7b8bfe09930c // indirect
golang.org/x/exp v0.0.0-20211029182501-9b944d235b9d // indirect
golang.org/x/mobile v0.0.0-20211030030900-170e11ba2351 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 // indirect
golang.org/x/sys v0.0.0-20211031064116-611d5d643895 // indirect
)

12
go.sum

@ -293,8 +293,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/exp v0.0.0-20211029153326-98a2daa683e3 h1:EThhdleNHAYpuHkwXUPv0bjZuNhSMmNrIvCandX6jSU=
golang.org/x/exp v0.0.0-20211029153326-98a2daa683e3/go.mod h1:OyI624f2tQ/aU3IMa7GB16Hk54CHURAfHfj6tMqtyhA=
golang.org/x/exp v0.0.0-20211029182501-9b944d235b9d h1:MKwb3mzSy4CTpgAm10+7Ru8Hq8ZnHOGgWAjo9fNVK+o=
golang.org/x/exp v0.0.0-20211029182501-9b944d235b9d/go.mod h1:OyI624f2tQ/aU3IMa7GB16Hk54CHURAfHfj6tMqtyhA=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@ -310,8 +310,8 @@ golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
golang.org/x/mobile v0.0.0-20210902104108-5d9a33257ab5/go.mod h1:c4YKU3ZylDmvbw+H/PSvm42vhdWbuxCzbonauEAP9B8=
golang.org/x/mobile v0.0.0-20211029123140-7b8bfe09930c h1:K3U/yO0T6tX3GbBJxRdmhVD/JAQBtDXynUQW38GUujM=
golang.org/x/mobile v0.0.0-20211029123140-7b8bfe09930c/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ=
golang.org/x/mobile v0.0.0-20211030030900-170e11ba2351 h1:e6m5p6EjRXHjmiHMe3gCyuL1f82OdkJ0m7WJOn8mnjo=
golang.org/x/mobile v0.0.0-20211030030900-170e11ba2351/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
@ -380,8 +380,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 h1:2B5p2L5IfGiD7+b9BOoRMC6DgObAVZV+Fsp050NqXik=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211031064116-611d5d643895 h1:iaNpwpnrgL5jzWS0vCNnfa8HqzxveCFpFx3uC/X4Tps=
golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=

13
level.go

@ -98,14 +98,11 @@ SPAWNLOCATION:
// NewLevel returns a new randomly generated Level.
func NewLevel(levelNum int, p *gamePlayer) (*Level, error) {
multiplier := levelNum
if multiplier > 2 {
multiplier = 2
}
div := 4 - levelNum
l := &Level{
num: levelNum,
w: 336 * multiplier,
h: 336 * multiplier,
w: 336 / div,
h: 336 / div,
tileSize: 32,
player: p,
}
@ -124,9 +121,9 @@ func NewLevel(levelNum int, p *gamePlayer) (*Level, error) {
}
rooms := 33
if multiplier == 2 {
/*if multiplier == 2 {
rooms = 66
}
}*/
d := dungeon.NewDungeon(l.w/dungeonScale, rooms)
dungeonFloor := 1
l.tiles = make([][]*Tile, l.h)

2
player.go

@ -24,8 +24,6 @@ type gamePlayer struct {
health int
holyWaters int
garlicUntil time.Time
holyWaterUntil time.Time
}

Loading…
Cancel
Save