Load and use cozy-people tileset

This commit is contained in:
Trevor Slocum 2022-06-12 17:23:31 -07:00
parent 48f852176d
commit 1239fcbfd3
8 changed files with 110 additions and 83 deletions

View File

@ -29,7 +29,11 @@ var (
ImgCrosshair = LoadImage("image/crosshair.png")
ImgFishTileset = LoadImage("image/cozy-fishing/global.png")
ImgFish = LoadImage("image/cozy-fishing/global.png")
ImgPeepBody = LoadImage("image/cozy-people/characters/char_all.png")
ImgPeepClothesShirt = LoadImage("image/cozy-people/clothes/basic.png")
ImgPeepClothesPants = LoadImage("image/cozy-people/clothes/pants.png")
)
func init() {
@ -127,35 +131,31 @@ func LoadOGG(context *audio.Context, p string, loop bool) *audio.Player {
return player
}
func FishTileAt(i int) *ebiten.Image {
const tileSize = 16
const tilesetWidth = 56
x, y := i%tilesetWidth, i/tilesetWidth
r := image.Rect(x*tileSize, y*tileSize, (x+1)*tileSize, (y+1)*tileSize)
return ImgFishTileset.SubImage(r).(*ebiten.Image)
}
func FishTileXY(x, y int) *ebiten.Image {
const tileSize = 16
const tilesetWidth = 56
r := image.Rect(x*tileSize, y*tileSize, (x+1)*tileSize, (y+1)*tileSize)
return ImgFishTileset.SubImage(r).(*ebiten.Image)
return ImgFish.SubImage(r).(*ebiten.Image)
}
func FishImage(i int) *ebiten.Image {
const tileSize = 16
const fishTilesetWidth = 10
x, y := i%fishTilesetWidth, i/fishTilesetWidth
const tilesetWidth = 10
x, y := i%tilesetWidth, i/tilesetWidth
x += 46
r := image.Rect(x*tileSize, y*tileSize, (x+1)*tileSize, (y+1)*tileSize)
return ImgFishTileset.SubImage(r).(*ebiten.Image)
return ImgFish.SubImage(r).(*ebiten.Image)
}
func PeepImage(tileset *ebiten.Image, i int, frame int) *ebiten.Image {
const tileSize = 32
const tilesetWidth = 8
x, y := frame%tilesetWidth, frame/tilesetWidth
offsetX, offsetY := i*32*8, 0
r := image.Rect(offsetX+x*tileSize, offsetY+y*tileSize, offsetX+(x+1)*tileSize, offsetY+(y+1)*tileSize)
return tileset.SubImage(r).(*ebiten.Image)
}

View File

@ -26,4 +26,8 @@ type Sprite struct {
OverrideColorScale bool
ColorScale float64
OffsetX, OffsetY float64
Images []*ebiten.Image
}

View File

@ -4,6 +4,8 @@ import (
"math/rand"
"sync"
"github.com/hajimehoshi/ebiten/v2"
"code.rocketnine.space/tslocum/fishfightback/asset"
"code.rocketnine.space/tslocum/fishfightback/component"
"code.rocketnine.space/tslocum/fishfightback/level"
@ -21,6 +23,10 @@ func newCreepID() int64 {
return newestCreepID
}
func randCreepType() int {
return rand.Intn(8)
}
func NewCreep(creepType int, x, y float64) gohan.Entity {
creepID := newCreepID()
@ -32,8 +38,18 @@ func NewCreep(creepType int, x, y float64) gohan.Entity {
Z: level.LayerCreep,
})
images := []*ebiten.Image{
asset.PeepImage(asset.ImgPeepBody, randCreepType(), 0),
}
if rand.Intn(3) == 0 {
images = append(images, asset.PeepImage(asset.ImgPeepClothesShirt, randCreepType(), 0))
}
images = append(images, asset.PeepImage(asset.ImgPeepClothesPants, randCreepType(), 0))
creep.AddComponent(&component.Sprite{
Image: asset.FishImage(int(level.FishMackerel)),
Images: images,
OffsetX: -16,
OffsetY: -16,
})
creep.AddComponent(&component.Creep{

View File

@ -22,7 +22,9 @@ func NewPlayerBullet(x, y, xSpeed, ySpeed float64) gohan.Entity {
})
bullet.AddComponent(&component.Sprite{
Image: asset.ImgBlackSquare,
Image: asset.ImgBlackSquare,
OffsetX: -2,
OffsetY: -2,
})
bullet.AddComponent(&component.PlayerBullet{})

View File

@ -2,7 +2,6 @@ package system
import (
"image"
"image/color"
"math"
"code.rocketnine.space/tslocum/fishfightback/component"
@ -11,8 +10,6 @@ import (
"github.com/hajimehoshi/ebiten/v2"
)
const rewindThreshold = 1
type MovementSystem struct {
Position *component.Position
Velocity *component.Velocity
@ -29,25 +26,6 @@ func NewMovementSystem() *MovementSystem {
return s
}
func drawDebugRect(r image.Rectangle, c color.Color, overrideColorScale bool) gohan.Entity {
rectEntity := gohan.NewEntity()
rectImg := ebiten.NewImage(r.Dx(), r.Dy())
rectImg.Fill(c)
rectEntity.AddComponent(&component.Position{
X: float64(r.Min.X),
Y: float64(r.Min.Y),
})
rectEntity.AddComponent(&component.Sprite{
Image: rectImg,
OverrideColorScale: overrideColorScale,
})
return rectEntity
}
func (s *MovementSystem) Update(e gohan.Entity) error {
if !world.World.GameStarted {
return nil
@ -128,27 +106,25 @@ func (s *MovementSystem) Update(e gohan.Entity) error {
if world.World.NoClip {
return nil
}
bulletSize := 4.0
bulletRect := image.Rect(int(position.X), int(position.Y), int(position.X+bulletSize), int(position.Y+bulletSize))
creepBullet := s.CreepBullet
playerBullet := s.PlayerBullet
var currentSection = world.World.SectionA
if world.World.SectionB.X != 0 && position.X >= world.World.SectionB.X && position.X < world.World.SectionB.X+world.SectionWidth {
currentSection = world.World.SectionB
}
tx, ty := int((position.X-currentSection.X)/TileWidth), int((position.Y-currentSection.Y)/TileWidth)
offscreen := tx < 0 || ty < 0 || tx >= world.SectionWidth/TileWidth || ty >= world.ScreenHeight/TileWidth
// Check hazard collisions.
if creepBullet != nil {
if offscreen {
playerRect := image.Rect(int(world.World.PlayerX), int(world.World.PlayerY), int(world.World.PlayerX+world.World.PlayerWidth), int(world.World.PlayerY+world.World.PlayerHeight))
bulletSize := 4.0
var currentSection = world.World.SectionA
if world.World.SectionB.X != 0 && position.X >= world.World.SectionB.X && position.X < world.World.SectionB.X+world.SectionWidth {
currentSection = world.World.SectionB
}
tx, ty := int((position.X-currentSection.X)/TileWidth), int((position.Y-currentSection.Y)/TileWidth)
if tx < 0 || ty < 0 || tx >= world.SectionWidth/TileWidth || ty >= world.ScreenHeight/TileWidth {
e.Remove()
return nil
}
playerRect := image.Rect(int(world.World.PlayerX), int(world.World.PlayerY), int(world.World.PlayerX+world.World.PlayerWidth), int(world.World.PlayerY+world.World.PlayerHeight))
bulletRect := image.Rect(int(position.X), int(position.Y), int(position.X+bulletSize), int(position.Y+bulletSize))
if bulletRect.Overlaps(playerRect) {
if !world.World.GodMode {
world.World.SetGameOver()
@ -159,29 +135,48 @@ func (s *MovementSystem) Update(e gohan.Entity) error {
}
if playerBullet != nil {
var offscreen bool
for oy := -2; oy < 5; oy++ {
for ox := -2; ox < 5; ox++ {
var currentSection = world.World.SectionA
if world.World.SectionB.X != 0 && position.X >= world.World.SectionB.X && position.X < world.World.SectionB.X+world.SectionWidth {
currentSection = world.World.SectionB
}
tx, ty := int((position.X+float64(ox)-currentSection.X)/TileWidth), int((position.Y+float64(oy)-currentSection.Y)/TileWidth)
if tx < 0 || ty < 0 || tx >= world.SectionWidth/TileWidth || ty >= world.ScreenHeight/TileWidth {
continue // Offscreen
}
offscreen = false
// Hit creep.
for offset := 0; offset < 2; offset++ {
if ty+offset >= world.ScreenHeight/TileWidth {
break
}
creepEntity := currentSection.Creeps[ty+offset][tx]
if creepEntity != 0 {
var hitCreep bool
creepEntity.With(func(creep *component.Creep) {
if creep == nil || !creep.Active {
return
}
creep.Health--
creep.DamageTicks = 6
hitCreep = true
})
if hitCreep {
e.Remove()
currentSection.Creeps[ty+offset][tx] = 0
}
}
}
}
}
if offscreen {
e.Remove()
return nil
}
// Hit creep.
creepEntity := currentSection.Creeps[ty][tx]
if creepEntity != 0 {
var hitCreep bool
creepEntity.With(func(creep *component.Creep) {
if creep == nil || !creep.Active {
return
}
creep.Health--
creep.DamageTicks = 6
hitCreep = true
})
if hitCreep {
e.Remove()
currentSection.Creeps[ty][tx] = 0
}
}
}
return nil

View File

@ -127,6 +127,11 @@ func (s *RenderSystem) Draw(e gohan.Entity, screen *ebiten.Image) error {
colorScale = sprite.ColorScale
}
s.renderSprite(position.X, position.Y, 0, 0, sprite.Angle, 1.0, colorScale, 1.0, sprite.HorizontalFlip, sprite.VerticalFlip, sprite.Image, screen)
if len(sprite.Images) == 0 {
s.renderSprite(position.X, position.Y, sprite.OffsetX, sprite.OffsetY, sprite.Angle, 1.0, colorScale, 1.0, sprite.HorizontalFlip, sprite.VerticalFlip, sprite.Image, screen)
}
for _, img := range sprite.Images {
s.renderSprite(position.X, position.Y, sprite.OffsetX, sprite.OffsetY, sprite.Angle, 1.0, colorScale, 1.0, sprite.HorizontalFlip, sprite.VerticalFlip, img, screen)
}
return nil
}

View File

@ -179,11 +179,8 @@ func (s *Section) Regenerate(lastShoreDepth int) {
}
// Generate buildings.
// TODO bag of random buildings
addBuildings := rand.Intn(14)
for j := 0; j < addBuildings; j++ {
specialBuilding := rand.Intn(4) == 0
@ -218,9 +215,10 @@ func (s *Section) Regenerate(lastShoreDepth int) {
}
// Generate creeps.
for attempt := 0; attempt < 7; attempt++ {
tx, ty := rand.Intn(SectionWidth/16), int(float64(rand.Intn(s.ShoreDepth)))
if !s.tileAvailable(tx, ty, true) {
const numCreeps = 40 // TODO
for attempt := 0; attempt < numCreeps; attempt++ {
tx, ty := rand.Intn(SectionWidth/16), int(float64(rand.Intn(s.ShoreDepth-1)))
if !s.tileAvailable(tx, ty, true) || (ty != 0 && !s.tileAvailable(tx, ty-1, true)) || !s.tileAvailable(tx, ty+1, true) || !s.tileAvailable(tx-1, ty, true) || !s.tileAvailable(tx+1, ty, true) {
continue
}

View File

@ -23,7 +23,12 @@ const (
ScreenHeight = 225
)
var RailSpeed = 0.4
const (
StartingRailSpeed = 0.4
FishSpeedIncrease = 0.05
)
var RailSpeed = StartingRailSpeed
var NumberPrinter = message.NewPrinter(language.English)
@ -155,4 +160,6 @@ func SetFish(fish level.FishType) {
sprite.Image = asset.FishImage(int(fish))
})
RailSpeed = StartingRailSpeed + (FishSpeedIncrease * float64(fish))
}