├── .gitignore ├── README.md ├── bindata.go ├── canvas └── canvas.go ├── images ├── ball1.png ├── ball2.png ├── ball3.png ├── chars.html ├── chars.png ├── pokemon │ ├── .gitkeep │ ├── bulbasaur.png │ ├── charmander.png │ ├── gopher.png │ ├── pikachu.png │ └── squirtle.png └── smoke.png └── pokemon.go /.gitignore: -------------------------------------------------------------------------------- 1 | images/pokemon/*.png 2 | pokemon.txt 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pokemon-Go 2 | 3 | ## Pokemons are hiding in your local directory 4 | ``` 5 | $ go build -o pokemongo pokemon.go; cd somewhere; path/to/pokemongo 6 | MQBTm uuuu 7 | .,,. ,. ... MY111 ,,@TmdddB 8 | gMTTT pT**" T* *TM1 m11j7*~~~:?V::TTMQQQT , 9 | gM gpTpu ggMggM. ,gMgga -jg; Q1 gpMQg----(gg(:]ugMT gQ#pQ, 10 | QQ ug uMgggM M"~M 41 M Q1 Q1 uMQMgMa]::TMQT::M Q1 ,M#:::M( 11 | "M, M *Q M ~Q 41 M` Q1 Q1 *QVTV:au]::::(ruvQQ1 ,V:Mp::(M! 12 | ^TTVT *TTTT T `* *" T` *TT' *TT" MM##TY11YBM1YbY1M*MTv((:TTTT?: 13 | *g1111111111111M 111111((:gTT 14 | M!!111111111!!:M*"a11""TT 15 | ,. #::::!!!j?!::::M g81m 16 | T* M:;QB:::u?:::(:::,#cj1aQ 17 | -jg; ggMggM. ggvog ggvjg gpTpu gET5; MmM??u::]:::u::(1MpyMg 18 | Q1 M"~M 41 g# M aM M uMgggM Mgg, MaMVuV:::TuyV::(11MgMdd 19 | Q1 M ~Q 41 Mg gM Qp gM *Q *TM p#(((:::::(((!!(111MT 20 | *TT' T `* *" `TTT'T `TTT~M *TTTT "TTTT* gM11111111111111111Q 21 | Tggg#* .MTjap*TTT*"""111y 22 | TTT* TgQg 23 | ... ,. .. 24 | *TM1 T* 4A Q* 25 | Q1 -jg; 4QgDQg ,M" 26 | Q1 Q1 4Q` M ,M` 27 | Q1 Q1 4G gM gT 28 | *TT" *TT' *TTTT gT 29 | ``` 30 | 31 | ## Go! Catch them! 32 | ``` 33 | ,!, 34 | |:!, 35 | |:::/ 36 | ~~~`- ```` 37 | -````~ `````````~ 38 | '.```~.. ````` `` ````` 39 | '.``` ````` 40 | ~ ````` `~`` ` 41 | -.`` ` ~.``` ` .... 42 | ~~~ ``` ```` .ubbbbbbbbb;. 43 | -.` .~~``..` .``` `.bbbbbbbbbbbbbbb. 44 | -~``````````````~~.` ;bbbbbbbbbbbbbbbbb, 45 | '~```````````````````kbbbbbbbbbbbbbbbbbb ` 46 | :..`````````````` `:?bbbbbbbbbbbbbbbbb 47 | ;`````````` `--:76bbbbbbbbbbbbY7 48 | |````````` `------+777777/---` 49 | ,```~```` ` `` ~---------------` 50 | o..``--`` -````...```-:~---------'' 51 | dr~~.~~.``:.``..-~~...~~:-~~:''`` 52 | d-~|~:|:````|`::|~~~~----{ ]::; 53 | ,,<-~~~~~`````.~~~~~-~-----vv|ii" 54 | dd::---~~..`..~----~-~------c* 55 | g;::-::::--------------::j 56 | ``` 57 | 58 | ``` 59 | $ cat pokemon.txt 60 | 61 | ,,,,{J???7vJvJ1],,,,;]<7?u(, 62 | ,w6Y7:----------!|JbbbJ::;-!bj 63 | .,Lb+-----------;])*""*7kyapQ-:bc 64 | ,57/------------o*` ,,vj7-:b~ 65 | ;kY--------------:/ .yMMQQAux" 66 | ,sY+--:;:-''~-;(:--o` 0 { 49 | image.Gray[y][x] = gray / alpha 50 | } 51 | } 52 | } 53 | return image 54 | } 55 | 56 | func NewImageBufferFromFile(fileName string) *ImageBuffer { 57 | file, err := os.Open(fileName) 58 | if err != nil { 59 | panic(err.Error()) 60 | } 61 | defer file.Close() 62 | return NewImageBufferFromReader(file) 63 | } 64 | 65 | func NewImageBuffer(width int, height int) *ImageBuffer { 66 | gray := make([][]float64, height) 67 | alpha := make([][]float64, height) 68 | for y := 0; y < height; y++ { 69 | gray[y] = make([]float64, width) 70 | alpha[y] = make([]float64, width) 71 | } 72 | return &ImageBuffer{width, height, gray, alpha} 73 | } 74 | 75 | func (image *ImageBuffer) Get(x, y float64) (float64, float64) { 76 | if x < 0 || y < 0 || x > 1 || y > 1 { 77 | return 0, 0 78 | } 79 | ix := int(x * float64(image.Width)) 80 | if ix >= image.Width { 81 | ix = image.Width - 1 82 | } 83 | iy := int(y * float64(image.Height)) 84 | if iy >= image.Height { 85 | iy = image.Height - 1 86 | } 87 | return image.Gray[iy][ix], image.Alpha[iy][ix] 88 | } 89 | 90 | func (image *ImageBuffer) Sub(x, y, w, h float64) *SubImage { 91 | return &SubImage{image, x, y, w, h} 92 | } 93 | 94 | func (image *ImageBuffer) Plot(x, y int, gray, alpha float64) { 95 | if x < 0 || y < 0 || x >= image.Width || y >= image.Height { 96 | return 97 | } 98 | dstGray, dstAlpha := image.Gray[y][x], image.Alpha[y][x] 99 | newAlpha := dstAlpha + alpha - dstAlpha*alpha 100 | image.Alpha[y][x] = newAlpha 101 | if newAlpha == 0 { 102 | image.Gray[y][x] = 0 103 | } else { 104 | image.Gray[y][x] = (dstGray*dstAlpha*(1-alpha) + gray*alpha) / newAlpha 105 | } 106 | } 107 | 108 | func (screen *ImageBuffer) Draw(image Image, x, y, w, h float64) { 109 | if x+w < 0 || y+h < 0 || float64(screen.Width) < x || float64(screen.Height) < y { 110 | return 111 | } 112 | for ix := int(x); float64(ix) < x+w; ix++ { 113 | for iy := int(y); float64(iy) < y+h; iy++ { 114 | gray, alpha := image.Get((float64(ix)-x)/w, (float64(iy)-y)/h) 115 | screen.Plot(ix, iy, gray, alpha) 116 | } 117 | } 118 | } 119 | 120 | func (image *ImageBuffer) String() string { 121 | lines := make([]string, image.Height/2) 122 | for y := 0; y < image.Height/2; y++ { 123 | var buf bytes.Buffer 124 | for x := 0; x < image.Width; x++ { 125 | ug, ua := image.Gray[2*y][x], image.Alpha[2*y][x] 126 | up := int(16 * (ug*ua + 1*(1-ua))) 127 | dg, da := image.Gray[2*y+1][x], image.Alpha[2*y+1][x] 128 | down := int(16 * (dg*da + 1*(1-da))) 129 | if up < 0 { 130 | up = 0 131 | } 132 | if down < 0 { 133 | down = 0 134 | } 135 | if up > 0xf { 136 | up = 0xf 137 | } 138 | if down > 0xf { 139 | down = 0xf 140 | } 141 | buf.WriteByte(charTable[up][down]) 142 | } 143 | lines[y] = buf.String() 144 | } 145 | return strings.Join(lines, "\n") 146 | } 147 | 148 | var out = colorable.NewColorableStdout() 149 | 150 | func (image *ImageBuffer) Print() { 151 | fmt.Fprint(out, "\x1B[1;1H") 152 | fmt.Print(image.String()) 153 | } 154 | 155 | var charTable []string = []string{ 156 | "MMMMMM###TTTTTTT", 157 | "QQBMMNW##TTTTTV*", 158 | "QQQBBEK@PTTTVVV*", 159 | "QQQmdE88P9VVVV**", 160 | "QQQmdGDU0YVV77**", 161 | "pQQmAbk65YY?7***", 162 | "ppgAww443vv?7***", 163 | "pggyysxcJv??7***", 164 | "pggyaLojrt<<+**\"", 165 | "gggaauuj{11!//\"\"", 166 | "gggaauui])|!/~~\"", 167 | "ggaauui]((;::~~^", 168 | "ggaauu](;;::-~~'", 169 | "ggauu(;;;;---~``", 170 | "gaau;;,,,,,...``", 171 | "gau,,,,,,,,... "} 172 | -------------------------------------------------------------------------------- /images/ball1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tompng/pokemon-go/90d348ced3e2efa751e65c16d307c96d1786727d/images/ball1.png -------------------------------------------------------------------------------- /images/ball2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tompng/pokemon-go/90d348ced3e2efa751e65c16d307c96d1786727d/images/ball2.png -------------------------------------------------------------------------------- /images/ball3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tompng/pokemon-go/90d348ced3e2efa751e65c16d307c96d1786727d/images/ball3.png -------------------------------------------------------------------------------- /images/chars.html: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /images/chars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tompng/pokemon-go/90d348ced3e2efa751e65c16d307c96d1786727d/images/chars.png -------------------------------------------------------------------------------- /images/pokemon/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tompng/pokemon-go/90d348ced3e2efa751e65c16d307c96d1786727d/images/pokemon/.gitkeep -------------------------------------------------------------------------------- /images/pokemon/bulbasaur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tompng/pokemon-go/90d348ced3e2efa751e65c16d307c96d1786727d/images/pokemon/bulbasaur.png -------------------------------------------------------------------------------- /images/pokemon/charmander.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tompng/pokemon-go/90d348ced3e2efa751e65c16d307c96d1786727d/images/pokemon/charmander.png -------------------------------------------------------------------------------- /images/pokemon/gopher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tompng/pokemon-go/90d348ced3e2efa751e65c16d307c96d1786727d/images/pokemon/gopher.png -------------------------------------------------------------------------------- /images/pokemon/pikachu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tompng/pokemon-go/90d348ced3e2efa751e65c16d307c96d1786727d/images/pokemon/pikachu.png -------------------------------------------------------------------------------- /images/pokemon/squirtle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tompng/pokemon-go/90d348ced3e2efa751e65c16d307c96d1786727d/images/pokemon/squirtle.png -------------------------------------------------------------------------------- /images/smoke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tompng/pokemon-go/90d348ced3e2efa751e65c16d307c96d1786727d/images/smoke.png -------------------------------------------------------------------------------- /pokemon.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | //go:generate go-bindata images images/pokemon 4 | 5 | import ( 6 | "bytes" 7 | "fmt" 8 | "io" 9 | "io/ioutil" 10 | "math" 11 | "math/rand" 12 | "os" 13 | "path" 14 | "path/filepath" 15 | "sort" 16 | "strings" 17 | "time" 18 | 19 | tty "github.com/mattn/go-tty" 20 | "github.com/tompng/pokemon-go/canvas" 21 | ) 22 | 23 | var fontData *canvas.ImageBuffer 24 | 25 | func DrawString(screen *canvas.ImageBuffer, message string, x, y, size float64) { 26 | if fontData == nil { 27 | fontData = canvas.NewImageBufferFromReader(file("images/chars.png")) 28 | } 29 | for i, c := range message { 30 | face := fontData.Sub(float64(c%16)/16.0, float64(c/16)/8.0, 1/16.0, 1/8.0) 31 | screen.Draw(face, x+float64(i)*size/2, y, size/2, size) 32 | } 33 | } 34 | 35 | func FileNames(path string) []string { 36 | fileInfos, err := ioutil.ReadDir(path) 37 | if err != nil { 38 | return []string{} 39 | } 40 | files := make([]string, len(fileInfos)) 41 | for i, fi := range fileInfos { 42 | file := fi.Name() 43 | if fi.IsDir() { 44 | file += "/" 45 | } 46 | files[i] = file 47 | } 48 | return files 49 | } 50 | 51 | func PokemonImage() *canvas.ImageBuffer { 52 | currentPath, err := filepath.Abs(".") 53 | if err != nil { 54 | panic("cannot get current path") 55 | } 56 | var seed int64 57 | for i, c := range currentPath { 58 | seed = seed*0x987654321 + int64(c) + int64(i) 59 | } 60 | var imageFiles []string 61 | for _, f := range AssetNames() { 62 | if strings.HasPrefix(f, "images/pokemon/") && path.Ext(f) == ".png" { 63 | imageFiles = append(imageFiles, f) 64 | } 65 | } 66 | sort.Strings(imageFiles) 67 | random := rand.New(rand.NewSource(seed)) 68 | f := imageFiles[random.Intn(len(imageFiles))] 69 | return canvas.NewImageBufferFromReader(file(f)) 70 | } 71 | 72 | func DrawScrollingMessages(screen *canvas.ImageBuffer, messages []string, time float64) { 73 | for i, message := range messages { 74 | DrawString(screen, message, 0, float64(i+1)*16-20*time, 16) 75 | } 76 | } 77 | 78 | func DrawGotcha(screen *canvas.ImageBuffer) { 79 | message := "Gotcha!" 80 | width := 80 81 | length := len(message) 82 | height := 2 * width / length 83 | r := 4.0 84 | for x := -int(r); x < width+int(r); x++ { 85 | for y := -int(r); y < height; y++ { 86 | dx, dy := 1.0, 1.0 87 | if x < 0 { 88 | dx = 1.0 + float64(x)/r 89 | } 90 | if x > width { 91 | dx = 1.0 - float64(x-width)/r 92 | } 93 | if y < 0 { 94 | dy = 1.0 + float64(y)/r 95 | } 96 | screen.Plot(screen.Width/2-width/2+x, screen.Height-height+y, 1, 0.8*dx*dy) 97 | } 98 | } 99 | DrawString(screen, message, float64(screen.Width-width)/2, float64(screen.Height-height), float64(height)) 100 | } 101 | 102 | func Save(pokemon canvas.Image) { 103 | screen := canvas.NewImageBuffer(80, 80) 104 | screen.Draw(pokemon, 0, 0, 80, 80) 105 | DrawGotcha(screen) 106 | ioutil.WriteFile("pokemon.txt", []byte(screen.String()), 0666) 107 | } 108 | 109 | func fatal(err error) { 110 | fmt.Fprintf(os.Stderr, "%v: %v", os.Args[0], err) 111 | os.Exit(1) 112 | } 113 | 114 | func file(n string) io.Reader { 115 | b, err := Asset(n) 116 | if err != nil { 117 | panic(err.Error()) 118 | } 119 | return bytes.NewReader(b) 120 | } 121 | 122 | func main() { 123 | tty, err := tty.Open() 124 | if err != nil { 125 | fatal(err) 126 | } 127 | 128 | ball1 := canvas.NewImageBufferFromReader(file("images/ball1.png")) 129 | smoke := canvas.NewImageBufferFromReader(file("images/smoke.png")) 130 | ball2 := canvas.NewImageBufferFromReader(file("images/ball2.png")) 131 | ball3 := canvas.NewImageBufferFromReader(file("images/ball3.png")) 132 | 133 | fileNames := FileNames(".") 134 | pokemon := PokemonImage() 135 | 136 | time0 := time.Now().UnixNano() 137 | rand.Seed(time0) 138 | 139 | dstx, dsty := 0.5, 0.5 140 | dx1, dy1 := 2*rand.Float64()-1, 2*rand.Float64()-1 141 | dx2, dy2 := 2*rand.Float64()-1, 2*rand.Float64()-1 142 | getTime := 20.0 143 | exitFlag := false 144 | currentTime := func() float64 { 145 | return float64(time.Now().UnixNano()-time0) / 1000 / 1000 / 1000 146 | } 147 | 148 | go func() { 149 | for { 150 | code, _ := tty.ReadRune() 151 | if code == 0x03 || code == 0x1C { 152 | exitFlag = true 153 | continue 154 | } 155 | time := currentTime() 156 | if time < 2.0 { 157 | time = 2.0 158 | } 159 | if time < getTime { 160 | getTime = time 161 | } 162 | } 163 | }() 164 | throwTime := 1.0 165 | for { 166 | terminalWidth, terminalHeight, err := tty.Size() 167 | if err != nil { 168 | fatal(err) 169 | } 170 | t := currentTime() 171 | screen := canvas.NewImageBuffer(terminalWidth, (terminalHeight-1)*2) 172 | 173 | size := 96 * (1 - math.Exp(-t)) * (1 + 0.1*(math.Sin(1.4*t)+math.Sin(1.9*t))) 174 | x := dstx + dx1*math.Exp(-t) + dx2*math.Exp(-t/2) + 0.1*(math.Sin(2.1*t)+math.Sin(1.7*t)) 175 | y := dsty + dy1*math.Exp(-t) + dy2*math.Exp(-t/2) + 0.1*(math.Sin(2.5*t)+math.Sin(1.3*t)) 176 | if t < getTime+throwTime { 177 | screen.Draw(pokemon, float64(screen.Width)*x-size/2, float64(screen.Height)*y-size/2, size, size) 178 | } 179 | DrawScrollingMessages(screen, fileNames, t) 180 | 181 | if getTime < t { 182 | phase := t - getTime 183 | if phase < throwTime { 184 | x := size/4*(2*rand.Float64()-1) + float64(screen.Width)/2 - size/2 185 | y := size/4*(2*rand.Float64()-1) + float64(screen.Height)/2 - size/2 186 | screen.Draw(smoke, x, y, size, size) 187 | } 188 | yt := phase * 2 189 | if yt < 0.5 { 190 | yt = 0.5 191 | } 192 | ytmod1 := yt - math.Floor(yt) 193 | pos := 4 * ytmod1 * (1 - ytmod1) * math.Exp(-math.Floor(yt)) 194 | if phase > 2 { 195 | pos = 0 196 | } 197 | ball := ball1 198 | if phase > 5 { 199 | ball = ball3 200 | } else if phase > 1 && phase-math.Floor(phase) < 0.1 { 201 | ball = ball2 202 | } 203 | screen.Draw(ball, float64(screen.Width)/2, (float64(screen.Height)/2+20)*(1-pos)-20, 20, 20) 204 | if phase > 5 { 205 | DrawGotcha(screen) 206 | screen.Print() 207 | Save(pokemon) 208 | break 209 | } 210 | } 211 | screen.Print() 212 | if exitFlag { 213 | break 214 | } 215 | time.Sleep(50 * time.Millisecond) 216 | } 217 | 218 | } 219 | --------------------------------------------------------------------------------