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
|
package blocks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
"github.com/hajimehoshi/ebiten"
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||||
"image"
|
|
||||||
"image/color"
|
"image/color"
|
||||||
"math"
|
"math"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var imageFont *ebiten.Image
|
var imageFont *ebiten.Image
|
||||||
@ -41,43 +40,51 @@ func textWidth(str string) int {
|
|||||||
return charWidth * len(str)
|
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 {
|
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{
|
options := &ebiten.DrawImageOptions{
|
||||||
Parts: parts,
|
ImageParts: fontImageParts(str),
|
||||||
}
|
}
|
||||||
options.GeoM.Scale(float64(scale), float64(scale))
|
options.GeoM.Scale(float64(scale), float64(scale))
|
||||||
options.GeoM.Translate(float64(ox), float64(oy))
|
options.GeoM.Translate(float64(ox), float64(oy))
|
||||||
|
|
||||||
c2 := color.NRGBA64Model.Convert(c).(color.NRGBA64)
|
ur, ug, ub, ua := c.RGBA()
|
||||||
const max = math.MaxUint16
|
const max = math.MaxUint16
|
||||||
r := float64(c2.R) / max
|
r := float64(ur) / max
|
||||||
g := float64(c2.G) / max
|
g := float64(ug) / max
|
||||||
b := float64(c2.B) / max
|
b := float64(ub) / max
|
||||||
a := float64(c2.A) / max
|
a := float64(ua) / max
|
||||||
|
if 0 < a {
|
||||||
|
r /= a
|
||||||
|
g /= a
|
||||||
|
b /= a
|
||||||
|
}
|
||||||
options.ColorM.Scale(r, g, b, a)
|
options.ColorM.Scale(r, g, b, a)
|
||||||
|
|
||||||
return rt.DrawImage(imageFont, options)
|
return rt.DrawImage(imageFont, options)
|
||||||
|
@ -17,7 +17,6 @@ package blocks
|
|||||||
import (
|
import (
|
||||||
"github.com/hajimehoshi/ebiten"
|
"github.com/hajimehoshi/ebiten"
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||||
"image"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var imageBlocks *ebiten.Image
|
var imageBlocks *ebiten.Image
|
||||||
@ -143,28 +142,36 @@ const blockHeight = 10
|
|||||||
const fieldBlockNumX = 10
|
const fieldBlockNumX = 10
|
||||||
const fieldBlockNumY = 20
|
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 {
|
func drawBlocks(r *ebiten.Image, blocks [][]BlockType, x, y int, clr ebiten.ColorM) error {
|
||||||
parts := blocksImageParts[:0]
|
op := &ebiten.DrawImageOptions{
|
||||||
for i, blockCol := range blocks {
|
ImageParts: blocksImageParts(blocks),
|
||||||
for j, block := range blockCol {
|
ColorM: clr,
|
||||||
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),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return r.DrawImage(imageBlocks, &ebiten.DrawImageOptions{
|
op.GeoM.Translate(float64(x), float64(y))
|
||||||
Parts: parts,
|
return r.DrawImage(imageBlocks, op)
|
||||||
ColorM: clr,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Piece) InitialPosition() (int, int) {
|
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)
|
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 {
|
func (i *innerImage) drawImage(c *opengl.Context, img *innerImage, options *DrawImageOptions) error {
|
||||||
if options == nil {
|
if options == nil {
|
||||||
options = &DrawImageOptions{}
|
options = &DrawImageOptions{}
|
||||||
}
|
}
|
||||||
parts := options.Parts
|
parts := options.ImageParts
|
||||||
if parts == nil {
|
if parts == nil {
|
||||||
w, h := img.size()
|
dparts := options.Parts
|
||||||
parts = []ImagePart{
|
if dparts != nil {
|
||||||
{
|
parts = imageParts(dparts)
|
||||||
Dst: image.Rect(0, 0, w, h),
|
} else {
|
||||||
Src: image.Rect(0, 0, w, h),
|
w, h := img.size()
|
||||||
},
|
parts = &wholeImage{w, h}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w, h := img.size()
|
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)
|
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 {
|
type textureQuads struct {
|
||||||
parts []ImagePart
|
parts ImageParts
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textureQuads) Len() 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) {
|
func (t *textureQuads) Vertex(i int) (x0, y0, x1, y1 float32) {
|
||||||
p := &t.parts[i]
|
ix0, iy0, ix1, iy1 := t.parts.Dst(i)
|
||||||
dst := &p.Dst
|
return float32(ix0), float32(iy0), float32(ix1), float32(iy1)
|
||||||
return float32(dst.Min.X), float32(dst.Min.Y), float32(dst.Max.X), float32(dst.Max.Y)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textureQuads) Texture(i int) (u0, v0, u1, v1 float32) {
|
func (t *textureQuads) Texture(i int) (u0, v0, u1, v1 float32) {
|
||||||
p := &t.parts[i]
|
x0, y0, x1, y1 := t.parts.Src(i)
|
||||||
src := &p.Src
|
|
||||||
w, h := t.width, t.height
|
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.
|
// Image represents an image.
|
||||||
@ -184,14 +216,25 @@ func (i *Image) At(x, y int) color.Color {
|
|||||||
return color.RGBA{r, g, b, a}
|
return color.RGBA{r, g, b, a}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ImageParts instead.
|
||||||
type ImagePart struct {
|
type ImagePart struct {
|
||||||
Dst image.Rectangle
|
Dst image.Rectangle
|
||||||
Src 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.
|
// A DrawImageOptions represents options to render an image on an image.
|
||||||
type DrawImageOptions struct {
|
type DrawImageOptions struct {
|
||||||
Parts []ImagePart
|
ImageParts ImageParts
|
||||||
GeoM GeoM
|
GeoM GeoM
|
||||||
ColorM ColorM
|
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++ {
|
for i := 0; i < quads.Len(); i++ {
|
||||||
x0, y0, x1, y1 := quads.Vertex(i)
|
x0, y0, x1, y1 := quads.Vertex(i)
|
||||||
u0, v0, u1, v1 := quads.Texture(i)
|
u0, v0, u1, v1 := quads.Texture(i)
|
||||||
|
if x0 == x1 || y0 == y1 || u0 == u1 || v0 == v1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
vertices = append(vertices,
|
vertices = append(vertices,
|
||||||
x0, y0, u0, v0,
|
x0, y0, u0, v0,
|
||||||
x1, y0, u1, v0,
|
x1, y0, u1, v0,
|
||||||
@ -83,7 +86,10 @@ func DrawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4
|
|||||||
x1, y1, u1, v1,
|
x1, y1, u1, v1,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if len(vertices) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
c.BufferSubData(c.ArrayBuffer, vertices)
|
c.BufferSubData(c.ArrayBuffer, vertices)
|
||||||
c.DrawElements(6 * quads.Len())
|
c.DrawElements(6 * len(vertices) / 16)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user