// Copyright 2017 The Ebiten Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //go:build example // +build example package main import ( "fmt" "image" "image/color" "log" "math" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/ebitenutil" ) const ( screenWidth = 640 screenHeight = 480 ) var ( emptyImage = ebiten.NewImage(3, 3) ) func init() { emptyImage.Fill(color.White) } type Game struct { count int } func line(x0, y0, x1, y1 float32, clr color.RGBA) ([]ebiten.Vertex, []uint16) { const width = 1 theta := math.Atan2(float64(y1-y0), float64(x1-x0)) theta += math.Pi / 2 dx := float32(math.Cos(theta)) dy := float32(math.Sin(theta)) r := float32(clr.R) / 0xff g := float32(clr.G) / 0xff b := float32(clr.B) / 0xff a := float32(clr.A) / 0xff return []ebiten.Vertex{ { DstX: x0 - width*dx/2, DstY: y0 - width*dy/2, SrcX: 1, SrcY: 1, ColorR: r, ColorG: g, ColorB: b, ColorA: a, }, { DstX: x0 + width*dx/2, DstY: y0 + width*dy/2, SrcX: 1, SrcY: 1, ColorR: r, ColorG: g, ColorB: b, ColorA: a, }, { DstX: x1 - width*dx/2, DstY: y1 - width*dy/2, SrcX: 1, SrcY: 1, ColorR: r, ColorG: g, ColorB: b, ColorA: a, }, { DstX: x1 + width*dx/2, DstY: y1 + width*dy/2, SrcX: 1, SrcY: 1, ColorR: r, ColorG: g, ColorB: b, ColorA: a, }, }, []uint16{0, 1, 2, 1, 2, 3} } func rect(x, y, w, h float32, clr color.RGBA) ([]ebiten.Vertex, []uint16) { r := float32(clr.R) / 0xff g := float32(clr.G) / 0xff b := float32(clr.B) / 0xff a := float32(clr.A) / 0xff x0 := x y0 := y x1 := x + w y1 := y + h return []ebiten.Vertex{ { DstX: x0, DstY: y0, SrcX: 1, SrcY: 1, ColorR: r, ColorG: g, ColorB: b, ColorA: a, }, { DstX: x1, DstY: y0, SrcX: 1, SrcY: 1, ColorR: r, ColorG: g, ColorB: b, ColorA: a, }, { DstX: x0, DstY: y1, SrcX: 1, SrcY: 1, ColorR: r, ColorG: g, ColorB: b, ColorA: a, }, { DstX: x1, DstY: y1, SrcX: 1, SrcY: 1, ColorR: r, ColorG: g, ColorB: b, ColorA: a, }, }, []uint16{0, 1, 2, 1, 2, 3} } func (g *Game) Update() error { g.count++ g.count %= 240 return nil } func (g *Game) Draw(screen *ebiten.Image) { src := emptyImage.SubImage(image.Rect(1, 1, 2, 2)).(*ebiten.Image) cf := float64(g.count) v, i := line(100, 100, 300, 100, color.RGBA{0xff, 0xff, 0xff, 0xff}) screen.DrawTriangles(v, i, src, nil) v, i = line(50, 150, 50, 350, color.RGBA{0xff, 0xff, 0x00, 0xff}) screen.DrawTriangles(v, i, src, nil) v, i = line(50, 100+float32(cf), 200+float32(cf), 250, color.RGBA{0x00, 0xff, 0xff, 0xff}) screen.DrawTriangles(v, i, src, nil) v, i = rect(50+float32(cf), 50+float32(cf), 100+float32(cf), 100+float32(cf), color.RGBA{0x80, 0x80, 0x80, 0x80}) screen.DrawTriangles(v, i, src, nil) v, i = rect(300-float32(cf), 50, 120, 120, color.RGBA{0x00, 0x80, 0x00, 0x80}) screen.DrawTriangles(v, i, src, nil) ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f", ebiten.ActualTPS())) } func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { return screenWidth, screenHeight } func main() { ebiten.SetWindowSize(screenWidth, screenHeight) ebiten.SetWindowTitle("Shapes (Ebiten Demo)") if err := ebiten.RunGame(&Game{}); err != nil { log.Fatal(err) } }