├── LICENSE └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | This repository is licensed under: 2 | 3 | CC0 1.0 Universal 4 | https://creativecommons.org/publicdomain/zero/1.0 5 | 6 | The repository logo was made by Artem Sedykh (https://github.com/sedyh). 7 | The Ebitengine logo image was modified with Hajime Hoshi permission (https://github.com/hajimehoshi). 8 | The derivative work is licensed under: 9 | 10 | Creative Commons Attribution 3.0 Unported 11 | https://creativecommons.org/licenses/by/3.0/ 12 | 13 | The Ebitengine logo is made by Hajime Hoshi (https://github.com/hajimehoshi) and licensed under: 14 | 15 | Creative Commons Attribution-NoDerivatives 4.0 International 16 | https://creativecommons.org/licenses/by-nd/4.0/ 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ebiten-cheatsheet Ebitengine Cheatsheet 2 | 3 | Useful tips and snippets for Ebitengine. 4 | 5 | ### Contents 6 | 7 | - [Relative crop](#relative-crop) 8 | - [Center text](#center-text) 9 | - [Flip Image](#flip-image) 10 | - [Quick start](#quick-start) 11 | 12 | ### Relative Crop 13 | 14 | back 15 | *If you try to make a sub image from another sub image, you may run into unusual behavior due to the fact that absolute coordinates are used for each crop, instead you can use this function so as not to constantly remember this nuance.* 16 | 17 | ```go 18 | func RelativeCrop(source *ebiten.Image, r image.Rectangle) *ebiten.Image { 19 | rx, ry := source.Bounds().Min.X+r.Min.X, source.Bounds().Min.Y+r.Min.Y 20 | return source.SubImage(image.Rect(rx, ry, rx+r.Max.X, ry+r.Max.Y)).(*ebiten.Image) 21 | } 22 | ``` 23 | 24 | ### Center text 25 | back 26 | *Text bounds behave differently than image bounds. To calculate center point you will need to subtract the minimum point and add half the size.* 27 | ```go 28 | func DrawCenteredText(screen *ebiten.Image, font font.Face, s string, cx, cy int) { 29 | bounds := text.BoundString(font, s) 30 | x, y := cx-bounds.Min.X-bounds.Dx()/2, cy-bounds.Min.Y-bounds.Dy()/2 31 | text.Draw(screen, s, font, x, y, colornames.Red) 32 | } 33 | ``` 34 | 35 | 36 | ### Flip Image 37 | back 38 | *Scale the image in the opposite direction by its size, and then move it into place.* 39 | ```go 40 | func FlipHorizontal(source *ebiten.Image) *ebiten.Image { 41 | result := ebiten.NewImage(source.Size()) 42 | op := &ebiten.DrawImageOptions{} 43 | op.GeoM.Scale(-1, 1) 44 | op.GeoM.Translate(float64(img.Bounds().Dx()), 0) 45 | return result.DrawImage(source, op) 46 | } 47 | 48 | func FlipVertical(source *ebiten.Image) *ebiten.Image { 49 | result := ebiten.NewImage(source.Size()) 50 | op := &ebiten.DrawImageOptions{} 51 | op.GeoM.Scale(1, -1) 52 | op.GeoM.Translate(0, float64(img.Bounds().Dy())) 53 | return result.DrawImage(source, op) 54 | } 55 | ``` 56 | 57 | ### Quick start 58 | back 59 | *Minimal game, vsync and resize are usually always helpful when debugging.* 60 | 61 | ```go 62 | func main() { 63 | ebiten.SetVsyncEnabled(true) 64 | ebiten.SetWindowResizingMode(ebiten.WindowResizingModeEnabled) 65 | if err := ebiten.RunGame(NewGame()); err != nil { 66 | log.Fatal(err) 67 | } 68 | } 69 | 70 | type Game struct{} 71 | 72 | func NewGame() *Game { 73 | return &Game{} 74 | } 75 | 76 | func (g *Game) Update() error { 77 | return nil 78 | } 79 | 80 | func (g *Game) Draw(screen *ebiten.Image) { 81 | screen.Fill(colornames.White) 82 | } 83 | 84 | func (g *Game) Layout(w, h int) (int, int) { 85 | return w, h 86 | } 87 | ``` 88 | --------------------------------------------------------------------------------