Draw software cursor
This commit is contained in:
parent
17ccff124a
commit
9a8c3287e9
|
@ -19,12 +19,17 @@ const sampleRate = 44100
|
|||
//go:embed image
|
||||
var FS embed.FS
|
||||
|
||||
var ImgWhiteSquare = ebiten.NewImage(4, 4)
|
||||
var ImgBlackSquare = ebiten.NewImage(3, 3)
|
||||
var ColorWater = color.RGBA{96, 160, 168, 255}
|
||||
|
||||
var (
|
||||
ImgWater = newWaterImage()
|
||||
ImgFish = LoadImage("image/cozy-fishing/global.png")
|
||||
ImgWhiteSquare = newFilledImage(4, 4, color.White)
|
||||
ImgBlackSquare = newFilledImage(4, 4, color.Black)
|
||||
|
||||
ImgWater = newFilledImage(16, 16, ColorWater)
|
||||
|
||||
ImgCrosshair = LoadImage("image/crosshair.png")
|
||||
|
||||
ImgFishTileset = LoadImage("image/cozy-fishing/global.png")
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -32,9 +37,9 @@ func init() {
|
|||
ImgBlackSquare.Fill(color.Black)
|
||||
}
|
||||
|
||||
func newWaterImage() *ebiten.Image {
|
||||
img := ebiten.NewImage(16, 16)
|
||||
img.Fill(color.RGBA{96, 160, 168, 255})
|
||||
func newFilledImage(w int, h int, c color.Color) *ebiten.Image {
|
||||
img := ebiten.NewImage(w, h)
|
||||
img.Fill(c)
|
||||
return img
|
||||
}
|
||||
|
||||
|
@ -130,7 +135,7 @@ func FishTileAt(i int) *ebiten.Image {
|
|||
|
||||
r := image.Rect(x*tileSize, y*tileSize, (x+1)*tileSize, (y+1)*tileSize)
|
||||
|
||||
return ImgFish.SubImage(r).(*ebiten.Image)
|
||||
return ImgFishTileset.SubImage(r).(*ebiten.Image)
|
||||
}
|
||||
|
||||
func FishTileXY(x, y int) *ebiten.Image {
|
||||
|
@ -139,7 +144,7 @@ func FishTileXY(x, y int) *ebiten.Image {
|
|||
|
||||
r := image.Rect(x*tileSize, y*tileSize, (x+1)*tileSize, (y+1)*tileSize)
|
||||
|
||||
return ImgFish.SubImage(r).(*ebiten.Image)
|
||||
return ImgFishTileset.SubImage(r).(*ebiten.Image)
|
||||
}
|
||||
|
||||
func FishImage(i int) *ebiten.Image {
|
||||
|
@ -152,5 +157,5 @@ func FishImage(i int) *ebiten.Image {
|
|||
|
||||
r := image.Rect(x*tileSize, y*tileSize, (x+1)*tileSize, (y+1)*tileSize)
|
||||
|
||||
return ImgFish.SubImage(r).(*ebiten.Image)
|
||||
return ImgFishTileset.SubImage(r).(*ebiten.Image)
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 570 B |
26
game/game.go
26
game/game.go
|
@ -5,7 +5,6 @@ import (
|
|||
"math/rand"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"code.rocketnine.space/tslocum/fishfightback/component"
|
||||
"code.rocketnine.space/tslocum/fishfightback/entity"
|
||||
|
@ -72,12 +71,7 @@ func (g *game) tileToGameCoords(x, y int) (float64, float64) {
|
|||
}
|
||||
|
||||
func (g *game) updateCursor() {
|
||||
if g.activeGamepad != -1 || g.gameWon {
|
||||
ebiten.SetCursorMode(ebiten.CursorModeHidden)
|
||||
return
|
||||
}
|
||||
ebiten.SetCursorMode(ebiten.CursorModeVisible)
|
||||
ebiten.SetCursorShape(ebiten.CursorShapeCrosshair)
|
||||
ebiten.SetCursorMode(ebiten.CursorModeHidden)
|
||||
}
|
||||
|
||||
// Layout is called when the game's layout changes.
|
||||
|
@ -96,7 +90,6 @@ func (g *game) Update() error {
|
|||
|
||||
if !g.addedSystems {
|
||||
g.addSystems()
|
||||
|
||||
g.addedSystems = true
|
||||
}
|
||||
|
||||
|
@ -105,25 +98,14 @@ func (g *game) Update() error {
|
|||
world.SetFish(level.FishParrot)
|
||||
}
|
||||
|
||||
const playerStartOffset = 128
|
||||
const camStartOffset = 480
|
||||
|
||||
/* w := float64(world.World.Map.Width * world.World.Map.TileWidth)
|
||||
h := float64(world.World.Map.Height * world.World.Map.TileHeight)*/
|
||||
|
||||
world.World.Player.With(func(position *component.Position) {
|
||||
//position.X, position.Y = w/2, h-playerStartOffset
|
||||
|
||||
position.X, position.Y = 200, 3500
|
||||
position.X, position.Y = float64(rand.Intn(world.ScreenWidth/2)), world.ScreenHeight-system.TileWidth-float64(rand.Intn(100))
|
||||
})
|
||||
|
||||
world.World.CamX, world.World.CamY = 1, 3700-camStartOffset
|
||||
world.World.CamX, world.World.CamY = 0, 0
|
||||
|
||||
g.nextSectionX = 0
|
||||
|
||||
// TODO Seed is configurable
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
world.World.ResetGame = false
|
||||
world.World.GameOver = false
|
||||
}
|
||||
|
@ -174,8 +156,10 @@ func (g *game) addSystems() {
|
|||
gohan.AddSystem(system.NewRenderSystem(layer))
|
||||
}
|
||||
|
||||
gohan.AddSystem(system.NewRenderHUDSystem())
|
||||
gohan.AddSystem(system.NewRenderMessageSystem())
|
||||
gohan.AddSystem(system.NewRenderDebugTextSystem(world.World.Player))
|
||||
gohan.AddSystem(system.NewRenderCursorSystem())
|
||||
gohan.AddSystem(system.NewProfileSystem(world.World.Player))
|
||||
}
|
||||
|
||||
|
|
1
go.mod
1
go.mod
|
@ -5,6 +5,7 @@ go 1.17
|
|||
require (
|
||||
code.rocketnine.space/tslocum/gohan v0.0.0-20220611080547-c66dd322f959
|
||||
github.com/hajimehoshi/ebiten/v2 v2.3.4
|
||||
golang.org/x/text v0.3.7
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
1
go.sum
1
go.sum
|
@ -76,6 +76,7 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
|
|||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
|
|
|
@ -25,7 +25,7 @@ func (s *CameraSystem) Update(e gohan.Entity) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
world.World.CamMoving = world.World.CamX > 0
|
||||
world.World.CamMoving = world.World.CamX >= 0
|
||||
if world.World.CamMoving {
|
||||
world.World.CamX += world.RailSpeed
|
||||
} else {
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
// pause time, screen X, screen Y
|
||||
type CreepSystem struct {
|
||||
Creep *component.Creep
|
||||
Position *component.Position
|
||||
|
@ -39,7 +38,7 @@ func (s *CreepSystem) Update(e gohan.Entity) error {
|
|||
|
||||
// Skip inactive creeps.
|
||||
sx, sy := world.LevelCoordinatesToScreen(position.X, position.Y)
|
||||
inactive := sx < 0 || sy < 0 || sx > float64(world.ScreenWidth) || sy > float64(world.ScreenHeight)
|
||||
inactive := sx < 0 || sy < 0 || sx > float64(world.ScreenWidth)+TileWidth/2 || sy > float64(world.ScreenHeight)
|
||||
if creep.Active != !inactive {
|
||||
creep.Active = !inactive
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ func (s *MovementSystem) Update(e gohan.Entity) error {
|
|||
|
||||
if playerBullet != nil {
|
||||
var currentSection = world.World.SectionA
|
||||
if position.X >= world.World.SectionA.X+world.SectionWidth {
|
||||
if world.World.SectionB.X != 0 && position.X >= world.World.SectionB.X && position.X < world.World.SectionB.X+world.SectionWidth {
|
||||
currentSection = world.World.SectionB
|
||||
}
|
||||
|
||||
|
@ -164,19 +164,20 @@ func (s *MovementSystem) Update(e gohan.Entity) error {
|
|||
// Hit creep.
|
||||
creepEntity := currentSection.Creeps[ty][tx]
|
||||
if creepEntity != 0 {
|
||||
var hitCreep bool
|
||||
creepEntity.With(func(creep *component.Creep) {
|
||||
if creep == nil {
|
||||
if creep == nil || !creep.Active {
|
||||
return
|
||||
}
|
||||
|
||||
if creep.Active {
|
||||
creep.Health--
|
||||
creep.DamageTicks = 6
|
||||
}
|
||||
creep.Health--
|
||||
creep.DamageTicks = 6
|
||||
hitCreep = true
|
||||
})
|
||||
if hitCreep {
|
||||
e.Remove()
|
||||
currentSection.Creeps[ty][tx] = 0
|
||||
}
|
||||
|
||||
e.Remove()
|
||||
currentSection.Creeps[ty][tx] = 0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"code.rocketnine.space/tslocum/fishfightback/asset"
|
||||
"code.rocketnine.space/tslocum/fishfightback/component"
|
||||
|
||||
"code.rocketnine.space/tslocum/gohan"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
type RenderCursorSystem struct {
|
||||
Position *component.Position
|
||||
Velocity *component.Velocity
|
||||
Weapon *component.Weapon
|
||||
|
||||
cx, cy int
|
||||
}
|
||||
|
||||
func NewRenderCursorSystem() *RenderCursorSystem {
|
||||
s := &RenderCursorSystem{}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *RenderCursorSystem) Update(_ gohan.Entity) error {
|
||||
s.cx, s.cy = ebiten.CursorPosition()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *RenderCursorSystem) Draw(_ gohan.Entity, screen *ebiten.Image) error {
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Translate(float64(s.cx-2), float64(s.cy-2))
|
||||
screen.DrawImage(asset.ImgCrosshair, op)
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"code.rocketnine.space/tslocum/fishfightback/component"
|
||||
"code.rocketnine.space/tslocum/fishfightback/world"
|
||||
"code.rocketnine.space/tslocum/gohan"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
||||
)
|
||||
|
||||
type RenderHUDSystem struct {
|
||||
Position *component.Position
|
||||
Velocity *component.Velocity
|
||||
Weapon *component.Weapon
|
||||
|
||||
op *ebiten.DrawImageOptions
|
||||
msgImg *ebiten.Image
|
||||
tmpImg *ebiten.Image
|
||||
|
||||
lastScore int
|
||||
}
|
||||
|
||||
func NewRenderHUDSystem() *RenderHUDSystem {
|
||||
s := &RenderHUDSystem{
|
||||
op: &ebiten.DrawImageOptions{},
|
||||
msgImg: ebiten.NewImage(1, 1),
|
||||
tmpImg: ebiten.NewImage(200, 200),
|
||||
lastScore: -1,
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *RenderHUDSystem) Update(_ gohan.Entity) error {
|
||||
return gohan.ErrUnregister
|
||||
}
|
||||
|
||||
func (s *RenderHUDSystem) Draw(_ gohan.Entity, screen *ebiten.Image) error {
|
||||
if !world.World.GameStarted {
|
||||
return nil
|
||||
}
|
||||
|
||||
if world.World.Score != s.lastScore {
|
||||
s.drawScore()
|
||||
}
|
||||
|
||||
// Draw score.
|
||||
s.op.GeoM.Reset()
|
||||
s.op.GeoM.Translate(1, world.ScreenHeight-15)
|
||||
screen.DrawImage(s.msgImg, s.op)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *RenderHUDSystem) drawScore() {
|
||||
message := world.NumberPrinter.Sprintf("%d", world.World.Score)
|
||||
|
||||
split := []string{message}
|
||||
width := 0
|
||||
for _, line := range split {
|
||||
lineSize := len(line) * 12
|
||||
if lineSize > width {
|
||||
width = lineSize
|
||||
}
|
||||
}
|
||||
height := len(split) * 32
|
||||
|
||||
const padding = 8
|
||||
width, height = width+padding*2, height+padding*2
|
||||
|
||||
s.msgImg = ebiten.NewImage(width, height)
|
||||
//s.msgImg.Fill(color.RGBA{17, 17, 17, 100})
|
||||
|
||||
s.tmpImg.Clear()
|
||||
s.tmpImg = ebiten.NewImage(width*2, height*2)
|
||||
s.op.GeoM.Reset()
|
||||
s.op.GeoM.Scale(1, 1)
|
||||
//s.op.GeoM.Translate(float64(padding), float64(padding))
|
||||
ebitenutil.DebugPrint(s.tmpImg, message)
|
||||
s.msgImg.DrawImage(s.tmpImg, s.op)
|
||||
s.op.ColorM.Reset()
|
||||
}
|
|
@ -14,8 +14,6 @@ import (
|
|||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
// TODO tweak
|
||||
|
||||
const SectionWidth = ScreenWidth * 2
|
||||
|
||||
type Section struct {
|
||||
|
@ -61,8 +59,6 @@ func (s *Section) SetPosition(x float64, y float64) {
|
|||
}
|
||||
|
||||
func (s *Section) tileAvailable(tx, ty int, creep bool) bool {
|
||||
// TODO use shore map and return false
|
||||
|
||||
if ty < 0 {
|
||||
return true // TODO
|
||||
} else if ty > s.ShoreDepth || (!creep && ty == s.ShoreDepth-1) {
|
||||
|
|
|
@ -2,7 +2,13 @@ package world
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message"
|
||||
|
||||
"code.rocketnine.space/tslocum/fishfightback/asset"
|
||||
|
||||
|
@ -17,7 +23,9 @@ const (
|
|||
ScreenHeight = 225
|
||||
)
|
||||
|
||||
const RailSpeed = 0.2
|
||||
var RailSpeed = 0.4
|
||||
|
||||
var NumberPrinter = message.NewPrinter(language.English)
|
||||
|
||||
var World = &GameWorld{
|
||||
CamScale: 1,
|
||||
|
@ -80,6 +88,15 @@ func Reset() {
|
|||
|
||||
World.SectionA.ShoreDepth = 0
|
||||
World.SectionB.ShoreDepth = 0
|
||||
|
||||
RailSpeed = 0.4
|
||||
|
||||
// TODO Seed is configurable
|
||||
seed := time.Now().UnixNano()
|
||||
|
||||
rand.Seed(seed)
|
||||
|
||||
log.Printf("Starting game with seed %d", seed)
|
||||
}
|
||||
|
||||
func LevelCoordinatesToScreen(x, y float64) (float64, float64) {
|
||||
|
@ -103,6 +120,8 @@ func (w *GameWorld) SetGameOver() {
|
|||
} else {
|
||||
SetMessage("GAME OVER", math.MaxInt)
|
||||
}
|
||||
|
||||
log.Printf("Game over - score %d", w.Score)
|
||||
}
|
||||
|
||||
func StartGame() {
|
||||
|
|
Loading…
Reference in New Issue