Support building structures
This commit is contained in:
parent
db7a74028e
commit
35a2293967
|
@ -19,8 +19,8 @@ const sampleRate = 44100
|
|||
//go:embed image map
|
||||
var FS embed.FS
|
||||
|
||||
var ImgWhiteSquare = ebiten.NewImage(8, 8)
|
||||
var ImgBlackSquare = ebiten.NewImage(8, 8)
|
||||
var ImgWhiteSquare = ebiten.NewImage(128, 128)
|
||||
var ImgBlackSquare = ebiten.NewImage(128, 128)
|
||||
|
||||
func init() {
|
||||
ImgWhiteSquare.Fill(color.White)
|
||||
|
|
|
@ -1,24 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.5" tiledversion="1.7.2" orientation="isometric" renderorder="right-down" width="6" height="6" tilewidth="128" tileheight="64" infinite="0" nextlayerid="4" nextobjectid="1">
|
||||
<map version="1.5" tiledversion="1.7.2" orientation="isometric" renderorder="right-down" width="3" height="3" tilewidth="128" tileheight="64" infinite="0" nextlayerid="4" nextobjectid="1">
|
||||
<tileset firstgid="1" source="../image/tileset/MRMO_BRIK.tsx"/>
|
||||
<layer id="1" name="1" width="6" height="6">
|
||||
<layer id="1" name="1" width="3" height="3">
|
||||
<data encoding="csv">
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,161,161,161,
|
||||
0,0,0,161,161,161,
|
||||
0,0,0,161,529,161
|
||||
161,161,161,
|
||||
161,161,161,
|
||||
161,529,161
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="2" name="2" width="6" height="6" offsetx="0" offsety="-80">
|
||||
<layer id="2" name="2" width="3" height="3" offsetx="0" offsety="-80">
|
||||
<data encoding="csv">
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,375,375,375,
|
||||
0,0,0,372,372,372,
|
||||
0,0,0,375,375,375
|
||||
375,375,375,
|
||||
372,372,372,
|
||||
375,375,375
|
||||
</data>
|
||||
</layer>
|
||||
</map>
|
||||
|
|
|
@ -1,24 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.5" tiledversion="1.7.2" orientation="isometric" renderorder="right-down" width="6" height="6" tilewidth="128" tileheight="64" infinite="0" nextlayerid="4" nextobjectid="1">
|
||||
<map version="1.5" tiledversion="1.7.2" orientation="isometric" renderorder="right-down" width="4" height="4" tilewidth="128" tileheight="64" infinite="0" nextlayerid="4" nextobjectid="1">
|
||||
<tileset firstgid="1" source="../image/tileset/MRMO_BRIK.tsx"/>
|
||||
<layer id="1" name="1" width="6" height="6">
|
||||
<layer id="1" name="1" width="4" height="4">
|
||||
<data encoding="csv">
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,67,67,67,67,
|
||||
0,0,67,67,67,67,
|
||||
0,0,67,67,67,67,
|
||||
0,0,67,67,527,67
|
||||
67,67,67,67,
|
||||
67,67,67,67,
|
||||
67,67,67,67,
|
||||
67,67,527,67
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="2" name="2" width="6" height="6" offsetx="0" offsety="-80">
|
||||
<layer id="2" name="2" width="4" height="4" offsetx="0" offsety="-80">
|
||||
<data encoding="csv">
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,504,0,0,504,
|
||||
0,0,0,444,444,0,
|
||||
0,0,0,444,444,0,
|
||||
0,0,504,0,0,504
|
||||
504,0,0,504,
|
||||
0,444,444,0,
|
||||
0,444,444,0,
|
||||
504,0,0,504
|
||||
</data>
|
||||
</layer>
|
||||
</map>
|
||||
|
|
26
game/game.go
26
game/game.go
|
@ -81,11 +81,11 @@ func (g *game) Update() error {
|
|||
if world.World.ResetGame {
|
||||
world.Reset()
|
||||
|
||||
world.BuildStructure(world.StructureHouse1, 0, 0)
|
||||
world.BuildStructure(world.StructureHouse1, false, 0, 0)
|
||||
|
||||
world.BuildStructure(world.StructureHouse1, 8, 12)
|
||||
world.BuildStructure(world.StructureHouse1, false, 8, 12)
|
||||
|
||||
world.BuildStructure(world.StructurePoliceStation, 12, 12)
|
||||
world.BuildStructure(world.StructurePoliceStation, false, 12, 12)
|
||||
|
||||
// TODO
|
||||
|
||||
|
@ -160,7 +160,11 @@ func (g *game) renderSprite(x float64, y float64, offsetx float64, offsety float
|
|||
// Center.
|
||||
g.op.GeoM.Translate(cx, cy)
|
||||
|
||||
g.op.ColorM.Reset()
|
||||
g.op.ColorM.Scale(colorScale, colorScale, colorScale, alpha)
|
||||
|
||||
target.DrawImage(sprite, g.op)
|
||||
g.op.ColorM.Reset()
|
||||
|
||||
/*s.op.GeoM.Scale(geoScale, geoScale)
|
||||
// Rotate
|
||||
|
@ -189,10 +193,22 @@ func (g *game) Draw(screen *ebiten.Image) {
|
|||
for i := range world.World.Level.Tiles {
|
||||
for x := range world.World.Level.Tiles[i] {
|
||||
for y, tile := range world.World.Level.Tiles[i][x] {
|
||||
if tile == nil || tile.Sprite == nil {
|
||||
if tile == nil {
|
||||
continue
|
||||
}
|
||||
g.renderSprite(float64(x), float64(y), 0, float64(i*-80), 0, 1, 1, 1, false, false, tile.Sprite, screen)
|
||||
var sprite *ebiten.Image
|
||||
alpha := 1.0
|
||||
colorScale := 1.0
|
||||
if tile.HoverSprite != nil {
|
||||
sprite = tile.HoverSprite
|
||||
alpha = 0.8
|
||||
colorScale = 0.6
|
||||
} else if tile.Sprite != nil {
|
||||
sprite = tile.Sprite
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
g.renderSprite(float64(x), float64(y), 0, float64(i*-80), 0, 1, colorScale, alpha, false, false, sprite, screen)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"code.rocketnine.space/tslocum/citylimits/component"
|
||||
|
@ -84,7 +83,29 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// TODO smooth camera zoom
|
||||
// Update target zoom level.
|
||||
var scrollY float64
|
||||
if ebiten.IsKeyPressed(ebiten.KeyC) || ebiten.IsKeyPressed(ebiten.KeyPageDown) {
|
||||
scrollY = -0.25
|
||||
} else if ebiten.IsKeyPressed(ebiten.KeyE) || ebiten.IsKeyPressed(ebiten.KeyPageUp) {
|
||||
scrollY = .25
|
||||
} else {
|
||||
_, scrollY = ebiten.Wheel()
|
||||
if scrollY < -1 {
|
||||
scrollY = -1
|
||||
} else if scrollY > 1 {
|
||||
scrollY = 1
|
||||
}
|
||||
}
|
||||
world.World.CamScaleTarget += scrollY * (world.World.CamScaleTarget / 7)
|
||||
|
||||
// Smooth zoom transition.
|
||||
div := 10.0
|
||||
if world.World.CamScaleTarget > world.World.CamScale {
|
||||
world.World.CamScale += (world.World.CamScaleTarget - world.World.CamScale) / div
|
||||
} else if world.World.CamScaleTarget < world.World.CamScale {
|
||||
world.World.CamScale -= (world.World.CamScale - world.World.CamScaleTarget) / div
|
||||
}
|
||||
|
||||
pressLeft := ebiten.IsKeyPressed(ebiten.KeyLeft)
|
||||
pressRight := ebiten.IsKeyPressed(ebiten.KeyRight)
|
||||
|
@ -132,13 +153,13 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
|
|||
if world.World.HoverStructure != 0 {
|
||||
xx, yy := world.ScreenToIso(x, y)
|
||||
tileX, tileY := world.IsoToCartesian(xx, yy)
|
||||
log.Println(x, y, tileX, tileY)
|
||||
if tileX >= 0 && tileY >= 0 && tileX < 256 && tileY < 256 {
|
||||
if int(tileX) != world.World.HoverX || int(tileY) != world.World.HoverY {
|
||||
world.BuildStructure(world.World.HoverStructure, int(tileX), int(tileY))
|
||||
world.World.HoverX, world.World.HoverY = int(tileX), int(tileY)
|
||||
log.Println("BUILD", x, y, int(tileX), int(tileY))
|
||||
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
|
||||
world.BuildStructure(world.World.HoverStructure, false, int(tileX), int(tileY))
|
||||
} else if int(tileX) != world.World.HoverX || int(tileY) != world.World.HoverY {
|
||||
world.BuildStructure(world.World.HoverStructure, true, int(tileX), int(tileY))
|
||||
}
|
||||
world.World.HoverX, world.World.HoverY = int(tileX), int(tileY)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package world
|
||||
|
||||
import "github.com/hajimehoshi/ebiten/v2"
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
type Tile struct {
|
||||
Sprite *ebiten.Image
|
||||
Sprite *ebiten.Image
|
||||
HoverSprite *ebiten.Image
|
||||
}
|
||||
|
||||
type GameLevel struct {
|
||||
|
@ -16,10 +19,6 @@ func NewLevel(size int) *GameLevel {
|
|||
l := &GameLevel{
|
||||
size: size,
|
||||
}
|
||||
const numLayers = 3
|
||||
for i := 0; i < numLayers; i++ {
|
||||
l.AddLayer()
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
|
@ -27,6 +26,25 @@ func (l *GameLevel) AddLayer() {
|
|||
tileMap := make([][]*Tile, l.size)
|
||||
for x := 0; x < l.size; x++ {
|
||||
tileMap[x] = make([]*Tile, l.size)
|
||||
// TODO
|
||||
/*for y := range tileMap[x] {
|
||||
tileMap[x][y] = &Tile{
|
||||
Sprite: asset.ImgWhiteSquare,
|
||||
}
|
||||
}*/
|
||||
}
|
||||
l.Tiles = append(l.Tiles, tileMap)
|
||||
}
|
||||
|
||||
func (l *GameLevel) ClearHoverSprites() {
|
||||
for i := range l.Tiles {
|
||||
for x := range l.Tiles[i] {
|
||||
for _, tile := range l.Tiles[i][x] {
|
||||
if tile == nil {
|
||||
continue
|
||||
}
|
||||
tile.HoverSprite = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"log"
|
||||
"math/rand"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"code.rocketnine.space/tslocum/citylimits/asset"
|
||||
"code.rocketnine.space/tslocum/citylimits/component"
|
||||
|
@ -25,13 +24,14 @@ const (
|
|||
)
|
||||
|
||||
var World = &GameWorld{
|
||||
CamScale: 1,
|
||||
CamMoving: true,
|
||||
PlayerWidth: 8,
|
||||
PlayerHeight: 32,
|
||||
TileImages: make(map[uint32]*ebiten.Image),
|
||||
ResetGame: true,
|
||||
Level: NewLevel(256),
|
||||
CamScale: 1,
|
||||
CamScaleTarget: 1,
|
||||
CamMoving: true,
|
||||
PlayerWidth: 8,
|
||||
PlayerHeight: 32,
|
||||
TileImages: make(map[uint32]*ebiten.Image),
|
||||
ResetGame: true,
|
||||
Level: NewLevel(256),
|
||||
}
|
||||
|
||||
type GameWorld struct {
|
||||
|
@ -58,9 +58,10 @@ type GameWorld struct {
|
|||
|
||||
PlayerX, PlayerY float64
|
||||
|
||||
CamX, CamY float64
|
||||
CamScale float64
|
||||
CamMoving bool
|
||||
CamX, CamY float64
|
||||
CamScale float64
|
||||
CamScaleTarget float64
|
||||
CamMoving bool
|
||||
|
||||
PlayerWidth float64
|
||||
PlayerHeight float64
|
||||
|
@ -115,11 +116,8 @@ func Reset() {
|
|||
World.MessageVisible = false
|
||||
}
|
||||
|
||||
func BuildStructure(structureType int, placeX int, placeY int) (*Structure, error) {
|
||||
tt := time.Now()
|
||||
defer func() {
|
||||
log.Println(time.Since(tt))
|
||||
}()
|
||||
func BuildStructure(structureType int, hover bool, placeX int, placeY int) (*Structure, error) {
|
||||
World.Level.ClearHoverSprites()
|
||||
|
||||
loader := tiled.Loader{
|
||||
FileSystem: asset.FS,
|
||||
|
@ -141,7 +139,7 @@ func BuildStructure(structureType int, placeX int, placeY int) (*Structure, erro
|
|||
log.Fatalf("error parsing world: %+v", err)
|
||||
}
|
||||
|
||||
if placeX < 0 || placeY < 0 || placeX+m.Width > 256 || placeY+m.Height > 256 {
|
||||
if placeX-m.Width < 0 || placeY-m.Height < 0 || placeX > 256 || placeY > 256 {
|
||||
return nil, errors.New("invalid location: building does not fit")
|
||||
}
|
||||
|
||||
|
@ -211,20 +209,21 @@ func BuildStructure(structureType int, placeX int, placeY int) (*Structure, erro
|
|||
continue
|
||||
}
|
||||
|
||||
for i > len(World.Level.Tiles)-2 {
|
||||
for i > len(World.Level.Tiles)-1 {
|
||||
World.Level.AddLayer()
|
||||
}
|
||||
|
||||
if World.Level.Tiles[i][x+placeX][y+placeY] == nil {
|
||||
World.Level.Tiles[i][x+placeX][y+placeY] = &Tile{}
|
||||
tx, ty := (x+placeX)-m.Width, (y+placeY)-m.Height
|
||||
if World.Level.Tiles[i][tx][ty] == nil {
|
||||
World.Level.Tiles[i][tx][ty] = &Tile{}
|
||||
}
|
||||
if hover {
|
||||
World.Level.Tiles[i][tx][ty].HoverSprite = World.TileImages[t.Tileset.FirstGID+t.ID]
|
||||
} else {
|
||||
World.Level.Tiles[i][tx][ty].Sprite = World.TileImages[t.Tileset.FirstGID+t.ID]
|
||||
}
|
||||
World.Level.Tiles[i][x+placeX][y+placeY].Sprite = World.TileImages[t.Tileset.FirstGID+t.ID]
|
||||
|
||||
// TODO handle flipping
|
||||
|
||||
//tileX, tileY := TileToGameCoords(x, y)
|
||||
//e := createTileEntity(t, tileX+float64(layer.OffsetY*2), tileY+float64(layer.OffsetY*2))
|
||||
//tileEntities = append(tileEntities, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -362,6 +361,7 @@ func CartesianToIso(x, y float64) (float64, float64) {
|
|||
func IsoToCartesian(x, y float64) (float64, float64) {
|
||||
cx := (x/float64(TileSize/2) + y/float64(TileSize/4)) / 2
|
||||
cy := (y/float64(TileSize/4) - (x / float64(TileSize/2))) / 2
|
||||
cy++ // TODO Why is this necessary?
|
||||
return cx, cy
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue