├── .gitignore ├── README.md ├── go.mod ├── go.sum ├── imgs ├── bg_ceiling_floor.png ├── crosshair.png ├── crosshair_dot.png ├── enemy8.png ├── fire.png ├── gun2.png ├── gun_pixelized.png ├── scanlines.png ├── scanlines2.png ├── splash_08.png ├── splash_dev.png ├── wall.png ├── wall32.png └── wall8.png ├── keyboard.go ├── minimap.go ├── other_imgs ├── engine.gif ├── gun_full_cleaned.png ├── icon.png ├── screenie.png └── screenie_crt.png ├── ray_engine.go ├── sound └── gun.mp3 └── textures.go /.gitignore: -------------------------------------------------------------------------------- 1 | ray_engine -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## ray_engine 2 | 3 | #### A toy raycasting engine built with Go + Ebiten v2 2D library 4 | 5 | Heavily based on [3DSage fantastic Youtube videos of a C/OpenGL raycasting engine](https://www.youtube.com/watch?v=gYRrGTC7GtA) 6 | 7 | _Gun mode ! (old version of the engine with scaling issues)_ 8 | 9 | ![img](other_imgs/engine.gif) 10 | 11 | _2D map rendered in 3D_ 12 | 13 | ![img](other_imgs/screenie.png) 14 | 15 | _CRT scanlines_ 16 | 17 | ![img](other_imgs/screenie_crt.png) 18 | 19 | 20 | #### Build & run 21 | 22 | Build with Go 1.16 and Ebiten v2 on Linux/macOS 23 | 24 | go build 25 | ./ray_engine 26 | 27 | #### Keymaps 28 | 29 | Arrows keys or ZSQD (Azerty) : Move 30 | 31 | 'i' : debug info toogle 32 | 33 | 'f' : fullscreen toogle 34 | 35 | 'l' : scanlines 36 | 37 | 'm' : Gun mode 38 | 39 | 'k' : quit 40 | 41 | #### Features, todos and idea box 42 | 43 | - [X] Port to Ebiten v2 44 | - [ ] Proper collisions 45 | - [ ] UI 46 | - [X] Scale map to 16x16 47 | - [X] 2D minimap for gun mode 48 | - [X] Add basic floor/ceiling - **Just a matching png for now** 49 | - [ ] Binary textures **wip** 50 | - [ ] Up/down parallax/Y-xhearing 51 | - [ ] Ebiten Audio mp3 sound support 52 | - [ ] Weapon swap/shield 53 | - [ ] Proper ballistics - **Rough prototype** 54 | - [ ] Cube destruction/basic enemies - **Rough prototype** 55 | - [X] Rebuild the 2D map (where actual raycasting is done) to fit the screen 56 | 57 | #### Known bugs 58 | 59 | - [ ] Enemies are seen through walls 60 | 61 | #### Assets 62 | 63 | Gun from Destiny 2 screenshot by Bungie -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/Myu-Unix/ray_engine 2 | 3 | go 1.16 4 | 5 | require github.com/hajimehoshi/ebiten/v2 v2.1.3 6 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 2 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210410170116-ea3d685f79fb h1:T6gaWBvRzJjuOrdCtg8fXXjKai2xSDqWTcKFUPuw8Tw= 3 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210410170116-ea3d685f79fb/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 4 | github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY= 5 | github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= 6 | github.com/hajimehoshi/bitmapfont/v2 v2.1.3/go.mod h1:2BnYrkTQGThpr/CY6LorYtt/zEPNzvE/ND69CRTaHMs= 7 | github.com/hajimehoshi/ebiten/v2 v2.1.3 h1:xuypQF0A3tOfepWKqUUvVxJH06UCkLghJBolIUxUFoo= 8 | github.com/hajimehoshi/ebiten/v2 v2.1.3/go.mod h1:mpAvpmTRbMdhQDZplZ4rfEogRhdsfAGTC0zLhxawKHY= 9 | github.com/hajimehoshi/file2byteslice v0.0.0-20200812174855-0e5e8a80490e/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE= 10 | github.com/hajimehoshi/go-mp3 v0.3.2/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM= 11 | github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI= 12 | github.com/hajimehoshi/oto v0.7.1/go.mod h1:wovJ8WWMfFKvP587mhHgot/MBr4DnNy9m6EepeVGnos= 13 | github.com/jakecoffman/cp v1.1.0/go.mod h1:JjY/Fp6d8E1CHnu74gWNnU0+b9VzEdUVPoJxg2PsTQg= 14 | github.com/jfreymuth/oggvorbis v1.0.3/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII= 15 | github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ= 16 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 17 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 18 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 19 | github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= 20 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 21 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 22 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 23 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 24 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 25 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 26 | golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 h1:estk1glOnSVeJ9tdEZZc5mAMDZk5lNJNyJ6DvrBkTEU= 27 | golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= 28 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 29 | golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 30 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 31 | golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk= 32 | golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 33 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 34 | golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 35 | golang.org/x/mobile v0.0.0-20210220033013-bdb1ca9a1e08 h1:h+GZ3ubjuWaQjGe8owMGcmMVCqs0xYJtRG5y2bpHaqU= 36 | golang.org/x/mobile v0.0.0-20210220033013-bdb1ca9a1e08/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= 37 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 38 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 39 | golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 40 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 41 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 42 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 43 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 44 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 45 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 46 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 47 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= 48 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 49 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 50 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 51 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 52 | golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 53 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 54 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 55 | golang.org/x/sys v0.0.0-20210415045647-66c3f260301c h1:6L+uOeS3OQt/f4eFHXZcTxeZrGCuz+CLElgEBjbcTA4= 56 | golang.org/x/sys v0.0.0-20210415045647-66c3f260301c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 57 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 58 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 59 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 60 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 61 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 62 | golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 63 | golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= 64 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 65 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 66 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 67 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 68 | -------------------------------------------------------------------------------- /imgs/bg_ceiling_floor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/imgs/bg_ceiling_floor.png -------------------------------------------------------------------------------- /imgs/crosshair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/imgs/crosshair.png -------------------------------------------------------------------------------- /imgs/crosshair_dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/imgs/crosshair_dot.png -------------------------------------------------------------------------------- /imgs/enemy8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/imgs/enemy8.png -------------------------------------------------------------------------------- /imgs/fire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/imgs/fire.png -------------------------------------------------------------------------------- /imgs/gun2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/imgs/gun2.png -------------------------------------------------------------------------------- /imgs/gun_pixelized.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/imgs/gun_pixelized.png -------------------------------------------------------------------------------- /imgs/scanlines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/imgs/scanlines.png -------------------------------------------------------------------------------- /imgs/scanlines2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/imgs/scanlines2.png -------------------------------------------------------------------------------- /imgs/splash_08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/imgs/splash_08.png -------------------------------------------------------------------------------- /imgs/splash_dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/imgs/splash_dev.png -------------------------------------------------------------------------------- /imgs/wall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/imgs/wall.png -------------------------------------------------------------------------------- /imgs/wall32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/imgs/wall32.png -------------------------------------------------------------------------------- /imgs/wall8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/imgs/wall8.png -------------------------------------------------------------------------------- /keyboard.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/hajimehoshi/ebiten/v2" 7 | ) 8 | 9 | func keyboard_handling() { 10 | 11 | if ebiten.IsKeyPressed(ebiten.KeyM) { 12 | keyStates[ebiten.KeyM]++ 13 | } else { 14 | keyStates[ebiten.KeyM] = 0 15 | } 16 | if ebiten.IsKeyPressed(ebiten.KeyF) { 17 | keyStates[ebiten.KeyF]++ 18 | } else { 19 | keyStates[ebiten.KeyF] = 0 20 | } 21 | if ebiten.IsKeyPressed(ebiten.KeyK) { 22 | keyStates[ebiten.KeyK]++ 23 | } else { 24 | keyStates[ebiten.KeyK] = 0 25 | } 26 | if ebiten.IsKeyPressed(ebiten.KeyL) { 27 | keyStates[ebiten.KeyL]++ 28 | } else { 29 | keyStates[ebiten.KeyL] = 0 30 | } 31 | if ebiten.IsKeyPressed(ebiten.KeyI) { 32 | keyStates[ebiten.KeyI]++ 33 | } else { 34 | keyStates[ebiten.KeyI] = 0 35 | } 36 | if ebiten.IsKeyPressed(ebiten.KeyJ) { 37 | keyStates[ebiten.KeyJ]++ 38 | } else { 39 | keyStates[ebiten.KeyJ] = 0 40 | } 41 | if ebiten.IsKeyPressed(ebiten.KeyEnter) { 42 | keyStates[ebiten.KeyEnter]++ 43 | } else { 44 | keyStates[ebiten.KeyEnter] = 0 45 | } 46 | if STATE_COLLISION == 0 { 47 | if ebiten.IsKeyPressed(ebiten.KeyUp) || ebiten.IsKeyPressed(ebiten.KeyW) { // Z Azerty 48 | player_pos_x = player_pos_x + player_delta_x 49 | player_pos_y = player_pos_y + player_delta_y 50 | // small bobbing 51 | if guny >= 350 && guny < 386 { 52 | guny += 12 53 | } else { 54 | guny = 350 55 | } 56 | } 57 | if ebiten.IsKeyPressed(ebiten.KeyDown) || ebiten.IsKeyPressed(ebiten.KeyS) { // S 58 | player_pos_x = player_pos_x - player_delta_x 59 | player_pos_y = player_pos_y - player_delta_y 60 | // small bobbing 61 | if guny >= 314 && guny <= 350 { 62 | guny -= 12 63 | } else { 64 | guny = 350 65 | } 66 | } 67 | if ebiten.IsKeyPressed(ebiten.KeyLeft) || ebiten.IsKeyPressed(ebiten.KeyA) { // Q Azerty 68 | player_pos_x = player_pos_x - player_strafe_delta_x 69 | player_pos_y = player_pos_y - player_strafe_delta_y 70 | // small bobbing 71 | if gunx > 476 && gunx <= 512 { 72 | gunx -= 12 73 | } else { 74 | gunx = 512 75 | } 76 | } 77 | if ebiten.IsKeyPressed(ebiten.KeyRight) || ebiten.IsKeyPressed(ebiten.KeyD) { // D 78 | player_pos_x = player_pos_x + player_strafe_delta_x 79 | player_pos_y = player_pos_y + player_strafe_delta_y 80 | // small bobbing 81 | if gunx >= 512 && gunx < 548 { 82 | gunx += 12 83 | } else { 84 | gunx = 512 85 | } 86 | } 87 | } 88 | if IsKeyTriggered(ebiten.KeyM) { 89 | if STATE_SHOW_2D_MAP == 0 { 90 | STATE_SHOW_2D_MAP = 1 91 | STATE_MINIMAP = 0 92 | x3d_orig = 530 93 | } else { 94 | STATE_SHOW_2D_MAP = 0 95 | STATE_MINIMAP = 1 96 | x3d_orig = 0 97 | } 98 | } 99 | if IsKeyTriggered(ebiten.KeyJ) { 100 | if STATE_MINIMAP == 0 { 101 | STATE_MINIMAP = 1 102 | } else { 103 | STATE_MINIMAP = 0 104 | } 105 | } 106 | if IsKeyTriggered(ebiten.KeyL) { 107 | if STATE_SCANLINES == 0 { 108 | STATE_SCANLINES = 1 109 | } else { 110 | STATE_SCANLINES = 0 111 | } 112 | } 113 | if IsKeyTriggered(ebiten.KeyF) { 114 | if STATE_FULLSCREEN == 0 { 115 | ebiten.SetFullscreen(true) 116 | STATE_FULLSCREEN = 1 117 | } else { 118 | ebiten.SetFullscreen(false) 119 | STATE_FULLSCREEN = 0 120 | } 121 | } 122 | if IsKeyTriggered(ebiten.KeyI) { 123 | if STATE_SHOW_DEBUG == 0 { 124 | STATE_SHOW_DEBUG = 1 125 | } else { 126 | STATE_SHOW_DEBUG = 0 127 | } 128 | } 129 | if IsKeyTriggered(ebiten.KeyK) { 130 | os.Exit(0) 131 | } 132 | if IsKeyTriggered(ebiten.KeyEnter) { 133 | boot = 0 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /minimap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/hajimehoshi/ebiten/v2" 5 | "github.com/hajimehoshi/ebiten/v2/ebitenutil" 6 | "image/color" 7 | ) 8 | 9 | func draw_minimap(screen *ebiten.Image) { 10 | if STATE_MINIMAP == 1 { 11 | for k := 0; k < mapX; k++ { 12 | for l := 0; l < mapY; l++ { 13 | if map_array[k*mapX+l] == 1 { 14 | opWallMinimap := &ebiten.DrawImageOptions{} 15 | opWallMinimap.GeoM.Translate(wall_minimap_posx, wall_minimap_posy) 16 | screen.DrawImage(wallMiniImage, opWallMinimap) 17 | } else if map_array[k*mapX+l] == 2 { 18 | opEnemyMinimap := &ebiten.DrawImageOptions{} 19 | opEnemyMinimap.GeoM.Translate(wall_minimap_posx, wall_minimap_posy) 20 | screen.DrawImage(wallEnemyImage, opEnemyMinimap) 21 | } 22 | if wall_minimap_posx <= 132 { // 20 (offset) + (16x8 -> 128) - 16 23 | wall_minimap_posx += 8 24 | } else { 25 | wall_minimap_posx = 20 // offset 26 | wall_minimap_posy += 8 27 | } 28 | } 29 | } 30 | // Minimap is place on the lower left corner of the screen 31 | wall_minimap_posx = 20 32 | wall_minimap_posy = 350 33 | 34 | // Draw player as a rect 35 | ebitenutil.DrawRect(screen, float64((player_pos_x/2)+wall_minimap_posx), float64((player_pos_y/2)+wall_minimap_posy), 4, 4, color.RGBA{196, 255, 0, 255}) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /other_imgs/engine.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/other_imgs/engine.gif -------------------------------------------------------------------------------- /other_imgs/gun_full_cleaned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/other_imgs/gun_full_cleaned.png -------------------------------------------------------------------------------- /other_imgs/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/other_imgs/icon.png -------------------------------------------------------------------------------- /other_imgs/screenie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/other_imgs/screenie.png -------------------------------------------------------------------------------- /other_imgs/screenie_crt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/other_imgs/screenie_crt.png -------------------------------------------------------------------------------- /ray_engine.go: -------------------------------------------------------------------------------- 1 | /* 2 | ray_engine by Myu-Unix - Sept 2020 - Jan 2022 3 | Inspired by 3DSage's C/OpenGL raycasting engine : https://www.youtube.com/watch?v=gYRrGTC7GtA 4 | */ 5 | 6 | package main 7 | 8 | import ( 9 | "fmt" 10 | "github.com/hajimehoshi/ebiten/v2" 11 | "github.com/hajimehoshi/ebiten/v2/ebitenutil" 12 | "github.com/hajimehoshi/ebiten/v2/inpututil" 13 | "image/color" 14 | _ "image/png" 15 | "log" 16 | "math" 17 | "os/exec" 18 | "strings" 19 | ) 20 | 21 | type game struct{} 22 | 23 | var ( 24 | STATE_SHOW_DEBUG = 1 25 | STATE_SHOW_2D_MAP = 0 26 | STATE_FULLSCREEN = 0 27 | STATE_MOUSE_SUPPORT = 1 28 | STATE_COLLISION = 0 29 | STATE_MINIMAP = 1 30 | STATE_SCANLINES = 0 31 | backgroundImage *ebiten.Image 32 | scanlinesImage *ebiten.Image 33 | splashImage *ebiten.Image 34 | wallImage *ebiten.Image 35 | wallMiniImage *ebiten.Image 36 | wallEnemyImage *ebiten.Image 37 | gunImage *ebiten.Image 38 | crossHairImage *ebiten.Image 39 | fireImage *ebiten.Image 40 | keyStates = map[ebiten.Key]int{} 41 | bg_posx float64 = 0 42 | bg_posy float64 = 0 43 | wall_posx float64 = 0 44 | wall_posy float64 = 0 45 | wall_minimap_posx float64 = 20 46 | wall_minimap_posy float64 = 350 47 | CONST_PI float64 = 3.1415926535 48 | CONST_PI2 float64 = CONST_PI / 2 49 | CONST_PI3 float64 = (3 * CONST_PI) / 2 50 | CONST_DR float64 = 0.0174533 // one radian in degrees 51 | CONST_HALF_DR float64 = 0.00872665 // one half radian in degrees 52 | player_pos_x float64 = 36 53 | player_pos_y float64 = 50 54 | player_delta_x float64 = 0 55 | player_delta_y float64 = 0 56 | player_strafe_delta_x float64 = 0 57 | player_strafe_delta_y float64 = 0 58 | player_angle float64 = 0 59 | mapX int = 16 60 | mapY int = 16 61 | max_dof int = 16 62 | boot = 1 63 | mpv_run []byte 64 | engine_version = "ray_engine 0.8.2" 65 | debug_str = "'Arrow : move, 'k' : exit, 'i' : debug info, 'l' : scanlines" 66 | debug_str2 = "'m' : Gun mode/2D map mode, 'f' : fullscreen, j : toogle minimap" 67 | str string 68 | map_array = [256]int{ 69 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 70 | 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 71 | 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 72 | 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 73 | 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 74 | 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 75 | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 76 | 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 77 | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 78 | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 79 | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 80 | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 81 | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 82 | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 83 | 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 84 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 85 | } 86 | 87 | // Rays vars 88 | r, mx, my, mp, dof int 89 | rx, ry, ra, xo, yo, hx, hy, vx, vy float64 90 | aTan float64 = 0 91 | nTan float64 = 0 92 | disH float64 = 1000000 93 | disV float64 = 1000000 94 | disT float64 = 0 95 | lineH float64 = 0 96 | lineO float64 = 0 97 | x3d float64 = 0 // Current offset to start to draw the 3D map 98 | x3d_orig float64 = 0 // Offset toogle - 0 = 2D MAP off, 530 = 2D map on - set at compile time 99 | ca float64 = 0 100 | ray int = 0 101 | COLOR_R, COLOR_G, COLOR_B uint8 102 | // Mouse vars 103 | x int = 0 104 | y int = 0 105 | // Gun vars 106 | gunx float64 = 512 107 | guny float64 = 350 108 | reset_gun_pos = 0 109 | // Ballistic vars 110 | center_x float64 = 480 // 1024/2 - 32 (which is half the crosshair size) 111 | center_y float64 = 224 // 512/2 - 32 (which is half the crosshair size) 112 | ENEMY_SIGHT int = 0 113 | enemy_mp int = 0 114 | ) 115 | 116 | func fix_fisheye() { 117 | ca = player_angle - ra 118 | if ca < 0 { 119 | ca = ca + (2 * CONST_PI) 120 | } 121 | if ca > 2*CONST_PI { 122 | ca = ca - (2 * CONST_PI) 123 | } 124 | disT = disT * math.Cos(ca) 125 | } 126 | 127 | func ballistics(screen *ebiten.Image) { 128 | // Ballistics. ray 63 is the middle ray 129 | if ray == 63 { 130 | if mp > 0 && mp < mapX*mapY && map_array[mp] == 2 { 131 | ebitenutil.DebugPrint(screen, "\n// DEBUG : Enemy in sight") 132 | ENEMY_SIGHT = 1 // Mark "destructible" 133 | enemy_mp = mp // Mark "destructible" 134 | } else { 135 | ENEMY_SIGHT = 0 136 | enemy_mp = 0 137 | } 138 | } 139 | } 140 | 141 | func check_horiz(screen *ebiten.Image) { 142 | dof = 0 143 | disH = 1000000 144 | hx = player_pos_x 145 | hy = player_pos_y 146 | aTan = -1 / math.Tan(ra) 147 | if ra > CONST_PI { 148 | ry = float64(((int(player_pos_y) >> 4) << 4)) - float64(0.0001) 149 | rx = (player_pos_y-ry)*aTan + player_pos_x 150 | yo = -16 151 | xo = -yo * aTan 152 | } 153 | if ra < CONST_PI { 154 | ry = float64(((int(player_pos_y) >> 4) << 4)) + float64(16) 155 | rx = (player_pos_y-ry)*aTan + player_pos_x 156 | yo = 16 157 | xo = -yo * aTan 158 | } 159 | // Looking left or right, will not hit horizontal lines 160 | if ra == 0 || ra == CONST_PI { 161 | rx = player_pos_x 162 | ry = player_pos_y 163 | dof = max_dof 164 | } 165 | for dof < max_dof { 166 | mx = (int(rx) >> 4) 167 | my = (int(ry) >> 4) 168 | mp = my*mapX + mx 169 | // Regular walls values are '1', enemies are '2' 170 | if mp > 0 && mp < mapX*mapY && map_array[mp] > 0 { 171 | dof = max_dof // hit wall 172 | hx = rx 173 | hy = ry 174 | // ax ay bx by ang 175 | disH = math.Sqrt(((hx - player_pos_x) * (hx - player_pos_x)) + ((hy - player_pos_y) * (hy - player_pos_y))) 176 | } else { 177 | rx = rx + xo 178 | ry = ry + yo 179 | dof++ 180 | } 181 | } 182 | // Handle gun 183 | ballistics(screen) 184 | } 185 | 186 | func check_verti(screen *ebiten.Image) { 187 | dof = 0 188 | disV = 1000000 189 | vx = player_pos_x 190 | vy = player_pos_y 191 | nTan = -math.Tan(ra) 192 | if ra > CONST_PI2 && ra < CONST_PI3 { 193 | rx = float64(((int(player_pos_x) >> 4) << 4)) - float64(0.0001) 194 | ry = (player_pos_x-rx)*nTan + player_pos_y 195 | xo = -16 196 | yo = -xo * nTan 197 | } 198 | if ra < CONST_PI2 || ra > CONST_PI3 { 199 | rx = float64(((int(player_pos_x) >> 4) << 4)) + float64(16) 200 | ry = (player_pos_x-rx)*nTan + player_pos_y 201 | xo = 16 202 | yo = -xo * nTan 203 | } 204 | // staight up or down 205 | if ra == 0 || ra == CONST_PI { 206 | rx = player_pos_x 207 | ry = player_pos_y 208 | dof = max_dof 209 | } 210 | for dof < max_dof { 211 | mx = (int(rx) >> 4) 212 | my = (int(ry) >> 4) 213 | mp = my*mapX + mx 214 | // Regular walls values are '1', enemies are '2' 215 | if mp > 0 && mp < mapX*mapY && map_array[mp] > 0 { // was == 1 216 | dof = max_dof // hit wall 217 | vx = rx 218 | vy = ry 219 | // ax ay bx by ang 220 | disV = math.Sqrt(((vx - player_pos_x) * (vx - player_pos_x)) + ((vy - player_pos_y) * (vy - player_pos_y))) 221 | } else { 222 | rx = rx + xo 223 | ry = ry + yo 224 | dof++ 225 | } 226 | } 227 | // Handle gun 228 | ballistics(screen) 229 | 230 | // disT compute + colors based on it 231 | if disV < disH { 232 | rx = vx 233 | ry = vy 234 | disT = disV 235 | COLOR_G = 0 236 | COLOR_B = 192 237 | } else if disH < disV { 238 | rx = hx 239 | ry = hy 240 | disT = disH 241 | COLOR_G = 0 242 | COLOR_B = 64 243 | } 244 | 245 | // Draw shortest ray based on disT in Orange on the 2D map 246 | if STATE_SHOW_2D_MAP == 1 { 247 | ebitenutil.DrawLine(screen, player_pos_x, player_pos_y, rx, ry, color.RGBA{255, 128, 0, 255}) 248 | } 249 | if ra < 0 { 250 | ra = ra + (2 * CONST_PI) 251 | } 252 | if ra > (2 * CONST_PI) { 253 | ra = ra - (2 * CONST_PI) 254 | } 255 | } 256 | 257 | func simple_shading() { 258 | if disT >= 255 { 259 | COLOR_R = 255 260 | } else if disT <= 0 { 261 | COLOR_R = 0 262 | } else { 263 | COLOR_R=uint8(float64(disT)) 264 | } 265 | } 266 | 267 | func cast_rays(screen *ebiten.Image) { 268 | ra = player_angle - (CONST_HALF_DR * 64) // numbers of rays/2 269 | if ra < 0 { 270 | ra = ra + (2 * CONST_PI) 271 | } 272 | if ra > (2 * CONST_PI) { 273 | ra = ra - (2 * CONST_PI) 274 | } 275 | 276 | for ray = 0; ray < 128; ray++ { // numbers of rays casted 277 | // Check horizontal lines 278 | check_horiz(screen) 279 | // Check vertical lines + determine smallest line and draw on 2D map 280 | check_verti(screen) 281 | // Fix fisheye effect 282 | fix_fisheye() 283 | //Shading 284 | simple_shading() 285 | 286 | // Simplistic and buggy collision detection FIXME 287 | if disT <= 4 { 288 | STATE_COLLISION = 1 289 | } else { 290 | STATE_COLLISION = 0 291 | } 292 | 293 | // Draw lines on 3D map section 294 | lineH = float64(16*800) / disT 295 | if lineH > float64(800) { 296 | lineH = float64(800) 297 | } 298 | 299 | // Basic Y Line offset 300 | lineO = 256 - float64(lineH/2) 301 | // Basic Y Line offset and up/down "shearing" 302 | //lineO = 256 - float64(lineH/2) -float64(y/4) 303 | 304 | // x, y, [ray@16px x64 = 1024 or ray@8px x 128 rays = 1024], lineH 305 | if mp > 0 && mp < mapX*mapY && map_array[mp] == 2 { // Enemy cube 306 | ebitenutil.DrawRect(screen, float64(x3d), float64(lineO), float64(8), lineH, color.RGBA{255, 255, 255, 255}) 307 | } else { 308 | // Draw each pixel from lineH 309 | // Before : ebitenutil.DrawRect(screen, float64(x3d), float64(lineO), float64(16), lineH, color.RGBA{COLOR_R, COLOR_G, COLOR_B, 255}) 310 | ebitenutil.DrawRect(screen, float64(x3d), float64(lineO), float64(8), lineH, color.RGBA{COLOR_R, COLOR_G, COLOR_B, 255}) 311 | /*img_pixel:=0 312 | for ypixel := 0; float64(ypixel) < lineH; ypixel++ { 313 | RED := texture_img_array[img_pixel+0] 314 | GREEN := texture_img_array[img_pixel+1] 315 | BLUE := texture_img_array[img_pixel+2] 316 | ebitenutil.DrawRect(screen, float64(x3d), float64(lineO), float64(16), float64(ypixel), color.RGBA{uint8(RED), uint8(GREEN), uint8(BLUE), 255}) 317 | img_pixel+=3 318 | }*/ 319 | } 320 | 321 | x3d = x3d + 8 322 | ra = (ra + CONST_HALF_DR) // increment 323 | } 324 | x3d = x3d_orig 325 | } 326 | 327 | func (g *game) Draw(screen *ebiten.Image) { 328 | 329 | opBackground := &ebiten.DrawImageOptions{} 330 | opSplash := &ebiten.DrawImageOptions{} 331 | opwall := &ebiten.DrawImageOptions{} 332 | opGun := &ebiten.DrawImageOptions{} 333 | opCrosshair := &ebiten.DrawImageOptions{} 334 | opFire := &ebiten.DrawImageOptions{} 335 | 336 | // Images options 337 | opBackground.GeoM.Translate(bg_posx, bg_posy) 338 | opwall.GeoM.Translate(wall_posx, wall_posy) 339 | opGun.GeoM.Translate(gunx, guny) 340 | opCrosshair.GeoM.Translate(center_x, center_y) 341 | opFire.GeoM.Translate(522, 386) 342 | 343 | // Reset gun position after firing 344 | if reset_gun_pos > 0 { 345 | reset_gun_pos = reset_gun_pos - 1 346 | } else { 347 | gunx = 512 348 | guny = 350 349 | } 350 | 351 | // Draw images 352 | if boot > 0 { 353 | //boot = boot - 1 354 | screen.DrawImage(splashImage, opSplash) 355 | if STATE_SCANLINES == 1 { 356 | screen.DrawImage(scanlinesImage, opBackground) 357 | } 358 | if boot == 0 { 359 | // Initial values for PDX/PDY, only applied once 360 | player_delta_x = math.Cos(player_angle) * 2 361 | player_delta_y = math.Sin(player_angle) * 2 362 | // Add 90 degrees in radians to get the right angle of player_angle 363 | player_strafe_delta_x = math.Cos(player_angle+(math.Pi/2)) * 2 364 | player_strafe_delta_y = math.Sin(player_angle+(math.Pi/2)) * 2 365 | } 366 | } else { 367 | screen.DrawImage(backgroundImage, opBackground) 368 | 369 | // 2D Map if enabled 370 | show2DMap(screen) 371 | // Raycasting 372 | cast_rays(screen) 373 | // Draw minimap 374 | draw_minimap(screen) 375 | 376 | // Draw player line of sight after raycast -> https://pkg.go.dev/github.com/hajimehoshi/ebiten/v2/ebitenutil#DrawLine 377 | if STATE_SHOW_2D_MAP == 1 { 378 | ebitenutil.DrawLine(screen, player_pos_x, player_pos_y, player_pos_x+(player_delta_x*5), player_pos_y+(player_delta_y*5), color.RGBA{255, 255, 0, 255}) 379 | } else { 380 | // Draw Gun and crosshair 381 | screen.DrawImage(gunImage, opGun) 382 | screen.DrawImage(crossHairImage, opCrosshair) 383 | } 384 | 385 | if STATE_SCANLINES == 1 { 386 | screen.DrawImage(scanlinesImage, opBackground) 387 | } 388 | 389 | // Show debug info 390 | str = `{{.below}} {{.newline}} {{.engine_version}} {{.newline}} {{.debug_str}} {{.newline}} {{.debug_str2}} {{.newline}} {{.player_x}} {{.newline}} {{.player_y}} {{.newline}} {{.player_a}} {{.newline}} {{.state_emp}} {{.newline}} {{.state_ms}} {{.newline}} {{.state_co}}` 391 | str = strings.Replace(str, "{{.engine_version}}", engine_version, -1) 392 | str = strings.Replace(str, "{{.debug_str}}", debug_str, -1) 393 | str = strings.Replace(str, "{{.debug_str2}}", debug_str2, -1) 394 | str = strings.Replace(str, "{{.below}}", "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", -1) 395 | str = strings.Replace(str, "{{.newline}}", "\n ", -1) 396 | str = strings.Replace(str, "{{.player_x}}", fmt.Sprintf("Player X : %f", player_pos_x), -1) 397 | str = strings.Replace(str, "{{.player_y}}", fmt.Sprintf("Player Y : %f", player_pos_y), -1) 398 | str = strings.Replace(str, "{{.player_a}}", fmt.Sprintf("Player Angle : %f", player_angle), -1) 399 | str = strings.Replace(str, "{{.state_ms}}", fmt.Sprintf("Mouse enabled : %d", STATE_MOUSE_SUPPORT), -1) 400 | str = strings.Replace(str, "{{.state_emp}}", fmt.Sprintf("Enemy block : %d", enemy_mp), -1) 401 | str = strings.Replace(str, "{{.state_co}}", fmt.Sprintf("Collision : %d", STATE_COLLISION), -1) 402 | if STATE_SHOW_DEBUG == 1 { 403 | ebitenutil.DebugPrint(screen, str) 404 | } 405 | } 406 | 407 | /* Keyboard - FIXME When running in goroutine, it somewhat breaks the mouse support. 408 | not possible to move left/right either */ 409 | keyboard_handling() 410 | 411 | // Mouse support 412 | if STATE_MOUSE_SUPPORT == 1 { 413 | ebiten.SetCursorMode(ebiten.CursorModeCaptured) 414 | x, y = ebiten.CursorPosition() 415 | player_angle = float64(x) / 360 416 | player_delta_x = math.Cos(player_angle) * 2 417 | player_delta_y = math.Sin(player_angle) * 2 418 | // Add 90 degrees in radians to get the right angle of player_angle 419 | player_strafe_delta_x = math.Cos(player_angle+(math.Pi/2)) * 2 420 | player_strafe_delta_y = math.Sin(player_angle+(math.Pi/2)) * 2 421 | // Mouse buttons 422 | if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) { 423 | // Ballistics 424 | if ENEMY_SIGHT == 1 && enemy_mp != 0 { 425 | //ebitenutil.DebugPrint(screen, "\n**** HIT !! ****") 426 | map_array[enemy_mp] = 0 // Destroy block 427 | ENEMY_SIGHT = 0 428 | } 429 | go gun_sound() 430 | screen.DrawImage(fireImage, opFire) 431 | guny = guny - 12 432 | reset_gun_pos = 4 433 | } 434 | } 435 | 436 | // TEXTURE ppm test 437 | if boot > 0 { 438 | pixel_x:=32 439 | pixel_y:=340 440 | for y := 0; y < 32; y++ { 441 | for x := 0; x < 32; x++ { 442 | pixel := (y*32+x)*3 443 | RED := texture_img_array[pixel+0] 444 | GREEN := texture_img_array[pixel+1] 445 | BLUE := texture_img_array[pixel+2] 446 | ebitenutil.DrawRect(screen, float64(pixel_x), float64(pixel_y), float64(4), 4 , color.RGBA{uint8(RED), uint8(GREEN), uint8(BLUE), 255}) 447 | pixel_x+=4 448 | } 449 | pixel_y+=4 450 | pixel_x=32 451 | } 452 | } 453 | fmt.Println(ebiten.CurrentFPS()) 454 | } 455 | 456 | func (g *game) Update() error { 457 | return nil 458 | } 459 | 460 | func (g *game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) { 461 | return 1024, 512 462 | } 463 | 464 | func main() { 465 | var err error 466 | backgroundImage, _, err = ebitenutil.NewImageFromFile("imgs/bg_ceiling_floor.png") 467 | if err != nil { 468 | log.Fatal(err) 469 | } 470 | scanlinesImage, _, err = ebitenutil.NewImageFromFile("imgs/scanlines2.png") 471 | if err != nil { 472 | log.Fatal(err) 473 | } 474 | splashImage, _, err = ebitenutil.NewImageFromFile("imgs/splash_08.png") 475 | if err != nil { 476 | log.Fatal(err) 477 | } 478 | wallImage, _, err = ebitenutil.NewImageFromFile("imgs/wall.png") 479 | if err != nil { 480 | log.Fatal(err) 481 | } 482 | wallMiniImage, _, err = ebitenutil.NewImageFromFile("imgs/wall8.png") 483 | if err != nil { 484 | log.Fatal(err) 485 | } 486 | wallEnemyImage, _, err = ebitenutil.NewImageFromFile("imgs/enemy8.png") 487 | if err != nil { 488 | log.Fatal(err) 489 | } 490 | gunImage, _, err = ebitenutil.NewImageFromFile("imgs/gun_pixelized.png") 491 | if err != nil { 492 | log.Fatal(err) 493 | } 494 | crossHairImage, _, err = ebitenutil.NewImageFromFile("imgs/crosshair_dot.png") 495 | if err != nil { 496 | log.Fatal(err) 497 | } 498 | fireImage, _, err = ebitenutil.NewImageFromFile("imgs/fire.png") 499 | if err != nil { 500 | log.Fatal(err) 501 | } 502 | fmt.Println(engine_version) 503 | ebiten.SetWindowTitle(engine_version) 504 | ebiten.SetWindowSize(1024, 512) 505 | //ebiten.SetCursorMode(CursorModeCaptured) 506 | g := &game{} 507 | ebiten.RunGame(g) 508 | } 509 | 510 | func IsKeyTriggered(key ebiten.Key) bool { 511 | return keyStates[key] == 1 512 | } 513 | 514 | // CHANGEME 515 | func gun_sound() { 516 | var errA error 517 | mpv_cmd := fmt.Sprintf("/Applications/mpv.app/Contents/MacOS/mpv --really-quiet --volume=42 sound/gun.mp3") 518 | mpv_run, errA = exec.Command("bash", "-c", mpv_cmd).Output() 519 | if errA != nil { 520 | fmt.Printf("Error playing sound\n") 521 | } 522 | } 523 | 524 | func show2DMap(screen *ebiten.Image) { 525 | // Draw 2D map 526 | if STATE_SHOW_2D_MAP == 1 { 527 | for i := 0; i < mapX; i++ { 528 | for j := 0; j < mapY; j++ { 529 | if map_array[i*mapX+j] > 0 { 530 | opwall := &ebiten.DrawImageOptions{} 531 | opwall.GeoM.Translate(wall_posx, wall_posy) 532 | screen.DrawImage(wallImage, opwall) 533 | } 534 | if wall_posx < 240 { // 256 (16*16) - 16 (wall size in px). 535 | wall_posx += 16 536 | } else { 537 | wall_posx = 0 538 | wall_posy += 16 539 | } 540 | } 541 | } 542 | wall_posx = 0 543 | wall_posy = 0 544 | // Draw player as a rect 545 | ebitenutil.DrawRect(screen, float64(player_pos_x), float64(player_pos_y), 12, 12, color.Black) 546 | ebitenutil.DrawRect(screen, float64(player_pos_x), float64(player_pos_y), 4, 4, color.RGBA{255, 100, 100, 255}) 547 | } 548 | } 549 | -------------------------------------------------------------------------------- /sound/gun.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Myu-Unix/ray_engine/5469f152244674c4597373510e1f9c6733e32488/sound/gun.mp3 -------------------------------------------------------------------------------- /textures.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | var( 4 | 5 | texture_array= [512]int{ 6 | 45,100,35, 255,100,35, 45,255,35, 45,100,255, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 255,255,255, 7 | 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 255,255,255, 8 | 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 255,255,255, 9 | 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 255,255,255, 10 | 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 255,255,255, 11 | 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 255,255,255, 12 | 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 255,255,255, 13 | 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 255,255,255, 14 | 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 255,255,255, 15 | 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 50,50,50, 255,255,255, 16 | 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 45,100,35, 255,255,255, 17 | } 18 | 19 | texture_bw_array= [4096]int{ 20 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 21 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 22 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 23 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 24 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 25 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 26 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 27 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 28 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 29 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 30 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 31 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 32 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 33 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 34 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 35 | 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 36 | } 37 | 38 | texture_img_array= [3072]int { 39 | 23, 40 | 20, 41 | 22, 42 | 24, 43 | 23, 44 | 21, 45 | 24, 46 | 23, 47 | 20, 48 | 24, 49 | 23, 50 | 20, 51 | 23, 52 | 22, 53 | 20, 54 | 24, 55 | 22, 56 | 21, 57 | 25, 58 | 23, 59 | 22, 60 | 26, 61 | 24, 62 | 22, 63 | 26, 64 | 24, 65 | 24, 66 | 27, 67 | 26, 68 | 26, 69 | 30, 70 | 28, 71 | 27, 72 | 30, 73 | 28, 74 | 28, 75 | 30, 76 | 28, 77 | 29, 78 | 31, 79 | 28, 80 | 29, 81 | 32, 82 | 29, 83 | 30, 84 | 32, 85 | 30, 86 | 32, 87 | 34, 88 | 30, 89 | 31, 90 | 32, 91 | 29, 92 | 30, 93 | 37, 94 | 28, 95 | 28, 96 | 29, 97 | 27, 98 | 26, 99 | 34, 100 | 26, 101 | 27, 102 | 29, 103 | 26, 104 | 26, 105 | 28, 106 | 25, 107 | 24, 108 | 27, 109 | 24, 110 | 25, 111 | 26, 112 | 24, 113 | 25, 114 | 25, 115 | 23, 116 | 22, 117 | 25, 118 | 23, 119 | 21, 120 | 25, 121 | 24, 122 | 22, 123 | 26, 124 | 25, 125 | 22, 126 | 25, 127 | 24, 128 | 21, 129 | 27, 130 | 26, 131 | 23, 132 | 28, 133 | 27, 134 | 25, 135 | 22, 136 | 20, 137 | 18, 138 | 23, 139 | 21, 140 | 19, 141 | 23, 142 | 22, 143 | 20, 144 | 24, 145 | 23, 146 | 21, 147 | 25, 148 | 23, 149 | 22, 150 | 25, 151 | 23, 152 | 23, 153 | 26, 154 | 24, 155 | 23, 156 | 26, 157 | 24, 158 | 22, 159 | 26, 160 | 24, 161 | 25, 162 | 28, 163 | 25, 164 | 26, 165 | 30, 166 | 27, 167 | 28, 168 | 32, 169 | 29, 170 | 30, 171 | 33, 172 | 32, 173 | 33, 174 | 35, 175 | 33, 176 | 34, 177 | 36, 178 | 34, 179 | 34, 180 | 35, 181 | 33, 182 | 34, 183 | 36, 184 | 31, 185 | 33, 186 | 33, 187 | 29, 188 | 31, 189 | 31, 190 | 29, 191 | 30, 192 | 30, 193 | 27, 194 | 28, 195 | 30, 196 | 27, 197 | 29, 198 | 30, 199 | 27, 200 | 29, 201 | 28, 202 | 25, 203 | 26, 204 | 31, 205 | 25, 206 | 25, 207 | 27, 208 | 24, 209 | 24, 210 | 27, 211 | 23, 212 | 24, 213 | 26, 214 | 24, 215 | 24, 216 | 27, 217 | 25, 218 | 24, 219 | 28, 220 | 27, 221 | 26, 222 | 29, 223 | 28, 224 | 27, 225 | 30, 226 | 28, 227 | 27, 228 | 29, 229 | 28, 230 | 26, 231 | 22, 232 | 21, 233 | 19, 234 | 23, 235 | 21, 236 | 19, 237 | 24, 238 | 22, 239 | 22, 240 | 25, 241 | 23, 242 | 23, 243 | 26, 244 | 24, 245 | 24, 246 | 27, 247 | 24, 248 | 24, 249 | 27, 250 | 25, 251 | 26, 252 | 27, 253 | 25, 254 | 26, 255 | 26, 256 | 24, 257 | 26, 258 | 27, 259 | 25, 260 | 26, 261 | 29, 262 | 28, 263 | 28, 264 | 32, 265 | 30, 266 | 31, 267 | 35, 268 | 34, 269 | 35, 270 | 36, 271 | 32, 272 | 34, 273 | 33, 274 | 25, 275 | 29, 276 | 31, 277 | 23, 278 | 27, 279 | 44, 280 | 23, 281 | 27, 282 | 30, 283 | 22, 284 | 26, 285 | 34, 286 | 24, 287 | 28, 288 | 32, 289 | 25, 290 | 28, 291 | 30, 292 | 27, 293 | 30, 294 | 40, 295 | 27, 296 | 29, 297 | 28, 298 | 26, 299 | 27, 300 | 28, 301 | 24, 302 | 25, 303 | 27, 304 | 24, 305 | 25, 306 | 26, 307 | 24, 308 | 25, 309 | 28, 310 | 25, 311 | 26, 312 | 29, 313 | 26, 314 | 27, 315 | 30, 316 | 27, 317 | 29, 318 | 30, 319 | 28, 320 | 28, 321 | 32, 322 | 30, 323 | 29, 324 | 32, 325 | 30, 326 | 30, 327 | 23, 328 | 22, 329 | 21, 330 | 23, 331 | 22, 332 | 21, 333 | 24, 334 | 22, 335 | 22, 336 | 27, 337 | 24, 338 | 26, 339 | 28, 340 | 26, 341 | 26, 342 | 29, 343 | 27, 344 | 26, 345 | 29, 346 | 27, 347 | 28, 348 | 28, 349 | 26, 350 | 27, 351 | 26, 352 | 25, 353 | 26, 354 | 27, 355 | 25, 356 | 26, 357 | 29, 358 | 28, 359 | 28, 360 | 33, 361 | 31, 362 | 32, 363 | 34, 364 | 28, 365 | 31, 366 | 35, 367 | 26, 368 | 30, 369 | 38, 370 | 26, 371 | 32, 372 | 55, 373 | 25, 374 | 31, 375 | 32, 376 | 22, 377 | 26, 378 | 37, 379 | 23, 380 | 28, 381 | 35, 382 | 24, 383 | 30, 384 | 34, 385 | 24, 386 | 28, 387 | 33, 388 | 25, 389 | 29, 390 | 39, 391 | 33, 392 | 37, 393 | 31, 394 | 29, 395 | 30, 396 | 29, 397 | 26, 398 | 28, 399 | 29, 400 | 27, 401 | 28, 402 | 29, 403 | 26, 404 | 28, 405 | 29, 406 | 26, 407 | 27, 408 | 29, 409 | 26, 410 | 27, 411 | 30, 412 | 28, 413 | 29, 414 | 31, 415 | 29, 416 | 29, 417 | 33, 418 | 31, 419 | 32, 420 | 34, 421 | 32, 422 | 33, 423 | 24, 424 | 22, 425 | 23, 426 | 25, 427 | 23, 428 | 24, 429 | 26, 430 | 24, 431 | 24, 432 | 27, 433 | 25, 434 | 25, 435 | 29, 436 | 27, 437 | 27, 438 | 28, 439 | 27, 440 | 27, 441 | 30, 442 | 28, 443 | 29, 444 | 28, 445 | 26, 446 | 27, 447 | 27, 448 | 26, 449 | 26, 450 | 27, 451 | 27, 452 | 27, 453 | 30, 454 | 29, 455 | 30, 456 | 32, 457 | 26, 458 | 29, 459 | 33, 460 | 25, 461 | 30, 462 | 39, 463 | 26, 464 | 33, 465 | 83, 466 | 27, 467 | 40, 468 | 69, 469 | 28, 470 | 38, 471 | 47, 472 | 28, 473 | 34, 474 | 41, 475 | 28, 476 | 35, 477 | 40, 478 | 27, 479 | 35, 480 | 34, 481 | 24, 482 | 29, 483 | 36, 484 | 24, 485 | 28, 486 | 48, 487 | 37, 488 | 43, 489 | 33, 490 | 33, 491 | 33, 492 | 33, 493 | 31, 494 | 33, 495 | 31, 496 | 29, 497 | 30, 498 | 30, 499 | 27, 500 | 29, 501 | 29, 502 | 27, 503 | 28, 504 | 29, 505 | 27, 506 | 28, 507 | 29, 508 | 27, 509 | 28, 510 | 31, 511 | 29, 512 | 30, 513 | 32, 514 | 30, 515 | 31, 516 | 34, 517 | 31, 518 | 33, 519 | 24, 520 | 22, 521 | 23, 522 | 27, 523 | 25, 524 | 26, 525 | 27, 526 | 25, 527 | 26, 528 | 29, 529 | 27, 530 | 28, 531 | 31, 532 | 28, 533 | 29, 534 | 31, 535 | 28, 536 | 29, 537 | 31, 538 | 28, 539 | 30, 540 | 31, 541 | 28, 542 | 29, 543 | 31, 544 | 29, 545 | 30, 546 | 31, 547 | 31, 548 | 31, 549 | 33, 550 | 31, 551 | 32, 552 | 33, 553 | 25, 554 | 30, 555 | 36, 556 | 27, 557 | 33, 558 | 66, 559 | 27, 560 | 36, 561 | 101, 562 | 28, 563 | 43, 564 | 50, 565 | 29, 566 | 37, 567 | 42, 568 | 28, 569 | 35, 570 | 44, 571 | 30, 572 | 39, 573 | 41, 574 | 28, 575 | 36, 576 | 34, 577 | 25, 578 | 30, 579 | 35, 580 | 23, 581 | 28, 582 | 46, 583 | 39, 584 | 46, 585 | 37, 586 | 34, 587 | 36, 588 | 34, 589 | 33, 590 | 34, 591 | 33, 592 | 30, 593 | 31, 594 | 31, 595 | 28, 596 | 30, 597 | 30, 598 | 28, 599 | 29, 600 | 29, 601 | 29, 602 | 28, 603 | 29, 604 | 28, 605 | 28, 606 | 30, 607 | 28, 608 | 29, 609 | 32, 610 | 29, 611 | 31, 612 | 31, 613 | 28, 614 | 29, 615 | 27, 616 | 25, 617 | 25, 618 | 27, 619 | 25, 620 | 25, 621 | 28, 622 | 25, 623 | 26, 624 | 29, 625 | 28, 626 | 29, 627 | 31, 628 | 28, 629 | 29, 630 | 30, 631 | 29, 632 | 30, 633 | 31, 634 | 29, 635 | 30, 636 | 31, 637 | 28, 638 | 30, 639 | 32, 640 | 29, 641 | 32, 642 | 32, 643 | 32, 644 | 32, 645 | 34, 646 | 31, 647 | 33, 648 | 35, 649 | 26, 650 | 31, 651 | 38, 652 | 25, 653 | 31, 654 | 87, 655 | 27, 656 | 40, 657 | 99, 658 | 27, 659 | 40, 660 | 39, 661 | 27, 662 | 34, 663 | 37, 664 | 26, 665 | 32, 666 | 38, 667 | 27, 668 | 34, 669 | 41, 670 | 27, 671 | 34, 672 | 36, 673 | 26, 674 | 33, 675 | 34, 676 | 24, 677 | 30, 678 | 54, 679 | 50, 680 | 62, 681 | 42, 682 | 36, 683 | 40, 684 | 34, 685 | 33, 686 | 34, 687 | 34, 688 | 32, 689 | 33, 690 | 34, 691 | 31, 692 | 32, 693 | 31, 694 | 29, 695 | 30, 696 | 29, 697 | 28, 698 | 29, 699 | 29, 700 | 27, 701 | 28, 702 | 29, 703 | 27, 704 | 28, 705 | 31, 706 | 28, 707 | 29, 708 | 28, 709 | 26, 710 | 26, 711 | 28, 712 | 26, 713 | 25, 714 | 27, 715 | 24, 716 | 25, 717 | 28, 718 | 25, 719 | 27, 720 | 29, 721 | 28, 722 | 29, 723 | 29, 724 | 28, 725 | 28, 726 | 30, 727 | 28, 728 | 30, 729 | 30, 730 | 29, 731 | 30, 732 | 31, 733 | 30, 734 | 32, 735 | 32, 736 | 31, 737 | 33, 738 | 34, 739 | 33, 740 | 34, 741 | 35, 742 | 29, 743 | 32, 744 | 34, 745 | 25, 746 | 29, 747 | 47, 748 | 33, 749 | 41, 750 | 93, 751 | 28, 752 | 41, 753 | 85, 754 | 26, 755 | 38, 756 | 36, 757 | 24, 758 | 30, 759 | 38, 760 | 25, 761 | 30, 762 | 37, 763 | 24, 764 | 29, 765 | 40, 766 | 25, 767 | 30, 768 | 33, 769 | 23, 770 | 28, 771 | 33, 772 | 23, 773 | 28, 774 | 47, 775 | 41, 776 | 50, 777 | 42, 778 | 36, 779 | 40, 780 | 35, 781 | 34, 782 | 35, 783 | 34, 784 | 34, 785 | 34, 786 | 33, 787 | 33, 788 | 34, 789 | 32, 790 | 29, 791 | 30, 792 | 31, 793 | 28, 794 | 29, 795 | 30, 796 | 27, 797 | 28, 798 | 28, 799 | 26, 800 | 27, 801 | 29, 802 | 27, 803 | 28, 804 | 29, 805 | 27, 806 | 28, 807 | 61, 808 | 56, 809 | 63, 810 | 30, 811 | 26, 812 | 29, 813 | 27, 814 | 24, 815 | 26, 816 | 27, 817 | 26, 818 | 26, 819 | 28, 820 | 27, 821 | 28, 822 | 28, 823 | 28, 824 | 29, 825 | 30, 826 | 29, 827 | 29, 828 | 31, 829 | 30, 830 | 31, 831 | 32, 832 | 32, 833 | 33, 834 | 33, 835 | 34, 836 | 33, 837 | 35, 838 | 26, 839 | 32, 840 | 33, 841 | 23, 842 | 29, 843 | 69, 844 | 30, 845 | 39, 846 | 98, 847 | 32, 848 | 45, 849 | 91, 850 | 27, 851 | 37, 852 | 49, 853 | 20, 854 | 24, 855 | 54, 856 | 22, 857 | 27, 858 | 50, 859 | 18, 860 | 22, 861 | 44, 862 | 20, 863 | 24, 864 | 41, 865 | 25, 866 | 30, 867 | 58, 868 | 25, 869 | 29, 870 | 57, 871 | 30, 872 | 34, 873 | 35, 874 | 30, 875 | 33, 876 | 36, 877 | 35, 878 | 36, 879 | 33, 880 | 33, 881 | 33, 882 | 33, 883 | 33, 884 | 34, 885 | 33, 886 | 31, 887 | 32, 888 | 31, 889 | 28, 890 | 30, 891 | 29, 892 | 26, 893 | 27, 894 | 29, 895 | 27, 896 | 28, 897 | 29, 898 | 27, 899 | 28, 900 | 29, 901 | 27, 902 | 28, 903 | 71, 904 | 67, 905 | 75, 906 | 66, 907 | 61, 908 | 69, 909 | 35, 910 | 31, 911 | 34, 912 | 26, 913 | 23, 914 | 24, 915 | 28, 916 | 27, 917 | 27, 918 | 29, 919 | 28, 920 | 28, 921 | 30, 922 | 28, 923 | 29, 924 | 31, 925 | 31, 926 | 32, 927 | 32, 928 | 32, 929 | 32, 930 | 34, 931 | 32, 932 | 33, 933 | 34, 934 | 24, 935 | 31, 936 | 61, 937 | 25, 938 | 29, 939 | 91, 940 | 25, 941 | 36, 942 | 132, 943 | 61, 944 | 76, 945 | 130, 946 | 40, 947 | 52, 948 | 102, 949 | 36, 950 | 44, 951 | 113, 952 | 46, 953 | 55, 954 | 110, 955 | 45, 956 | 54, 957 | 98, 958 | 46, 959 | 56, 960 | 88, 961 | 53, 962 | 64, 963 | 45, 964 | 22, 965 | 27, 966 | 93, 967 | 27, 968 | 30, 969 | 30, 970 | 23, 971 | 26, 972 | 37, 973 | 35, 974 | 37, 975 | 34, 976 | 34, 977 | 35, 978 | 33, 979 | 33, 980 | 33, 981 | 32, 982 | 31, 983 | 33, 984 | 30, 985 | 28, 986 | 30, 987 | 28, 988 | 26, 989 | 27, 990 | 29, 991 | 27, 992 | 28, 993 | 29, 994 | 27, 995 | 28, 996 | 27, 997 | 25, 998 | 26, 999 | 49, 1000 | 43, 1001 | 48, 1002 | 78, 1003 | 72, 1004 | 82, 1005 | 87, 1006 | 81, 1007 | 92, 1008 | 64, 1009 | 59, 1010 | 66, 1011 | 37, 1012 | 33, 1013 | 36, 1014 | 30, 1015 | 28, 1016 | 29, 1017 | 28, 1018 | 28, 1019 | 30, 1020 | 31, 1021 | 31, 1022 | 32, 1023 | 33, 1024 | 32, 1025 | 33, 1026 | 37, 1027 | 27, 1028 | 32, 1029 | 35, 1030 | 23, 1031 | 29, 1032 | 78, 1033 | 27, 1034 | 31, 1035 | 107, 1036 | 34, 1037 | 44, 1038 | 148, 1039 | 65, 1040 | 78, 1041 | 165, 1042 | 68, 1043 | 81, 1044 | 155, 1045 | 66, 1046 | 79, 1047 | 185, 1048 | 76, 1049 | 91, 1050 | 150, 1051 | 65, 1052 | 78, 1053 | 146, 1054 | 65, 1055 | 78, 1056 | 109, 1057 | 55, 1058 | 66, 1059 | 96, 1060 | 27, 1061 | 30, 1062 | 83, 1063 | 27, 1064 | 30, 1065 | 31, 1066 | 21, 1067 | 25, 1068 | 33, 1069 | 25, 1070 | 28, 1071 | 36, 1072 | 33, 1073 | 34, 1074 | 33, 1075 | 33, 1076 | 33, 1077 | 31, 1078 | 31, 1079 | 31, 1080 | 30, 1081 | 29, 1082 | 30, 1083 | 29, 1084 | 27, 1085 | 29, 1086 | 28, 1087 | 26, 1088 | 27, 1089 | 29, 1090 | 27, 1091 | 28, 1092 | 28, 1093 | 25, 1094 | 27, 1095 | 27, 1096 | 24, 1097 | 26, 1098 | 30, 1099 | 25, 1100 | 27, 1101 | 59, 1102 | 51, 1103 | 58, 1104 | 65, 1105 | 60, 1106 | 68, 1107 | 79, 1108 | 67, 1109 | 78, 1110 | 101, 1111 | 86, 1112 | 100, 1113 | 93, 1114 | 78, 1115 | 91, 1116 | 77, 1117 | 71, 1118 | 77, 1119 | 54, 1120 | 38, 1121 | 45, 1122 | 40, 1123 | 25, 1124 | 31, 1125 | 38, 1126 | 22, 1127 | 28, 1128 | 83, 1129 | 32, 1130 | 36, 1131 | 134, 1132 | 42, 1133 | 52, 1134 | 156, 1135 | 68, 1136 | 76, 1137 | 215, 1138 | 50, 1139 | 51, 1140 | 165, 1141 | 66, 1142 | 77, 1143 | 165, 1144 | 80, 1145 | 96, 1146 | 155, 1147 | 65, 1148 | 76, 1149 | 203, 1150 | 51, 1151 | 52, 1152 | 134, 1153 | 69, 1154 | 77, 1155 | 122, 1156 | 29, 1157 | 31, 1158 | 45, 1159 | 23, 1160 | 27, 1161 | 34, 1162 | 22, 1163 | 26, 1164 | 37, 1165 | 21, 1166 | 27, 1167 | 39, 1168 | 23, 1169 | 28, 1170 | 35, 1171 | 32, 1172 | 33, 1173 | 31, 1174 | 31, 1175 | 32, 1176 | 31, 1177 | 29, 1178 | 30, 1179 | 29, 1180 | 27, 1181 | 28, 1182 | 28, 1183 | 26, 1184 | 27, 1185 | 29, 1186 | 26, 1187 | 27, 1188 | 28, 1189 | 26, 1190 | 27, 1191 | 27, 1192 | 24, 1193 | 27, 1194 | 27, 1195 | 24, 1196 | 27, 1197 | 27, 1198 | 24, 1199 | 26, 1200 | 40, 1201 | 33, 1202 | 37, 1203 | 118, 1204 | 101, 1205 | 117, 1206 | 119, 1207 | 104, 1208 | 121, 1209 | 123, 1210 | 106, 1211 | 123, 1212 | 160, 1213 | 143, 1214 | 159, 1215 | 152, 1216 | 144, 1217 | 158, 1218 | 75, 1219 | 62, 1220 | 71, 1221 | 47, 1222 | 35, 1223 | 42, 1224 | 118, 1225 | 44, 1226 | 45, 1227 | 152, 1228 | 36, 1229 | 40, 1230 | 158, 1231 | 41, 1232 | 46, 1233 | 174, 1234 | 33, 1235 | 37, 1236 | 177, 1237 | 47, 1238 | 54, 1239 | 183, 1240 | 48, 1241 | 56, 1242 | 172, 1243 | 47, 1244 | 54, 1245 | 168, 1246 | 30, 1247 | 34, 1248 | 166, 1249 | 39, 1250 | 43, 1251 | 106, 1252 | 35, 1253 | 40, 1254 | 102, 1255 | 84, 1256 | 95, 1257 | 35, 1258 | 23, 1259 | 26, 1260 | 48, 1261 | 23, 1262 | 31, 1263 | 39, 1264 | 19, 1265 | 26, 1266 | 44, 1267 | 22, 1268 | 28, 1269 | 37, 1270 | 29, 1271 | 32, 1272 | 31, 1273 | 30, 1274 | 32, 1275 | 33, 1276 | 29, 1277 | 31, 1278 | 31, 1279 | 28, 1280 | 30, 1281 | 29, 1282 | 27, 1283 | 28, 1284 | 29, 1285 | 27, 1286 | 28, 1287 | 27, 1288 | 24, 1289 | 25, 1290 | 26, 1291 | 23, 1292 | 25, 1293 | 26, 1294 | 23, 1295 | 25, 1296 | 31, 1297 | 25, 1298 | 26, 1299 | 71, 1300 | 48, 1301 | 56, 1302 | 102, 1303 | 83, 1304 | 96, 1305 | 121, 1306 | 103, 1307 | 121, 1308 | 121, 1309 | 103, 1310 | 120, 1311 | 128, 1312 | 107, 1313 | 124, 1314 | 111, 1315 | 91, 1316 | 105, 1317 | 43, 1318 | 36, 1319 | 42, 1320 | 43, 1321 | 34, 1322 | 41, 1323 | 73, 1324 | 33, 1325 | 38, 1326 | 63, 1327 | 31, 1328 | 37, 1329 | 122, 1330 | 41, 1331 | 47, 1332 | 112, 1333 | 29, 1334 | 34, 1335 | 130, 1336 | 28, 1337 | 33, 1338 | 115, 1339 | 34, 1340 | 40, 1341 | 122, 1342 | 50, 1343 | 56, 1344 | 57, 1345 | 28, 1346 | 33, 1347 | 66, 1348 | 26, 1349 | 31, 1350 | 94, 1351 | 70, 1352 | 83, 1353 | 71, 1354 | 54, 1355 | 63, 1356 | 53, 1357 | 23, 1358 | 31, 1359 | 57, 1360 | 24, 1361 | 33, 1362 | 62, 1363 | 24, 1364 | 34, 1365 | 63, 1366 | 24, 1367 | 34, 1368 | 53, 1369 | 24, 1370 | 32, 1371 | 54, 1372 | 27, 1373 | 34, 1374 | 32, 1375 | 29, 1376 | 31, 1377 | 32, 1378 | 29, 1379 | 31, 1380 | 32, 1381 | 29, 1382 | 30, 1383 | 27, 1384 | 25, 1385 | 25, 1386 | 26, 1387 | 24, 1388 | 23, 1389 | 26, 1390 | 25, 1391 | 23, 1392 | 28, 1393 | 26, 1394 | 25, 1395 | 32, 1396 | 31, 1397 | 31, 1398 | 75, 1399 | 62, 1400 | 71, 1401 | 109, 1402 | 87, 1403 | 102, 1404 | 83, 1405 | 69, 1406 | 80, 1407 | 84, 1408 | 50, 1409 | 61, 1410 | 65, 1411 | 51, 1412 | 60, 1413 | 46, 1414 | 27, 1415 | 35, 1416 | 53, 1417 | 25, 1418 | 33, 1419 | 45, 1420 | 23, 1421 | 28, 1422 | 56, 1423 | 25, 1424 | 29, 1425 | 89, 1426 | 72, 1427 | 80, 1428 | 70, 1429 | 57, 1430 | 63, 1431 | 77, 1432 | 58, 1433 | 65, 1434 | 64, 1435 | 51, 1436 | 56, 1437 | 91, 1438 | 75, 1439 | 83, 1440 | 69, 1441 | 45, 1442 | 50, 1443 | 46, 1444 | 33, 1445 | 41, 1446 | 101, 1447 | 83, 1448 | 97, 1449 | 105, 1450 | 87, 1451 | 100, 1452 | 56, 1453 | 47, 1454 | 51, 1455 | 58, 1456 | 26, 1457 | 35, 1458 | 74, 1459 | 25, 1460 | 37, 1461 | 76, 1462 | 23, 1463 | 35, 1464 | 71, 1465 | 26, 1466 | 37, 1467 | 57, 1468 | 28, 1469 | 35, 1470 | 32, 1471 | 29, 1472 | 32, 1473 | 31, 1474 | 28, 1475 | 32, 1476 | 33, 1477 | 30, 1478 | 32, 1479 | 25, 1480 | 22, 1481 | 23, 1482 | 26, 1483 | 23, 1484 | 24, 1485 | 27, 1486 | 24, 1487 | 25, 1488 | 27, 1489 | 26, 1490 | 26, 1491 | 32, 1492 | 30, 1493 | 31, 1494 | 36, 1495 | 33, 1496 | 34, 1497 | 49, 1498 | 43, 1499 | 47, 1500 | 85, 1501 | 51, 1502 | 62, 1503 | 97, 1504 | 27, 1505 | 38, 1506 | 96, 1507 | 27, 1508 | 40, 1509 | 56, 1510 | 26, 1511 | 33, 1512 | 45, 1513 | 26, 1514 | 33, 1515 | 65, 1516 | 29, 1517 | 34, 1518 | 60, 1519 | 31, 1520 | 35, 1521 | 63, 1522 | 25, 1523 | 34, 1524 | 66, 1525 | 30, 1526 | 39, 1527 | 73, 1528 | 46, 1529 | 57, 1530 | 76, 1531 | 43, 1532 | 51, 1533 | 74, 1534 | 41, 1535 | 49, 1536 | 58, 1537 | 28, 1538 | 32, 1539 | 79, 1540 | 62, 1541 | 74, 1542 | 102, 1543 | 84, 1544 | 99, 1545 | 106, 1546 | 89, 1547 | 103, 1548 | 77, 1549 | 61, 1550 | 67, 1551 | 49, 1552 | 34, 1553 | 39, 1554 | 47, 1555 | 35, 1556 | 39, 1557 | 84, 1558 | 25, 1559 | 37, 1560 | 63, 1561 | 24, 1562 | 33, 1563 | 55, 1564 | 25, 1565 | 32, 1566 | 30, 1567 | 27, 1568 | 30, 1569 | 30, 1570 | 27, 1571 | 30, 1572 | 30, 1573 | 28, 1574 | 29, 1575 | 25, 1576 | 22, 1577 | 23, 1578 | 26, 1579 | 23, 1580 | 25, 1581 | 27, 1582 | 25, 1583 | 26, 1584 | 29, 1585 | 27, 1586 | 28, 1587 | 32, 1588 | 29, 1589 | 30, 1590 | 36, 1591 | 34, 1592 | 36, 1593 | 39, 1594 | 37, 1595 | 38, 1596 | 71, 1597 | 36, 1598 | 41, 1599 | 81, 1600 | 25, 1601 | 37, 1602 | 67, 1603 | 24, 1604 | 33, 1605 | 90, 1606 | 29, 1607 | 40, 1608 | 85, 1609 | 28, 1610 | 39, 1611 | 47, 1612 | 28, 1613 | 34, 1614 | 52, 1615 | 32, 1616 | 36, 1617 | 65, 1618 | 26, 1619 | 34, 1620 | 83, 1621 | 26, 1622 | 38, 1623 | 91, 1624 | 39, 1625 | 50, 1626 | 79, 1627 | 28, 1628 | 38, 1629 | 72, 1630 | 25, 1631 | 35, 1632 | 69, 1633 | 37, 1634 | 46, 1635 | 68, 1636 | 56, 1637 | 63, 1638 | 96, 1639 | 81, 1640 | 91, 1641 | 102, 1642 | 87, 1643 | 101, 1644 | 94, 1645 | 79, 1646 | 88, 1647 | 46, 1648 | 42, 1649 | 46, 1650 | 49, 1651 | 35, 1652 | 39, 1653 | 90, 1654 | 25, 1655 | 38, 1656 | 45, 1657 | 29, 1658 | 33, 1659 | 57, 1660 | 26, 1661 | 33, 1662 | 30, 1663 | 27, 1664 | 30, 1665 | 29, 1666 | 27, 1667 | 28, 1668 | 29, 1669 | 27, 1670 | 28, 1671 | 25, 1672 | 23, 1673 | 24, 1674 | 27, 1675 | 25, 1676 | 26, 1677 | 28, 1678 | 26, 1679 | 27, 1680 | 29, 1681 | 27, 1682 | 28, 1683 | 32, 1684 | 30, 1685 | 31, 1686 | 35, 1687 | 34, 1688 | 36, 1689 | 39, 1690 | 37, 1691 | 38, 1692 | 44, 1693 | 39, 1694 | 40, 1695 | 69, 1696 | 32, 1697 | 39, 1698 | 68, 1699 | 34, 1700 | 40, 1701 | 52, 1702 | 43, 1703 | 45, 1704 | 63, 1705 | 40, 1706 | 44, 1707 | 92, 1708 | 37, 1709 | 48, 1710 | 73, 1711 | 29, 1712 | 38, 1713 | 51, 1714 | 31, 1715 | 36, 1716 | 80, 1717 | 34, 1718 | 44, 1719 | 175, 1720 | 156, 1721 | 161, 1722 | 89, 1723 | 45, 1724 | 56, 1725 | 75, 1726 | 35, 1727 | 45, 1728 | 56, 1729 | 45, 1730 | 52, 1731 | 93, 1732 | 80, 1733 | 89, 1734 | 99, 1735 | 85, 1736 | 94, 1737 | 102, 1738 | 87, 1739 | 101, 1740 | 104, 1741 | 87, 1742 | 101, 1743 | 70, 1744 | 52, 1745 | 60, 1746 | 74, 1747 | 29, 1748 | 38, 1749 | 63, 1750 | 30, 1751 | 36, 1752 | 33, 1753 | 31, 1754 | 33, 1755 | 61, 1756 | 26, 1757 | 33, 1758 | 32, 1759 | 29, 1760 | 33, 1761 | 30, 1762 | 28, 1763 | 29, 1764 | 28, 1765 | 27, 1766 | 28, 1767 | 26, 1768 | 25, 1769 | 26, 1770 | 28, 1771 | 26, 1772 | 27, 1773 | 29, 1774 | 27, 1775 | 28, 1776 | 30, 1777 | 27, 1778 | 28, 1779 | 31, 1780 | 29, 1781 | 30, 1782 | 31, 1783 | 31, 1784 | 33, 1785 | 36, 1786 | 35, 1787 | 36, 1788 | 37, 1789 | 37, 1790 | 38, 1791 | 40, 1792 | 39, 1793 | 40, 1794 | 46, 1795 | 45, 1796 | 47, 1797 | 57, 1798 | 52, 1799 | 56, 1800 | 76, 1801 | 55, 1802 | 61, 1803 | 111, 1804 | 98, 1805 | 108, 1806 | 89, 1807 | 60, 1808 | 70, 1809 | 87, 1810 | 29, 1811 | 43, 1812 | 64, 1813 | 32, 1814 | 39, 1815 | 168, 1816 | 162, 1817 | 171, 1818 | 69, 1819 | 63, 1820 | 82, 1821 | 48, 1822 | 54, 1823 | 82, 1824 | 92, 1825 | 70, 1826 | 82, 1827 | 89, 1828 | 55, 1829 | 65, 1830 | 106, 1831 | 87, 1832 | 102, 1833 | 119, 1834 | 99, 1835 | 113, 1836 | 120, 1837 | 100, 1838 | 115, 1839 | 58, 1840 | 52, 1841 | 58, 1842 | 41, 1843 | 39, 1844 | 43, 1845 | 53, 1846 | 32, 1847 | 37, 1848 | 86, 1849 | 26, 1850 | 37, 1851 | 64, 1852 | 29, 1853 | 36, 1854 | 32, 1855 | 30, 1856 | 33, 1857 | 31, 1858 | 28, 1859 | 30, 1860 | 28, 1861 | 26, 1862 | 27, 1863 | 27, 1864 | 26, 1865 | 27, 1866 | 29, 1867 | 27, 1868 | 28, 1869 | 28, 1870 | 26, 1871 | 27, 1872 | 31, 1873 | 28, 1874 | 29, 1875 | 31, 1876 | 29, 1877 | 30, 1878 | 32, 1879 | 31, 1880 | 32, 1881 | 34, 1882 | 33, 1883 | 34, 1884 | 37, 1885 | 37, 1886 | 37, 1887 | 41, 1888 | 40, 1889 | 40, 1890 | 54, 1891 | 48, 1892 | 51, 1893 | 109, 1894 | 82, 1895 | 96, 1896 | 107, 1897 | 85, 1898 | 97, 1899 | 100, 1900 | 65, 1901 | 74, 1902 | 76, 1903 | 66, 1904 | 83, 1905 | 48, 1906 | 48, 1907 | 69, 1908 | 80, 1909 | 32, 1910 | 43, 1911 | 165, 1912 | 153, 1913 | 162, 1914 | 76, 1915 | 61, 1916 | 69, 1917 | 61, 1918 | 50, 1919 | 61, 1920 | 92, 1921 | 44, 1922 | 57, 1923 | 103, 1924 | 84, 1925 | 99, 1926 | 112, 1927 | 93, 1928 | 108, 1929 | 122, 1930 | 103, 1931 | 117, 1932 | 119, 1933 | 99, 1934 | 114, 1935 | 43, 1936 | 43, 1937 | 46, 1938 | 40, 1939 | 41, 1940 | 43, 1941 | 47, 1942 | 37, 1943 | 40, 1944 | 53, 1945 | 32, 1946 | 36, 1947 | 34, 1948 | 33, 1949 | 36, 1950 | 33, 1951 | 32, 1952 | 35, 1953 | 31, 1954 | 29, 1955 | 31, 1956 | 28, 1957 | 26, 1958 | 27, 1959 | 27, 1960 | 27, 1961 | 27, 1962 | 28, 1963 | 26, 1964 | 27, 1965 | 27, 1966 | 25, 1967 | 27, 1968 | 30, 1969 | 27, 1970 | 28, 1971 | 31, 1972 | 28, 1973 | 30, 1974 | 31, 1975 | 29, 1976 | 31, 1977 | 34, 1978 | 33, 1979 | 34, 1980 | 38, 1981 | 38, 1982 | 38, 1983 | 42, 1984 | 42, 1985 | 42, 1986 | 93, 1987 | 71, 1988 | 82, 1989 | 133, 1990 | 112, 1991 | 131, 1992 | 123, 1993 | 104, 1994 | 120, 1995 | 108, 1996 | 69, 1997 | 83, 1998 | 86, 1999 | 51, 2000 | 63, 2001 | 91, 2002 | 65, 2003 | 77, 2004 | 63, 2005 | 53, 2006 | 62, 2007 | 187, 2008 | 184, 2009 | 193, 2010 | 179, 2011 | 161, 2012 | 169, 2013 | 98, 2014 | 73, 2015 | 81, 2016 | 56, 2017 | 41, 2018 | 48, 2019 | 90, 2020 | 73, 2021 | 86, 2022 | 112, 2023 | 94, 2024 | 109, 2025 | 120, 2026 | 99, 2027 | 114, 2028 | 110, 2029 | 91, 2030 | 105, 2031 | 42, 2032 | 43, 2033 | 47, 2034 | 40, 2035 | 41, 2036 | 44, 2037 | 38, 2038 | 38, 2039 | 41, 2040 | 37, 2041 | 36, 2042 | 38, 2043 | 35, 2044 | 33, 2045 | 35, 2046 | 33, 2047 | 32, 2048 | 34, 2049 | 31, 2050 | 28, 2051 | 31, 2052 | 28, 2053 | 26, 2054 | 29, 2055 | 27, 2056 | 26, 2057 | 27, 2058 | 28, 2059 | 26, 2060 | 27, 2061 | 28, 2062 | 26, 2063 | 27, 2064 | 28, 2065 | 26, 2066 | 27, 2067 | 31, 2068 | 35, 2069 | 46, 2070 | 34, 2071 | 61, 2072 | 84, 2073 | 38, 2074 | 69, 2075 | 88, 2076 | 44, 2077 | 36, 2078 | 38, 2079 | 72, 2080 | 33, 2081 | 40, 2082 | 124, 2083 | 102, 2084 | 121, 2085 | 141, 2086 | 124, 2087 | 146, 2088 | 127, 2089 | 103, 2090 | 120, 2091 | 121, 2092 | 81, 2093 | 95, 2094 | 90, 2095 | 53, 2096 | 64, 2097 | 86, 2098 | 50, 2099 | 59, 2100 | 115, 2101 | 97, 2102 | 110, 2103 | 214, 2104 | 206, 2105 | 217, 2106 | 147, 2107 | 134, 2108 | 143, 2109 | 115, 2110 | 89, 2111 | 103, 2112 | 107, 2113 | 32, 2114 | 43, 2115 | 84, 2116 | 32, 2117 | 39, 2118 | 70, 2119 | 57, 2120 | 66, 2121 | 107, 2122 | 88, 2123 | 102, 2124 | 98, 2125 | 81, 2126 | 94, 2127 | 43, 2128 | 44, 2129 | 47, 2130 | 41, 2131 | 42, 2132 | 45, 2133 | 39, 2134 | 39, 2135 | 42, 2136 | 38, 2137 | 38, 2138 | 40, 2139 | 36, 2140 | 34, 2141 | 36, 2142 | 33, 2143 | 32, 2144 | 33, 2145 | 30, 2146 | 28, 2147 | 30, 2148 | 28, 2149 | 26, 2150 | 28, 2151 | 28, 2152 | 26, 2153 | 27, 2154 | 28, 2155 | 26, 2156 | 27, 2157 | 28, 2158 | 26, 2159 | 27, 2160 | 28, 2161 | 26, 2162 | 27, 2163 | 61, 2164 | 29, 2165 | 35, 2166 | 58, 2167 | 65, 2168 | 95, 2169 | 42, 2170 | 84, 2171 | 115, 2172 | 72, 2173 | 59, 2174 | 79, 2175 | 90, 2176 | 38, 2177 | 50, 2178 | 139, 2179 | 124, 2180 | 145, 2181 | 143, 2182 | 124, 2183 | 147, 2184 | 70, 2185 | 45, 2186 | 53, 2187 | 72, 2188 | 61, 2189 | 77, 2190 | 77, 2191 | 62, 2192 | 83, 2193 | 125, 2194 | 74, 2195 | 84, 2196 | 137, 2197 | 85, 2198 | 93, 2199 | 194, 2200 | 185, 2201 | 197, 2202 | 112, 2203 | 89, 2204 | 103, 2205 | 96, 2206 | 70, 2207 | 82, 2208 | 58, 2209 | 42, 2210 | 57, 2211 | 109, 2212 | 35, 2213 | 47, 2214 | 127, 2215 | 30, 2216 | 39, 2217 | 72, 2218 | 35, 2219 | 41, 2220 | 63, 2221 | 52, 2222 | 61, 2223 | 41, 2224 | 42, 2225 | 45, 2226 | 40, 2227 | 42, 2228 | 44, 2229 | 39, 2230 | 40, 2231 | 43, 2232 | 38, 2233 | 38, 2234 | 41, 2235 | 37, 2236 | 35, 2237 | 36, 2238 | 33, 2239 | 33, 2240 | 35, 2241 | 30, 2242 | 28, 2243 | 31, 2244 | 28, 2245 | 26, 2246 | 27, 2247 | 27, 2248 | 25, 2249 | 26, 2250 | 28, 2251 | 26, 2252 | 27, 2253 | 29, 2254 | 27, 2255 | 28, 2256 | 34, 2257 | 27, 2258 | 29, 2259 | 93, 2260 | 32, 2261 | 43, 2262 | 95, 2263 | 32, 2264 | 44, 2265 | 74, 2266 | 61, 2267 | 86, 2268 | 46, 2269 | 78, 2270 | 107, 2271 | 46, 2272 | 66, 2273 | 93, 2274 | 42, 2275 | 106, 2276 | 139, 2277 | 56, 2278 | 59, 2279 | 75, 2280 | 72, 2281 | 58, 2282 | 75, 2283 | 92, 2284 | 72, 2285 | 94, 2286 | 121, 2287 | 104, 2288 | 115, 2289 | 177, 2290 | 85, 2291 | 91, 2292 | 121, 2293 | 67, 2294 | 82, 2295 | 141, 2296 | 116, 2297 | 131, 2298 | 145, 2299 | 116, 2300 | 128, 2301 | 107, 2302 | 90, 2303 | 101, 2304 | 42, 2305 | 31, 2306 | 39, 2307 | 33, 2308 | 24, 2309 | 29, 2310 | 67, 2311 | 29, 2312 | 36, 2313 | 122, 2314 | 28, 2315 | 37, 2316 | 102, 2317 | 31, 2318 | 39, 2319 | 48, 2320 | 35, 2321 | 39, 2322 | 41, 2323 | 39, 2324 | 42, 2325 | 39, 2326 | 39, 2327 | 41, 2328 | 38, 2329 | 38, 2330 | 40, 2331 | 36, 2332 | 35, 2333 | 37, 2334 | 33, 2335 | 32, 2336 | 34, 2337 | 29, 2338 | 28, 2339 | 30, 2340 | 27, 2341 | 25, 2342 | 27, 2343 | 28, 2344 | 26, 2345 | 27, 2346 | 28, 2347 | 27, 2348 | 28, 2349 | 29, 2350 | 27, 2351 | 28, 2352 | 75, 2353 | 29, 2354 | 36, 2355 | 97, 2356 | 34, 2357 | 46, 2358 | 92, 2359 | 32, 2360 | 44, 2361 | 72, 2362 | 46, 2363 | 64, 2364 | 49, 2365 | 86, 2366 | 114, 2367 | 137, 2368 | 125, 2369 | 144, 2370 | 133, 2371 | 123, 2372 | 145, 2373 | 58, 2374 | 49, 2375 | 60, 2376 | 70, 2377 | 56, 2378 | 70, 2379 | 106, 2380 | 88, 2381 | 99, 2382 | 160, 2383 | 66, 2384 | 74, 2385 | 166, 2386 | 137, 2387 | 145, 2388 | 201, 2389 | 196, 2390 | 205, 2391 | 129, 2392 | 108, 2393 | 125, 2394 | 125, 2395 | 97, 2396 | 108, 2397 | 57, 2398 | 45, 2399 | 57, 2400 | 54, 2401 | 43, 2402 | 53, 2403 | 36, 2404 | 26, 2405 | 30, 2406 | 32, 2407 | 22, 2408 | 25, 2409 | 32, 2410 | 22, 2411 | 25, 2412 | 78, 2413 | 31, 2414 | 37, 2415 | 106, 2416 | 32, 2417 | 43, 2418 | 72, 2419 | 36, 2420 | 42, 2421 | 44, 2422 | 38, 2423 | 41, 2424 | 39, 2425 | 37, 2426 | 39, 2427 | 36, 2428 | 36, 2429 | 37, 2430 | 32, 2431 | 31, 2432 | 33, 2433 | 30, 2434 | 28, 2435 | 31, 2436 | 27, 2437 | 25, 2438 | 27, 2439 | 27, 2440 | 27, 2441 | 27, 2442 | 28, 2443 | 27, 2444 | 28, 2445 | 30, 2446 | 27, 2447 | 28, 2448 | 98, 2449 | 33, 2450 | 45, 2451 | 94, 2452 | 34, 2453 | 46, 2454 | 73, 2455 | 32, 2456 | 39, 2457 | 35, 2458 | 50, 2459 | 70, 2460 | 113, 2461 | 110, 2462 | 125, 2463 | 164, 2464 | 152, 2465 | 171, 2466 | 167, 2467 | 153, 2468 | 172, 2469 | 85, 2470 | 75, 2471 | 85, 2472 | 67, 2473 | 57, 2474 | 64, 2475 | 167, 2476 | 140, 2477 | 145, 2478 | 206, 2479 | 195, 2480 | 202, 2481 | 201, 2482 | 193, 2483 | 203, 2484 | 153, 2485 | 128, 2486 | 142, 2487 | 96, 2488 | 74, 2489 | 83, 2490 | 37, 2491 | 27, 2492 | 31, 2493 | 38, 2494 | 27, 2495 | 32, 2496 | 36, 2497 | 26, 2498 | 31, 2499 | 35, 2500 | 25, 2501 | 30, 2502 | 34, 2503 | 24, 2504 | 26, 2505 | 34, 2506 | 25, 2507 | 27, 2508 | 37, 2509 | 38, 2510 | 40, 2511 | 44, 2512 | 36, 2513 | 39, 2514 | 85, 2515 | 32, 2516 | 42, 2517 | 97, 2518 | 31, 2519 | 44, 2520 | 62, 2521 | 36, 2522 | 42, 2523 | 41, 2524 | 36, 2525 | 40, 2526 | 32, 2527 | 32, 2528 | 33, 2529 | 29, 2530 | 27, 2531 | 29, 2532 | 27, 2533 | 25, 2534 | 27, 2535 | 27, 2536 | 27, 2537 | 27, 2538 | 29, 2539 | 28, 2540 | 28, 2541 | 49, 2542 | 29, 2543 | 32, 2544 | 96, 2545 | 32, 2546 | 43, 2547 | 84, 2548 | 28, 2549 | 35, 2550 | 41, 2551 | 30, 2552 | 32, 2553 | 34, 2554 | 32, 2555 | 33, 2556 | 158, 2557 | 151, 2558 | 165, 2559 | 168, 2560 | 159, 2561 | 175, 2562 | 168, 2563 | 154, 2564 | 174, 2565 | 163, 2566 | 156, 2567 | 166, 2568 | 203, 2569 | 203, 2570 | 209, 2571 | 219, 2572 | 217, 2573 | 225, 2574 | 191, 2575 | 178, 2576 | 189, 2577 | 153, 2578 | 128, 2579 | 142, 2580 | 97, 2581 | 81, 2582 | 89, 2583 | 76, 2584 | 64, 2585 | 70, 2586 | 74, 2587 | 63, 2588 | 70, 2589 | 85, 2590 | 73, 2591 | 81, 2592 | 85, 2593 | 73, 2594 | 80, 2595 | 80, 2596 | 68, 2597 | 74, 2598 | 64, 2599 | 53, 2600 | 58, 2601 | 35, 2602 | 29, 2603 | 31, 2604 | 34, 2605 | 35, 2606 | 37, 2607 | 36, 2608 | 36, 2609 | 39, 2610 | 34, 2611 | 34, 2612 | 36, 2613 | 55, 2614 | 31, 2615 | 36, 2616 | 100, 2617 | 31, 2618 | 44, 2619 | 92, 2620 | 34, 2621 | 44, 2622 | 54, 2623 | 38, 2624 | 43, 2625 | 37, 2626 | 32, 2627 | 35, 2628 | 27, 2629 | 26, 2630 | 28, 2631 | 28, 2632 | 27, 2633 | 29, 2634 | 30, 2635 | 28, 2636 | 29, 2637 | 53, 2638 | 29, 2639 | 32, 2640 | 90, 2641 | 28, 2642 | 36, 2643 | 89, 2644 | 29, 2645 | 36, 2646 | 78, 2647 | 27, 2648 | 33, 2649 | 102, 2650 | 93, 2651 | 101, 2652 | 178, 2653 | 172, 2654 | 186, 2655 | 198, 2656 | 194, 2657 | 206, 2658 | 219, 2659 | 218, 2660 | 228, 2661 | 223, 2662 | 223, 2663 | 232, 2664 | 210, 2665 | 204, 2666 | 213, 2667 | 178, 2668 | 157, 2669 | 171, 2670 | 139, 2671 | 119, 2672 | 131, 2673 | 75, 2674 | 70, 2675 | 79, 2676 | 67, 2677 | 63, 2678 | 72, 2679 | 63, 2680 | 60, 2681 | 73, 2682 | 58, 2683 | 52, 2684 | 62, 2685 | 90, 2686 | 90, 2687 | 97, 2688 | 65, 2689 | 63, 2690 | 74, 2691 | 54, 2692 | 49, 2693 | 59, 2694 | 50, 2695 | 42, 2696 | 48, 2697 | 45, 2698 | 41, 2699 | 45, 2700 | 33, 2701 | 34, 2702 | 36, 2703 | 34, 2704 | 34, 2705 | 36, 2706 | 32, 2707 | 32, 2708 | 34, 2709 | 31, 2710 | 31, 2711 | 33, 2712 | 31, 2713 | 29, 2714 | 30, 2715 | 76, 2716 | 30, 2717 | 38, 2718 | 110, 2719 | 33, 2720 | 46, 2721 | 88, 2722 | 38, 2723 | 47, 2724 | 47, 2725 | 41, 2726 | 44, 2727 | 28, 2728 | 28, 2729 | 30, 2730 | 29, 2731 | 28, 2732 | 29, 2733 | 31, 2734 | 28, 2735 | 29, 2736 | 63, 2737 | 29, 2738 | 33, 2739 | 90, 2740 | 29, 2741 | 37, 2742 | 91, 2743 | 29, 2744 | 37, 2745 | 167, 2746 | 160, 2747 | 172, 2748 | 212, 2749 | 212, 2750 | 222, 2751 | 220, 2752 | 220, 2753 | 230, 2754 | 217, 2755 | 216, 2756 | 226, 2757 | 200, 2758 | 188, 2759 | 199, 2760 | 171, 2761 | 148, 2762 | 164, 2763 | 129, 2764 | 112, 2765 | 123, 2766 | 64, 2767 | 61, 2768 | 70, 2769 | 64, 2770 | 64, 2771 | 76, 2772 | 66, 2773 | 65, 2774 | 74, 2775 | 60, 2776 | 55, 2777 | 65, 2778 | 54, 2779 | 45, 2780 | 57, 2781 | 57, 2782 | 52, 2783 | 61, 2784 | 65, 2785 | 63, 2786 | 72, 2787 | 48, 2788 | 42, 2789 | 50, 2790 | 51, 2791 | 44, 2792 | 50, 2793 | 35, 2794 | 34, 2795 | 37, 2796 | 32, 2797 | 32, 2798 | 35, 2799 | 32, 2800 | 32, 2801 | 34, 2802 | 32, 2803 | 32, 2804 | 34, 2805 | 31, 2806 | 31, 2807 | 31, 2808 | 31, 2809 | 28, 2810 | 31, 2811 | 31, 2812 | 29, 2813 | 32, 2814 | 40, 2815 | 28, 2816 | 31, 2817 | 99, 2818 | 32, 2819 | 43, 2820 | 116, 2821 | 36, 2822 | 49, 2823 | 28, 2824 | 28, 2825 | 29, 2826 | 29, 2827 | 27, 2828 | 28, 2829 | 29, 2830 | 27, 2831 | 28, 2832 | 29, 2833 | 26, 2834 | 27, 2835 | 58, 2836 | 26, 2837 | 30, 2838 | 111, 2839 | 78, 2840 | 86, 2841 | 193, 2842 | 184, 2843 | 196, 2844 | 211, 2845 | 208, 2846 | 219, 2847 | 206, 2848 | 201, 2849 | 212, 2850 | 187, 2851 | 170, 2852 | 182, 2853 | 163, 2854 | 142, 2855 | 158, 2856 | 109, 2857 | 96, 2858 | 105, 2859 | 71, 2860 | 68, 2861 | 75, 2862 | 78, 2863 | 78, 2864 | 86, 2865 | 69, 2866 | 69, 2867 | 80, 2868 | 63, 2869 | 58, 2870 | 68, 2871 | 53, 2872 | 44, 2873 | 53, 2874 | 55, 2875 | 46, 2876 | 58, 2877 | 79, 2878 | 78, 2879 | 88, 2880 | 66, 2881 | 64, 2882 | 74, 2883 | 53, 2884 | 48, 2885 | 56, 2886 | 39, 2887 | 35, 2888 | 39, 2889 | 32, 2890 | 32, 2891 | 34, 2892 | 31, 2893 | 31, 2894 | 33, 2895 | 31, 2896 | 31, 2897 | 33, 2898 | 32, 2899 | 32, 2900 | 33, 2901 | 31, 2902 | 30, 2903 | 31, 2904 | 31, 2905 | 29, 2906 | 32, 2907 | 30, 2908 | 29, 2909 | 31, 2910 | 31, 2911 | 30, 2912 | 32, 2913 | 31, 2914 | 30, 2915 | 32, 2916 | 65, 2917 | 31, 2918 | 36, 2919 | 29, 2920 | 28, 2921 | 31, 2922 | 29, 2923 | 28, 2924 | 30, 2925 | 28, 2926 | 26, 2927 | 28, 2928 | 27, 2929 | 25, 2930 | 26, 2931 | 28, 2932 | 25, 2933 | 27, 2934 | 101, 2935 | 83, 2936 | 91, 2937 | 178, 2938 | 159, 2939 | 172, 2940 | 182, 2941 | 157, 2942 | 170, 2943 | 171, 2944 | 144, 2945 | 157, 2946 | 154, 2947 | 131, 2948 | 144, 2949 | 95, 2950 | 75, 2951 | 82, 2952 | 38, 2953 | 25, 2954 | 27, 2955 | 50, 2956 | 43, 2957 | 49, 2958 | 59, 2959 | 53, 2960 | 63, 2961 | 54, 2962 | 44, 2963 | 52, 2964 | 58, 2965 | 49, 2966 | 58, 2967 | 52, 2968 | 43, 2969 | 55, 2970 | 63, 2971 | 59, 2972 | 67, 2973 | 75, 2974 | 73, 2975 | 84, 2976 | 78, 2977 | 77, 2978 | 81, 2979 | 46, 2980 | 39, 2981 | 46, 2982 | 40, 2983 | 37, 2984 | 40, 2985 | 30, 2986 | 30, 2987 | 31, 2988 | 31, 2989 | 30, 2990 | 32, 2991 | 30, 2992 | 29, 2993 | 31, 2994 | 32, 2995 | 30, 2996 | 33, 2997 | 33, 2998 | 30, 2999 | 33, 3000 | 31, 3001 | 29, 3002 | 31, 3003 | 31, 3004 | 31, 3005 | 33, 3006 | 33, 3007 | 33, 3008 | 35, 3009 | 32, 3010 | 31, 3011 | 34, 3012 | 31, 3013 | 31, 3014 | 33, 3015 | 29, 3016 | 30, 3017 | 32, 3018 | 28, 3019 | 28, 3020 | 31, 3021 | 31, 3022 | 30, 3023 | 32, 3024 | 34, 3025 | 33, 3026 | 34, 3027 | 33, 3028 | 31, 3029 | 33, 3030 | 60, 3031 | 49, 3032 | 53, 3033 | 141, 3034 | 108, 3035 | 119, 3036 | 146, 3037 | 115, 3038 | 127, 3039 | 112, 3040 | 88, 3041 | 98, 3042 | 57, 3043 | 36, 3044 | 53, 3045 | 67, 3046 | 49, 3047 | 60, 3048 | 95, 3049 | 78, 3050 | 84, 3051 | 60, 3052 | 48, 3053 | 55, 3054 | 50, 3055 | 40, 3056 | 48, 3057 | 55, 3058 | 45, 3059 | 54, 3060 | 57, 3061 | 50, 3062 | 61, 3063 | 71, 3064 | 69, 3065 | 78, 3066 | 72, 3067 | 70, 3068 | 82, 3069 | 70, 3070 | 66, 3071 | 78, 3072 | 62, 3073 | 59, 3074 | 68, 3075 | 82, 3076 | 79, 3077 | 86, 3078 | 36, 3079 | 32, 3080 | 35, 3081 | 30, 3082 | 29, 3083 | 31, 3084 | 31, 3085 | 28, 3086 | 32, 3087 | 31, 3088 | 29, 3089 | 32, 3090 | 32, 3091 | 31, 3092 | 33, 3093 | 32, 3094 | 32, 3095 | 34, 3096 | 32, 3097 | 32, 3098 | 34, 3099 | 33, 3100 | 33, 3101 | 35, 3102 | 33, 3103 | 33, 3104 | 36, 3105 | 32, 3106 | 32, 3107 | 35, 3108 | 32, 3109 | 32, 3110 | 34, 3111 | } 3112 | ) --------------------------------------------------------------------------------