Browse Source

Add bats

master
Trevor Slocum 2 weeks ago
parent
commit
7b407ab94a
  1. BIN
      assets/creeps/bat/bat.aseprite
  2. BIN
      assets/creeps/bat/bat.gif
  3. BIN
      assets/creeps/bat/bite.png
  4. BIN
      assets/creeps/bat/fly.png
  5. BIN
      assets/creeps/bat/formation.png
  6. BIN
      assets/creeps/bat/hit and death.png
  7. BIN
      assets/creeps/bat/idle to fly.png
  8. BIN
      assets/creeps/bat/idle.png
  9. 52
      bat_spritesheet.go
  10. 40
      creep.go
  11. 49
      game.go
  12. 7
      goreleaser.yml

BIN
assets/creeps/bat/bat.aseprite

Binary file not shown.

BIN
assets/creeps/bat/bat.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

BIN
assets/creeps/bat/bite.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
assets/creeps/bat/fly.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

BIN
assets/creeps/bat/formation.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

BIN
assets/creeps/bat/hit and death.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
assets/creeps/bat/idle to fly.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
assets/creeps/bat/idle.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

52
bat_spritesheet.go

@ -0,0 +1,52 @@
package main
import (
"image"
_ "image/png"
"github.com/hajimehoshi/ebiten/v2"
)
// BatSpriteSheet represents a collection of sprite images.
type BatSpriteSheet struct {
Frame1 *ebiten.Image
Frame2 *ebiten.Image
Frame3 *ebiten.Image
Frame4 *ebiten.Image
Frame5 *ebiten.Image
Frame6 *ebiten.Image
Frame7 *ebiten.Image
}
// LoadBatSpriteSheet loads the embedded BatSpriteSheet.
func LoadBatSpriteSheet() (*BatSpriteSheet, error) {
tileSize := 32
f, err := assetsFS.Open("assets/creeps/bat/fly.png")
if err != nil {
return nil, err
}
img, _, err := image.Decode(f)
if err != nil {
return nil, err
}
sheet := ebiten.NewImageFromImage(img)
// spriteAt returns a sprite at the provided coordinates.
spriteAt := func(x, y int) *ebiten.Image {
return sheet.SubImage(image.Rect(x*tileSize, (y+1)*tileSize, (x+1)*tileSize, y*tileSize)).(*ebiten.Image)
}
// Populate CharacterSpriteSheet.
s := &BatSpriteSheet{}
s.Frame1 = spriteAt(0, 0)
s.Frame2 = spriteAt(1, 0)
s.Frame3 = spriteAt(2, 0)
s.Frame4 = spriteAt(3, 0)
s.Frame5 = spriteAt(4, 0)
s.Frame6 = spriteAt(5, 0)
s.Frame7 = spriteAt(6, 0)
return s, nil
}

40
creep.go

@ -4,13 +4,27 @@ import (
"math"
"math/rand"
"sync"
"time"
"github.com/hajimehoshi/ebiten/v2"
)
const (
TypeVampire = iota
TypeBat
TypeGhost
)
type gameCreep struct {
x, y float64
sprite *ebiten.Image
x, y float64
sprites []*ebiten.Image
frame int
frames int
lastFrame time.Time
creepType int
moveX, moveY float64
@ -27,6 +41,14 @@ type gameCreep struct {
sync.Mutex
}
func (c *gameCreep) queueNextAction() {
if c.creepType == TypeBat {
c.nextAction = 288 + rand.Intn(288)
return
}
c.nextAction = 144 + rand.Intn(720)
}
func (c *gameCreep) doNextAction() {
randMovementA := (rand.Float64() - 0.5) / 7
randMovementB := (rand.Float64() - 0.5) / 7
@ -60,19 +82,7 @@ func (c *gameCreep) doNextAction() {
c.moveY *= 1
}
c.nextAction = 144 + rand.Intn(720)
}
func NewCreep(sprite *ebiten.Image, level *Level, player *gamePlayer) *gameCreep {
return &gameCreep{
x: float64(1 + rand.Intn(108)),
y: float64(1 + rand.Intn(108)),
sprite: sprite,
level: level,
player: player,
health: 1,
killScore: 50,
}
c.queueNextAction()
}
func (c *gameCreep) Update() {

49
game.go

@ -77,6 +77,8 @@ type game struct {
projectiles []*projectile
batSS *BatSpriteSheet
ojasSS *CharacterSpriteSheet
heartImg *ebiten.Image
@ -146,6 +148,11 @@ func (g *game) loadAssets() error {
return fmt.Errorf("failed to load embedded spritesheet: %s", err)
}
g.batSS, err = LoadBatSpriteSheet()
if err != nil {
return fmt.Errorf("failed to load embedded spritesheet: %s", err)
}
f, err := assetsFS.Open("assets/weapons/bullet.png")
if err != nil {
return err
@ -224,6 +231,33 @@ func (g *game) loadAssets() error {
return nil
}
func (g *game) newCreep(creepType int) *gameCreep {
sprites := []*ebiten.Image{g.vampireImage}
if creepType == TypeBat {
sprites = []*ebiten.Image{
g.batSS.Frame1,
g.batSS.Frame2,
g.batSS.Frame3,
g.batSS.Frame4,
g.batSS.Frame5,
g.batSS.Frame6,
g.batSS.Frame7,
}
}
return &gameCreep{
creepType: creepType,
x: float64(1 + rand.Intn(108)),
y: float64(1 + rand.Intn(108)),
sprites: sprites,
frames: len(sprites),
level: g.currentLevel,
player: g.player,
health: 1,
killScore: 50,
}
}
func (g *game) reset() error {
var err error
g.currentLevel, err = NewLevel()
@ -245,7 +279,11 @@ func (g *game) reset() error {
g.creeps = make([]*gameCreep, 1000)
addedCreeps := make(map[string]bool)
for i := 0; i < 1000; i++ {
c := NewCreep(g.vampireImage, g.currentLevel, g.player)
creepType := TypeVampire
if rand.Intn(7) == 0 {
creepType = TypeBat
}
c := g.newCreep(creepType)
safeSpace := 7.0
dx, dy := deltaXY(g.player.x, g.player.y, c.x, c.y)
@ -735,7 +773,14 @@ func (g *game) renderLevel(screen *ebiten.Image) int {
continue
}
drawn += g.renderSprite(c.x, c.y, 0, 0, 0, c.sprite, screen)
drawn += g.renderSprite(c.x, c.y, 0, 0, 0, c.sprites[c.frame], screen)
if c.frames > 1 && time.Since(c.lastFrame) >= 75*time.Millisecond {
c.frame++
if c.frame == c.frames {
c.frame = 0
}
c.lastFrame = time.Now()
}
}
for _, p := range g.projectiles {

7
goreleaser.yml

@ -6,12 +6,12 @@ builds:
# ldflags:
# - -s -w -X code.rocketnine.space/tslocum/carotidartillery/main.Version={{.Version}}
goos:
- js
- linux
- windows
# - darwin
# - freebsd
goarch:
- amd64
- wasm
archives:
-
id: carotidartillery
@ -20,11 +20,12 @@ archives:
replacements:
386: i386
format_overrides:
- goos: js
format: zip
- goos: windows
format: zip
files:
- ./*.md
# - CHANGELOG
- LICENSE
checksum:
name_template: 'checksums.txt'

Loading…
Cancel
Save