mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
Introduce ImageParts
This commit is contained in:
parent
8994ffad9b
commit
cdc29210db
@ -15,12 +15,11 @@
|
||||
package blocks
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||
"image"
|
||||
"image/color"
|
||||
"math"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var imageFont *ebiten.Image
|
||||
@ -41,43 +40,51 @@ func textWidth(str string) int {
|
||||
return charWidth * len(str)
|
||||
}
|
||||
|
||||
var fontImageParts = make([]ebiten.ImagePart, 0, 256)
|
||||
type fontImageParts string
|
||||
|
||||
func (f fontImageParts) Len() int {
|
||||
return len(f)
|
||||
}
|
||||
|
||||
func (f fontImageParts) Dst(i int) (x0, y0, x1, y1 int) {
|
||||
x := i - strings.LastIndex(string(f)[:i], "\n") - 1
|
||||
y := strings.Count(string(f)[:i], "\n")
|
||||
x *= charWidth
|
||||
y *= charHeight
|
||||
if x < 0 {
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
return x, y, x + charWidth, y + charHeight
|
||||
}
|
||||
|
||||
func (f fontImageParts) Src(i int) (x0, y0, x1, y1 int) {
|
||||
code := int(f[i])
|
||||
if code == '\n' {
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
x := (code % 16) * charWidth
|
||||
y := ((code - 32) / 16) * charHeight
|
||||
return x, y, x + charWidth, y + charHeight
|
||||
}
|
||||
|
||||
func drawText(rt *ebiten.Image, str string, ox, oy, scale int, c color.Color) error {
|
||||
if cap(fontImageParts) < len(str) {
|
||||
return errors.New("str is too long")
|
||||
}
|
||||
parts := fontImageParts[:0]
|
||||
|
||||
locationX, locationY := 0, 0
|
||||
for _, c := range str {
|
||||
if c == '\n' {
|
||||
locationX = 0
|
||||
locationY += charHeight
|
||||
continue
|
||||
}
|
||||
code := int(c)
|
||||
x := (code % 16) * charWidth
|
||||
y := ((code - 32) / 16) * charHeight
|
||||
parts = append(parts, ebiten.ImagePart{
|
||||
Dst: image.Rect(locationX, locationY, locationX+charWidth, locationY+charHeight),
|
||||
Src: image.Rect(x, y, x+charWidth, y+charHeight),
|
||||
})
|
||||
locationX += charWidth
|
||||
}
|
||||
|
||||
options := &ebiten.DrawImageOptions{
|
||||
Parts: parts,
|
||||
ImageParts: fontImageParts(str),
|
||||
}
|
||||
options.GeoM.Scale(float64(scale), float64(scale))
|
||||
options.GeoM.Translate(float64(ox), float64(oy))
|
||||
|
||||
c2 := color.NRGBA64Model.Convert(c).(color.NRGBA64)
|
||||
ur, ug, ub, ua := c.RGBA()
|
||||
const max = math.MaxUint16
|
||||
r := float64(c2.R) / max
|
||||
g := float64(c2.G) / max
|
||||
b := float64(c2.B) / max
|
||||
a := float64(c2.A) / max
|
||||
r := float64(ur) / max
|
||||
g := float64(ug) / max
|
||||
b := float64(ub) / max
|
||||
a := float64(ua) / max
|
||||
if 0 < a {
|
||||
r /= a
|
||||
g /= a
|
||||
b /= a
|
||||
}
|
||||
options.ColorM.Scale(r, g, b, a)
|
||||
|
||||
return rt.DrawImage(imageFont, options)
|
||||
|
@ -17,7 +17,6 @@ package blocks
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||
"image"
|
||||
)
|
||||
|
||||
var imageBlocks *ebiten.Image
|
||||
@ -143,28 +142,36 @@ const blockHeight = 10
|
||||
const fieldBlockNumX = 10
|
||||
const fieldBlockNumY = 20
|
||||
|
||||
var blocksImageParts = make([]ebiten.ImagePart, 0, fieldBlockNumX*fieldBlockNumY)
|
||||
type blocksImageParts [][]BlockType
|
||||
|
||||
func (b blocksImageParts) Len() int {
|
||||
return len(b) * len(b[0])
|
||||
}
|
||||
|
||||
func (b blocksImageParts) Dst(i int) (x0, y0, x1, y1 int) {
|
||||
i, j := i%len(b), i/len(b)
|
||||
x := i * blockWidth
|
||||
y := j * blockHeight
|
||||
return x, y, x + blockWidth, y + blockHeight
|
||||
}
|
||||
|
||||
func (b blocksImageParts) Src(i int) (x0, y0, x1, y1 int) {
|
||||
i, j := i%len(b), i/len(b)
|
||||
block := b[i][j]
|
||||
if block == BlockTypeNone {
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
x := (int(block) - 1) * blockWidth
|
||||
return x, 0, x + blockWidth, blockHeight
|
||||
}
|
||||
|
||||
func drawBlocks(r *ebiten.Image, blocks [][]BlockType, x, y int, clr ebiten.ColorM) error {
|
||||
parts := blocksImageParts[:0]
|
||||
for i, blockCol := range blocks {
|
||||
for j, block := range blockCol {
|
||||
if block == BlockTypeNone {
|
||||
continue
|
||||
}
|
||||
locationX := i*blockWidth + x
|
||||
locationY := j*blockHeight + y
|
||||
srcX := (int(block) - 1) * blockWidth
|
||||
parts = append(parts, ebiten.ImagePart{
|
||||
Dst: image.Rect(locationX, locationY, locationX+blockWidth, locationY+blockHeight),
|
||||
Src: image.Rect(srcX, 0, srcX+blockWidth, blockHeight),
|
||||
})
|
||||
}
|
||||
op := &ebiten.DrawImageOptions{
|
||||
ImageParts: blocksImageParts(blocks),
|
||||
ColorM: clr,
|
||||
}
|
||||
return r.DrawImage(imageBlocks, &ebiten.DrawImageOptions{
|
||||
Parts: parts,
|
||||
ColorM: clr,
|
||||
})
|
||||
op.GeoM.Translate(float64(x), float64(y))
|
||||
return r.DrawImage(imageBlocks, op)
|
||||
}
|
||||
|
||||
func (p *Piece) InitialPosition() (int, int) {
|
||||
|
81
image.go
81
image.go
@ -49,22 +49,56 @@ func (i *innerImage) Fill(c *opengl.Context, clr color.Color) error {
|
||||
return i.framebuffer.Fill(c, r, g, b, a)
|
||||
}
|
||||
|
||||
// TODO: Remove this in the future.
|
||||
type imageParts []ImagePart
|
||||
|
||||
func (p imageParts) Len() int {
|
||||
return len(p)
|
||||
}
|
||||
|
||||
func (p imageParts) Dst(i int) (x0, y0, x1, y1 int) {
|
||||
dst := &p[i].Dst
|
||||
return dst.Min.X, dst.Min.Y, dst.Max.X, dst.Max.Y
|
||||
}
|
||||
|
||||
func (p imageParts) Src(i int) (x0, y0, x1, y1 int) {
|
||||
src := &p[i].Src
|
||||
return src.Min.X, src.Min.Y, src.Max.X, src.Max.Y
|
||||
}
|
||||
|
||||
type wholeImage struct {
|
||||
width int
|
||||
height int
|
||||
}
|
||||
|
||||
func (w *wholeImage) Len() int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (w *wholeImage) Dst(i int) (x0, y0, x1, y1 int) {
|
||||
return 0, 0, w.width, w.height
|
||||
}
|
||||
|
||||
func (w *wholeImage) Src(i int) (x0, y0, x1, y1 int) {
|
||||
return 0, 0, w.width, w.height
|
||||
}
|
||||
|
||||
func (i *innerImage) drawImage(c *opengl.Context, img *innerImage, options *DrawImageOptions) error {
|
||||
if options == nil {
|
||||
options = &DrawImageOptions{}
|
||||
}
|
||||
parts := options.Parts
|
||||
parts := options.ImageParts
|
||||
if parts == nil {
|
||||
w, h := img.size()
|
||||
parts = []ImagePart{
|
||||
{
|
||||
Dst: image.Rect(0, 0, w, h),
|
||||
Src: image.Rect(0, 0, w, h),
|
||||
},
|
||||
dparts := options.Parts
|
||||
if dparts != nil {
|
||||
parts = imageParts(dparts)
|
||||
} else {
|
||||
w, h := img.size()
|
||||
parts = &wholeImage{w, h}
|
||||
}
|
||||
}
|
||||
w, h := img.size()
|
||||
quads := &textureQuads{parts, w, h}
|
||||
quads := &textureQuads{parts: parts, width: w, height: h}
|
||||
return i.framebuffer.DrawTexture(c, img.texture, quads, &options.GeoM, &options.ColorM)
|
||||
}
|
||||
|
||||
@ -77,26 +111,24 @@ func v(y float32, height int) float32 {
|
||||
}
|
||||
|
||||
type textureQuads struct {
|
||||
parts []ImagePart
|
||||
parts ImageParts
|
||||
width int
|
||||
height int
|
||||
}
|
||||
|
||||
func (t *textureQuads) Len() int {
|
||||
return len(t.parts)
|
||||
return t.parts.Len()
|
||||
}
|
||||
|
||||
func (t *textureQuads) Vertex(i int) (x0, y0, x1, y1 float32) {
|
||||
p := &t.parts[i]
|
||||
dst := &p.Dst
|
||||
return float32(dst.Min.X), float32(dst.Min.Y), float32(dst.Max.X), float32(dst.Max.Y)
|
||||
ix0, iy0, ix1, iy1 := t.parts.Dst(i)
|
||||
return float32(ix0), float32(iy0), float32(ix1), float32(iy1)
|
||||
}
|
||||
|
||||
func (t *textureQuads) Texture(i int) (u0, v0, u1, v1 float32) {
|
||||
p := &t.parts[i]
|
||||
src := &p.Src
|
||||
x0, y0, x1, y1 := t.parts.Src(i)
|
||||
w, h := t.width, t.height
|
||||
return u(float32(src.Min.X), w), v(float32(src.Min.Y), h), u(float32(src.Max.X), w), v(float32(src.Max.Y), h)
|
||||
return u(float32(x0), w), v(float32(y0), h), u(float32(x1), w), v(float32(y1), h)
|
||||
}
|
||||
|
||||
// Image represents an image.
|
||||
@ -184,14 +216,25 @@ func (i *Image) At(x, y int) color.Color {
|
||||
return color.RGBA{r, g, b, a}
|
||||
}
|
||||
|
||||
// Deprecated: Use ImageParts instead.
|
||||
type ImagePart struct {
|
||||
Dst image.Rectangle
|
||||
Src image.Rectangle
|
||||
}
|
||||
|
||||
// An ImageParts represents the parts of the destination image and the parts of the source image.
|
||||
type ImageParts interface {
|
||||
Len() int
|
||||
Dst(i int) (x0, y0, x1, y1 int)
|
||||
Src(i int) (x0, y0, x1, y1 int)
|
||||
}
|
||||
|
||||
// A DrawImageOptions represents options to render an image on an image.
|
||||
type DrawImageOptions struct {
|
||||
Parts []ImagePart
|
||||
GeoM GeoM
|
||||
ColorM ColorM
|
||||
ImageParts ImageParts
|
||||
GeoM GeoM
|
||||
ColorM ColorM
|
||||
|
||||
// Deprecated: Use ImageParts instead.
|
||||
Parts []ImagePart
|
||||
}
|
||||
|
@ -76,6 +76,9 @@ func DrawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4
|
||||
for i := 0; i < quads.Len(); i++ {
|
||||
x0, y0, x1, y1 := quads.Vertex(i)
|
||||
u0, v0, u1, v1 := quads.Texture(i)
|
||||
if x0 == x1 || y0 == y1 || u0 == u1 || v0 == v1 {
|
||||
continue
|
||||
}
|
||||
vertices = append(vertices,
|
||||
x0, y0, u0, v0,
|
||||
x1, y0, u1, v0,
|
||||
@ -83,7 +86,10 @@ func DrawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4
|
||||
x1, y1, u1, v1,
|
||||
)
|
||||
}
|
||||
if len(vertices) == 0 {
|
||||
return nil
|
||||
}
|
||||
c.BufferSubData(c.ArrayBuffer, vertices)
|
||||
c.DrawElements(6 * quads.Len())
|
||||
c.DrawElements(6 * len(vertices) / 16)
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user