main.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. // Copyright 2019 The Ebiten Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package main
  15. import (
  16. "fmt"
  17. "image/color"
  18. "log"
  19. "math"
  20. "github.com/hajimehoshi/ebiten/v2"
  21. "github.com/hajimehoshi/ebiten/v2/ebitenutil"
  22. "github.com/hajimehoshi/ebiten/v2/inpututil"
  23. "github.com/hajimehoshi/ebiten/v2/vector"
  24. )
  25. const (
  26. screenWidth = 640
  27. screenHeight = 480
  28. )
  29. type Game struct {
  30. counter int
  31. aa bool
  32. line bool
  33. }
  34. func (g *Game) drawEbitenText(screen *ebiten.Image, x, y int, aa bool, line bool) {
  35. var path vector.Path
  36. // E
  37. path.MoveTo(20, 20)
  38. path.LineTo(20, 70)
  39. path.LineTo(70, 70)
  40. path.LineTo(70, 60)
  41. path.LineTo(30, 60)
  42. path.LineTo(30, 50)
  43. path.LineTo(70, 50)
  44. path.LineTo(70, 40)
  45. path.LineTo(30, 40)
  46. path.LineTo(30, 30)
  47. path.LineTo(70, 30)
  48. path.LineTo(70, 20)
  49. path.Close()
  50. // B
  51. path.MoveTo(80, 20)
  52. path.LineTo(80, 70)
  53. path.LineTo(100, 70)
  54. path.QuadTo(150, 57.5, 100, 45)
  55. path.QuadTo(150, 32.5, 100, 20)
  56. path.Close()
  57. // I
  58. path.MoveTo(140, 20)
  59. path.LineTo(140, 70)
  60. path.LineTo(150, 70)
  61. path.LineTo(150, 20)
  62. path.Close()
  63. // T
  64. path.MoveTo(160, 20)
  65. path.LineTo(160, 30)
  66. path.LineTo(180, 30)
  67. path.LineTo(180, 70)
  68. path.LineTo(190, 70)
  69. path.LineTo(190, 30)
  70. path.LineTo(210, 30)
  71. path.LineTo(210, 20)
  72. path.Close()
  73. // E
  74. path.MoveTo(220, 20)
  75. path.LineTo(220, 70)
  76. path.LineTo(270, 70)
  77. path.LineTo(270, 60)
  78. path.LineTo(230, 60)
  79. path.LineTo(230, 50)
  80. path.LineTo(270, 50)
  81. path.LineTo(270, 40)
  82. path.LineTo(230, 40)
  83. path.LineTo(230, 30)
  84. path.LineTo(270, 30)
  85. path.LineTo(270, 20)
  86. path.Close()
  87. // N
  88. path.MoveTo(280, 20)
  89. path.LineTo(280, 70)
  90. path.LineTo(290, 70)
  91. path.LineTo(290, 35)
  92. path.LineTo(320, 70)
  93. path.LineTo(330, 70)
  94. path.LineTo(330, 20)
  95. path.LineTo(320, 20)
  96. path.LineTo(320, 55)
  97. path.LineTo(290, 20)
  98. path.Close()
  99. if line {
  100. op := &vector.StrokeOptions{}
  101. op.Width = 5
  102. op.LineJoin = vector.LineJoinRound
  103. vector.StrokePath(screen, &path, color.RGBA{0xdb, 0x56, 0x20, 0xff}, aa, op)
  104. } else {
  105. vector.DrawFilledPath(screen, &path, color.RGBA{0xdb, 0x56, 0x20, 0xff}, aa, vector.FillRuleNonZero)
  106. }
  107. }
  108. func (g *Game) drawEbitenLogo(screen *ebiten.Image, x, y int, aa bool, line bool) {
  109. const unit = 16
  110. var path vector.Path
  111. // TODO: Add curves
  112. path.MoveTo(0, 4*unit)
  113. path.LineTo(0, 6*unit)
  114. path.LineTo(2*unit, 6*unit)
  115. path.LineTo(2*unit, 5*unit)
  116. path.LineTo(3*unit, 5*unit)
  117. path.LineTo(3*unit, 4*unit)
  118. path.LineTo(4*unit, 4*unit)
  119. path.LineTo(4*unit, 2*unit)
  120. path.LineTo(6*unit, 2*unit)
  121. path.LineTo(6*unit, 1*unit)
  122. path.LineTo(5*unit, 1*unit)
  123. path.LineTo(5*unit, 0)
  124. path.LineTo(4*unit, 0)
  125. path.LineTo(4*unit, 2*unit)
  126. path.LineTo(2*unit, 2*unit)
  127. path.LineTo(2*unit, 3*unit)
  128. path.LineTo(unit, 3*unit)
  129. path.LineTo(unit, 4*unit)
  130. path.Close()
  131. var geoM ebiten.GeoM
  132. geoM.Translate(float64(x), float64(y))
  133. if line {
  134. op := &vector.StrokeOptions{}
  135. op.Width = 5
  136. op.LineJoin = vector.LineJoinRound
  137. vector.StrokePath(screen, path.ApplyGeoM(geoM), color.RGBA{0xdb, 0x56, 0x20, 0xff}, aa, op)
  138. } else {
  139. vector.DrawFilledPath(screen, path.ApplyGeoM(geoM), color.RGBA{0xdb, 0x56, 0x20, 0xff}, aa, vector.FillRuleNonZero)
  140. }
  141. }
  142. func (g *Game) drawArc(screen *ebiten.Image, count int, aa bool, line bool) {
  143. var path vector.Path
  144. path.MoveTo(350, 100)
  145. const cx, cy, r = 450, 100, 70
  146. theta1 := math.Pi * float64(count) / 180
  147. x := cx + r*math.Cos(theta1)
  148. y := cy + r*math.Sin(theta1)
  149. path.ArcTo(450, 100, float32(x), float32(y), 30)
  150. path.LineTo(float32(x), float32(y))
  151. theta2 := math.Pi * float64(count) / 180 / 3
  152. path.MoveTo(550, 100)
  153. path.Arc(550, 100, 50, float32(theta1), float32(theta2), vector.Clockwise)
  154. path.Close()
  155. if line {
  156. op := &vector.StrokeOptions{}
  157. op.Width = 5
  158. op.LineJoin = vector.LineJoinRound
  159. vector.StrokePath(screen, &path, color.RGBA{0x33, 0xcc, 0x66, 0xff}, aa, op)
  160. } else {
  161. vector.DrawFilledPath(screen, &path, color.RGBA{0x33, 0xcc, 0x66, 0xff}, aa, vector.FillRuleNonZero)
  162. }
  163. }
  164. func maxCounter(index int) int {
  165. return 128 + (17*index+32)%64
  166. }
  167. func (g *Game) drawWave(screen *ebiten.Image, counter int, aa bool, line bool) {
  168. var path vector.Path
  169. const npoints = 8
  170. indexToPoint := func(i int, counter int) (float32, float32) {
  171. x, y := float32(i*screenWidth/(npoints-1)), float32(screenHeight/2)
  172. y += float32(30 * math.Sin(float64(counter)*2*math.Pi/float64(maxCounter(i))))
  173. return x, y
  174. }
  175. for i := 0; i <= npoints; i++ {
  176. if i == 0 {
  177. path.MoveTo(indexToPoint(i, counter))
  178. continue
  179. }
  180. cpx0, cpy0 := indexToPoint(i-1, counter)
  181. x, y := indexToPoint(i, counter)
  182. cpx1, cpy1 := x, y
  183. cpx0 += 30
  184. cpx1 -= 30
  185. path.CubicTo(cpx0, cpy0, cpx1, cpy1, x, y)
  186. }
  187. path.LineTo(screenWidth, screenHeight)
  188. path.LineTo(0, screenHeight)
  189. if line {
  190. op := &vector.StrokeOptions{}
  191. op.Width = 5
  192. op.LineJoin = vector.LineJoinRound
  193. vector.StrokePath(screen, &path, color.RGBA{0x33, 0x66, 0xff, 0xff}, aa, op)
  194. } else {
  195. vector.DrawFilledPath(screen, &path, color.RGBA{0x33, 0x66, 0xff, 0xff}, aa, vector.FillRuleNonZero)
  196. }
  197. }
  198. func (g *Game) Update() error {
  199. g.counter++
  200. // Switch anti-alias.
  201. if inpututil.IsKeyJustPressed(ebiten.KeyA) {
  202. g.aa = !g.aa
  203. }
  204. // Switch lines.
  205. if inpututil.IsKeyJustPressed(ebiten.KeyL) {
  206. g.line = !g.line
  207. }
  208. return nil
  209. }
  210. func (g *Game) Draw(screen *ebiten.Image) {
  211. dst := screen
  212. dst.Fill(color.RGBA{0xe0, 0xe0, 0xe0, 0xff})
  213. g.drawEbitenText(dst, 0, 50, g.aa, g.line)
  214. g.drawEbitenLogo(dst, 20, 150, g.aa, g.line)
  215. g.drawArc(dst, g.counter, g.aa, g.line)
  216. g.drawWave(dst, g.counter, g.aa, g.line)
  217. msg := fmt.Sprintf("TPS: %0.2f\nFPS: %0.2f", ebiten.ActualTPS(), ebiten.ActualFPS())
  218. msg += "\nPress A to switch anti-alias."
  219. msg += "\nPress L to switch the fill mode and the line mode."
  220. ebitenutil.DebugPrint(screen, msg)
  221. }
  222. func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
  223. return screenWidth, screenHeight
  224. }
  225. func main() {
  226. g := &Game{counter: 0}
  227. ebiten.SetWindowSize(screenWidth, screenHeight)
  228. ebiten.SetWindowTitle("Vector (Ebitengine Demo)")
  229. if err := ebiten.RunGame(g); err != nil {
  230. log.Fatal(err)
  231. }
  232. }