Last active
June 21, 2023 07:49
-
-
Save Zyko0/185f7b625a46cfc4c1df34efad29a6fa to your computer and use it in GitHub Desktop.
Ebiten: apparent seams when drawing tiles with DrawTriangles
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"errors" | |
"fmt" | |
"image" | |
"image/color" | |
"log" | |
"github.com/hajimehoshi/ebiten/v2" | |
"github.com/hajimehoshi/ebiten/v2/ebitenutil" | |
) | |
const ( | |
MouseSensitivity = 0.32109 | |
ScreenWidth, ScreenHeight = 1920, 1080 | |
SrcTileSize = 512 | |
SrcSheetCols = 5 | |
SrcSheetRows = 2 | |
DstTileCols = 17 | |
DstTileRows = 17 | |
DstTileSize = ScreenWidth / DstTileCols | |
DstTileScale = float64(DstTileSize) / SrcTileSize | |
) | |
var ( | |
sheetImage = ebiten.NewImage(SrcSheetCols*SrcTileSize, SrcSheetCols*SrcTileSize) | |
quadIndices = [6]uint16{0, 1, 2, 1, 2, 3} | |
) | |
func init() { | |
// Drawing sheet | |
sheetImage.Fill(color.RGBA{128, 0, 128, 255}) | |
// Y = 0 | |
sheetImage.SubImage(image.Rect(0, 0, SrcTileSize, SrcTileSize)).(*ebiten.Image).Fill(color.RGBA{196, 0, 0, 255}) | |
sheetImage.SubImage(image.Rect(SrcTileSize*1, 0, SrcTileSize*2, SrcTileSize)).(*ebiten.Image).Fill(color.RGBA{0, 196, 0, 255}) | |
sheetImage.SubImage(image.Rect(SrcTileSize*2, 0, SrcTileSize*3, SrcTileSize)).(*ebiten.Image).Fill(color.RGBA{0, 0, 196, 255}) | |
sheetImage.SubImage(image.Rect(SrcTileSize*3, 0, SrcTileSize*4, SrcTileSize)).(*ebiten.Image).Fill(color.RGBA{196, 64, 0, 255}) | |
sheetImage.SubImage(image.Rect(SrcTileSize*4, 0, SrcTileSize*5, SrcTileSize)).(*ebiten.Image).Fill(color.RGBA{196, 0, 64, 255}) | |
// Y = 1 | |
sheetImage.SubImage(image.Rect(0, SrcTileSize, SrcTileSize, SrcTileSize*2)).(*ebiten.Image).Fill(color.RGBA{64, 196, 0, 255}) | |
sheetImage.SubImage(image.Rect(SrcTileSize*1, SrcTileSize, SrcTileSize*2, SrcTileSize*2)).(*ebiten.Image).Fill(color.RGBA{0, 196, 64, 255}) | |
sheetImage.SubImage(image.Rect(SrcTileSize*2, SrcTileSize, SrcTileSize*3, SrcTileSize*2)).(*ebiten.Image).Fill(color.RGBA{64, 0, 196, 255}) | |
sheetImage.SubImage(image.Rect(SrcTileSize*3, SrcTileSize, SrcTileSize*4, SrcTileSize*2)).(*ebiten.Image).Fill(color.RGBA{0, 64, 196, 255}) | |
sheetImage.SubImage(image.Rect(SrcTileSize*4, SrcTileSize, SrcTileSize*5, SrcTileSize*2)).(*ebiten.Image).Fill(color.RGBA{64, 64, 255, 255}) | |
} | |
const ( | |
ModeDrawTriangles = false | |
ModeDrawImage = true | |
) | |
type Game struct { | |
mouseX int | |
mouseY int | |
offsetX float64 | |
offsetY float64 | |
mode bool | |
} | |
func (g *Game) Update() error { | |
if ebiten.IsKeyPressed(ebiten.KeyEscape) { | |
return errors.New("quit") | |
} | |
// Reset to problematic offset (debug purposes) | |
// Mine for example: (-68.71326, 712.49871) | |
// Another one (-818.45, -406.499) | |
// It seems Y needs to end with .499 for black bars to show | |
if ebiten.IsKeyPressed(ebiten.KeyR) { | |
g.offsetX = -68.71326 | |
g.offsetY = 712.499 | |
} | |
x, y := ebiten.CursorPosition() | |
dx, dy := x-g.mouseX, y-g.mouseY | |
g.mouseX, g.mouseY = x, y | |
g.offsetX += float64(dx) * MouseSensitivity | |
g.offsetY += float64(dy) * MouseSensitivity | |
g.mode = ebiten.IsKeyPressed(ebiten.KeySpace) | |
return nil | |
} | |
func (g *Game) Draw(screen *ebiten.Image) { | |
index := 0 | |
for x := 0; x < DstTileCols; x++ { | |
for y := 0; y < DstTileRows; y++ { | |
srcx := (x % SrcSheetCols) * SrcTileSize | |
srcy := (y % SrcSheetRows) * SrcTileSize | |
dstx := float64(x*DstTileSize) - g.offsetX | |
dsty := float64(y*DstTileSize) - g.offsetY | |
switch g.mode { | |
case ModeDrawTriangles: | |
vertices := []ebiten.Vertex{} | |
indices := []uint16{} | |
vertices = append(vertices, []ebiten.Vertex{ | |
{ | |
DstX: float32(dstx), | |
DstY: float32(dsty), | |
SrcX: float32(srcx), | |
SrcY: float32(srcy), | |
ColorR: 1, | |
ColorG: 1, | |
ColorB: 1, | |
ColorA: 1, | |
}, | |
{ | |
DstX: float32(dstx + DstTileSize), | |
DstY: float32(dsty), | |
SrcX: float32(srcx + SrcTileSize), | |
SrcY: float32(srcy), | |
ColorR: 1, | |
ColorG: 1, | |
ColorB: 1, | |
ColorA: 1, | |
}, | |
{ | |
DstX: float32(dstx), | |
DstY: float32(dsty + DstTileSize), | |
SrcX: float32(srcx), | |
SrcY: float32(srcy + SrcTileSize), | |
ColorR: 1, | |
ColorG: 1, | |
ColorB: 1, | |
ColorA: 1, | |
}, | |
{ | |
DstX: float32(dstx + DstTileSize), | |
DstY: float32(dsty + DstTileSize), | |
SrcX: float32(srcx + SrcTileSize), | |
SrcY: float32(srcy + SrcTileSize), | |
ColorR: 1, | |
ColorG: 1, | |
ColorB: 1, | |
ColorA: 1, | |
}, | |
}...) | |
indiceCursor := uint16(index * 4) | |
indices = append(indices, []uint16{ | |
quadIndices[0] + indiceCursor, | |
quadIndices[1] + indiceCursor, | |
quadIndices[2] + indiceCursor, | |
quadIndices[3] + indiceCursor, | |
quadIndices[4] + indiceCursor, | |
quadIndices[5] + indiceCursor, | |
}...) | |
screen.DrawTriangles(vertices, indices, sheetImage, &ebiten.DrawTrianglesOptions{}) | |
case ModeDrawImage: | |
opts := &ebiten.DrawImageOptions{} | |
opts.GeoM.Scale(DstTileScale, DstTileScale) | |
opts.GeoM.Translate(dstx, dsty) | |
screen.DrawImage( | |
sheetImage.SubImage(image.Rect(srcx, srcy, srcx+SrcTileSize, srcy+SrcTileSize)).(*ebiten.Image), opts, | |
) | |
} | |
} | |
} | |
debug := "Mode (Press 'space' to switch): DrawTriangles" | |
if g.mode == ModeDrawImage { | |
debug = "Move: DrawImage" | |
} | |
debug += fmt.Sprintf(" Offset (%.5f, %.5f) - Reset to the fixed one (Press 'R')", g.offsetX, g.offsetY) | |
ebitenutil.DebugPrint(screen, debug) | |
} | |
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { | |
return ScreenWidth, ScreenHeight | |
} | |
func main() { | |
ebiten.SetFullscreen(true) | |
ebiten.SetVsyncEnabled(true) | |
ebiten.SetCursorMode(ebiten.CursorModeCaptured) | |
// Below is black borders test | |
// broken: 1c09ec5e44727a0c38b605552d93e4d470a128ab | |
// perfect: 7c0fbce0cfd887a81c4f5a57757d6b804da803b5 | |
if err := ebiten.RunGame(&Game{ | |
mouseX: ScreenWidth / 2, | |
mouseY: ScreenHeight / 2, | |
}); err != nil { | |
log.Fatal(err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment