Browse Source

Support building structures

main
Trevor Slocum 7 months ago
parent
commit
35a2293967
  1. 4
      asset/asset.go
  2. 24
      asset/map/house1.tmx
  3. 26
      asset/map/policestation.tmx
  4. 26
      game/game.go
  5. 35
      system/input_move.go
  6. 30
      world/level.go
  7. 50
      world/world.go

4
asset/asset.go

@ -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)

24
asset/map/house1.tmx

@ -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>

26
asset/map/policestation.tmx

@ -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

@ -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
}
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, 1, 1, false, false, tile.Sprite, screen)
g.renderSprite(float64(x), float64(y), 0, float64(i*-80), 0, 1, colorScale, alpha, false, false, sprite, screen)
}
}
}

35
system/input_move.go

@ -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)
}
}

30
world/level.go

@ -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
}
}
}
}

50
world/world.go

@ -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…
Cancel
Save