123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684 |
- package tile
- import "fmt"
- import "gitlab.com/beoran/al5go/al"
- import "gitlab.com/beoran/ebsgo/engine/physics"
- import "gitlab.com/beoran/ebsgo/engine/fifi"
- import "gitlab.com/beoran/ebsgo/monolog"
- const (
- BLEND_NORTHWEST = 0
- BLEND_NORTH = 1
- BLEND_NORTHEAST = 2
- BLEND_WEST = 3
- BLEND_EAST = 4
- BLEND_SOUTHWEST = 5
- BLEND_SOUTH = 6
- BLEND_SOUTHEAST = 7
- BLEND_DIRECTION_MAX = 8
- )
- const (
- BLEND_CORNER = 0
- BLEND_SIDE = 1
- BLEND_SHAPE_MAX = 2
- )
- const (
- BLEND_SHARP = 0
- BLEND_GRADUAL = 1
- BLEND_FUZZY = 2
- BLEND_FUZZY_GRADUAL = 3
- BLEND_TYPE_MAX = 3
- )
- const BLEND_BITMAPS_MAX = 255
- var BlendMasks [BLEND_TYPE_MAX][BLEND_SHAPE_MAX]*al.Bitmap
- var BlendFlags [BLEND_DIRECTION_MAX]int = [BLEND_DIRECTION_MAX] int{
- 0,
- 0,
- al.FLIP_HORIZONTAL,
- 0,
- al.FLIP_HORIZONTAL,
- al.FLIP_VERTICAL,
- al.FLIP_VERTICAL,
- al.FLIP_HORIZONTAL | al.FLIP_VERTICAL,
- }
- var BlendSides [BLEND_DIRECTION_MAX]int = [BLEND_DIRECTION_MAX]int {
- BLEND_CORNER,
- BLEND_SIDE ,
- BLEND_CORNER,
- BLEND_SIDE ,
- BLEND_SIDE ,
- BLEND_CORNER,
- BLEND_SIDE ,
- BLEND_CORNER,
- }
- var BlendAngles [BLEND_DIRECTION_MAX]float32 = [BLEND_DIRECTION_MAX]float32 {
- 0.0,
- 0.0,
- 0.0,
- 3 * al.PI / 2.0,
- al.PI / 2.0,
- 0.0,
- 0.0,
- 0.0,
- }
- func PrepareBlend(blend * al.Bitmap, tile * Tile, blentile * Tile, direction int ) * al.Bitmap {
- side := BlendSides[direction]
- angle := BlendAngles[direction]
- flags := BlendFlags[direction]
- maskid:= tile.BlendMask
- mask := BlendMasks[maskid][side]
- if mask == nil {
- return nil
- } else {
- tile.DrawMaskedTo(blend, mask, angle, flags)
- return blend
- }
- }
- type Cell struct {
- * Tile
- Blend * al.Bitmap
- Flags int
- Rotate float32
- Shadows [][8]float32
- }
- type Pane struct {
- Tileset * Set
- Cells [][]Cell
- GridW int
- GridH int
- PixelW int
- PixelH int
-
- Blends * al.Bitmap
- Name string
- };
- func (pane * Pane) FirstGID() int {
- if pane.Tileset == nil {
- return 0
- } else {
- return pane.Tileset.FirstGID
- }
- }
- func (pane * Pane) Init(set * Set, gridw, gridh int, name string) (* Pane) {
- pane.Tileset = set
- pane.GridW = gridw
- pane.GridH = gridh
- pane.PixelW = pane.GridW * set.TileW
- pane.PixelH = pane.GridW * set.TileH
- pane.Name = name
- pane.Cells = make([][]Cell, pane.GridH)
- for i := range (pane.Cells) {
- pane.Cells[i] = make([]Cell, pane.GridW)
- }
- return pane
- }
- func NewPane(set * Set, gridw, gridh int, name string) (pane * Pane) {
- pane = &Pane{}
- return pane.Init(set, gridw, gridh, name)
- }
-
- func (pane * Pane) Outside(gridx, gridy int) bool {
- return ((gridx < 0) || (gridy < 0)) ||
- ((gridx >= pane.GridW) || (gridy >= pane.GridH))
- }
- func (pane * Pane) Cell(gridx, gridy int) * Cell {
- if pane.Outside(gridx, gridy) {
- return nil
- }
- return & pane.Cells[gridy][gridx]
- }
- func (pane * Pane) Tile(gridx, gridy int) * Tile {
- if pane.Outside(gridx, gridy) {
- return nil
- }
- return pane.Cells[gridy][gridx].Tile
- }
- func (pane * Pane) Blend(gridx, gridy int) * al.Bitmap {
- if pane.Outside(gridx, gridy) {
- return nil
- }
- return pane.Cells[gridy][gridx].Blend
- }
- func (pane * Pane) SetTile(gridx, gridy int, tile * Tile) * Tile {
- if pane.Outside(gridx, gridy) {
- return nil
- }
- pane.Cells[gridy][gridx].Tile = tile
- return tile
- }
- func (pane * Pane) SetTileIndex(gridx, gridy, index int) * Tile {
- return pane.SetTile(gridx, gridy, pane.Tileset.Tile(index))
- }
- func (pane * Pane) SetBlend(gridx, gridy int, blend * al.Bitmap) * al.Bitmap {
- if pane.Outside(gridx, gridy) {
- return nil
- }
- if nil != pane.Cells[gridy][gridx].Blend {
- pane.Cells[gridy][gridx].Blend.Destroy()
- }
- pane.Cells[gridy][gridx].Blend = blend
- return blend
- }
- func (pane * Pane) SetFlags(gridx, gridy int, flags int) int {
- if pane.Outside(gridx, gridy) {
- return -1
- }
- pane.Cells[gridy][gridx].Flags = flags
- return flags
- }
- func (pane * Pane) SetTileRect(gridx, gridy, gridw, gridh int, tile * Tile) * Tile {
- for jj := gridy ; jj < (gridy + gridh) ; jj++ {
- for ii := gridx ; ii < (gridx + gridh) ; ii++ {
- pane.SetTile(ii, jj, tile)
- }
- }
- return tile
- }
- func (pane * Pane) Fill(tile * Tile) * Tile {
- return pane.SetTileRect(0, 0, pane.GridW, pane.GridH, nil)
- }
- func (cell * Cell) AddShadowPolygon(polygon [8]float32) {
- cell.Shadows = append(cell.Shadows, polygon)
- }
- func (cell * Cell) DeleteShadowPolygons() {
- cell.Shadows = nil
- }
- type DrawIterator func (cell * Cell, x, y float32, tx, ty int)
- func (pane * Pane) DrawIterate(camera * physics.Camera, iter DrawIterator) {
- gridwide := pane.GridW
- gridhigh := pane.GridH
- tilewide := pane.Tileset.TileW
- tilehigh := pane.Tileset.TileH
- x := int(camera.X)
- y := int(camera.Y)
- tx_start := x / tilewide
- ty_start := y / tilehigh
- tx_delta := 1 + (int(camera.W) / tilewide)
- ty_delta := 1 + (int(camera.H) / tilehigh)
- tx_stop := tx_start + tx_delta
- ty_stop := ty_start + ty_delta
- tx_index := 0
- ty_index := 0
-
-
-
- if tx_start < 0 { tx_start = 0; }
- if ty_start < 0 { ty_start = 0; }
- if tx_stop > gridwide { tx_stop = gridwide; }
- if ty_stop > gridhigh { ty_stop = gridhigh; }
- y_draw := float32(-y + (ty_start * tilehigh))
- for ty_index = ty_start; ty_index < ty_stop; ty_index++ {
- y_draw += float32(tilehigh)
- x_draw := float32(-x + (tx_start * tilewide))
- row := pane.Cells[ty_index]
- for tx_index = tx_start ; tx_index < tx_stop; tx_index++ {
- x_draw += float32(tilewide)
- cell := &row[tx_index]
- iter(cell, x_draw, y_draw, tx_index, ty_index)
- }
- }
- }
- func (pane * Pane) DrawTiles(camera * physics.Camera) {
- gridwide := pane.GridW
- gridhigh := pane.GridH
- tilewide := pane.Tileset.TileW
- tilehigh := pane.Tileset.TileH
- x := int(camera.X)
- y := int(camera.Y)
- tx_start := x / tilewide
- ty_start := y / tilehigh
- tx_delta := 1 + (int(camera.W) / tilewide)
- ty_delta := 1 + (int(camera.H) / tilehigh)
- tx_stop := tx_start + tx_delta
- ty_stop := ty_start + ty_delta
- tx_index := 0
- ty_index := 0
-
-
-
- al.HoldBitmapDrawing(true)
- if tx_start < 0 { tx_start = 0; }
- if ty_start < 0 { ty_start = 0; }
- if tx_stop > gridwide { tx_stop = gridwide; }
- if ty_stop > gridhigh { ty_stop = gridhigh; }
- y_draw := float32(-y + (ty_start * tilehigh))
- for ty_index = ty_start; ty_index < ty_stop; ty_index++ {
- y_draw += float32(tilehigh)
- x_draw := float32(-x + (tx_start * tilewide))
- row := pane.Cells[ty_index]
- for tx_index = tx_start ; tx_index < tx_stop; tx_index++ {
- x_draw += float32(tilewide)
- cell := row[tx_index]
- if (cell.Tile != nil) {
- cell.Tile.Draw(x_draw, y_draw, cell.Flags)
- }
- }
- }
-
- al.HoldBitmapDrawing(false)
- }
- func (pane * Pane) DrawBlends(camera * physics.Camera) {
- gridwide := pane.GridW
- gridhigh := pane.GridH
- tilewide := pane.Tileset.TileW
- tilehigh := pane.Tileset.TileH
- x := int(camera.X)
- y := int(camera.Y)
- tx_start := x / tilewide
- ty_start := y / tilehigh
- tx_delta := 1 + (int(camera.W) / tilewide)
- ty_delta := 1 + (int(camera.H) / tilehigh)
- tx_stop := tx_start + tx_delta
- ty_stop := ty_start + ty_delta
- tx_index := 0
- ty_index := 0
-
-
-
-
- if tx_start < 0 { tx_start = 0; }
- if ty_start < 0 { ty_start = 0; }
- if tx_stop > gridwide { tx_stop = gridwide; }
- if ty_stop > gridhigh { ty_stop = gridhigh; }
- y_draw := float32(-y + (ty_start * tilehigh))
- for ty_index = ty_start; ty_index < ty_stop; ty_index++ {
- y_draw += float32(tilehigh)
- x_draw := float32(-x + (tx_start * tilewide))
- row := pane.Cells[ty_index]
- for tx_index = tx_start ; tx_index < tx_stop; tx_index++ {
- x_draw += float32(tilewide)
- cell := row[tx_index]
- if (cell.Blend != nil) {
- cell.Blend.Draw(x_draw, y_draw, cell.Flags)
- }
- }
- }
-
-
- }
- func (pane * Pane) DrawOneShadowOn(cell * Cell, pane_below * Pane,
- tx, ty int, x, y float32) {
- tile := cell.Tile
- if (tile == nil) { return; }
- if (tile.Shadow == 0) { return; }
- shadow_color := al.MapRGBA(0, 0, 0, 128)
- edge_tile := pane.Tile(tx + 1, ty - 1)
- aid_tile := pane.Tile(tx + 1, ty)
- shadow_trapezium := false
- if (edge_tile != nil) && edge_tile.IsWall() {
- shadow_trapezium = true
-
- }
-
-
- tw := float32(pane.Tileset.TileW)
- th := float32(pane.Tileset.TileH)
-
-
-
- if (aid_tile == nil) || !aid_tile.IsWall() {
- low_tile := pane_below.Tile(tx + 1, ty)
- if (low_tile != nil) && (low_tile.ShadowMask != 1) {
- polygon := [8]float32 {
- x + tw , y ,
- x + tw , y + th ,
- x + tw * 1.5 , y + th * 0.5 ,
- x + tw * 1.5 , y - th * 0.5 ,
- }
-
- if (shadow_trapezium) {
- polygon[7] = y
- }
- al.DrawFilledPolygon(polygon[0:8], 0, shadow_color)
- }
- }
-
- aid_tile = pane.Tile(tx, ty-1)
-
-
- if (aid_tile == nil) || !aid_tile.IsWall() {
- low_tile := pane_below.Tile(tx, ty - 1)
- if (low_tile != nil) && (low_tile.ShadowMask != 1) {
- polygon := [8]float32 {
- x + tw , y ,
- x + tw , y ,
- x + tw * 1.5 , y - th * 0.5 ,
- x + tw * 0.5 , y - th * 0.5 ,
- }
-
- if (shadow_trapezium) {
- polygon[4] = x + tw
- }
- al.DrawFilledPolygon(polygon[0:8], 0, shadow_color)
- }
- }
- }
- func (pane * Pane) DrawShadowsOn(pane_below * Pane, camera * physics.Camera) {
- gridwide := pane.GridW
- gridhigh := pane.GridH
- tilewide := pane.Tileset.TileW
- tilehigh := pane.Tileset.TileH
- x := int(camera.X)
- y := int(camera.Y)
- tx_start := x / tilewide
- ty_start := y / tilehigh
- tx_delta := 1 + (int(camera.W) / tilewide)
- ty_delta := 1 + (int(camera.H) / tilehigh)
- tx_stop := tx_start + tx_delta
- ty_stop := ty_start + ty_delta
- tx_index := 0
- ty_index := 0
-
-
-
-
- if tx_start < 0 { tx_start = 0; }
- if ty_start < 0 { ty_start = 0; }
- if tx_stop > gridwide { tx_stop = gridwide; }
- if ty_stop > gridhigh { ty_stop = gridhigh; }
- y_draw := float32(-y + (ty_start * tilehigh))
- for ty_index = ty_start; ty_index < ty_stop; ty_index++ {
- y_draw += float32(tilehigh)
- x_draw := float32(-x + (tx_start * tilewide))
- row := pane.Cells[ty_index]
- for tx_index = tx_start ; tx_index < tx_stop; tx_index++ {
- x_draw += float32(tilewide)
- cell := &row[tx_index]
- pane.DrawOneShadowOn(cell, pane_below, tx_index, ty_index, x_draw, y_draw)
- }
- }
-
-
- }
- func (pane * Pane) Update(dt float64) {
- if pane.Tileset != nil {
- pane.Tileset.Update(dt)
- }
- }
- func (pane * Pane) TileFromSet(index int) * Tile {
- set := pane.Tileset
- if nil == set {
- return nil;
- }
- return set.Tile(index)
- }
- type BlendOffset struct {
- tx int
- ty int
- }
- var BlendOffsets [8]BlendOffset = [8]BlendOffset{
- {-1, -1},
- { 0, -1},
- { 1, -1},
- {-1, 0},
- { 1, 0},
- {-1, 1},
- { 0, 1},
- { 1, 1},
- }
- func (pane * Pane) InitBlendTile(index, tx, ty int, tile * Tile) bool {
-
- pane.SetBlend(tx, ty, nil)
-
- target := al.TargetBitmap()
- tile_prio := tile.Blend
- for i:= 0; i < len(BlendOffsets) ; i++ {
- offset := BlendOffsets[i]
- txn := tx + offset.tx
- tyn := ty + offset.ty
- aid_tile := pane.Tile(txn, tyn)
- if aid_tile == nil { continue; }
- aid_prio := aid_tile.Blend
- if aid_prio <= tile_prio { continue; }
- blend_bmp := al.CreateBitmap(pane.Tileset.TileW, pane.Tileset.TileH )
- if blend_bmp == nil { return false; }
- al.SetTargetBitmap(blend_bmp)
- al.ClearToColor(al.MapRGBA(0,0,0,0))
- PrepareBlend(blend_bmp, tile, aid_tile, i);
- }
-
- al.SetTargetBitmap(target)
- return true
- }
- const (
- MASK_SIDE_W = 16
- MASK_SIDE_H = 16
- MASK_CORNER_W = 16
- MASK_CORNER_H = 16
- MASK_W = 8
- MASK_H = 8
- )
- func InitBlendMasks() {
-
- for blend_type := 0; blend_type < BLEND_TYPE_MAX ; blend_type++ {
- fin1 := fmt.Sprintf("/image/masks/corner_mask_%d.png", blend_type)
- fin2 := fmt.Sprintf("/image/masks/side_mask_%d.png", blend_type)
-
- bmp1 := fifi.LoadBitmap(fin1)
- bmp2 := fifi.LoadBitmap(fin2)
- BlendMasks[blend_type][BLEND_CORNER] = bmp1
- BlendMasks[blend_type][BLEND_SIDE] = bmp2
- if bmp1 == nil {
- monolog.Error("Could not load blend mask %d %d", blend_type, BLEND_CORNER)
- }
- if bmp2 == nil {
- monolog.Error("Could not load blend mask %d %d", blend_type, BLEND_SIDE)
- }
- }
- }
- func (pane * Pane) InitBlend(index int) bool {
- if pane == nil { return false }
- if pane.Blends == nil { return false }
- w := pane.GridW
- h := pane.GridH
- for ty := 0 ; ty < h; ty++ {
- for tx := 0; tx < w; tx++ {
- tile := pane.Tile(tx, ty)
- if tile == nil { continue; }
- if tile.Blend < 1 { continue; }
- monolog.Info("Will it blend? %d %d %d", tx, ty, tile.Blend)
- pane.InitBlendTile(index, tx, ty, tile)
- }
- }
- return true
- }
- func (pane * Pane) Close() {
-
- w := pane.GridW
- h := pane.GridH
- for ty := 0 ; ty < h; ty++ {
- for tx := 0; tx < w; tx++ {
- pane.SetBlend(tx, ty, nil)
- }
- }
-
- if pane.Blends != nil {
- pane.Blends.Destroy()
- pane.Blends = nil
- }
- }
|