123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- // Copyright 2022 The Ebitengine 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.
- package main
- import (
- "fmt"
- "image"
- "image/color"
- "log"
- "math"
- "github.com/hajimehoshi/ebiten/v2"
- "github.com/hajimehoshi/ebiten/v2/ebitenutil"
- "github.com/hajimehoshi/ebiten/v2/inpututil"
- "github.com/hajimehoshi/ebiten/v2/vector"
- )
- const (
- screenWidth = 640
- screenHeight = 480
- )
- type Game struct {
- counter int
- aa bool
- showCenter bool
- }
- func (g *Game) Update() error {
- g.counter++
- if inpututil.IsKeyJustPressed(ebiten.KeyA) {
- g.aa = !g.aa
- }
- if inpututil.IsKeyJustPressed(ebiten.KeyC) {
- g.showCenter = !g.showCenter
- }
- return nil
- }
- func (g *Game) Draw(screen *ebiten.Image) {
- target := screen
- joins := []vector.LineJoin{
- vector.LineJoinMiter,
- vector.LineJoinMiter,
- vector.LineJoinBevel,
- vector.LineJoinRound,
- }
- caps := []vector.LineCap{
- vector.LineCapButt,
- vector.LineCapRound,
- vector.LineCapSquare,
- }
- ow, oh := target.Bounds().Dx(), target.Bounds().Dy()
- size := min(ow/(len(joins)+1), oh/(len(caps)+1))
- offsetX, offsetY := (ow-size*len(joins))/2, (oh-size*len(caps))/2
- // Render the lines on the target.
- for j, cap := range caps {
- for i, join := range joins {
- r := image.Rect(i*size+offsetX, j*size+offsetY, (i+1)*size+offsetX, (j+1)*size+offsetY)
- miterLimit := float32(5)
- if i == 1 {
- miterLimit = 10
- }
- g.drawLine(target, r, cap, join, miterLimit)
- }
- }
- msg := fmt.Sprintf(`FPS: %0.2f, TPS: %0.2f
- Press A to switch anti-aliasing.
- Press C to switch to draw the center lines.`, ebiten.ActualFPS(), ebiten.ActualTPS())
- ebitenutil.DebugPrint(screen, msg)
- }
- func (g *Game) drawLine(screen *ebiten.Image, region image.Rectangle, cap vector.LineCap, join vector.LineJoin, miterLimit float32) {
- c0x := float64(region.Min.X + region.Dx()/4)
- c0y := float64(region.Min.Y + region.Dy()/4)
- c1x := float64(region.Max.X - region.Dx()/4)
- c1y := float64(region.Max.Y - region.Dy()/4)
- r := float64(min(region.Dx(), region.Dy()) / 4)
- a0 := 2 * math.Pi * float64(g.counter) / (16 * ebiten.DefaultTPS)
- a1 := 2 * math.Pi * float64(g.counter) / (9 * ebiten.DefaultTPS)
- var path vector.Path
- sin0, cos0 := math.Sincos(a0)
- sin1, cos1 := math.Sincos(a1)
- path.MoveTo(float32(r*cos0+c0x), float32(r*sin0+c0y))
- path.LineTo(float32(-r*cos0+c0x), float32(-r*sin0+c0y))
- path.LineTo(float32(r*cos1+c1x), float32(r*sin1+c1y))
- path.LineTo(float32(-r*cos1+c1x), float32(-r*sin1+c1y))
- // Draw the main line in white.
- op := &vector.StrokeOptions{}
- op.LineCap = cap
- op.LineJoin = join
- op.MiterLimit = miterLimit
- op.Width = float32(r / 2)
- vector.StrokePath(screen, &path, color.White, g.aa, op)
- // Draw the center line in red.
- if g.showCenter {
- op.Width = 1
- vector.StrokePath(screen, &path, color.RGBA{0xff, 0, 0, 0xff}, g.aa, op)
- }
- }
- func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
- return screenWidth, screenHeight
- }
- func main() {
- var g Game
- ebiten.SetWindowSize(screenWidth, screenHeight)
- ebiten.SetWindowTitle("Lines (Ebitengine Demo)")
- if err := ebiten.RunGame(&g); err != nil {
- log.Fatal(err)
- }
- }
|