├── LICENSE ├── README.md ├── STYLE.md ├── demos ├── README.md ├── assets │ ├── csv │ │ ├── atlas.csv │ │ ├── map0.csv │ │ └── map_camera_test.csv │ ├── fnt │ │ ├── FSEX300.ttf │ │ └── default8x16.png │ ├── gfx │ │ ├── atlas.png │ │ ├── button_circle.png │ │ ├── button_square.png │ │ ├── cursor.png │ │ ├── dwarf.png │ │ ├── earth.png │ │ ├── earth32.png │ │ ├── grid.png │ │ ├── icon_x.png │ │ ├── knight.gif │ │ ├── puff.png │ │ ├── spaceman.png │ │ ├── sprite0.png │ │ ├── target.png │ │ ├── text_input.png │ │ └── tile0.png │ ├── mus │ │ ├── absolu.mod │ │ ├── biotech.xm │ │ ├── cancan.mod │ │ └── cornered!.xm │ └── sfx │ │ └── tack.wav ├── demo1 │ ├── README.md │ ├── demo1.nim │ ├── demo1.png │ ├── mainscene.nim │ └── spaceman.nim ├── demo10 │ ├── README.md │ ├── demo10.nim │ ├── demo10.png │ ├── earth.nim │ ├── mainscene.nim │ └── spaceman.nim ├── demo11 │ ├── README.md │ ├── demo11.nim │ ├── demo11.png │ ├── earth.nim │ └── mainscene.nim ├── demo12 │ ├── README.md │ ├── demo12.nim │ ├── demo12.png │ └── mainscene.nim ├── demo13 │ ├── README.md │ ├── cursor.nim │ ├── demo13.nim │ ├── demo13.png │ └── mainscene.nim ├── demo14 │ ├── README.md │ ├── demo14.nim │ ├── demo14.png │ ├── dwarf.nim │ └── mainscene.nim ├── demo15 │ ├── README.md │ ├── demo15.nim │ ├── demo15.png │ └── mainscene.nim ├── demo16 │ ├── README.md │ ├── demo16.nim │ ├── demo16.png │ └── mainscene.nim ├── demo17 │ ├── README.md │ ├── btnCircle.nim │ ├── btnSquare.nim │ ├── demo17.nim │ ├── demo17.png │ └── mainscene.nim ├── demo18 │ ├── README.md │ ├── demo18.nim │ ├── demo18.png │ └── mainscene.nim ├── demo19 │ ├── README.md │ ├── demo19.nim │ ├── demo19.png │ └── mainscene.nim ├── demo2 │ ├── README.md │ ├── demo2.nim │ ├── demo2.png │ ├── earth.nim │ ├── mainscene.nim │ └── spaceman.nim ├── demo20 │ ├── README.md │ ├── demo20.nim │ ├── demo20.png │ └── mainscene.nim ├── demo21 │ ├── README.md │ ├── demo21.nim │ ├── demo21.png │ ├── joypoint.nim │ └── mainscene.nim ├── demo22 │ ├── README.md │ ├── demo22.nim │ ├── demo22.png │ ├── mainscene.nim │ └── video.mpg ├── demo23 │ ├── README.md │ ├── demo23.nim │ ├── demo23.png │ ├── mainscene.nim │ └── private │ │ ├── border_fill_graphic.nim │ │ ├── circle_graphic.nim │ │ └── frame.nim ├── demo3 │ ├── README.md │ ├── demo3.nim │ ├── demo3.png │ ├── mainscene.nim │ └── spaceman.nim ├── demo4 │ ├── README.md │ ├── demo4.nim │ ├── demo4.png │ ├── dwarf.nim │ └── mainscene.nim ├── demo5 │ ├── README.md │ ├── cursor.nim │ ├── demo5.nim │ ├── demo5.png │ ├── earth.nim │ ├── line.nim │ ├── mainscene.nim │ ├── poly1.nim │ ├── poly2.nim │ ├── poly3.nim │ ├── poly9.nim │ └── spaceman.nim ├── demo6 │ ├── README.md │ ├── demo6.nim │ ├── demo6.png │ ├── earth.nim │ ├── mainscene.nim │ └── spaceman.nim ├── demo7 │ ├── README.md │ ├── demo7.nim │ ├── demo7.png │ ├── earth.nim │ └── mainscene.nim ├── demo8 │ ├── README.md │ ├── demo8.nim │ ├── demo8.png │ └── mainscene.nim ├── demo9 │ ├── README.md │ ├── demo9.nim │ ├── demo9.png │ └── mainscene.nim └── nim.cfg ├── docs ├── changelog.html ├── demos.html ├── docs.html ├── docs │ ├── assets.html │ ├── audio.html │ ├── bitmapfont.html │ ├── count.html │ ├── draw.html │ ├── emitter.html │ ├── entity.html │ ├── font.html │ ├── graphic.html │ ├── gui │ │ ├── button.html │ │ ├── progressbar.html │ │ ├── radio.html │ │ ├── textinput.html │ │ └── widget.html │ ├── indexedimage.html │ ├── input.html │ ├── mosaic.html │ ├── nimgame.html │ ├── perspectiveimage.html │ ├── plugin │ │ ├── mpeggraphic.html │ │ ├── tar.html │ │ └── zzip.html │ ├── private │ │ └── collider.html │ ├── procgraphic.html │ ├── scene.html │ ├── settings.html │ ├── textfield.html │ ├── textgraphic.html │ ├── textureatlas.html │ ├── texturegraphic.html │ ├── tilemap.html │ ├── truetypefont.html │ ├── tween.html │ ├── types.html │ ├── typewriter.html │ └── utils.html ├── favicon.ico ├── images │ ├── icons │ │ ├── check.png │ │ ├── checkn.png │ │ ├── email.png │ │ ├── logo.png │ │ ├── outlink.png │ │ ├── stare.png │ │ └── starf.png │ ├── screenshots │ │ ├── demo14.png │ │ ├── demo14_thumb.png │ │ ├── ng2gggrotto.png │ │ ├── ng2gggrotto_thumb.png │ │ ├── ng2planetoids.png │ │ ├── ng2planetoids_thumb.png │ │ ├── ng2platformer.png │ │ ├── ng2platformer_thumb.png │ │ ├── ng2tbk.png │ │ └── ng2tbk_thumb.png │ ├── tut101_bounce │ │ ├── ball.png │ │ ├── colliders.png │ │ ├── paddle.png │ │ ├── paddles.png │ │ ├── score.png │ │ ├── thumb.png │ │ └── titlescene.png │ └── tut102_platformer │ │ ├── button.png │ │ ├── enemy.png │ │ ├── player.png │ │ ├── thumb.png │ │ └── tiles.png ├── index.html ├── links.html ├── snippets.html ├── structure.js ├── style.css ├── template.html ├── template_tutorial.html ├── tut101_bounce.html ├── tut102_platformer.html └── tutorials.html ├── nimgame2.nim ├── nimgame2.nimble └── nimgame2 ├── assets.nim ├── audio.nim ├── bitmapfont.nim ├── draw.nim ├── emitter.nim ├── entity.nim ├── font.nim ├── graphic.nim ├── gui ├── button.nim ├── progressbar.nim ├── radio.nim ├── textinput.nim └── widget.nim ├── indexedimage.nim ├── input.nim ├── mosaic.nim ├── nimgame.nim ├── perspectiveimage.nim ├── plugin ├── mpeggraphic.nim ├── tar.nim └── zzip.nim ├── private └── collider.nim ├── procgraphic.nim ├── scene.nim ├── settings.nim ├── textfield.nim ├── textgraphic.nim ├── textureatlas.nim ├── texturegraphic.nim ├── tilemap.nim ├── truetypefont.nim ├── tween.nim ├── types.nim ├── typewriter.nim └── utils.nim /LICENSE: -------------------------------------------------------------------------------- 1 | # nimgame2 2 | # Copyright (c) 2016-2020 Vladimir Arabadzhi (Vladar) 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | # vladar4@gmail.com 23 | # https://github.com/Vladar4 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2 2 | ========= 3 | 4 | A simple 2D game engine for Nim language. 5 | 6 | For more information check [home page](https://vladar4.github.io/nimgame2/). 7 | 8 | [Coding style guide](STYLE.md) for the contributors. 9 | 10 | All pull requests should be done into the **devel** branch. 11 | 12 | Status: v0.6.2 alpha 13 | -------------------- 14 | 15 | 16 | Requires: 17 | --------- 18 | 19 | * [sdl2_nim](https://github.com/Vladar4/sdl2_nim) package (v2.0.14.2 or newer). 20 | * Runtime libraries for: 21 | * SDL 2.0.12 or newer 22 | * SDL_gfx 1.0.1 23 | * SDL_image 2.0.2 24 | * SDL_mixer 2.0.2 25 | * SDL_ttf 2.0.14 26 | (see [SDL2 links](https://github.com/Vladar4/sdl2_nim/blob/master/LINKS.md)) 27 | 28 | 29 | Optional dependencies: 30 | ---------------------- 31 | 32 | * For plugin/mpeggraphic 33 | * mpg123 runtime library (dll is distributed within SDL_) 34 | * For plugin/tar: 35 | * [zip](https://github.com/nim-lang/zip) 36 | * zlib runtime library (dll is distributed within SDL2_image builds) 37 | * For plugin/zzip: 38 | * [zip](https://github.com/nim-lang/zip) 39 | * zlib runtime library (dll is distributed within SDL2_image builds) 40 | * zzip runtime library 41 | 42 | 43 | Installation through [Nimble](https://github.com/nim-lang/nimble): 44 | ------------------------------------------------------------------ 45 | 46 | * stable version: `nimble install nimgame2@#head` 47 | * development version: `nimble install nimgame2@#devel` 48 | 49 | 50 | Recommended compilation flags: 51 | ------------------------------ 52 | `--multimethods:on -d:release --opt:speed` 53 | 54 | 55 | Links: 56 | ------ 57 | 58 | * [home page](https://vladar4.github.io/nimgame2/) 59 | * [demos](demos) 60 | * [tutorials](https://vladar4.github.io/nimgame2/tutorials) 61 | * [documentation](https://vladar4.github.io/nimgame2/docs.html) 62 | * [ng2planetoids](https://github.com/Vladar4/ng2planetoids) - first demo game. 63 | * [ng2gggrotto](https://github.com/Vladar4/ng2gggrotto) - Linux Game Jam 2017 entry. 64 | 65 | 66 | Changelog: 67 | ---------- 68 | 69 | ### v0.6.2 alpha (2021-08-20) 70 | * Maintenance release to keep up with the current versions of Nim and sdl2_nim until v0.7 is ready 71 | 72 | ### v0.6.1 alpha (2019-06-15) 73 | * Nim v0.20.0 transition 74 | 75 | ### v0.6 alpha (2019-01-21) 76 | * new modules: typewriter 77 | * new plugins: mpeggraphic (+demo22), tar, zzip 78 | * new utils procedures: textureFormat, textureFormats, toSeq, neg, new rand procedures 79 | * color constants 80 | * audio: playing template 81 | * emitter: emission areas, procedure argument for emit 82 | * entity: animation callback, blinking, scale parameters, dim template (by [CodeDoes](https://github.com/CodeDoes)) 83 | * input: mouse wheel events (by [CodeDoes](https://github.com/CodeDoes)) 84 | * icon surface init option 85 | * RW loading procedures 86 | * simplified time counters 87 | * demo23 (transform) (by [CodeDoes](https://github.com/CodeDoes)) 88 | * various minor changes and upgrades, code refactoring 89 | * Nim v0.19.0 transition 90 | 91 | 92 | ### v0.5 alpha (2017-08-01) 93 | * changed physics and logic systems 94 | * platformer physics 95 | * CoordInt type 96 | * now collider module is autmatically included into the entity module 97 | * group collider 98 | * huge Tilemap optimizations 99 | * various utility Tilemap procedures 100 | * TextureGraphic.drawTiled 101 | * GUI: 102 | * GUIProgressBar 103 | * widget actions 104 | * various minor changes and upgrades 105 | * Nim v0.17.0 transition 106 | * documentation, snippets, and demos update 107 | * [second tutorial](https://vladar4.github.io/nimgame2/tut102_platformer.html) 108 | 109 | ### v0.4 alpha (2017-05-04) 110 | * GUI: 111 | * RadioGroup 112 | * RadioButton 113 | * IndexedImage 114 | * PerspectiveImage 115 | * TextureAtlas 116 | * joysticks support 117 | * window management procedures 118 | * 4 new demos 119 | * [first tutorial](https://vladar4.github.io/nimgame2/tut101_bounce.html) 120 | 121 | 122 | ### v0.3 alpha (2017-03-10) 123 | * camera property (Scene) 124 | * new collision procedures 125 | * reworked input 126 | * Mosaic 127 | * parallax property (Entity) 128 | * TextField 129 | * GUI: 130 | * Widget 131 | * Button 132 | * TextInput 133 | * 3 new demos 134 | * home page, snippets, and documentation 135 | 136 | ### v0.2 alpha (2017-01-31) 137 | * collider optimizations 138 | * music playlists 139 | * random procedures 140 | * tilemaps 141 | * tweens 142 | * emitters 143 | * various fixes 144 | * 4 new demos 145 | 146 | ### v0.1 alpha (2017-01-16) 147 | * base scene/entity system 148 | * assets manager 149 | * basic sound and music 150 | * colliders (point, box, circle, line, and polygon) 151 | * fonts (bitmap and TrueType) and text output 152 | * keyboard and mouse input 153 | * vector drawing procedures 154 | 155 | -------------------------------------------------------------------------------- /STYLE.md: -------------------------------------------------------------------------------- 1 | Nimgame 2 code formatting style 2 | =============================== 3 | 4 | In general, follow [NEP1](https://nim-lang.org/docs/nep1.html) if it doesn't contradict this document. 5 | 6 | 7 | Line Spacing 8 | ------------ 9 | * two empty lines before and one empty line after the header-comment; 10 | * two empty lines between blocks (such as `const`, `type`, `proc`, etc.); 11 | * one empty line to separate segments inside these blocks if needed; 12 | * one empty line at the end of files. 13 | 14 | 15 | Comments 16 | -------- 17 | 18 | * if there is more than one type declared in one module, their procedures should be separated with header-comments: 19 | ``` 20 | #==========# 21 | # SomeType # 22 | #==========# 23 | ``` 24 | * documentation comments are always offset by one indentation level inside their procedures, have two spaces before their text, and one empty comment line to separate it from the code below. 25 | ``` 26 | proc someProc() = 27 | ## Documentation comment. 28 | ## 29 | var someVar 30 | ... 31 | ``` 32 | 33 | 34 | Naming 35 | ------ 36 | * types and constants in PascalCase; 37 | * all other identifiers in camelCase; 38 | * if an object is a first argument of a procedure, generally it should be named after its type, e.g.: 39 | ``` 40 | proc foo(bar: Bar, val: int): int = 41 | ``` 42 | 43 | 44 | Objects 45 | ------- 46 | * private and public fields should be separated with comments if possible; 47 | * `ref object` types should have the following initialization scheme: 48 | ``` 49 | type SomeType = ref object of SomeParent 50 | someValue*: int 51 | 52 | 53 | proc initSomeType*(someType: SomeType) = 54 | someType.initSomeParent() # don't forget the parent initialization 55 | SomeType.someValue = 0 56 | ... 57 | 58 | 59 | proc newSomeType*(): SomeType = 60 | result = new SomeType 61 | result.initSomeType() 62 | ``` 63 | * types that are inherited from the `Entity` type should follow the following update scheme: 64 | ``` 65 | type 66 | SomeEntity = ref object of Entity 67 | 68 | 69 | proc updateSomeEntity*(someEntity: SomeEntiy, elapsed: float) = 70 | someEntity.updateEntity(elapsed) # don't forget the parent update 71 | ... 72 | 73 | 74 | method update*(someEntity: SomeEntiy, elapsed: float) = 75 | updateSomeEntity(someEntity, elapsed) 76 | ``` 77 | 78 | 79 | Code 80 | ---- 81 | * don't forget proper spaces between elements; 82 | * procedural arguments are separated by commas, e.g.: 83 | ``` 84 | proc someProc(arg1: int, arg2, arg3: float): float = 85 | ``` 86 | * if there are a lot of arguments, they could be brought to a new line and indented by two levels for the sake of readability, e.g.: 87 | ``` 88 | proc someLongAndComplexProcedure( 89 | arg1, arg2, arg3, arg4: int 90 | arg5, arg6, arg7, arg8: float) = 91 | ## Documentation 92 | ## 93 | ... 94 | ``` 95 | 96 | 97 | Example 98 | ------- 99 | ``` 100 | # Header 101 | 102 | type 103 | SomeType1 = object 104 | # Private 105 | fHidden: int 106 | # Public 107 | value*: int 108 | 109 | SomeType2 = object 110 | a, b*: float 111 | 112 | 113 | const 114 | SomeConst1 = 42 115 | 116 | 117 | proc someProc*(arg1: int): int = 118 | ... 119 | 120 | 121 | #===========# 122 | # SomeType1 # 123 | #===========# 124 | 125 | proc someProc1*(someType1: SomeType1, a, b: int) = 126 | ... 127 | 128 | 129 | #===========# 130 | # SomeType2 # 131 | #===========# 132 | 133 | ... 134 | 135 | ``` 136 | 137 | -------------------------------------------------------------------------------- /demos/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2 Demos 2 | =============== 3 | 4 | * [demo1](demo1) Performance 5 | 6 | * [demo2](demo2) Graphic 7 | 8 | * [demo3](demo3) Input 9 | 10 | * [demo4](demo4) Sprite 11 | 12 | * [demo5](demo5) Colliders 13 | 14 | * [demo6](demo6) Grouping 15 | 16 | * [demo7](demo7) Text 17 | 18 | * [demo8](demo8) ProcGraphic 19 | 20 | * [demo9](demo9) Audio 21 | 22 | * [demo10](demo10) Layers 23 | 24 | * [demo11](demo11) Tweens 25 | 26 | * [demo12](demo12) Emitters 27 | 28 | * [demo13](demo13) TileMaps 29 | 30 | * [demo14](demo14) TileMaps, Tweens, Emitters 31 | 32 | * [demo15](demo15) Camera 33 | 34 | * [demo16](demo16) Parallax 35 | 36 | * [demo17](demo17) GUI (Button, TextField) 37 | 38 | * [demo18](demo18) IndexedImage 39 | 40 | * [demo19](demo19) PerspectiveImage 41 | 42 | * [demo20](demo20) TextureAtlas 43 | 44 | * [demo21](demo21) Joysticks 45 | 46 | * [demo22](demo22) MpegGraphic 47 | 48 | * [demo23](demo23) Transform 49 | 50 | -------------------------------------------------------------------------------- /demos/assets/csv/atlas.csv: -------------------------------------------------------------------------------- 1 | spaceman, 12, 33, 42, 66 2 | gradient, 65, 9, 16, 90 3 | button, 82, 26, 48, 72 4 | sprite, 132, 0, 68, 100 5 | -------------------------------------------------------------------------------- /demos/assets/csv/map0.csv: -------------------------------------------------------------------------------- 1 | 0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 2 | 3,3,3,1,1,1,3,1,1,1,1,1,3,1,1,1,1,1,1,1,1,3,1,1,1,3 3 | 3,1,1,1,1,1,1,1,1,1,3,1,1,1,3,3,3,3,1,1,1,3,1,2,1,3 4 | 3,1,3,1,1,1,3,3,1,3,3,3,3,3,3,1,1,3,1,3,3,3,1,1,1,3 5 | 3,1,3,3,1,3,3,1,1,1,1,1,1,1,1,1,1,3,1,3,0,3,3,1,3,3 6 | 3,1,3,1,1,1,3,3,3,3,3,1,1,3,3,1,1,3,1,3,0,0,3,1,3,0 7 | 3,1,1,1,1,1,1,1,1,1,3,3,1,3,3,3,1,3,1,3,3,3,3,1,3,0 8 | 3,3,3,1,1,1,3,1,1,1,3,1,1,1,3,3,1,1,1,3,1,1,1,1,3,0 9 | 0,0,3,3,1,3,3,1,1,1,3,1,1,1,3,3,3,3,3,3,3,3,3,1,3,0 10 | 3,3,3,1,1,1,3,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,3,1,3,0 11 | 3,1,1,1,1,1,3,3,3,1,3,3,3,3,3,3,3,3,3,3,3,1,1,1,3,0 12 | 3,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3 13 | 3,1,3,3,3,3,3,3,3,1,3,3,3,3,3,3,1,3,1,1,1,1,1,1,1,3 14 | 3,1,1,1,1,1,1,1,3,1,3,3,1,1,1,3,1,3,1,3,3,3,3,3,1,3 15 | 3,3,3,1,3,1,1,1,3,1,3,3,1,1,1,3,1,3,1,3,1,1,1,3,1,3 16 | 0,0,3,1,3,1,3,3,3,1,3,3,1,1,1,1,1,3,1,3,1,1,1,1,1,3 17 | 3,3,3,3,3,1,3,3,1,1,1,3,3,3,3,3,1,3,1,3,1,1,1,3,1,3 18 | 3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,3,3,3,3,1,3 19 | 3,1,1,3,3,3,3,3,1,1,1,3,3,3,3,3,3,3,1,1,1,1,1,1,1,3 20 | 3,3,3,3,0,0,0,3,3,3,3,3,0,0,0,0,0,3,3,3,3,3,3,3,3,3 21 | -------------------------------------------------------------------------------- /demos/assets/fnt/FSEX300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/fnt/FSEX300.ttf -------------------------------------------------------------------------------- /demos/assets/fnt/default8x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/fnt/default8x16.png -------------------------------------------------------------------------------- /demos/assets/gfx/atlas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/atlas.png -------------------------------------------------------------------------------- /demos/assets/gfx/button_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/button_circle.png -------------------------------------------------------------------------------- /demos/assets/gfx/button_square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/button_square.png -------------------------------------------------------------------------------- /demos/assets/gfx/cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/cursor.png -------------------------------------------------------------------------------- /demos/assets/gfx/dwarf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/dwarf.png -------------------------------------------------------------------------------- /demos/assets/gfx/earth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/earth.png -------------------------------------------------------------------------------- /demos/assets/gfx/earth32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/earth32.png -------------------------------------------------------------------------------- /demos/assets/gfx/grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/grid.png -------------------------------------------------------------------------------- /demos/assets/gfx/icon_x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/icon_x.png -------------------------------------------------------------------------------- /demos/assets/gfx/knight.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/knight.gif -------------------------------------------------------------------------------- /demos/assets/gfx/puff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/puff.png -------------------------------------------------------------------------------- /demos/assets/gfx/spaceman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/spaceman.png -------------------------------------------------------------------------------- /demos/assets/gfx/sprite0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/sprite0.png -------------------------------------------------------------------------------- /demos/assets/gfx/target.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/target.png -------------------------------------------------------------------------------- /demos/assets/gfx/text_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/text_input.png -------------------------------------------------------------------------------- /demos/assets/gfx/tile0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/gfx/tile0.png -------------------------------------------------------------------------------- /demos/assets/mus/absolu.mod: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/mus/absolu.mod -------------------------------------------------------------------------------- /demos/assets/mus/biotech.xm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/mus/biotech.xm -------------------------------------------------------------------------------- /demos/assets/mus/cancan.mod: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/mus/cancan.mod -------------------------------------------------------------------------------- /demos/assets/mus/cornered!.xm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/mus/cornered!.xm -------------------------------------------------------------------------------- /demos/assets/sfx/tack.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/assets/sfx/tack.wav -------------------------------------------------------------------------------- /demos/demo1/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 1 2 | ================= 3 | 4 | Performance demo. 5 | 6 | ![Screenshot](demo1.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo1/demo1.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 1 (Performance)"): 8 | showInfo = true 9 | game.scene = newMainScene() 10 | game.run() 11 | 12 | -------------------------------------------------------------------------------- /demos/demo1/demo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo1/demo1.png -------------------------------------------------------------------------------- /demos/demo1/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/draw, 4 | nimgame2/entity, 5 | nimgame2/texturegraphic, 6 | nimgame2/scene, 7 | nimgame2/settings, 8 | nimgame2/types, 9 | spaceman 10 | 11 | 12 | const 13 | NumMin = 100 14 | NumMax = 50_000 15 | NumStep = 100 16 | NumStart = 500 17 | 18 | 19 | type 20 | MainScene = ref object of Scene 21 | spacemanG: TextureGraphic 22 | num: int 23 | 24 | 25 | proc spacemanPhysics*(entity: Entity, elapsed: float) = 26 | defaultPhysics(entity, elapsed) 27 | 28 | # Screen collision 29 | if entity.pos.x < 0: 30 | entity.vel.x *= -1 31 | if entity.pos.y < 0: 32 | entity.vel.y *= -1 33 | if entity.pos.x >= game.size.w.float: 34 | entity.vel.x *= -1 35 | if entity.pos.y >= game.size.h.float: 36 | entity.vel.y *= -1 37 | 38 | 39 | proc init*(scene: MainScene) = 40 | Scene(scene).init() 41 | scene.spacemanG = newTextureGraphic() 42 | discard scene.spacemanG.load("../assets/gfx/spaceman.png") 43 | scene.num = NumStart 44 | for i in 1..scene.num: 45 | scene.add(newSpaceman(scene, scene.spacemanG, spacemanPhysics)) 46 | 47 | 48 | proc free*(scene: MainScene) = 49 | scene.spacemanG.free 50 | 51 | 52 | proc newMainScene*(): MainScene = 53 | new result, free 54 | result.init() 55 | 56 | 57 | method event*(scene: MainScene, event: Event) = 58 | if event.kind == KeyDown: 59 | case event.key.keysym.sym: 60 | of K_Escape: 61 | gameRunning = false 62 | of K_Up: 63 | if scene.num < NumMax: 64 | scene.num += NumStep 65 | for i in scene.count..scene.num-1: 66 | scene.add(newSpaceman(scene, scene.spacemanG, spacemanPhysics)) 67 | of K_Down: 68 | if scene.num > NumMin: 69 | scene.num -= NumStep 70 | for i in scene.num..(scene.count - 1): 71 | discard scene.pop() 72 | else: discard 73 | 74 | 75 | method render*(scene: MainScene) = 76 | scene.renderScene() 77 | discard box((4, 60), (260, 84), 0x000000CC'u32) 78 | discard string( 79 | (8, 64), "Arrow Up - more entities", 0xFF0000FF'u32) 80 | discard string( 81 | (8, 72), "Arrow Down - less entities", 0xFF0000FF'u32) 82 | 83 | 84 | method update*(scene: MainScene, elapsed: float) = 85 | scene.updateScene(elapsed) 86 | 87 | -------------------------------------------------------------------------------- /demos/demo1/spaceman.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity, 4 | nimgame2/graphic, 5 | nimgame2/scene, 6 | nimgame2/types, 7 | nimgame2/utils 8 | 9 | type 10 | Spaceman* = ref object of Entity 11 | scene*: Scene 12 | 13 | 14 | proc init*(entity: Spaceman, s: Scene, g: Graphic, p: PhysicsProc) = 15 | entity.initEntity() 16 | entity.scene = s 17 | entity.graphic = g 18 | entity.physics = p 19 | entity.pos.x = rand(game.size.w).float 20 | entity.pos.y = rand(game.size.h).float 21 | entity.vel.x = rand(10.0..100.0) * randSign().float 22 | entity.vel.y = rand(10.0..100.0) * randSign().float 23 | entity.centrify() 24 | entity.rot = rand(360.0) 25 | entity.rotVel = rand(10.0..60.0) * randSign().float 26 | 27 | 28 | proc newSpaceman*(s: Scene, g: Graphic, p: PhysicsProc): Spaceman = 29 | result = new Spaceman 30 | result.init(s, g, p) 31 | 32 | -------------------------------------------------------------------------------- /demos/demo10/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 10 2 | ================== 3 | 4 | Layers demo. Demonstrates entity layering. 5 | 6 | ![Screenshot](demo10.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo10/demo10.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 10 (Layers)"): 8 | showInfo = true 9 | game.scene = newMainScene() 10 | game.run() 11 | 12 | -------------------------------------------------------------------------------- /demos/demo10/demo10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo10/demo10.png -------------------------------------------------------------------------------- /demos/demo10/earth.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Earth* = ref object of Entity 7 | 8 | 9 | proc init*(entity: Earth) = 10 | entity.initEntity() 11 | entity.pos.x = 128.0 12 | entity.pos.y = 96.0 13 | 14 | 15 | proc newEarth*(): Earth = 16 | result = new Earth 17 | result.init() 18 | 19 | -------------------------------------------------------------------------------- /demos/demo10/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | math, 3 | nimgame2/nimgame, 4 | nimgame2/draw, 5 | nimgame2/entity, 6 | nimgame2/texturegraphic, 7 | nimgame2/input, 8 | nimgame2/scene, 9 | nimgame2/settings, 10 | nimgame2/types, 11 | earth, spaceman 12 | 13 | 14 | type 15 | MainScene = ref object of Scene 16 | earthG, spacemanG: TextureGraphic 17 | e: Earth 18 | s: Spaceman 19 | 20 | 21 | proc init*(scene: MainScene) = 22 | Scene(scene).init() 23 | # Earth 24 | scene.e = newEarth() 25 | scene.earthG = newTextureGraphic() 26 | discard scene.earthG.load("../assets/gfx/earth.png") 27 | scene.e.graphic = scene.earthG 28 | # Spaceman 29 | scene.s = newSpaceman() 30 | scene.spacemanG = newTextureGraphic() 31 | discard scene.spacemanG.load("../assets/gfx/spaceman.png") 32 | scene.s.graphic = scene.spacemanG 33 | 34 | # add to scene 35 | scene.add(scene.s) 36 | scene.add(scene.e) 37 | 38 | 39 | proc free*(scene: MainScene) = 40 | scene.earthG.free 41 | scene.spacemanG.free 42 | 43 | 44 | proc newMainScene*(): MainScene = 45 | new result, free 46 | result.init() 47 | 48 | 49 | method event*(scene: MainScene, event: Event) = 50 | if event.kind == KeyDown: 51 | case event.key.keysym.sym: 52 | of K_Escape: 53 | gameRunning = false 54 | else: discard 55 | 56 | 57 | method render*(scene: MainScene) = 58 | scene.renderScene() 59 | discard box((4, 60), (220, 76), 0x000000CC'u32) 60 | discard string( 61 | (8, 64), "1/2 - Change layer", 0xFF0000FF'u32) 62 | 63 | 64 | method update*(scene: MainScene, elapsed: float) = 65 | scene.updateScene(elapsed) 66 | if Scancode1.down: scene.s.layer = -1 67 | if Scancode2.down: scene.s.layer = 1 68 | 69 | -------------------------------------------------------------------------------- /demos/demo10/spaceman.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Spaceman* = ref object of Entity 7 | 8 | 9 | proc init*(entity: Spaceman) = 10 | entity.initEntity() 11 | entity.pos.x = 200.0 12 | entity.pos.y = 64.0 13 | 14 | 15 | proc newSpaceman*(): Spaceman = 16 | result = new Spaceman 17 | result.init() 18 | 19 | -------------------------------------------------------------------------------- /demos/demo11/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 11 2 | ================== 3 | 4 | Tweens demo. Demonstrates tweening procedures. 5 | 6 | ![Screenshot](demo11.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo11/demo11.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 1280, h = 720, title = "Nimgame 2: Demo 11 (Tweens)"): 8 | #showInfo = true 9 | game.scene = newMainScene() 10 | game.run() 11 | 12 | -------------------------------------------------------------------------------- /demos/demo11/demo11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo11/demo11.png -------------------------------------------------------------------------------- /demos/demo11/earth.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity, 4 | nimgame2/types 5 | 6 | type 7 | Earth* = ref object of Entity 8 | 9 | 10 | proc init*(entity: Earth, pos: Coord) = 11 | entity.initEntity() 12 | entity.pos = pos 13 | 14 | 15 | proc newEarth*(pos: Coord): Earth = 16 | result = new Earth 17 | result.init(pos) 18 | 19 | -------------------------------------------------------------------------------- /demos/demo11/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/bitmapfont, 4 | nimgame2/draw, 5 | nimgame2/entity, 6 | nimgame2/textgraphic, 7 | nimgame2/texturegraphic, 8 | nimgame2/input, 9 | nimgame2/scene, 10 | nimgame2/settings, 11 | nimgame2/tween, 12 | nimgame2/types, 13 | earth 14 | 15 | 16 | type 17 | MainScene = ref object of Scene 18 | earthG: TextureGraphic 19 | font: BitmapFont 20 | tweens: seq[Tween[Entity,Coord]] 21 | 22 | 23 | proc addEntity*(scene: MainScene, 24 | name: string, 25 | pos: Coord, 26 | procedure: TweenProcedure[Coord]) = 27 | # Name 28 | let n = newTextGraphic() 29 | n.font = scene.font 30 | n.lines = [name] 31 | let ne = newEntity() 32 | ne.graphic = n 33 | ne.pos = pos - (98.0, 8.0) 34 | scene.add(ne) 35 | 36 | # Entity 37 | let e = newEarth(pos) 38 | e.graphic = scene.earthG 39 | e.centrify() 40 | scene.add(e) 41 | 42 | # Tween 43 | let t = newTween[Entity,Coord]( 44 | e, 45 | proc(t: Entity): Coord = t.pos, 46 | proc(t: Entity, val: Coord) = t.pos = val) 47 | t.procedure = procedure 48 | scene.tweens.add(t) 49 | t.setup(e.pos, e.pos + (150.0, 0.0), 3.0, -1) 50 | t.play() 51 | 52 | 53 | proc init*(scene: MainScene) = 54 | Scene(scene).init() 55 | scene.tweens = @[] 56 | 57 | # Earth graphic 58 | scene.earthG = newTextureGraphic() 59 | discard scene.earthG.load("../assets/gfx/earth32.png") 60 | 61 | # Font 62 | scene.font = newBitmapFont() 63 | discard scene.font.load("../assets/fnt/default8x16.png", (8, 16)) 64 | 65 | # Column 1 66 | scene.addEntity("linear", (100.0, 35.0), linear) 67 | scene.addEntity("inQuad", (100.0, 85.0), inQuad) 68 | scene.addEntity("outQuad", (100.0, 135.0), outQuad) 69 | scene.addEntity("inOutQuad", (100.0, 185.0), inOutQuad) 70 | 71 | scene.addEntity("inCubic", (100.0, 285.0), inCubic) 72 | scene.addEntity("outCubic", (100.0, 335.0), outCubic) 73 | scene.addEntity("inOutCubic", (100.0, 385.0), inOutCubic) 74 | scene.addEntity("outInCubic", (100.0, 435.0), outInCubic) 75 | 76 | scene.addEntity("inQuart", (100.0, 535.0), inQuart) 77 | scene.addEntity("outQuart", (100.0, 585.0), outQuart) 78 | scene.addEntity("inOutQuart", (100.0, 635.0), inOutQuart) 79 | scene.addEntity("outInQuart", (100.0, 685.0), outInQuart) 80 | 81 | # Column 2 82 | scene.addEntity("inQuint", (400.0, 35.0), inQuint) 83 | scene.addEntity("outQuint", (400.0, 85.0), outQuint) 84 | scene.addEntity("inOutQuint", (400.0, 135.0), inOutQuint) 85 | scene.addEntity("outInQuint", (400.0, 185.0), outInQuint) 86 | 87 | scene.addEntity("inSine", (400.0, 285.0), inSine) 88 | scene.addEntity("outSine", (400.0, 335.0), outSine) 89 | scene.addEntity("inOutSine", (400.0, 385.0), inOutSine) 90 | scene.addEntity("outInSine", (400.0, 435.0), outInSine) 91 | 92 | # Column 3 93 | scene.addEntity("inExpo", (700.0, 35.0), inExpo) 94 | scene.addEntity("outExpo", (700.0, 85.0), outExpo) 95 | scene.addEntity("inOutExpo", (700.0, 135.0), inOutExpo) 96 | scene.addEntity("outInExpo", (700.0, 185.0), outInExpo) 97 | 98 | scene.addEntity("inCirc", (700.0, 285.0), inCirc) 99 | scene.addEntity("outCirc", (700.0, 335.0), outCirc) 100 | scene.addEntity("inOutCirc", (700.0, 385.0), inOutCirc) 101 | scene.addEntity("outInCirc", (700.0, 435.0), outInCirc) 102 | 103 | # Column 4 104 | scene.addEntity("inBounce", (1000.0, 35.0), inBounce) 105 | scene.addEntity("outBounce", (1000.0, 85.0), outBounce) 106 | scene.addEntity("inOutBounce", (1000.0, 135.0), inOutBounce) 107 | scene.addEntity("outInBounce", (1000.0, 185.0), outInBounce) 108 | 109 | scene.addEntity("inElastic", (1000.0, 285.0), inElastic) 110 | scene.addEntity("outElastic", (1000.0, 335.0), outElastic) 111 | scene.addEntity("inOutElastic", (1000.0, 385.0), inOutElastic) 112 | scene.addEntity("outInElastic", (1000.0, 435.0), outInElastic) 113 | 114 | scene.addEntity("inBack", (1000.0, 535.0), inBack) 115 | scene.addEntity("outBack", (1000.0, 585.0), outBack) 116 | scene.addEntity("inOutBack", (1000.0, 635.0), inOutBack) 117 | scene.addEntity("outInBack", (1000.0, 685.0), outInBack) 118 | 119 | 120 | proc free*(scene: MainScene) = 121 | scene.earthG.free 122 | 123 | 124 | proc newMainScene*(): MainScene = 125 | new result, free 126 | result.init() 127 | 128 | 129 | method event*(scene: MainScene, event: Event) = 130 | if event.kind == KeyDown: 131 | case event.key.keysym.sym: 132 | of K_Escape: 133 | gameRunning = false 134 | else: discard 135 | 136 | 137 | method render*(scene: MainScene) = 138 | scene.renderScene() 139 | 140 | 141 | method update*(scene: MainScene, elapsed: float) = 142 | for tween in scene.tweens: 143 | tween.update(elapsed) 144 | scene.updateScene(elapsed) 145 | 146 | -------------------------------------------------------------------------------- /demos/demo12/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 12 2 | ================== 3 | 4 | Emitter demo. Demonstrates particle emitter usage. 5 | 6 | ![Screenshot](demo12.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo12/demo12.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 12 (Emitter)"): 8 | showInfo = true 9 | game.scene = newMainScene() 10 | game.run() 11 | 12 | -------------------------------------------------------------------------------- /demos/demo12/demo12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo12/demo12.png -------------------------------------------------------------------------------- /demos/demo12/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/draw, 4 | nimgame2/entity, 5 | nimgame2/emitter, 6 | nimgame2/texturegraphic, 7 | nimgame2/input, 8 | nimgame2/scene, 9 | nimgame2/settings, 10 | nimgame2/types 11 | 12 | 13 | type 14 | MainScene = ref object of Scene 15 | particleG: TextureGraphic 16 | ePoint, eLine, eCircle, eBox, eScaled: Emitter 17 | 18 | 19 | proc init*(scene: MainScene) = 20 | Scene(scene).init() 21 | # Particle Graphic 22 | scene.particleG = newTextureGraphic() 23 | discard scene.particleG.load("../assets/gfx/puff.png") 24 | 25 | # Particle 26 | var particle: Particle 27 | particle = newParticle() 28 | particle.graphic = scene.particleG 29 | particle.initSprite((5, 5)) 30 | particle.centrify() 31 | discard particle.addAnimation("play", toSeq(0..4), 1/5) 32 | particle.play("play", 1, kill = true) 33 | 34 | # Point emitter 35 | scene.ePoint = newEmitter(scene) 36 | scene.ePoint.randomVel = (10.0, 10.0) 37 | scene.ePoint.randomAcc = (5.0, 5.0) 38 | scene.ePoint.randomTTL = 5.0 39 | scene.ePoint.particle = particle 40 | scene.add(scene.ePoint) 41 | 42 | # Line emitter 43 | scene.eLine = newEmitter(scene, eaLine) 44 | scene.eLine.area.length = 100.0 45 | scene.eLine.randomVel = (10.0, 10.0) 46 | scene.eLine.randomAcc = (5.0, 5.0) 47 | scene.eLine.randomTTL = 5.0 48 | scene.eLine.particle = particle 49 | scene.eLine.pos = game.size / 2 50 | scene.add(scene.eLine) 51 | 52 | # Circle emitter 53 | scene.eCircle = newEmitter(scene, eaCircle) 54 | scene.eCircle.area.radius = 100.0 55 | scene.eCircle.randomVel = (10.0, 10.0) 56 | scene.eCircle.randomAcc = (5.0, 5.0) 57 | scene.eCircle.randomTTL = 5.0 58 | scene.eCircle.particle = particle 59 | scene.eCircle.pos = game.size / 4 60 | scene.add(scene.eCircle) 61 | 62 | # Box emitter 63 | scene.eBox = newEmitter(scene, eaBox) 64 | scene.eBox.area.dim = (100.0, 50.0) 65 | scene.eBox.rotVel = -90.0 66 | scene.eBox.randomVel = (10.0, 10.0) 67 | scene.eBox.randomAcc = (5.0, 5.0) 68 | scene.eBox.randomTTL = 5.0 69 | scene.eBox.particle = particle 70 | scene.eBox.pos = game.size / 2 + game.size / 4 71 | scene.add(scene.eBox) 72 | 73 | # Scaling particles 74 | var particleScaled: Particle 75 | particleScaled = newParticle() 76 | particleScaled.graphic = scene.particleG 77 | particleScaled.initSprite((5, 5)) 78 | particleScaled.centrify() 79 | discard particleScaled.addAnimation("play", toSeq(0..4), 1/2) 80 | particleScaled.play("play", 1, kill = true) 81 | particleScaled.scale = 0.5 82 | particleScaled.scaleVel = 1.0 83 | 84 | scene.eScaled = newEmitter(scene) 85 | scene.eScaled.randomVel = (50.0, 50.0) 86 | scene.eScaled.randomAcc = (5.0, 5.0) 87 | scene.eScaled.randomTTL = 5.0 88 | scene.eScaled.particle = particleScaled 89 | scene.eScaled.pos = (game.size.w div 2 + game.size.w div 4, game.size.h div 4) 90 | scene.add(scene.eScaled) 91 | 92 | 93 | 94 | proc free*(scene: MainScene) = 95 | scene.particleG.free() 96 | 97 | 98 | proc newMainScene*(): MainScene = 99 | new result, free 100 | result.init() 101 | 102 | 103 | method event*(scene: MainScene, event: Event) = 104 | if event.kind == KeyDown: 105 | case event.key.keysym.sym: 106 | of K_Escape: 107 | gameRunning = false 108 | else: discard 109 | 110 | 111 | method render*(scene: MainScene) = 112 | # Draw line between the spaceman and the mouse position if LMB is pressed 113 | scene.renderScene() 114 | 115 | 116 | method update*(scene: MainScene, elapsed: float) = 117 | scene.updateScene(elapsed) 118 | # Point emitter 119 | scene.ePoint.pos = mouse.abs 120 | if MouseButton.left.down: 121 | scene.ePoint.emit(5) 122 | # Line emitter 123 | scene.eLine.rot += 90 * elapsed 124 | scene.eLine.emit(5) 125 | # Circle emitter 126 | scene.eCircle.area.radius = if MouseButton.left.down: 50.0 else: 100.0 127 | scene.eCircle.emit(scene.eCircle.area.radius.int div 20) 128 | # Box emitter 129 | scene.eBox.rot += scene.eBox.rotVel * elapsed 130 | scene.eBox.emit(5) 131 | # Scaled emitter 132 | scene.eScaled.emit(5) 133 | 134 | -------------------------------------------------------------------------------- /demos/demo13/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 13 2 | ================== 3 | 4 | TileMap demo. Demonstrates tile maps usage. 5 | 6 | Note 7 | ---- 8 | For the performance purposes TileCollider is based on BoxCollider. It means, that usually you shouldn't initialize collider on a TileMap that will be rotated. 9 | 10 | ![Screenshot](demo13.png) 11 | 12 | -------------------------------------------------------------------------------- /demos/demo13/cursor.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity, 4 | nimgame2/input, 5 | nimgame2/tilemap 6 | 7 | type 8 | Cursor* = ref object of Entity 9 | collidedWith*: seq[string] 10 | 11 | 12 | proc init*(entity: Cursor) = 13 | entity.initEntity() 14 | entity.tags.add("Cursor") 15 | entity.pos = mouse.abs 16 | entity.collidedWith = @[] 17 | 18 | 19 | proc newCursor*(): Cursor = 20 | result = new Cursor 21 | result.init() 22 | 23 | 24 | method update*(entity: Cursor, elapsed: float) = 25 | entity.updateEntity(elapsed) 26 | entity.collidedWith = @[] 27 | entity.pos = mouse.abs 28 | 29 | 30 | method onCollide*(entity: Cursor, target: Entity) = 31 | if target.tags.len > 0: 32 | if "map" in target.tags: 33 | let collider = TilemapCollider(target.collider) 34 | let clist = collider.collisionList(entity.pos) 35 | for tile in clist: 36 | entity.collidedWith.add( 37 | "[" & $tile.index.x & ":" & $tile.index.y & "] -> " & $tile.value) 38 | 39 | -------------------------------------------------------------------------------- /demos/demo13/demo13.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 13 (TileMap)"): 8 | showInfo = true 9 | game.scene = newMainScene() 10 | game.run() 11 | 12 | -------------------------------------------------------------------------------- /demos/demo13/demo13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo13/demo13.png -------------------------------------------------------------------------------- /demos/demo13/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/draw, 4 | nimgame2/entity, 5 | nimgame2/texturegraphic, 6 | nimgame2/tilemap, 7 | nimgame2/input, 8 | nimgame2/scene, 9 | nimgame2/settings, 10 | nimgame2/types, 11 | cursor 12 | 13 | 14 | type 15 | MainScene = ref object of Scene 16 | tilesG: TextureGraphic 17 | tm: TileMap 18 | cursor: Cursor 19 | 20 | 21 | proc init*(scene: MainScene) = 22 | Scene(scene).init() 23 | 24 | # Cursor 25 | hideCursor() 26 | scene.cursor = newCursor() 27 | let cursorG = newTextureGraphic() 28 | discard cursorG.load("../assets/gfx/cursor.png") 29 | scene.cursor.graphic = cursorG 30 | scene.cursor.collider = newCollider(scene.cursor) 31 | scene.add(scene.cursor) 32 | 33 | # Tiles Graphic 34 | scene.tilesG = newTextureGraphic() 35 | discard scene.tilesG.load("../assets/gfx/sprite0.png") 36 | # TileMap 37 | scene.tm = newTileMap(scaleFix = true) 38 | scene.tm.tags.add("map") 39 | scene.tm.graphic = scene.tilesG 40 | scene.tm.initSprite((64, 64), offset = (32, 32)) 41 | scene.tm.map = @[ 42 | @[0, 0, 0, 0], 43 | @[1, 0, 0, 1], 44 | @[2, 3, 3, 2] 45 | ] 46 | scene.tm.passable.add(0) 47 | scene.tm.centrify() 48 | scene.tm.initCollider() 49 | scene.tm.pos = (320.0, 240.0) 50 | scene.add(scene.tm) 51 | 52 | 53 | 54 | proc free*(scene: MainScene) = 55 | scene.tilesG.free() 56 | 57 | 58 | proc newMainScene*(): MainScene = 59 | new result, free 60 | result.init() 61 | 62 | 63 | method event*(scene: MainScene, event: Event) = 64 | if event.kind == KeyDown: 65 | case event.key.keysym.sym: 66 | of K_Escape: 67 | gameRunning = false 68 | of K_Space: 69 | colliderOutline = not colliderOutline 70 | else: discard 71 | 72 | 73 | method render*(scene: MainScene) = 74 | scene.renderScene() 75 | discard box((4, 60), (300, 108), 0x000000CC'u32) 76 | 77 | discard string((8, 64), "WSAD or Arrows - move", 0xFFFFFFFF'u32) 78 | 79 | discard string((8, 72), "Q/E - change angle", 0xFFFFFFFF'u32) 80 | 81 | discard string((8, 80), "R/F - change scale", 0xFFFFFFFF'u32) 82 | 83 | discard string((8, 88), "Space - toggle collider outlines", 0xFFFFFFFF'u32) 84 | 85 | var collides: string = "" 86 | for collision in scene.cursor.collidedWith: 87 | collides &= collision & " " 88 | 89 | discard string((8, 96), 90 | if scene.cursor.collidedWith.len > 0: 91 | "Cursor collides with: " & collides 92 | else: 93 | "Cursor isn't over a collidable tile", 94 | 0xFFFFFFFF'u32) 95 | 96 | 97 | method update*(scene: MainScene, elapsed: float) = 98 | scene.updateScene(elapsed) 99 | if ScancodeW.down or ScancodeUp.down: scene.tm.pos.y -= 100 * elapsed 100 | if ScancodeS.down or ScancodeDown.down: scene.tm.pos.y += 100 * elapsed 101 | if ScancodeA.down or ScancodeLeft.down: scene.tm.pos.x -= 100 * elapsed 102 | if ScancodeD.down or ScancodeRight.down: scene.tm.pos.x += 100 * elapsed 103 | if ScancodeQ.down: scene.tm.rot -= 100 * elapsed 104 | if ScancodeE.down: scene.tm.rot += 100 * elapsed 105 | if ScancodeR.down: scene.tm.scale -= 0.5 * elapsed 106 | if ScancodeF.down: scene.tm.scale += 0.5 * elapsed 107 | 108 | -------------------------------------------------------------------------------- /demos/demo14/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 14 2 | ================== 3 | 4 | Second TileMap demo. Demonstrates practical TileMap usage, along with Tween an Emitter usage. 5 | 6 | F10 - Show/Hide info panel. 7 | 8 | ![Screenshot](demo14.png) 9 | 10 | -------------------------------------------------------------------------------- /demos/demo14/demo14.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 14 (TileMap 2)"): 8 | showInfo = true 9 | game.scene = newMainScene() 10 | game.run() 11 | 12 | -------------------------------------------------------------------------------- /demos/demo14/demo14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo14/demo14.png -------------------------------------------------------------------------------- /demos/demo14/dwarf.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity, 4 | nimgame2/texturegraphic, 5 | nimgame2/tilemap, 6 | nimgame2/tween, 7 | nimgame2/types 8 | 9 | 10 | const 11 | Framerate = 1/12 12 | ScreenOffset*: Coord = (8.0, 0.0) 13 | Step* = 24.0 14 | 15 | 16 | type 17 | Direction* = enum dNone, dDown, dUp, dLeft, dRight 18 | 19 | Dwarf* = ref object of Entity 20 | tween*: Tween[Dwarf,Coord] 21 | virtualPos*: tuple[x: int, y: int] 22 | map*: TileMap 23 | 24 | 25 | proc init*(entity: Dwarf, graphic: TextureGraphic, map: TileMap) = 26 | entity.initEntity() 27 | entity.tags.add("dwarf") 28 | entity.graphic = graphic 29 | entity.initSprite((24, 48)) 30 | discard entity.addAnimation( 31 | "down", [0, 1, 2, 3, 4, 5], Framerate) 32 | discard entity.addAnimation( 33 | "up", [6, 7, 8, 9, 10, 11], Framerate) 34 | discard entity.addAnimation( 35 | "left", [12, 13, 14, 15, 16, 17], Framerate) 36 | discard entity.addAnimation( 37 | "right", [12, 13, 14, 15, 16, 17], Framerate, Flip.horizontal) 38 | entity.pos = (44.0, 444.0) 39 | entity.virtualPos = (1, 18) 40 | entity.center = (12.0, 36.0) 41 | entity.map = map 42 | entity.map.show = ( 43 | x: (entity.virtualPos.x - 2)..(entity.virtualPos.x + 2), 44 | y: (entity.virtualPos.y - 2)..(entity.virtualPos.y + 2) 45 | ) 46 | 47 | 48 | proc newDwarf*(graphic: TextureGraphic, map: TileMap): Dwarf = 49 | result = new Dwarf 50 | result.init(graphic, map) 51 | 52 | 53 | proc actuate(entity: Dwarf, anim: string, movement: Coord) = 54 | if entity.tween == nil or not entity.tween.playing: 55 | let 56 | newPos = entity.pos + movement 57 | newVirtualPos: tuple[x: int, y: int] = 58 | (int(newPos.x - ScreenOffset.x) div Step.int, 59 | int(newPos.y - ScreenOffset.y) div Step.int) 60 | 61 | if entity.map.map[newVirtualPos.y][newVirtualPos.x] > 2: 62 | return # unpassable 63 | 64 | entity.play(anim, 1) 65 | entity.tween = newTween[Dwarf,Coord]( 66 | entity, 67 | proc(t: Dwarf): Coord = t.pos, 68 | proc(t: Dwarf, val: Coord) = t.pos = val) 69 | entity.tween.setup(entity.pos, newPos, 0.5, 0) 70 | entity.virtualPos = newVirtualPos 71 | entity.tween.play() 72 | entity.map.show = ( 73 | x: (newVirtualPos.x - 2)..(newVirtualPos.x + 2), 74 | y: (newVirtualPos.y - 2)..(newVirtualPos.y + 2) 75 | ) 76 | 77 | 78 | proc move*(entity: Dwarf, direction: Direction) = 79 | case direction: 80 | of dDown: entity.actuate("down", (0.0, Step)) 81 | of dUp: entity.actuate("up", (0.0, -Step)) 82 | of dRight: entity.actuate("right", (Step, 0.0)) 83 | of dLeft: entity.actuate("left", (-Step, 0.0)) 84 | of dNone: discard 85 | 86 | -------------------------------------------------------------------------------- /demos/demo14/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | parseutils, 3 | nimgame2/nimgame, 4 | nimgame2/draw, 5 | nimgame2/emitter, 6 | nimgame2/entity, 7 | nimgame2/texturegraphic, 8 | nimgame2/tilemap, 9 | nimgame2/input, 10 | nimgame2/scene, 11 | nimgame2/settings, 12 | nimgame2/tween, 13 | nimgame2/types, 14 | nimgame2/utils, 15 | dwarf 16 | 17 | 18 | type 19 | MainScene = ref object of Scene 20 | dG, tilesG, sparkG: TextureGraphic 21 | d: Dwarf 22 | sparks: Emitter 23 | map: TileMap 24 | 25 | 26 | proc init*(scene: MainScene) = 27 | Scene(scene).init() 28 | 29 | # Spark 30 | scene.sparkG = newTextureGraphic() 31 | discard scene.sparkG.load("../assets/gfx/puff.png") 32 | 33 | # TileMap 34 | scene.tilesG = newTextureGraphic() 35 | discard scene.tilesG.load("../assets/gfx/tile0.png") 36 | scene.map = newTileMap() 37 | scene.map.tags.add("map") 38 | scene.map.graphic = scene.tilesG 39 | scene.map.initSprite((24, 24)) 40 | scene.map.map = loadCSV[int]( 41 | "../assets/csv/map0.csv", 42 | proc(input: string): int = discard parseInt(input, result)) 43 | scene.map.pos = (8.0, 0.0) 44 | 45 | # Dwarf 46 | scene.dG = newTextureGraphic() 47 | discard scene.dG.load("../assets/gfx/dwarf.png") 48 | scene.d = newDwarf(scene.dG, scene.map) 49 | scene.d.layer = 10 50 | 51 | # Add to scene 52 | scene.add(scene.d) 53 | scene.add(scene.map) 54 | 55 | proc free*(scene: MainScene) = 56 | scene.dG.free 57 | 58 | 59 | proc newMainScene*(): MainScene = 60 | new result, free 61 | result.init() 62 | 63 | 64 | method event*(scene: MainScene, event: Event) = 65 | if event.kind == KeyDown: 66 | case event.key.keysym.sym: 67 | of K_Escape: 68 | gameRunning = false 69 | of K_F10: 70 | showInfo = not showInfo 71 | else: discard 72 | 73 | 74 | method render*(scene: MainScene) = 75 | scene.renderScene() 76 | 77 | 78 | method update*(scene: MainScene, elapsed: float) = 79 | scene.updateScene(elapsed) 80 | if scene.d.tween != nil: 81 | scene.d.tween.update(elapsed) 82 | 83 | # Controls and speed 84 | var direction: dwarf.Direction = 85 | if ScancodeDown.down or ScancodeS.down: dDown 86 | elif ScancodeUp.down or ScancodeW.down: dUp 87 | elif ScancodeLeft.down or ScancodeA.down: dLeft 88 | elif ScancodeRight.down or ScancodeD.down: dRight 89 | else: dNone 90 | 91 | scene.d.move(direction) 92 | 93 | # Sparks 94 | if scene.sparks == nil: 95 | if scene.map.map[scene.d.virtualPos.y][scene.d.virtualPos.x] == 2: 96 | scene.sparks = newEmitter(scene) 97 | scene.sparks.pos = ((scene.d.virtualPos.x.float, 98 | scene.d.virtualPos.y.float) * Step) + 99 | ScreenOffset + scene.d.center - (0.0, Step) 100 | scene.sparks.randomVel = (25.0, 25.0) 101 | scene.sparks.randomAcc = (10.0, 10.0) 102 | scene.sparks.randomTTL = 2.5 103 | scene.sparks.particle = newParticle() 104 | scene.sparks.particle.graphic = scene.sparkG 105 | scene.sparks.particle.initSprite((5, 5)) 106 | scene.sparks.particle.centrify() 107 | discard scene.sparks.particle.addAnimation("play", toSeq(0..4), 1/5) 108 | scene.sparks.particle.play("play", 1, kill = true) 109 | scene.add(scene.sparks) 110 | else: 111 | scene.sparks.emit(10) 112 | 113 | 114 | -------------------------------------------------------------------------------- /demos/demo15/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 15 2 | ================== 3 | 4 | Camera demo. Demonstrates camera usage. 5 | 6 | Note a negative sign in front of the camera's position. 7 | 8 | ![Screenshot](demo15.png) 9 | 10 | -------------------------------------------------------------------------------- /demos/demo15/demo15.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 15 (Camera)"): 8 | showInfo = true 9 | game.scene = newMainScene() 10 | game.run() 11 | 12 | -------------------------------------------------------------------------------- /demos/demo15/demo15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo15/demo15.png -------------------------------------------------------------------------------- /demos/demo15/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | parseutils, 3 | nimgame2/nimgame, 4 | nimgame2/draw, 5 | nimgame2/entity, 6 | nimgame2/texturegraphic, 7 | nimgame2/tilemap, 8 | nimgame2/input, 9 | nimgame2/scene, 10 | nimgame2/settings, 11 | nimgame2/types, 12 | nimgame2/utils 13 | 14 | 15 | type 16 | MainScene = ref object of Scene 17 | tilesG, spacemanG: TextureGraphic 18 | spaceman: Entity 19 | map: TileMap 20 | 21 | 22 | proc init*(scene: MainScene) = 23 | Scene(scene).init() 24 | 25 | scene.camera = newEntity() 26 | scene.cameraBondOffset = game.size / 2 27 | 28 | # Tiles Graphic 29 | scene.tilesG = newTextureGraphic() 30 | discard scene.tilesG.load("../assets/gfx/tile0.png") 31 | 32 | # TileMap 33 | scene.map = newTileMap(scaleFix = true) 34 | scene.map.parent = scene.camera 35 | scene.map.tags.add("map") 36 | scene.map.graphic = scene.tilesG 37 | scene.map.initSprite((24, 24)) 38 | scene.map.map = loadCSV[int]("../assets/csv/map_camera_test.csv", 39 | proc(s: string): int = discard parseInt(s, result)) 40 | scene.map.passable.add(0) 41 | scene.map.initCollider() 42 | scene.map.pos = (0.0, 0.0) 43 | 44 | # SpacemanG 45 | scene.spacemanG = newTextureGraphic() 46 | discard scene.spacemanG.load("../assets/gfx/spaceman.png") 47 | 48 | # Spaceman 49 | scene.spaceman = newEntity() 50 | scene.spaceman.parent = scene.map 51 | scene.spaceman.graphic = scene.spacemanG 52 | scene.spaceman.centrify() 53 | scene.spaceman.pos = (200.0, 200.0) 54 | 55 | # Add 56 | scene.add(scene.spaceman) 57 | scene.add(scene.map) 58 | 59 | 60 | 61 | proc free*(scene: MainScene) = 62 | scene.tilesG.free() 63 | scene.spacemanG.free() 64 | 65 | 66 | proc newMainScene*(): MainScene = 67 | new result, free 68 | result.init() 69 | 70 | 71 | method event*(scene: MainScene, event: Event) = 72 | if event.kind == KeyDown: 73 | case event.key.keysym.sym: 74 | of K_Escape: 75 | gameRunning = false 76 | of K_Space: 77 | colliderOutline = not colliderOutline 78 | of K_Return: 79 | scene.cameraBond = if scene.cameraBond != nil: nil 80 | else: scene.spaceman 81 | else: discard 82 | 83 | 84 | method render*(scene: MainScene) = 85 | scene.renderScene() 86 | discard box((4, 60), (300, 108), 0x000000CC'u32) 87 | 88 | discard string((8, 64), "Arrows - move camera", 0xFFFFFFFF'u32) 89 | discard string((8, 72), "WSAD - move spaceman", 0xFFFFFFFF'u32) 90 | discard string((8, 80), "Enter - toggle following (" & 91 | (if scene.cameraBond != nil: "on" else: "off") & ")", 0xFFFFFFFF'u32) 92 | 93 | discard string((8, 88), "camera.pos = " & $(-scene.camera.pos), 94 | 0xFFFFFFFF'u32) 95 | discard string((8, 96), "spaceman.pos = " & $(scene.spaceman.pos), 96 | 0xFFFFFFFF'u32) 97 | 98 | 99 | method update*(scene: MainScene, elapsed: float) = 100 | scene.updateScene(elapsed) 101 | let move = 100 * elapsed 102 | if scene.cameraBond == nil: 103 | if ScancodeUp.down: scene.camera.pos.y += move 104 | if ScancodeDown.down: scene.camera.pos.y -= move 105 | if ScancodeLeft.down: scene.camera.pos.x += move 106 | if ScancodeRight.down: scene.camera.pos.x -= move 107 | if ScancodeW.down: scene.spaceman.pos.y -= move 108 | if ScancodeS.down: scene.spaceman.pos.y += move 109 | if ScancodeA.down: scene.spaceman.pos.x -= move 110 | if ScancodeD.down: scene.spaceman.pos.x += move 111 | 112 | -------------------------------------------------------------------------------- /demos/demo16/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 16 2 | ================== 3 | 4 | Parallax demo. Demonstrates parallax effect. 5 | 6 | ![Screenshot](demo16.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo16/demo16.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 16 (Parallax)"): 8 | showInfo = true 9 | game.scene = newMainScene() 10 | game.run() 11 | 12 | -------------------------------------------------------------------------------- /demos/demo16/demo16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo16/demo16.png -------------------------------------------------------------------------------- /demos/demo16/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity, 4 | nimgame2/texturegraphic, 5 | nimgame2/input, 6 | nimgame2/scene, 7 | nimgame2/settings, 8 | nimgame2/types 9 | 10 | 11 | type 12 | MainScene = ref object of Scene 13 | spacemanG: TextureGraphic 14 | p0125, p025, p05, p1: Entity 15 | 16 | 17 | proc init*(scene: MainScene) = 18 | Scene(scene).init() 19 | 20 | # Graphics 21 | scene.spacemanG = newTextureGraphic() 22 | discard scene.spacemanG.load("../assets/gfx/spaceman.png") 23 | 24 | # Entities 25 | scene.camera = newEntity() 26 | scene.camera.pos = game.size / 2 27 | 28 | scene.p0125 = newEntity() 29 | scene.p0125.parent = scene.camera 30 | scene.p0125.graphic = scene.spacemanG 31 | scene.p0125.centrify() 32 | scene.p0125.pos = game.size / 2 33 | scene.p0125.pos.y -= 150 34 | scene.p0125.parallax = 0.125 35 | 36 | scene.p025 = newEntity() 37 | scene.p025.parent = scene.camera 38 | scene.p025.graphic = scene.spacemanG 39 | scene.p025.centrify() 40 | scene.p025.pos = game.size / 2 41 | scene.p025.pos.y -= 100 42 | scene.p025.parallax = 0.25 43 | 44 | scene.p05 = newEntity() 45 | scene.p05.parent = scene.camera 46 | scene.p05.graphic = scene.spacemanG 47 | scene.p05.centrify() 48 | scene.p05.pos = game.size / 2 49 | scene.p05.pos.y -= 50 50 | scene.p05.parallax = 0.5 51 | 52 | scene.p1 = newEntity() 53 | scene.p1.parent = scene.camera 54 | scene.p1.graphic = scene.spacemanG 55 | scene.p1.centrify() 56 | scene.p1.pos = game.size / 2 57 | 58 | scene.cameraBond = scene.p1 59 | 60 | # add to scene 61 | scene.add(scene.p1) 62 | scene.add(scene.p05) 63 | scene.add(scene.p025) 64 | scene.add(scene.p0125) 65 | 66 | 67 | proc free*(scene: MainScene) = 68 | scene.spacemanG.free() 69 | 70 | 71 | proc newMainScene*(): MainScene = 72 | new result, free 73 | result.init() 74 | 75 | 76 | method event*(scene: MainScene, event: Event) = 77 | scene.eventScene(event) 78 | if event.kind == KeyDown: 79 | case event.key.keysym.sym: 80 | of K_Escape: 81 | gameRunning = false 82 | of K_Space: 83 | colliderOutline = not colliderOutline 84 | else: discard 85 | 86 | 87 | method render*(scene: MainScene) = 88 | scene.renderScene() 89 | 90 | 91 | method update*(scene: MainScene, elapsed: float) = 92 | scene.updateScene(elapsed) 93 | scene.camera.pos = mouse.abs - Coord(game.size / 2) 94 | 95 | -------------------------------------------------------------------------------- /demos/demo17/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 17 2 | ================== 3 | 4 | First GUI demo. Demonstrates buttons and text field usage. 5 | 6 | ![Screenshot](demo17.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo17/btnCircle.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/graphic, 3 | nimgame2/input, 4 | nimgame2/gui/widget, 5 | nimgame2/gui/button 6 | 7 | 8 | type 9 | CircleButton* = ref object of GuiButton 10 | 11 | 12 | proc init*(btn: CircleButton, graphic: Graphic) = 13 | GuiButton(btn).init(graphic, circle = true) 14 | 15 | 16 | proc newCircleButton*(graphic: Graphic): CircleButton = 17 | new result 18 | result.init(graphic) 19 | 20 | 21 | method onClick*(btn: CircleButton, mb: MouseButton) = 22 | echo "clicked circle button, toggled " & (if btn.toggled: "on" else: "off") 23 | 24 | -------------------------------------------------------------------------------- /demos/demo17/btnSquare.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/graphic, 3 | nimgame2/input, 4 | nimgame2/gui/button 5 | 6 | 7 | type 8 | SquareButton* = ref object of GuiButton 9 | 10 | 11 | proc init*(btn: SquareButton, graphic: Graphic, image: Graphic = nil) = 12 | GuiButton(btn).init(graphic, image) 13 | 14 | 15 | proc newSquareButton*(graphic: Graphic, image: Graphic = nil): SquareButton = 16 | new result 17 | result.init(graphic, image) 18 | 19 | 20 | method onClick*(btn: SquareButton, mb: MouseButton) = 21 | echo "clicked square button" 22 | 23 | -------------------------------------------------------------------------------- /demos/demo17/demo17.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 17 (GUI)"): 8 | showInfo = true 9 | game.scene = newMainScene() 10 | game.run() 11 | 12 | -------------------------------------------------------------------------------- /demos/demo17/demo17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo17/demo17.png -------------------------------------------------------------------------------- /demos/demo17/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/draw, 4 | nimgame2/entity, 5 | nimgame2/texturegraphic, 6 | nimgame2/input, 7 | nimgame2/mosaic, 8 | nimgame2/scene, 9 | nimgame2/settings, 10 | nimgame2/truetypefont, 11 | nimgame2/types, 12 | nimgame2/gui/widget, 13 | nimgame2/gui/radio, 14 | nimgame2/gui/textinput, 15 | nimgame2/gui/progressbar, 16 | btnSquare, btnCircle 17 | 18 | 19 | type 20 | MainScene = ref object of Scene 21 | btnSquareG, btnCircleG, iconX, btnMosaicG, inputG: TextureGraphic 22 | btnsRadio: array[3, GuiRadioButton] 23 | radioGroup: GuiRadioGroup 24 | btnSquare, btnMosaic: SquareButton 25 | btnCircle: CircleButton 26 | textInput: GuiTextInput 27 | progressBar: GuiProgressBar 28 | font: TrueTypeFont 29 | 30 | 31 | proc init*(scene: MainScene) = 32 | Scene(scene).init() 33 | 34 | # Graphics 35 | scene.btnSquareG = newTextureGraphic() 36 | discard scene.btnSquareG.load("../assets/gfx/button_square.png") 37 | scene.btnCircleG = newTextureGraphic() 38 | discard scene.btnCircleG.load("../assets/gfx/button_circle.png") 39 | scene.iconX = newTextureGraphic() 40 | discard scene.iconX.load("../assets/gfx/icon_x.png") 41 | let mosaic = newMosaic("../assets/gfx/button_square.png", (8, 8)) 42 | scene.btnMosaicG = newTextureGraphic() 43 | discard scene.btnMosaicG.assignTexture mosaic.render( 44 | patternStretchBorder(4, 2)) 45 | 46 | # Square Button 47 | scene.btnSquare = newSquareButton(scene.btnSquareG, scene.iconX) 48 | scene.btnSquare.mbAllow.set(MouseButton.right) 49 | scene.btnSquare.pos = (100, 100) 50 | # Circle Button 51 | scene.btnCircle = newCircleButton(scene.btnCircleG) 52 | scene.btnCircle.pos = (150, 100) 53 | scene.btnCircle.toggle = true 54 | # Mosaic Button 55 | scene.btnMosaic = newSquareButton(scene.btnMosaicG) 56 | scene.btnMosaic.pos = (200, 100) 57 | 58 | # Text Input 59 | scene.font = newTrueTypeFont() 60 | discard scene.font.load("../assets/fnt/FSEX300.ttf", 16) 61 | let inputmosaic = newMosaic("../assets/gfx/text_input.png", (8, 8)) 62 | scene.inputG = newTextureGraphic() 63 | discard scene.inputG.assignTexture inputmosaic.render( 64 | patternStretchBorder(16, 1)) 65 | scene.textInput = newGuiTextInput(scene.inputG, scene.font) 66 | scene.textInput.pos = (100, 150) 67 | scene.textInput.text.limit = 16 68 | 69 | # Radio Button 70 | scene.radioGroup = newGuiRadioGroup() 71 | scene.radioGroup.pos = (100, 200) 72 | for i in 0..scene.btnsRadio.high: 73 | scene.btnsRadio[i] = newGuiRadioButton( 74 | scene.radioGroup, scene.btnCircleG, circle = true) 75 | scene.btnsRadio[i].pos = (i.float * 50.0, 0.0) 76 | scene.btnsRadio[0].toggled = true 77 | 78 | # Progress Bar 79 | scene.progressBar = newProgressBar((200, 50), 0xFF0000FF'u32, 0x00FF00FF'u32, 80 | scene.font) 81 | scene.progressBar.min = 0 82 | scene.progressBar.max = 100 83 | scene.progressBar.value = 0 84 | scene.progressBar.direction = Direction.leftRight 85 | scene.progressBar.outline = (1, 1) 86 | scene.progressBar.pos = (100, 250) 87 | 88 | # add to scene 89 | scene.add(scene.progressBar) 90 | scene.add(scene.radioGroup) 91 | for b in scene.btnsRadio: 92 | scene.add(b) 93 | scene.add(scene.textInput) 94 | scene.add(scene.btnMosaic) 95 | scene.add(scene.btnSquare) 96 | scene.add(scene.btnCircle) 97 | 98 | 99 | proc free*(scene: MainScene) = 100 | scene.inputG.free() 101 | scene.btnMosaicG.free() 102 | scene.btnSquareG.free() 103 | scene.btnCircleG.free() 104 | scene.iconX.free() 105 | 106 | 107 | proc newMainScene*(): MainScene = 108 | new result, free 109 | result.init() 110 | 111 | 112 | method event*(scene: MainScene, event: Event) = 113 | scene.eventScene(event) 114 | if event.kind == KeyDown: 115 | case event.key.keysym.sym: 116 | of K_Escape: 117 | gameRunning = false 118 | of K_Space: 119 | colliderOutline = not colliderOutline 120 | else: discard 121 | 122 | 123 | method render*(scene: MainScene) = 124 | scene.renderScene() 125 | discard box((4, 60), (220, 76), 0x000000CC'u32) 126 | discard string( 127 | (8, 64), "Space - toggle collider outlines", 0xFFFFFFFF'u32) 128 | 129 | 130 | method update*(scene: MainScene, elapsed: float) = 131 | scene.updateScene(elapsed) 132 | 133 | # progressBar 134 | if scene.progressBar.value < scene.progressBar.max: 135 | scene.progressBar.value += 10 * elapsed 136 | if scene.progressBar.value > scene.progressBar.max: 137 | scene.progressBar.value = scene.progressBar.max 138 | 139 | 140 | -------------------------------------------------------------------------------- /demos/demo18/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 18 2 | ================== 3 | 4 | IndexedImage. Demonstrates palette swapping in indexed images. 5 | 6 | ![Screenshot](demo18.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo18/demo18.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 320, h = 240, title = "Nimgame 2: Demo 18 (IndexedImage)"): 8 | game.windowSize = (640, 480) 9 | showInfo = true 10 | game.scene = newMainScene() 11 | game.run() 12 | 13 | -------------------------------------------------------------------------------- /demos/demo18/demo18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo18/demo18.png -------------------------------------------------------------------------------- /demos/demo18/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/draw, 4 | nimgame2/entity, 5 | nimgame2/texturegraphic, 6 | nimgame2/input, 7 | nimgame2/indexedimage, 8 | nimgame2/scene, 9 | nimgame2/settings, 10 | nimgame2/types 11 | 12 | 13 | type 14 | MainScene = ref object of Scene 15 | idximg: IndexedImage 16 | knightG: TextureGraphic 17 | knight: Entity 18 | 19 | 20 | proc init*(scene: MainScene) = 21 | Scene(scene).init() 22 | 23 | scene.idximg = newIndexedImage("../assets/gfx/knight.gif") 24 | 25 | scene.knightG = newTextureGraphic() 26 | discard scene.knightG.assignTexture scene.idximg.render() 27 | 28 | scene.knight = newEntity() 29 | scene.knight.graphic = scene.knightG 30 | scene.knight.pos = (128, 128) 31 | 32 | # add to scene 33 | scene.add(scene.knight) 34 | 35 | 36 | proc free*(scene: MainScene) = 37 | scene.knightG.free() 38 | 39 | 40 | proc newMainScene*(): MainScene = 41 | new result, free 42 | result.init() 43 | 44 | 45 | method event*(scene: MainScene, event: Event) = 46 | scene.eventScene(event) 47 | if event.kind == KeyDown: 48 | case event.key.keysym.sym: 49 | of K_Escape: 50 | gameRunning = false 51 | else: discard 52 | 53 | 54 | method render*(scene: MainScene) = 55 | scene.renderScene() 56 | discard box((4, 60), (220, 76), 0x000000CC'u32) 57 | discard string( 58 | (8, 64), "QWER - increase RGBA values (1st color)", 0xFFFFFFFF'u32) 59 | discard string( 60 | (8, 72), "ASDF - decrease RGBA values (1st color)", 0xFFFFFFFF'u32) 61 | discard string( 62 | (8, 80), "TYUI - increase RGBA values (2nd color)", 0xFFFFFFFF'u32) 63 | discard string( 64 | (8, 88), "GHJK - decrease RGBA values (2nd color)", 0xFFFFFFFF'u32) 65 | discard string( 66 | (8, 96), "1st: " & $scene.idximg.palette[3], 0xFFFFFFFF'u32) 67 | discard string( 68 | (8, 104), "2nd: " & $scene.idximg.palette[11], 0xFFFFFFFF'u32) 69 | 70 | 71 | const 72 | Step = 15 73 | 74 | 75 | method update*(scene: MainScene, elapsed: float) = 76 | scene.updateScene(elapsed) 77 | let palette = scene.idximg.palette 78 | var 79 | upd = false 80 | color1 = palette[3] 81 | color2 = palette[11] 82 | 83 | # color1 84 | if ScancodeQ.pressed: 85 | color1.r = clamp(color1.r.int + Step, 0, 255).uint8 86 | upd = true 87 | if ScancodeW.pressed: 88 | color1.g = clamp(color1.g.int + Step, 0, 255).uint8 89 | upd = true 90 | if ScancodeE.pressed: 91 | color1.b = clamp(color1.b.int + Step, 0, 255).uint8 92 | upd = true 93 | if ScancodeR.pressed: 94 | color1.a = clamp(color1.a.int + Step, 0, 255).uint8 95 | upd = true 96 | if ScancodeA.pressed: 97 | color1.r = clamp(color1.r.int - Step, 0, 255).uint8 98 | upd = true 99 | if ScancodeS.pressed: 100 | color1.g = clamp(color1.g.int - Step, 0, 255).uint8 101 | upd = true 102 | if ScancodeD.pressed: 103 | color1.b = clamp(color1.b.int - Step, 0, 255).uint8 104 | upd = true 105 | if ScancodeF.pressed: 106 | color1.a = clamp(color1.a.int - Step, 0, 255).uint8 107 | upd = true 108 | 109 | # color2 110 | if ScancodeT.pressed: 111 | color2.r = clamp(color2.r.int + Step, 0, 255).uint8 112 | upd = true 113 | if ScancodeY.pressed: 114 | color2.g = clamp(color2.g.int + Step, 0, 255).uint8 115 | upd = true 116 | if ScancodeU.pressed: 117 | color2.b = clamp(color2.b.int + Step, 0, 255).uint8 118 | upd = true 119 | if ScancodeI.pressed: 120 | color2.a = clamp(color2.a.int + Step, 0, 255).uint8 121 | upd = true 122 | if ScancodeG.pressed: 123 | color2.r = clamp(color2.r.int - Step, 0, 255).uint8 124 | upd = true 125 | if ScancodeH.pressed: 126 | color2.g = clamp(color2.g.int - Step, 0, 255).uint8 127 | upd = true 128 | if ScancodeJ.pressed: 129 | color2.b = clamp(color2.b.int - Step, 0, 255).uint8 130 | upd = true 131 | if ScancodeK.pressed: 132 | color2.a = clamp(color2.a.int - Step, 0, 255).uint8 133 | upd = true 134 | 135 | if upd: 136 | scene.idximg.palette[3] = color1 137 | scene.idximg.palette[11] = color2 138 | discard scene.knightG.assignTexture(scene.idximg.render()) 139 | 140 | -------------------------------------------------------------------------------- /demos/demo19/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 19 2 | ================== 3 | 4 | PerspectiveImage. Demonstrates perspective transformations. 5 | 6 | ![Screenshot](demo19.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo19/demo19.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 19 (PerspectiveImage)"): 8 | showInfo = true 9 | game.scene = newMainScene() 10 | game.run() 11 | 12 | -------------------------------------------------------------------------------- /demos/demo19/demo19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo19/demo19.png -------------------------------------------------------------------------------- /demos/demo19/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity, 4 | nimgame2/texturegraphic, 5 | nimgame2/input, 6 | nimgame2/perspectiveimage, 7 | nimgame2/scene, 8 | nimgame2/settings, 9 | nimgame2/types 10 | 11 | 12 | const 13 | GraphicCount = 17 14 | Positions: array[GraphicCount, Coord] = [ 15 | (125.0, 125.0), (275, 125), (375, 125), (475, 125), (575, 125), 16 | (75, 275), (175, 275), (275, 275), (375, 275), (475, 275), (575, 275), 17 | (75, 425), (175, 425), (275, 425), (375, 425), (475, 400), (575, 425), 18 | ] 19 | 20 | 21 | type 22 | MainScene = ref object of Scene 23 | pimg: PerspectiveImage 24 | graphics: array[GraphicCount, TextureGraphic] 25 | entities: array[GraphicCount, Entity] 26 | 27 | 28 | proc init*(scene: MainScene) = 29 | Scene(scene).init() 30 | 31 | scene.pimg = newPerspectiveImage("../assets/gfx/grid.png") 32 | 33 | # graphics 34 | for i in 0..scene.graphics.high: 35 | scene.graphics[i] = newTextureGraphic() 36 | 37 | discard scene.graphics[0].assignTexture(scene.pimg.render( 38 | pdHor, 0, 0)) 39 | discard scene.graphics[1].assignTexture(scene.pimg.render( 40 | pdHor, 96, 32)) 41 | discard scene.graphics[2].assignTexture(scene.pimg.render( 42 | pdHor, 32, 96)) 43 | discard scene.graphics[3].assignTexture(scene.pimg.render( 44 | pdHor, 64, 32, 32)) 45 | discard scene.graphics[4].assignTexture(scene.pimg.render( 46 | pdHor, 32, 64, 32)) 47 | discard scene.graphics[5].assignTexture(scene.pimg.render( 48 | pdVer, 96, 32)) 49 | discard scene.graphics[6].assignTexture(scene.pimg.render( 50 | pdVer, 64, 32, 32)) 51 | discard scene.graphics[7].assignTexture(scene.pimg.render( 52 | pdHor, 64, 32, shift = 0.0)) 53 | discard scene.graphics[8].assignTexture(scene.pimg.render( 54 | pdHor, 32, 64, shift = 1.0)) 55 | discard scene.graphics[9].assignTexture(scene.pimg.render( 56 | pdHor, 64, 32, shift = 0.25)) 57 | discard scene.graphics[10].assignTexture(scene.pimg.render( 58 | pdHor, 32, 64, shift = 0.75)) 59 | discard scene.graphics[11].assignTexture(scene.pimg.render( 60 | pdVer, 32, 96)) 61 | discard scene.graphics[12].assignTexture(scene.pimg.render( 62 | pdVer, 32, 64, 32)) 63 | discard scene.graphics[13].assignTexture(scene.pimg.render( 64 | pdVer, 64, 32, shift = 0.0)) 65 | discard scene.graphics[14].assignTexture(scene.pimg.render( 66 | pdVer, 64, 32, shift = 1.0)) 67 | discard scene.graphics[15].assignTexture(scene.pimg.render( 68 | pdVer, 64, 32, shift = 0.25)) 69 | discard scene.graphics[16].assignTexture(scene.pimg.render( 70 | pdVer, 32, 64, shift = 0.75)) 71 | 72 | # entities 73 | for i in 0..scene.entities.high: 74 | scene.entities[i] = newEntity() 75 | scene.entities[i].graphic = scene.graphics[i] 76 | scene.entities[i].centrify() 77 | scene.entities[i].pos = Positions[i] 78 | 79 | # add to scene 80 | for entity in scene.entities: 81 | scene.add(entity) 82 | 83 | 84 | proc free*(scene: MainScene) = 85 | scene.pimg.free() 86 | for graphic in scene.graphics: 87 | graphic.free() 88 | 89 | 90 | proc newMainScene*(): MainScene = 91 | new result, free 92 | result.init() 93 | 94 | 95 | method event*(scene: MainScene, event: Event) = 96 | scene.eventScene(event) 97 | if event.kind == KeyDown: 98 | case event.key.keysym.sym: 99 | of K_Escape: 100 | gameRunning = false 101 | else: discard 102 | 103 | 104 | method render*(scene: MainScene) = 105 | scene.renderScene() 106 | 107 | -------------------------------------------------------------------------------- /demos/demo2/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 2 2 | ================= 3 | 4 | Graphic demo. 5 | 6 | Demonstrates color and alpha modifiers, blending modes, and scaling. 7 | 8 | ![Screenshot](demo2.png) 9 | 10 | -------------------------------------------------------------------------------- /demos/demo2/demo2.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 2 (Graphic)", 8 | scaleQuality = 0): 9 | showInfo = true 10 | game.scene = newMainScene() 11 | game.run() 12 | 13 | -------------------------------------------------------------------------------- /demos/demo2/demo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo2/demo2.png -------------------------------------------------------------------------------- /demos/demo2/earth.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Earth* = ref object of Entity 7 | 8 | 9 | proc init*(entity: Earth) = 10 | entity.initEntity() 11 | entity.pos.x = 128.0 12 | entity.pos.y = 96.0 13 | 14 | 15 | proc newEarth*(): Earth = 16 | result = new Earth 17 | result.init() 18 | 19 | -------------------------------------------------------------------------------- /demos/demo2/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | math, 3 | nimgame2/nimgame, 4 | nimgame2/draw, 5 | nimgame2/entity, 6 | nimgame2/texturegraphic, 7 | nimgame2/input, 8 | nimgame2/scene, 9 | nimgame2/settings, 10 | nimgame2/types, 11 | earth, spaceman 12 | 13 | 14 | type 15 | MainScene = ref object of Scene 16 | earthG, spacemanG: TextureGraphic 17 | e: Earth 18 | s: Spaceman 19 | 20 | 21 | proc init*(scene: MainScene) = 22 | Scene(scene).init() 23 | # Earth 24 | scene.e = newEarth() 25 | scene.earthG = newTextureGraphic() 26 | discard scene.earthG.load("../assets/gfx/earth.png") 27 | scene.e.graphic = scene.earthG 28 | # Spaceman 29 | scene.s = newSpaceman() 30 | scene.spacemanG = newTextureGraphic() 31 | discard scene.spacemanG.load("../assets/gfx/spaceman.png") 32 | scene.s.graphic = scene.spacemanG 33 | 34 | # add to scene 35 | scene.add(scene.s) 36 | scene.add(scene.e) 37 | 38 | 39 | proc free*(scene: MainScene) = 40 | scene.earthG.free 41 | scene.spacemanG.free 42 | 43 | 44 | proc newMainScene*(): MainScene = 45 | new result, free 46 | result.init() 47 | 48 | 49 | proc changeBlendMod(scene: MainScene, increase = true) = 50 | # get blend mod 51 | var b = TextureGraphic(scene.s.graphic).blendMod 52 | # change blend mod 53 | if increase: 54 | if b.int == 0: 55 | b = Blend(1) 56 | elif b < Blend.high: 57 | b = Blend(b.int shl 1) 58 | else: # decrease 59 | if b.int > 0: 60 | b = Blend(b.int shr 1) 61 | # set blend mod 62 | TextureGraphic(scene.s.graphic).blendMod = b 63 | 64 | 65 | const 66 | ScaleMax = 3 67 | ScaleMin = 0.5 68 | ScaleMod = 0.25 69 | 70 | proc changeResolution(scene: MainScene, increase = true) = 71 | # get current scale 72 | var scale = game.scale 73 | # change scale 74 | if increase: 75 | if scale.x < ScaleMax: 76 | scale.x += ScaleMod 77 | scale.y += ScaleMod 78 | else: # decrease 79 | if scale.x > ScaleMin: 80 | scale.x -= ScaleMod 81 | scale.y -= ScaleMod 82 | # set resolution 83 | game.windowSize = Dim(Coord(game.size) * scale) 84 | 85 | 86 | method event*(scene: MainScene, event: Event) = 87 | if event.kind == KeyDown: 88 | case event.key.keysym.sym: 89 | of K_Escape: 90 | gameRunning = false 91 | of K_T: 92 | scene.changeBlendMod() 93 | of K_G: 94 | scene.changeBlendMod(false) 95 | of K_Y: 96 | scene.changeResolution() 97 | of K_H: 98 | scene.changeResolution(false) 99 | else: discard 100 | 101 | 102 | method render*(scene: MainScene) = 103 | scene.renderScene() 104 | let c = TextureGraphic(scene.s.graphic).colorMod 105 | let res = game.windowSize 106 | let scale: Coord = (game.scale.x.round(2), game.scale.y.round(2)) 107 | discard box((4, 60), (220, 124), 0x000000CC'u32) 108 | discard string( 109 | (8, 64), "Q/A - red mod: " & $c.r.int, 0xFF0000FF'u32) 110 | discard string( 111 | (8, 72), "W/S - green mod: " & $c.g.int, 0xFF0000FF'u32) 112 | discard string( 113 | (8, 80), "E/D - blue mod: " & $c.b.int, 0xFF0000FF'u32) 114 | discard string( 115 | (8, 88), "R/F - alpha mod: " & 116 | $TextureGraphic(scene.s.graphic).alphaMod.int, 0xFF0000FF'u32) 117 | discard string( 118 | (8, 96), "T/G - blend mod: " & 119 | $TextureGraphic(scene.s.graphic).blendMod, 0xFF0000FF'u32) 120 | discard string( 121 | (8, 104), "Y/H - resolution: " & $res.w & "x" & $res.h, 0xFF0000FF'u32) 122 | discard string( 123 | (8, 112), "Scale: " & $scale.x & "x" & $scale.y, 0xFF0000FF'u32) 124 | 125 | 126 | type 127 | ColorElement = enum 128 | ceR, ceG, ceB 129 | 130 | 131 | proc changeColorMod(scene: MainScene, elem: ColorElement, val: int) = 132 | var color = TextureGraphic(scene.s.graphic).colorMod 133 | # Get color element 134 | var e = int(case elem: 135 | of ceR: color.r 136 | of ceG: color.g 137 | of ceB: color.b) 138 | # Change color element 139 | inc(e, val) 140 | # Correct value 141 | if e < 0x00: e = 0x00 142 | elif e > 0xFF: e = 0xFF 143 | # Set color mod 144 | case elem: 145 | of ceR: color.r = e.uint8 146 | of ceG: color.g = e.uint8 147 | of ceB: color.b = e.uint8 148 | TextureGraphic(scene.s.graphic).colorMod = color 149 | 150 | 151 | proc changeAlphaMod(scene: MainScene, val: int) = 152 | # Get alpha mod 153 | var a = TextureGraphic(scene.s.graphic).alphaMod.int 154 | # Change alpha mod 155 | inc(a, val) 156 | # Correct value 157 | if a < 0x00: a = 0x00 158 | elif a > 0xFF: a = 0xFF 159 | # Set alpha mod 160 | TextureGraphic(scene.s.graphic).alphaMod = a.uint8 161 | 162 | 163 | method update*(scene: MainScene, elapsed: float) = 164 | let val = int(0xFF * elapsed) 165 | scene.updateScene(elapsed) 166 | if ScancodeQ.down: scene.changeColorMod(ceR, val) 167 | if ScancodeA.down: scene.changeColorMod(ceR, -val) 168 | if ScancodeW.down: scene.changeColorMod(ceG, val) 169 | if ScancodeS.down: scene.changeColorMod(ceG, -val) 170 | if ScancodeE.down: scene.changeColorMod(ceB, val) 171 | if ScancodeD.down: scene.changeColorMod(ceB, -val) 172 | if ScancodeR.down: scene.changeAlphaMod(val) 173 | if ScancodeF.down: scene.changeAlphaMod(-val) 174 | 175 | -------------------------------------------------------------------------------- /demos/demo2/spaceman.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Spaceman* = ref object of Entity 7 | 8 | 9 | proc init*(entity: Spaceman) = 10 | entity.initEntity() 11 | entity.pos.x = 200.0 12 | entity.pos.y = 64.0 13 | 14 | 15 | proc newSpaceman*(): Spaceman = 16 | result = new Spaceman 17 | result.init() 18 | 19 | -------------------------------------------------------------------------------- /demos/demo20/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 20 2 | ================== 3 | 4 | TextureAtlas. Demonstrates texture atlas loading and access. 5 | 6 | ![Screenshot](demo20.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo20/demo20.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 320, h = 240, title = "Nimgame 2: Demo 20 (TextureAtlas)"): 8 | showInfo = true 9 | game.windowSize = (640, 480) 10 | game.scene = newMainScene() 11 | game.run() 12 | 13 | -------------------------------------------------------------------------------- /demos/demo20/demo20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo20/demo20.png -------------------------------------------------------------------------------- /demos/demo20/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity, 4 | nimgame2/gui/button, 5 | nimgame2/texturegraphic, 6 | nimgame2/textureatlas, 7 | nimgame2/input, 8 | nimgame2/scene, 9 | nimgame2/settings, 10 | nimgame2/types 11 | 12 | 13 | type 14 | MainScene = ref object of Scene 15 | atlas: TextureAtlas 16 | 17 | 18 | proc init*(scene: MainScene) = 19 | Scene(scene).init() 20 | 21 | scene.atlas = newTextureAtlas("../assets/gfx/atlas.png", 22 | "../assets/csv/atlas.csv") 23 | 24 | let 25 | eSpaceman = newEntity() 26 | eGradient = newEntity() 27 | eButton = newGuiButton(scene.atlas["button"]) 28 | eSprite = newEntity() 29 | 30 | eSpaceman.graphic = scene.atlas["spaceman"] 31 | eSpaceman.pos = (50.0, 100.0) 32 | 33 | eGradient.graphic = scene.atlas["gradient"] 34 | eGradient.pos = (150.0, 100.0) 35 | 36 | eButton.pos = (200.0, 100.0) 37 | 38 | eSprite.graphic = scene.atlas["sprite"] 39 | eSprite.initSprite((32, 32), (0, 32), (1, 1)) 40 | discard eSprite.addAnimation("play", toSeq(0..3), 1/4) 41 | eSprite.play("play") 42 | eSprite.pos = (200.0, 150.0) 43 | 44 | scene.add(eSpaceman) 45 | scene.add(eGradient) 46 | scene.add(eButton) 47 | scene.add(eSprite) 48 | 49 | 50 | proc free*(scene: MainScene) = 51 | scene.atlas.free() 52 | 53 | 54 | proc newMainScene*(): MainScene = 55 | new result, free 56 | result.init() 57 | 58 | 59 | method event*(scene: MainScene, event: Event) = 60 | scene.eventScene(event) 61 | if event.kind == KeyDown: 62 | case event.key.keysym.sym: 63 | of K_Escape: 64 | gameRunning = false 65 | else: discard 66 | 67 | 68 | method render*(scene: MainScene) = 69 | scene.renderScene() 70 | 71 | -------------------------------------------------------------------------------- /demos/demo21/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 21 2 | ================== 3 | 4 | Joysticks. Demonstrates joystick input handling. 5 | 6 | ![Screenshot](demo21.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo21/demo21.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 21 (Joysticks)"): 8 | showInfo = true 9 | game.scene = newMainScene() 10 | game.run() 11 | 12 | -------------------------------------------------------------------------------- /demos/demo21/demo21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo21/demo21.png -------------------------------------------------------------------------------- /demos/demo21/joypoint.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity, 4 | nimgame2/textgraphic, 5 | nimgame2/texturegraphic, 6 | nimgame2/font, 7 | nimgame2/bitmapfont, 8 | nimgame2/input, 9 | nimgame2/types 10 | 11 | 12 | type 13 | JoyPoint* = ref object of Entity 14 | joy: int 15 | label: TextGraphic 16 | 17 | 18 | proc init(jp: JoyPoint, id: int) = 19 | jp.initEntity() 20 | jp.joy = id 21 | jp.graphic = newTextureGraphic("../assets/gfx/target.png") 22 | jp.centrify() 23 | jp.pos = game.size / 2 24 | # label 25 | let font = newBitmapFont() 26 | discard font.load("../assets/fnt/default8x16.png", (8, 16)) 27 | jp.label = newTextGraphic(font) 28 | jp.label.lines = [$id] 29 | 30 | 31 | proc newJoyPoint*(joystick: int): JoyPoint = 32 | new result 33 | result.init(joystick) 34 | 35 | 36 | method render*(jp: JoyPoint) = 37 | jp.renderEntity() 38 | jp.label.draw( 39 | jp.absPos + jp.center - Coord(jp.label.dim / 2) + (1.0, 1.0), 40 | jp.absRot, 41 | jp.absScale, 42 | jp.center, 43 | jp.flip) 44 | 45 | 46 | const Speed = 100 47 | 48 | method update*(jp: JoyPoint, elapsed: float) = 49 | let move = Speed * elapsed / JoyAxis.high.float 50 | jp.updateEntity(elapsed) 51 | jp.pos.x += jp.joy.joyAxis(0).float * move 52 | jp.pos.x = clamp(jp.pos.x, 0.0, game.size.w.float) 53 | jp.pos.y += jp.joy.joyAxis(1).float * move 54 | jp.pos.y = clamp(jp.pos.y, 0.0, game.size.h.float) 55 | 56 | -------------------------------------------------------------------------------- /demos/demo21/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/draw, 4 | nimgame2/entity, 5 | nimgame2/texturegraphic, 6 | nimgame2/input, 7 | nimgame2/scene, 8 | nimgame2/settings, 9 | nimgame2/types, 10 | joypoint 11 | 12 | 13 | type 14 | MainScene = ref object of Scene 15 | joypoints: seq[JoyPoint] 16 | 17 | 18 | proc init*(scene: MainScene) = 19 | Scene(scene).init() 20 | scene.joypoints = @[] 21 | for i in 0..= game.size.w.float: 29 | entity.vel.x *= -1 30 | if entity.pos.y >= game.size.h.float: 31 | entity.vel.y *= -1 32 | 33 | 34 | proc init*(scene: MainScene) = 35 | Scene(scene).init() 36 | # Movie 37 | scene.movie = newMpegGraphic("video.mpg") 38 | scene.movie.loop = true 39 | scene.e = newEntity() 40 | scene.e.graphic = scene.movie 41 | scene.e.physics = moviePhysics 42 | scene.e.pos.x = rand(game.size.w).float 43 | scene.e.pos.y = rand(game.size.h).float 44 | scene.e.vel.x = rand(10.0..100.0) * randSign().float 45 | scene.e.vel.y = rand(10.0..100.0) * randSign().float 46 | scene.e.centrify() 47 | scene.e.rotVel = rand(10.0..60.0) * randSign().float 48 | 49 | # add to scene 50 | scene.add(scene.e) 51 | 52 | 53 | proc free*(scene: MainScene) = 54 | scene.movie.free() 55 | 56 | 57 | proc newMainScene*(): MainScene = 58 | new result, free 59 | result.init() 60 | 61 | 62 | method event*(scene: MainScene, event: Event) = 63 | if event.kind == KeyDown: 64 | case event.key.keysym.sym: 65 | of K_Escape: 66 | gameRunning = false 67 | else: discard 68 | 69 | 70 | method render*(scene: MainScene) = 71 | scene.renderScene() 72 | discard box((4, 60), (220, 124), 0x000000CC'u32) 73 | discard string( 74 | (8, 64), "Enter - play", 0xFF0000FF'u32) 75 | discard string( 76 | (8, 72), "Space - pause", 0xFF0000FF'u32) 77 | discard string( 78 | (8, 80), "Backspace - stop", 0xFF0000FF'u32) 79 | discard string( 80 | (8, 88), "R - Rewind", 0xFF0000FF'u32) 81 | discard string( 82 | (8, 96), "Up/Down - volume: " & $scene.movie.volume, 0xFF0000FF'u32) 83 | discard string( 84 | (8, 104), "Right - skip 5s", 0xFF0000FF'u32) 85 | discard string( 86 | (8, 112), "Time: " & scene.movie.currentTime.formatFloat(precision = 3) & 87 | "s of " & scene.movie.totalTime.formatFloat(precision = 3) & "s", 0xFF0000FF'u32) 88 | 89 | 90 | method update*(scene: MainScene, elapsed: float) = 91 | scene.updateScene(elapsed) 92 | if ScancodeReturn.pressed: scene.movie.play() 93 | if ScancodeSpace.pressed: scene.movie.pause() 94 | if ScancodeBackspace.pressed: scene.movie.stop() 95 | if ScancodeR.pressed: scene.movie.rewind() 96 | if ScancodeUp.pressed: scene.movie.volume = 97 | (scene.movie.volume + 10).clamp(0, 100) 98 | if ScancodeDown.pressed: scene.movie.volume = 99 | (scene.movie.volume - 10).clamp(0, 100) 100 | if ScancodeRight.pressed: scene.movie.skip(5.0) 101 | 102 | -------------------------------------------------------------------------------- /demos/demo22/video.mpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo22/video.mpg -------------------------------------------------------------------------------- /demos/demo23/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 23 2 | ================== 3 | 4 | Transform demo by [CodeDoes](https://github.com/CodeDoes). 5 | 6 | ![Screenshot](demo23.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo23/demo23.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2 / [ 3 | nimgame, settings 4 | ], 5 | mainscene 6 | 7 | 8 | game = newGame() 9 | if game.init(640, 480, "Nimgame 2: Demo 22 (Transform)"): 10 | game.scene = newMainScene() 11 | settings.updateInterval = 1000 12 | settings.showInfo = true 13 | game.run() 14 | 15 | -------------------------------------------------------------------------------- /demos/demo23/demo23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo23/demo23.png -------------------------------------------------------------------------------- /demos/demo23/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2 / [ 3 | truetypefont, textgraphic, entity, 4 | nimgame, scene, types, 5 | graphic, input, settings], 6 | nimgame2 / gui / widget, 7 | private / [ 8 | circle_graphic, 9 | frame] 10 | 11 | 12 | type 13 | MainScene* = ref object of Scene 14 | font*: TrueTypeFont 15 | 16 | 17 | proc newCircleEntity*(): Entity = 18 | var cgraphic = newCircleGraphic() 19 | cgraphic.radius = 4.0 20 | cgraphic.draw_border = false 21 | 22 | result = newEntity() 23 | result.graphic = cgraphic 24 | result.centrify() 25 | 26 | 27 | proc createRotScaleTestEnts*( 28 | scene: MainScene, text: string, 29 | pos: var Coord, rot: Angle = 0.0, scale: Scale = 1.0) = 30 | var 31 | textEnt = newEntity() 32 | textgraphic = newTextGraphic(scene.font) 33 | 34 | scene.add(textEnt) 35 | textEnt.graphic = textgraphic 36 | 37 | textgraphic.setText text 38 | 39 | textEnt.scale = scale 40 | textEnt.pos = pos + (textEnt.bottomleft * textEnt.absScale) 41 | textEnt.center += textEnt.bottomleft 42 | echo textEnt.pos 43 | # Want rel_pos before rotation 44 | pos.y = (textEnt.transform * textEnt.bottomleft).y 45 | textEnt.rot = rot * 90.0 46 | for p in textEnt.world_corners.items(): 47 | var cent = newCircleEntity() 48 | scene.add(cent) 49 | cent.pos = p 50 | var frameEnt = newGuiWidget() 51 | scene.add(frameEnt) 52 | var fGraphic = newFrameGraphic() 53 | frameEnt.graphic = fGraphic 54 | fGraphic.draw_filled = false 55 | fGraphic.border_color = ColorRed 56 | fGraphic.rect.x = textEnt.topleft.x.cint 57 | fGraphic.rect.y = textEnt.topleft.y.cint 58 | fGraphic.rect.w = textEnt.dim.w.cint 59 | fGraphic.rect.h = textEnt.dim.h.cint 60 | frameEnt.logic = proc (entity: Entity, elapsed: float) = 61 | let color = 62 | if entity.GuiWidget.state.isFocused: ColorOrange 63 | else: ColorGreen 64 | entity.graphic.FrameGraphic.border_color = color 65 | 66 | frameEnt.center = textEnt.center 67 | frameEnt.pos = textEnt.pos 68 | frameEnt.rot = textEnt.rot 69 | frameEnt.scale = textEnt.scale 70 | var corners = newseq[Coord]() 71 | for c in frameEnt.corners: 72 | corners.add(c) 73 | frameEnt.collider = frameEnt.newPolyCollider(frameEnt.pos, corners) 74 | 75 | 76 | proc init*(scene: MainScene) = 77 | scene.Scene.init() 78 | scene.font = newTrueTypeFont() 79 | discard scene.font.load("../assets/fnt/FSEX300.ttf", 32) 80 | 81 | var rel_pos: Coord = (0.0, 100.0) 82 | for scale in [0.8, 0.3, 0.4, 0.6, 0.7, 0.2]: 83 | createRotScaleTestEnts(scene, "Scale Test", rel_pos, scale = scale) 84 | 85 | for f in [0.8, 0.3, 0.4, 0.6, 0.7, 0.2]: 86 | createRotScaleTestEnts(scene, "Rot Scale Test", rel_pos, rot = f, scale = f) 87 | 88 | rel_pos = (400.0, 0.0) 89 | for rot in [0.8, 0.3, 0.4, 0.6, 0.7, 0.2]: 90 | createRotScaleTestEnts(scene, "Rot Test", rel_pos, rot = rot) 91 | 92 | 93 | proc newMainScene*(): MainScene = 94 | new result 95 | result.init() 96 | 97 | -------------------------------------------------------------------------------- /demos/demo23/private/border_fill_graphic.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2 / [ 3 | types, graphic, types 4 | ] 5 | 6 | 7 | type 8 | BorderFillGraphic* = ref object of Graphic 9 | border_color*, fill_color*: Color 10 | # border_thickness*: float #NOTE can't set border thickness at the moment 11 | draw_border*, draw_filled*: bool 12 | 13 | 14 | proc initBorderFillGraphic*(self: BorderFillGraphic) = 15 | self.draw_border = true 16 | self.draw_filled = true 17 | self.fill_color = ColorPurple ## Traditional visual debugging color 18 | self.border_color = ColorPink 19 | # self.border_thickness = 1.0 20 | 21 | 22 | method draw*(graphic: BorderFillGraphic, 23 | pos: Coord = (0.0, 0.0), 24 | angle: Angle = 0.0, 25 | scale: Scale = 1.0, 26 | center: Coord = (0.0, 0.0), 27 | flip: Flip = Flip.none, 28 | region: Rect = Rect(x: 0, y: 0, w: 0, h: 0)) = 29 | raise newException(CatchableError, "Can't use BorderFillGraphic draw method.") 30 | 31 | 32 | method dim*(graphic: BorderFillGraphic): Dim = 33 | raise newException(CatchableError, "Can't use BorderFillGraphic dim method.") 34 | 35 | -------------------------------------------------------------------------------- /demos/demo23/private/circle_graphic.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2 / [ 3 | types, graphic, draw, utils 4 | ], 5 | border_fill_graphic 6 | 7 | 8 | type 9 | CircleGraphic* = ref object of BorderFillGraphic 10 | radius*: float 11 | 12 | 13 | proc drawCircleGraphic*(self: CircleGraphic, 14 | pos: Coord = (0.0, 0.0), 15 | angle: Angle = 0.0, 16 | scale: Scale = 1.0, 17 | center: Coord = (0.0, 0.0), 18 | flip: Flip = Flip.none, 19 | region: Rect = Rect(x: 0, y: 0, w: 0, h: 0)) = 20 | let point: Coord = pos 21 | if self.draw_filled: 22 | discard circle(point, self.radius, self.fill_color, DrawMode.filled) 23 | if self.draw_border: 24 | discard circle(point, self.radius, self.border_color, DrawMode.default) 25 | 26 | 27 | method draw*(graphic: CircleGraphic, 28 | pos: Coord = (0.0, 0.0), 29 | angle: Angle = 0.0, 30 | scale: Scale = 1.0, 31 | center: Coord = (0.0, 0.0), 32 | flip: Flip = Flip.none, 33 | region: Rect = Rect(x: 0, y: 0, w: 0, h: 0)) = 34 | drawCircleGraphic(graphic, pos, angle, scale, center, flip, region) 35 | 36 | 37 | proc newCircleGraphic*(): CircleGraphic = 38 | new result 39 | result.initBorderFillGraphic() 40 | result.radius = 5.0 41 | 42 | 43 | method dim*(self: CircleGraphic): Dim = 44 | return (int self.radius * 2, int self.radius * 2) 45 | -------------------------------------------------------------------------------- /demos/demo23/private/frame.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2 / [ 3 | types, graphic, draw, utils 4 | ], 5 | border_fill_graphic 6 | 7 | type 8 | FrameGraphic* = ref object of BorderFillGraphic 9 | rect*: Rect 10 | 11 | Bounds = tuple[a: Coord, b: Coord] 12 | 13 | AngledBounds* = ref object of RootObj 14 | bounds*: Bounds 15 | angle*: Angle 16 | center*: Coord 17 | 18 | 19 | proc points*(abounds: AngledBounds): auto {.inline.} = 20 | let 21 | a = abounds.bounds.a 22 | b = abounds.bounds.b 23 | center = abounds.center 24 | angle = abounds.angle 25 | 26 | template apply(coord: Coord): Coord = 27 | rotate(coord, center, angle) 28 | 29 | return @[ 30 | apply(a), 31 | apply((b.x, a.y)), 32 | apply(b), 33 | apply((a.x, b.y)) 34 | ] 35 | 36 | 37 | proc points*(graphic: FrameGraphic, pos: Coord, angle: Angle, 38 | scale: Scale, center: Coord): seq[Coord] = 39 | var 40 | abounds = new AngledBounds 41 | 42 | abounds.bounds = (a: -center * scale, 43 | b: (-center + graphic.dim.toCoord) * scale).Bounds 44 | abounds.angle = angle 45 | abounds.center = pos 46 | return abounds.points 47 | 48 | 49 | proc initFrameGraphic(graphic: FrameGraphic) = 50 | graphic.initBorderFillGraphic() 51 | graphic.rect= Rect(x: 0, y: 0, w: 0, h: 0) 52 | 53 | 54 | proc newFrameGraphic*(): FrameGraphic = 55 | new result 56 | result.initFrameGraphic() 57 | 58 | 59 | method dim*(self: FrameGraphic): Dim = 60 | (self.rect.w.int, self.rect.h.int) 61 | 62 | 63 | proc drawFrameGraphic*(self: FrameGraphic, 64 | pos: Coord, 65 | angle: Angle, 66 | scale: Scale, 67 | center: Coord, 68 | flip: Flip, 69 | region: Rect) = 70 | var points = self.points(pos,angle, scale,center) 71 | if self.draw_border: 72 | discard draw.polygon(points, self.border_color, DrawMode.default) 73 | if self.draw_filled: 74 | discard draw.polygon(points, self.fill_color, DrawMode.filled) 75 | 76 | 77 | method draw*( 78 | graphic: FrameGraphic, 79 | pos: Coord = (0.0, 0.0), 80 | angle: Angle = 0.0, 81 | scale: Scale = 1.0, 82 | center: Coord = (0.0, 0.0), 83 | flip: Flip = Flip.none, 84 | region: Rect = Rect(x: 0, y: 0, w: 0, h: 0)) = 85 | drawFrameGraphic(graphic, pos, angle, scale, center, flip, region) 86 | 87 | -------------------------------------------------------------------------------- /demos/demo3/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 3 2 | ================= 3 | 4 | Input demo. Demonstrates keyboard and mouse input. 5 | 6 | ![Screenshot](demo3.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo3/demo3.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 3 (Input & Physics)"): 8 | showInfo = true 9 | game.scene = newMainScene() 10 | game.run() 11 | 12 | -------------------------------------------------------------------------------- /demos/demo3/demo3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo3/demo3.png -------------------------------------------------------------------------------- /demos/demo3/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/draw, 4 | nimgame2/entity, 5 | nimgame2/texturegraphic, 6 | nimgame2/input, 7 | nimgame2/scene, 8 | nimgame2/settings, 9 | nimgame2/types, 10 | spaceman 11 | 12 | 13 | type 14 | MainScene = ref object of Scene 15 | spacemanG: TextureGraphic 16 | s: Spaceman 17 | 18 | 19 | proc spacemanPhysics(entity: Entity, elapsed: float) = 20 | defaultPhysics(entity, elapsed) 21 | if entity.pos.x.int < 0: 22 | entity.pos.x = 0 23 | entity.vel.x = 0 24 | if entity.pos.x.int > game.size.w: 25 | entity.pos.x = game.size.w.float 26 | entity.vel.x = 0 27 | if entity.pos.y.int < 0: 28 | entity.pos.y = 0 29 | entity.vel.y = 0 30 | if entity.pos.y.int > game.size.h: 31 | entity.pos.y = game.size.h.float 32 | entity.vel.y = 0 33 | 34 | 35 | proc init*(scene: MainScene) = 36 | Scene(scene).init() 37 | # Spaceman 38 | scene.s = newSpaceman() 39 | scene.spacemanG = newTextureGraphic() 40 | discard scene.spacemanG.load("../assets/gfx/spaceman.png") 41 | scene.s.graphic = scene.spacemanG 42 | scene.s.physics = spacemanPhysics 43 | scene.s.centrify() 44 | scene.add(scene.s) 45 | # Mouse 46 | #discard mouseRelative(true) 47 | 48 | proc free*(scene: MainScene) = 49 | scene.spacemanG.free() 50 | 51 | 52 | proc newMainScene*(): MainScene = 53 | new result, free 54 | result.init() 55 | 56 | 57 | method event*(scene: MainScene, event: Event) = 58 | if event.kind == KeyDown: 59 | case event.key.keysym.sym: 60 | of K_Escape: 61 | gameRunning = false 62 | else: discard 63 | 64 | 65 | method render*(scene: MainScene) = 66 | # Draw line between the spaceman and the mouse position if LMB is pressed 67 | if MouseButton.left.down: 68 | discard line(scene.s.pos, mouse.abs, 0xFF0000FF'u32) 69 | 70 | scene.renderScene() 71 | 72 | var arrows: string = "" 73 | if ScancodeUp.down: arrows &= "Up " 74 | if ScancodeDown.down: arrows &= "Down " 75 | if ScancodeLeft.down: arrows &= "Left " 76 | if ScancodeRight.down: arrows &= "Right" 77 | 78 | var wsad: string = "" 79 | if ScancodeW.down: wsad &= "W " 80 | if ScancodeS.down: wsad &= "S " 81 | if ScancodeA.down: wsad &= "A " 82 | if ScancodeD.down: wsad &= "D " 83 | 84 | var mouse: string = "Abs(" & $mouse.abs.x.int & ":" & $mouse.abs.y.int & 85 | ") Rel(" & $mouse.rel.x.int & ":" & $mouse.rel.y.int & ")" 86 | 87 | var buttons: string = "" 88 | if MouseButton.left.down: buttons &= "L " 89 | if MouseButton.middle.down: buttons &= "M " 90 | if MouseButton.right.down: buttons &= "R " 91 | if MouseButton.x1.down: buttons &= "X1 " 92 | if MouseButton.x2.down: buttons &= "X2 " 93 | 94 | 95 | discard box((4, 60), (260, 100), 0xCC000000'u32) 96 | discard string( 97 | (8, 64), "Arrows: " & arrows, 0xFF0000FF'u32) 98 | discard string( 99 | (8, 72), "WSAD: " & wsad, 0xFF0000FF'u32) 100 | discard string( 101 | (8, 80), "Mouse: " & mouse, 0xFF0000FF'u32) 102 | discard string( 103 | (8, 88), "Mouse buttons: " & buttons, 0xFF0000FF'u32) 104 | discard string( 105 | (8, 96), "Mouse wheel: " & $mouseWheel, 0xFF0000FF'u32) 106 | 107 | const 108 | Acc = 100.0 109 | 110 | 111 | method update*(scene: MainScene, elapsed: float) = 112 | scene.updateScene(elapsed) 113 | # Arrows and WSAD 114 | if ScancodeUp.down or ScancodeW.down: scene.s.vel.y -= Acc * elapsed 115 | if ScancodeDown.down or ScancodeS.down: scene.s.vel.y += Acc * elapsed 116 | if ScancodeLeft.down or ScancodeA.down: scene.s.vel.x -= Acc * elapsed 117 | if ScancodeRight.down or ScancodeD.down: scene.s.vel.x += Acc * elapsed 118 | # Mouse 119 | if MouseButton.left.down: 120 | var vector: Coord 121 | vector = (mouse.abs - scene.s.pos) * elapsed 122 | scene.s.vel += vector 123 | 124 | -------------------------------------------------------------------------------- /demos/demo3/spaceman.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Spaceman* = ref object of Entity 7 | 8 | 9 | proc init*(entity: Spaceman) = 10 | entity.initEntity() 11 | entity.pos.x = game.size.w.float / 2 12 | entity.pos.y = game.size.h.float / 2 13 | entity.drg.x = 10.0 14 | entity.drg.y = 10.0 15 | 16 | 17 | proc newSpaceman*(): Spaceman = 18 | result = new Spaceman 19 | result.init() 20 | 21 | -------------------------------------------------------------------------------- /demos/demo4/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 4 2 | ================= 3 | 4 | Sprite demo. Demonstrates sprite animation. 5 | 6 | ![Screenshot](demo4.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo4/demo4.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 4 (Sprite & Animation)"): 8 | showInfo = true 9 | game.scene = newMainScene() 10 | game.run() 11 | 12 | -------------------------------------------------------------------------------- /demos/demo4/demo4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo4/demo4.png -------------------------------------------------------------------------------- /demos/demo4/dwarf.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Dwarf* = ref object of Entity 7 | 8 | 9 | proc init*(entity: Dwarf) = 10 | entity.initEntity() 11 | entity.centrify() 12 | entity.physics = defaultPhysics 13 | 14 | 15 | proc newDwarf*(): Dwarf = 16 | result = new Dwarf 17 | result.init() 18 | 19 | -------------------------------------------------------------------------------- /demos/demo4/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | math, 3 | nimgame2/nimgame, 4 | nimgame2/draw, 5 | nimgame2/entity, 6 | nimgame2/texturegraphic, 7 | nimgame2/input, 8 | nimgame2/scene, 9 | nimgame2/settings, 10 | nimgame2/types, 11 | dwarf 12 | 13 | 14 | type 15 | MainScene = ref object of Scene 16 | dG: TextureGraphic 17 | d: Dwarf 18 | 19 | 20 | const Framerate = 1/12 21 | 22 | 23 | proc init*(scene: MainScene) = 24 | Scene(scene).init() 25 | # Dwarf 26 | scene.dG = newTextureGraphic() 27 | discard scene.dG.load("../assets/gfx/dwarf.png") 28 | scene.d = newDwarf() 29 | scene.d.pos = (200, 100) 30 | scene.d.graphic = scene.dG 31 | scene.d.initSprite((24, 48)) 32 | discard scene.d.addAnimation( 33 | "down", [0, 1, 2, 3, 4, 5], Framerate) 34 | discard scene.d.addAnimation( 35 | "up", [6, 7, 8, 9, 10, 11], Framerate) 36 | discard scene.d.addAnimation( 37 | "left", [12, 13, 14, 15, 16, 17], Framerate) 38 | discard scene.d.addAnimation( 39 | "right", [12, 13, 14, 15, 16, 17], Framerate, Flip.horizontal) 40 | scene.add(scene.d) 41 | 42 | 43 | proc free*(scene: MainScene) = 44 | scene.dG.free 45 | 46 | 47 | proc newMainScene*(): MainScene = 48 | new result, free 49 | result.init() 50 | 51 | 52 | method event*(scene: MainScene, event: Event) = 53 | if event.kind == KeyDown: 54 | case event.key.keysym.sym: 55 | of K_Escape: 56 | gameRunning = false 57 | else: discard 58 | 59 | 60 | method render*(scene: MainScene) = 61 | scene.renderScene() 62 | 63 | 64 | const Speed = 50 65 | 66 | 67 | method update*(scene: MainScene, elapsed: float) = 68 | scene.updateScene(elapsed) 69 | 70 | # Controls and speed 71 | type Direction = enum none, down, up, left, right 72 | var direction = 73 | if ScancodeDown.down or ScancodeS.down: down 74 | elif ScancodeUp.down or ScancodeW.down: up 75 | elif ScancodeLeft.down or ScancodeA.down: left 76 | elif ScancodeRight.down or ScancodeD.down: right 77 | else: none 78 | 79 | case direction: 80 | of none: 81 | if not scene.d.sprite.playing: 82 | scene.d.vel = (0, 0) 83 | of down: 84 | if not scene.d.sprite.playing or 85 | (scene.d.currentAnimationName != "down"): 86 | scene.d.play("down", 1) 87 | scene.d.vel = (0, Speed) 88 | of up: 89 | if not scene.d.sprite.playing or 90 | (scene.d.currentAnimationName != "up"): 91 | scene.d.play("up", 1) 92 | scene.d.vel = (0, -Speed) 93 | of left: 94 | if not scene.d.sprite.playing or 95 | (scene.d.currentAnimationName != "left"): 96 | scene.d.play("left", 1) 97 | scene.d.vel = (-Speed, 0) 98 | of right: 99 | if not scene.d.sprite.playing or 100 | (scene.d.currentAnimationName != "right"): 101 | scene.d.play("right", 1) 102 | scene.d.vel = (Speed, 0) 103 | 104 | -------------------------------------------------------------------------------- /demos/demo5/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 5 2 | ================= 3 | 4 | Colliders demo. Demonstrates different colliders. 5 | 6 | ![Screenshot](demo5.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo5/cursor.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity, 4 | nimgame2/input 5 | 6 | type 7 | Cursor* = ref object of Entity 8 | collidedWith*: seq[string] 9 | 10 | 11 | proc init*(entity: Cursor) = 12 | entity.initEntity() 13 | entity.tags.add("Cursor") 14 | entity.pos = mouse.abs 15 | entity.collidedWith = @[] 16 | 17 | 18 | proc newCursor*(): Cursor = 19 | result = new Cursor 20 | result.init() 21 | 22 | 23 | method update*(entity: Cursor, elapsed: float) = 24 | entity.updateEntity(elapsed) 25 | entity.collidedWith = @[] 26 | entity.pos = mouse.abs 27 | 28 | 29 | method onCollide*(entity: Cursor, target: Entity) = 30 | if target.tags.len > 0: 31 | entity.collidedWith.add(target.tags[0]) 32 | 33 | -------------------------------------------------------------------------------- /demos/demo5/demo5.nim: -------------------------------------------------------------------------------- 1 | import 2 | sdl2_nim/sdl, 3 | nimgame2/nimgame, 4 | nimgame2/settings, 5 | mainscene 6 | 7 | game = newGame() 8 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 5 (Collisions)", 9 | scaleQuality = 0): 10 | showInfo = true 11 | colliderOutline = true 12 | discard sdl.showCursor(0) 13 | game.scene = newMainScene() 14 | game.run() 15 | 16 | -------------------------------------------------------------------------------- /demos/demo5/demo5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo5/demo5.png -------------------------------------------------------------------------------- /demos/demo5/earth.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Earth* = ref object of Entity 7 | collidedWith*: seq[string] 8 | 9 | 10 | proc init*(entity: Earth) = 11 | entity.initEntity() 12 | entity.tags.add("Earth") 13 | entity.pos = (0.0, 150.0) 14 | entity.collidedWith = @[] 15 | 16 | 17 | proc newEarth*(): Earth = 18 | result = new Earth 19 | result.init() 20 | 21 | 22 | method update*(entity: Earth, elapsed: float) = 23 | entity.updateEntity(elapsed) 24 | entity.collidedWith = @[] 25 | 26 | 27 | method onCollide*(entity: Earth, target: Entity) = 28 | if target.tags.len > 0: 29 | entity.collidedWith.add(target.tags[0]) 30 | 31 | -------------------------------------------------------------------------------- /demos/demo5/line.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Line* = ref object of Entity 7 | collidedWith*: seq[string] 8 | 9 | 10 | proc init*(entity: Line) = 11 | entity.initEntity() 12 | entity.tags.add("Line") 13 | entity.collidedWith = @[] 14 | 15 | 16 | proc newLine*(): Line = 17 | result = new Line 18 | result.init() 19 | 20 | 21 | method update*(entity: Line, elapsed: float) = 22 | entity.updateEntity(elapsed) 23 | entity.collidedWith = @[] 24 | 25 | 26 | method onCollide*(entity: Line, target: Entity) = 27 | if target.tags.len > 0: 28 | entity.collidedWith.add(target.tags[0]) 29 | 30 | -------------------------------------------------------------------------------- /demos/demo5/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | math, 3 | nimgame2/nimgame, 4 | nimgame2/draw, 5 | nimgame2/entity, 6 | nimgame2/texturegraphic, 7 | nimgame2/input, 8 | nimgame2/scene, 9 | nimgame2/settings, 10 | nimgame2/types, 11 | cursor, earth, line, poly1, poly2, poly3, poly9, spaceman 12 | 13 | 14 | type 15 | MainScene = ref object of Scene 16 | cursorG, earthG, spacemanG: TextureGraphic 17 | c: Cursor 18 | e: Earth 19 | d1, d2: Line 20 | s: Spaceman 21 | p1: Poly1 22 | p2: Poly2 23 | p3: Poly3 24 | p9: Poly9 25 | 26 | 27 | proc init*(scene: MainScene) = 28 | Scene(scene).init() 29 | 30 | # Cursor 31 | scene.c = newCursor() 32 | scene.cursorG = newTextureGraphic() 33 | discard scene.cursorG.load("../assets/gfx/cursor.png") 34 | scene.c.graphic = scene.cursorG 35 | scene.c.collider = newCollider(scene.c) 36 | 37 | # Line 1 38 | scene.d1 = newLine() 39 | scene.d1.pos = (50.0, 420.0) 40 | scene.d1.center = (25.0, 0.0) 41 | scene.d1.collider = scene.d1.newLineCollider((-25, 0), (25, 0)) 42 | 43 | # Line 2 44 | scene.d2 = newLine() 45 | scene.d2.pos = (50.0, 450.0) 46 | scene.d2.collider = scene.d2.newLineCollider((0, 0), (100, 0)) 47 | 48 | # Earth 49 | scene.e = newEarth() 50 | scene.earthG = newTextureGraphic() 51 | discard scene.earthG.load("../assets/gfx/earth.png") 52 | scene.e.graphic = scene.earthG 53 | let radius = scene.earthG.dim.w.float / 2 54 | scene.e.collider = newCircleCollider(scene.e, (radius, radius), radius) 55 | 56 | # Spaceman 57 | scene.s = newSpaceman() 58 | scene.spacemanG = newTextureGraphic() 59 | discard scene.spacemanG.load("../assets/gfx/spaceman.png") 60 | scene.s.graphic = scene.spacemanG 61 | scene.s.centrify() 62 | scene.s.collider = newBoxCollider(scene.s, (0, 0), scene.spacemanG.dim) 63 | 64 | # Poly1 65 | scene.p1 = newPoly1() 66 | scene.p1.pos = (350, 160) 67 | 68 | # Poly2 69 | scene.p2 = newPoly2() 70 | scene.p2.pos = (350, 210) 71 | 72 | # Poly3 73 | scene.p3 = newPoly3() 74 | scene.p3.pos = (350, 260) 75 | 76 | # Poly9 77 | scene.p9 = newPoly9() 78 | scene.p9.pos = (350, 360) 79 | 80 | # add to scene 81 | scene.add(scene.d1) 82 | scene.add(scene.d2) 83 | scene.add(scene.s) 84 | scene.add(scene.e) 85 | scene.add(scene.c) 86 | scene.add(scene.p1) 87 | scene.add(scene.p2) 88 | scene.add(scene.p3) 89 | scene.add(scene.p9) 90 | 91 | 92 | proc free*(scene: MainScene) = 93 | scene.earthG.free 94 | scene.spacemanG.free 95 | 96 | 97 | proc newMainScene*(): MainScene = 98 | new result, free 99 | result.init() 100 | 101 | 102 | method event*(scene: MainScene, event: Event) = 103 | if event.kind == KeyDown: 104 | case event.key.keysym.sym: 105 | of K_Escape: 106 | gameRunning = false 107 | of K_Space: 108 | colliderOutline = not colliderOutline 109 | else: discard 110 | 111 | 112 | proc generateCollisionString(name: string, list: seq[string]): string = 113 | if list.len > 0: 114 | result = name & " collides with: " 115 | for tag in list: 116 | result.add(tag & ", ") 117 | result = result[0 .. ^3] 118 | else: 119 | result = name & " isn't colliding with anything" 120 | 121 | 122 | method render*(scene: MainScene) = 123 | scene.renderScene() 124 | discard box((4, 60), (380, 140), 0x000000CC'u32) 125 | 126 | discard string( 127 | (8, 64), generateCollisionString("Cursor", scene.c.collidedWith), 128 | 0xFFFFFFFF'u32) 129 | 130 | discard string( 131 | (8, 72), generateCollisionString("Line", scene.d1.collidedWith), 132 | 0xFFFFFFFF'u32) 133 | 134 | discard string( 135 | (8, 80), generateCollisionString("Earth", scene.e.collidedWith), 136 | 0xFFFFFFFF'u32) 137 | 138 | discard string( 139 | (8, 88), generateCollisionString("Spaceman", scene.s.collidedWith), 140 | 0xFFFFFFFF'u32) 141 | 142 | discard string( 143 | (8, 96), generateCollisionString("Poly9", scene.p9.collidedWith), 144 | 0xFFFFFFFF'u32) 145 | 146 | discard string( 147 | (8, 120), "Space toggles outlines, Arrows control spaceman", 148 | 0xFFFFFFFF'u32) 149 | 150 | discard string( 151 | (8, 128), "WASDQE control line, IJKLUO control polygon", 152 | 0xFFFFFFFF'u32) 153 | 154 | 155 | method update*(scene: MainScene, elapsed: float) = 156 | scene.updateScene(elapsed) 157 | # Spaceman 158 | if ScancodeRight.down: scene.s.pos.x += 1 159 | if ScancodeLeft.down: scene.s.pos.x -= 1 160 | if ScancodeDown.down: scene.s.pos.y += 1 161 | if ScancodeUp.down: scene.s.pos.y -= 1 162 | # Line 163 | if ScancodeD.down: scene.d1.pos.x += 1 164 | if ScancodeA.down: scene.d1.pos.x -= 1 165 | if ScancodeS.down: scene.d1.pos.y += 1 166 | if ScancodeW.down: scene.d1.pos.y -= 1 167 | if ScancodeQ.down: scene.d1.rot -= 1 168 | if ScancodeE.down: scene.d1.rot += 1 169 | # Poly9 170 | if ScancodeL.down: scene.p9.pos.x += 1 171 | if ScancodeJ.down: scene.p9.pos.x -= 1 172 | if ScancodeK.down: scene.p9.pos.y += 1 173 | if ScancodeI.down: scene.p9.pos.y -= 1 174 | if ScancodeU.down: scene.p9.rot -= 1 175 | if ScancodeO.down: scene.p9.rot += 1 176 | 177 | -------------------------------------------------------------------------------- /demos/demo5/poly1.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Poly1* = ref object of Entity 7 | collidedWith*: seq[string] 8 | 9 | 10 | proc init*(entity: Poly1) = 11 | entity.initEntity() 12 | entity.tags.add("Poly1") 13 | entity.collider = entity.newPolyCollider((0.0, 0.0), 14 | [ (0.0, 0.0)]) 15 | entity.collidedWith = @[] 16 | 17 | 18 | proc newPoly1*(): Poly1 = 19 | result = new Poly1 20 | result.init() 21 | 22 | 23 | method update*(entity: Poly1, elapsed: float) = 24 | entity.updateEntity(elapsed) 25 | entity.collidedWith = @[] 26 | 27 | 28 | method onCollide*(entity: Poly1, target: Entity) = 29 | if target.tags.len > 0: 30 | entity.collidedWith.add(target.tags[0]) 31 | 32 | -------------------------------------------------------------------------------- /demos/demo5/poly2.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Poly2* = ref object of Entity 7 | collidedWith*: seq[string] 8 | 9 | 10 | proc init*(entity: Poly2) = 11 | entity.initEntity() 12 | entity.tags.add("Poly2") 13 | entity.collider = entity.newPolyCollider((0.0, 0.0), 14 | [ (0.0, 0.0), 15 | (50.0, 0.0)]) 16 | entity.collidedWith = @[] 17 | 18 | 19 | proc newPoly2*(): Poly2 = 20 | result = new Poly2 21 | result.init() 22 | 23 | 24 | method update*(entity: Poly2, elapsed: float) = 25 | entity.updateEntity(elapsed) 26 | entity.collidedWith = @[] 27 | 28 | 29 | method onCollide*(entity: Poly2, target: Entity) = 30 | if target.tags.len > 0: 31 | entity.collidedWith.add(target.tags[0]) 32 | 33 | -------------------------------------------------------------------------------- /demos/demo5/poly3.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Poly3* = ref object of Entity 7 | collidedWith*: seq[string] 8 | 9 | 10 | proc init*(entity: Poly3) = 11 | entity.initEntity() 12 | entity.tags.add("Poly3") 13 | entity.collider = entity.newPolyCollider((0.0, 0.0), 14 | [ (0.0, 0.0), 15 | (50.0, 0.0), 16 | (25.0, 35.0)]) 17 | entity.collidedWith = @[] 18 | 19 | 20 | proc newPoly3*(): Poly3 = 21 | result = new Poly3 22 | result.init() 23 | 24 | 25 | method update*(entity: Poly3, elapsed: float) = 26 | entity.updateEntity(elapsed) 27 | entity.collidedWith = @[] 28 | 29 | 30 | method onCollide*(entity: Poly3, target: Entity) = 31 | if target.tags.len > 0: 32 | entity.collidedWith.add(target.tags[0]) 33 | 34 | -------------------------------------------------------------------------------- /demos/demo5/poly9.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Poly9* = ref object of Entity 7 | collidedWith*: seq[string] 8 | 9 | 10 | proc init*(entity: Poly9) = 11 | entity.initEntity() 12 | entity.tags.add("Poly9") 13 | entity.centrify 14 | entity.collider = entity.newPolyCollider((0.0, 0.0), 15 | [ (-40.0, -50.0), 16 | (-20.0, -50.0), 17 | (-30.0, 20.0), 18 | ( 30.0, 20.0), 19 | ( 20.0, -50.0), 20 | ( 40.0, -50.0), 21 | ( 40.0, 30.0), 22 | ( 0.0, 50.0), 23 | (-40.0, 30.0)]) 24 | entity.collidedWith = @[] 25 | 26 | 27 | proc newPoly9*(): Poly9 = 28 | result = new Poly9 29 | result.init() 30 | 31 | 32 | method update*(entity: Poly9, elapsed: float) = 33 | entity.updateEntity(elapsed) 34 | entity.collidedWith = @[] 35 | 36 | 37 | method onCollide*(entity: Poly9, target: Entity) = 38 | if target.tags.len > 0: 39 | entity.collidedWith.add(target.tags[0]) 40 | 41 | -------------------------------------------------------------------------------- /demos/demo5/spaceman.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Spaceman* = ref object of Entity 7 | collidedWith*: seq[string] 8 | 9 | 10 | proc init*(entity: Spaceman) = 11 | entity.initEntity() 12 | entity.tags.add("Spaceman") 13 | entity.pos = (450.0, 100.0) 14 | entity.collidedWith = @[] 15 | 16 | 17 | proc newSpaceman*(): Spaceman = 18 | result = new Spaceman 19 | result.init() 20 | 21 | 22 | method update*(entity: Spaceman, elapsed: float) = 23 | entity.updateEntity(elapsed) 24 | entity.collidedWith = @[] 25 | 26 | 27 | method onCollide*(entity: Spaceman, target: Entity) = 28 | if target.tags.len > 0: 29 | entity.collidedWith.add(target.tags[0]) 30 | 31 | -------------------------------------------------------------------------------- /demos/demo6/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 6 2 | ================= 3 | 4 | Grouping demo. Demonstrates effects of setting up entity parent. 5 | 6 | ![Screenshot](demo6.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo6/demo6.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 6 (Grouping)", 8 | scaleQuality = 0): 9 | showInfo = true 10 | game.scene = newMainScene() 11 | game.run() 12 | 13 | -------------------------------------------------------------------------------- /demos/demo6/demo6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo6/demo6.png -------------------------------------------------------------------------------- /demos/demo6/earth.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Earth* = ref object of Entity 7 | 8 | 9 | proc init*(entity: Earth) = 10 | entity.initEntity() 11 | entity.tags.add("Earth") 12 | entity.pos = (320.0, 240.0) 13 | 14 | 15 | proc newEarth*(): Earth = 16 | result = new Earth 17 | result.init() 18 | 19 | -------------------------------------------------------------------------------- /demos/demo6/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | math, 3 | nimgame2/nimgame, 4 | nimgame2/draw, 5 | nimgame2/entity, 6 | nimgame2/texturegraphic, 7 | nimgame2/input, 8 | nimgame2/scene, 9 | nimgame2/settings, 10 | nimgame2/types, 11 | earth, spaceman 12 | 13 | 14 | type 15 | MainScene = ref object of Scene 16 | cursorG, earthG, spacemanG: TextureGraphic 17 | e: Earth 18 | s: Spaceman 19 | 20 | 21 | proc init*(scene: MainScene) = 22 | Scene(scene).init() 23 | 24 | # Earth 25 | scene.e = newEarth() 26 | scene.earthG = newTextureGraphic() 27 | discard scene.earthG.load("../assets/gfx/earth.png") 28 | scene.e.graphic = scene.earthG 29 | scene.e.centrify() 30 | scene.e.collider = scene.e.newCircleCollider((0, 0), 128) 31 | 32 | # Spaceman 33 | scene.s = newSpaceman() 34 | scene.spacemanG = newTextureGraphic() 35 | discard scene.spacemanG.load("../assets/gfx/spaceman.png") 36 | scene.s.graphic = scene.spacemanG 37 | scene.s.centrify() 38 | scene.s.parent = scene.e 39 | scene.s.collider = scene.s.newBoxCollider((0, 0), (100, 160)) 40 | 41 | # add to scene 42 | scene.add(scene.s) 43 | scene.add(scene.e) 44 | 45 | 46 | proc free*(scene: MainScene) = 47 | scene.earthG.free 48 | scene.spacemanG.free 49 | 50 | 51 | proc newMainScene*(): MainScene = 52 | new result, free 53 | result.init() 54 | 55 | 56 | method event*(scene: MainScene, event: Event) = 57 | if event.kind == KeyDown: 58 | case event.key.keysym.sym: 59 | of K_Escape: 60 | gameRunning = false 61 | of K_Space: 62 | colliderOutline = not colliderOutline 63 | else: discard 64 | 65 | 66 | method render*(scene: MainScene) = 67 | scene.renderScene() 68 | discard box((4, 60), (260, 100), 0x000000CC'u32) 69 | 70 | discard string((8, 64), "WASD - move group", 0xFFFFFFFF'u32) 71 | discard string((8, 72), "QE - rotate group", 0xFFFFFFFF'u32) 72 | discard string((8, 80), "RF - scale group", 0xFFFFFFFF'u32) 73 | discard string((8, 88), "Space - toggle outlines", 0xFFFFFFFF'u32) 74 | 75 | 76 | method update*(scene: MainScene, elapsed: float) = 77 | scene.updateScene(elapsed) 78 | if ScancodeD.down: scene.e.pos.x += 1 79 | if ScancodeA.down: scene.e.pos.x -= 1 80 | if ScancodeS.down: scene.e.pos.y += 1 81 | if ScancodeW.down: scene.e.pos.y -= 1 82 | if ScancodeQ.down: scene.e.rot -= 1 83 | if ScancodeE.down: scene.e.rot += 1 84 | if ScancodeR.down: scene.e.scale -= 0.01 85 | if ScancodeF.down: scene.e.scale += 0.01 86 | 87 | -------------------------------------------------------------------------------- /demos/demo6/spaceman.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Spaceman* = ref object of Entity 7 | 8 | 9 | proc init*(entity: Spaceman) = 10 | entity.initEntity() 11 | entity.tags.add("Spaceman") 12 | entity.pos = (200.0, 0.0) 13 | 14 | 15 | proc newSpaceman*(): Spaceman = 16 | result = new Spaceman 17 | result.init() 18 | 19 | 20 | method update*(entity: Spaceman, elapsed: float) = 21 | entity.updateEntity(elapsed) 22 | 23 | -------------------------------------------------------------------------------- /demos/demo7/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 7 2 | ================= 3 | 4 | Text demo. Demonstrates bitmap and TrueType fonts. 5 | 6 | ![Screenshot](demo7.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo7/demo7.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 6 (Text)", 8 | scaleQuality = 0): 9 | showInfo = true 10 | game.scene = newMainScene() 11 | game.run() 12 | 13 | -------------------------------------------------------------------------------- /demos/demo7/demo7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo7/demo7.png -------------------------------------------------------------------------------- /demos/demo7/earth.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/entity 4 | 5 | type 6 | Earth* = ref object of Entity 7 | 8 | 9 | proc init*(entity: Earth) = 10 | entity.initEntity() 11 | entity.tags.add("Earth") 12 | entity.pos = (0.0, 50.0) 13 | 14 | 15 | proc newEarth*(): Earth = 16 | result = new Earth 17 | result.init() 18 | 19 | -------------------------------------------------------------------------------- /demos/demo7/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | math, 3 | nimgame2/nimgame, 4 | nimgame2/font, 5 | nimgame2/bitmapfont, 6 | nimgame2/truetypefont, 7 | nimgame2/draw, 8 | nimgame2/entity, 9 | nimgame2/graphic, 10 | nimgame2/textgraphic, 11 | nimgame2/texturegraphic, 12 | nimgame2/typewriter, 13 | nimgame2/input, 14 | nimgame2/scene, 15 | nimgame2/settings, 16 | nimgame2/types, 17 | earth 18 | 19 | 20 | type 21 | MainScene = ref object of Scene 22 | earthG: TextureGraphic 23 | e: Earth 24 | bmFont: BitmapFont 25 | bmText: TextGraphic 26 | bmEntity: Entity 27 | ttFont: TrueTypeFont 28 | ttText: TextGraphic 29 | ttEntity: Entity 30 | twText: TextGraphic 31 | twEntity: Typewriter 32 | 33 | 34 | proc init*(scene: MainScene) = 35 | Scene(scene).init() 36 | 37 | # Earth 38 | scene.e = newEarth() 39 | scene.earthG = newTextureGraphic() 40 | discard scene.earthG.load("../assets/gfx/earth.png") 41 | scene.e.graphic = scene.earthG 42 | 43 | # BitmapFont 44 | scene.bmFont = newBitmapFont() 45 | discard scene.bmFont.load("../assets/fnt/default8x16.png", (8, 16)) 46 | 47 | # TrueTypeFont 48 | scene.ttFont = newTrueTypeFont() 49 | discard scene.ttFont.load("../assets/fnt/FSEX300.ttf", 16) 50 | 51 | # Text 52 | scene.bmText = newTextGraphic() 53 | scene.bmText.font = scene.bmFont 54 | scene.bmText.lines = 55 | [ "The quick brown fox", 56 | "jumps over the lazy dog"] 57 | 58 | scene.ttText = newTextGraphic() 59 | scene.ttText.font = scene.ttFont 60 | scene.ttText.lines = 61 | [ "В чащах юга жил бы цитрус?", 62 | "Да, но фальшивый экземпляр!"] 63 | 64 | scene.twText = newTextGraphic() 65 | scene.twText.font = scene.ttFont 66 | 67 | # Entity 68 | scene.bmEntity = newEntity() 69 | scene.bmEntity.pos = (8, 128) 70 | scene.bmEntity.graphic = scene.bmText 71 | 72 | scene.ttEntity = newEntity() 73 | scene.ttEntity.pos = (8, 192) 74 | scene.ttEntity.graphic = scene.ttText 75 | 76 | scene.twEntity = newTypewriter(scene.twText, 0.1) 77 | #scene.twEntity.width = 10 # uncomment to enable text wrapping 78 | scene.twEntity.pos = (300, 8) 79 | scene.twEntity.add "Fancy typewriter effect!" 80 | 81 | # add to scene 82 | scene.add(scene.bmEntity) 83 | scene.add(scene.ttEntity) 84 | scene.add(scene.twEntity) 85 | scene.add(scene.e) 86 | 87 | 88 | proc free*(scene: MainScene) = 89 | scene.bmFont.free() 90 | scene.ttFont.free() 91 | scene.bmText.free() 92 | scene.ttText.free() 93 | 94 | 95 | proc newMainScene*(): MainScene = 96 | new result, free 97 | result.init() 98 | 99 | 100 | proc changeAlign(scene: MainScene, increase = true) = 101 | # get 102 | var a = scene.bmText.align 103 | # change 104 | if increase: 105 | if a.int == 0: 106 | a = TextAlign(1) 107 | elif a < TextAlign.high: 108 | a = TextAlign(a.int shl 1) 109 | else: # decrease 110 | if a.int > 0: 111 | a = TextAlign(a.int shr 1) 112 | # set 113 | scene.bmText.align = a 114 | scene.ttText.align = a 115 | 116 | let 117 | colors = [0xFFFFFFFF'u32, 0xFF0000FF'u32, 0x00FF00FF'u32, 0x0000FFFF'u32] 118 | colorNames = ["white", "red", "green", "blue"] 119 | var clr = 0 120 | 121 | proc changeColor(scene: MainScene, increase = true) = 122 | # get alpha 123 | let a = scene.bmText.color.a 124 | # change 125 | if increase: 126 | if clr < colors.high: 127 | inc clr 128 | else: # decrease 129 | if clr > 0: 130 | dec clr 131 | # set 132 | var color: Color = colors[clr] 133 | color.a = a 134 | scene.bmText.color = color 135 | scene.ttText.color = color 136 | 137 | 138 | proc changeAlpha(scene: MainScene, increase = true) = 139 | # get 140 | var 141 | c = scene.bmText.color 142 | a = c.a.int 143 | # change 144 | if increase: 145 | a += 15 146 | else: # decrease 147 | a -= 15 148 | # check limits 149 | if a < 0: 150 | a = 0 151 | if a > 255: 152 | a = 255 153 | # set 154 | c.a = a.uint8 155 | scene.bmText.color = c 156 | scene.ttText.color = c 157 | 158 | 159 | method event*(scene: MainScene, event: Event) = 160 | if event.kind == KeyDown: 161 | case event.key.keysym.sym: 162 | of K_Escape: 163 | gameRunning = false 164 | of K_Q: 165 | scene.changeAlign() 166 | of K_A: 167 | scene.changeAlign(false) 168 | of K_W: 169 | scene.changeColor() 170 | of K_S: 171 | scene.changeColor(false) 172 | of K_E: 173 | scene.changeAlpha() 174 | of K_D: 175 | scene.changeAlpha(false) 176 | else: discard 177 | 178 | 179 | method render*(scene: MainScene) = 180 | scene.renderScene() 181 | 182 | discard box((4, 60), (260, 100), 0x000000CC'u32) 183 | 184 | discard string((8, 64), "BitmapFont and TrueTypeFont:", 0xFFFFFFFF'u32) 185 | discard string((8, 72), 186 | "QA - change alignment: " & $scene.bmText.align, 0xFFFFFFFF'u32) 187 | discard string((8, 80), 188 | "WS - change color: " & colorNames[clr], 0xFFFFFFFF'u32) 189 | discard string((8, 88), 190 | "ED - change alpha: " & $scene.bmText.color.a.int, 0xFFFFFFFF'u32) 191 | 192 | 193 | method update*(scene: MainScene, elapsed: float) = 194 | scene.updateScene(elapsed) 195 | 196 | if ScancodeReturn.down: scene.twEntity.force() 197 | 198 | -------------------------------------------------------------------------------- /demos/demo8/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 8 2 | ================= 3 | 4 | ProcGraphic demo. Demonstrates procedural graphics. 5 | 6 | ![Screenshot](demo8.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo8/demo8.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | mainscene 5 | 6 | game = newGame() 7 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 8 (ProcGraphic)", 8 | scaleQuality = 0): 9 | showInfo = true 10 | game.scene = newMainScene() 11 | game.run() 12 | 13 | -------------------------------------------------------------------------------- /demos/demo8/demo8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo8/demo8.png -------------------------------------------------------------------------------- /demos/demo8/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | math, 3 | nimgame2/nimgame, 4 | nimgame2/draw, 5 | nimgame2/entity, 6 | nimgame2/graphic, 7 | nimgame2/input, 8 | nimgame2/procgraphic, 9 | nimgame2/scene, 10 | nimgame2/settings, 11 | nimgame2/types, 12 | nimgame2/utils 13 | 14 | 15 | type 16 | MainScene = ref object of Scene 17 | polyG: ProcGraphic 18 | poly: Entity 19 | 20 | 21 | const polyLines0 = [ 22 | ( 0.0, -70.0), 23 | ( 40.0, -30.0), 24 | ( 80.0, -50.0), 25 | ( 60.0, 30.0), 26 | (-60.0, 30.0), 27 | (-80.0, -50.0), 28 | (-40.0, -30.0)] 29 | 30 | const polyLines1 = [ 31 | ((-30.0, 10.0), (-30.0, -10.0)), 32 | ((-30.0, -10.0), (-10.0, 10.0)), 33 | ((-10.0, 10.0), (-10.0, -10.0)), 34 | (( 0.0, -10.0), ( 0.0, 10.0)), 35 | (( 10.0, 10.0), ( 10.0, -10.0)), 36 | (( 10.0, -10.0), ( 20.0, 0.0)), 37 | (( 20.0, 0.0), ( 30.0, -10.0)), 38 | (( 30.0, -10.0), ( 30.0, 10.0))] 39 | 40 | 41 | proc polyProc(graphic: ProcGraphic, 42 | pos: Coord, 43 | angle: Angle, 44 | scale: Scale, 45 | center: Coord, 46 | flip: Flip, 47 | region: Rect) = 48 | let 49 | color0: Color = 0xFFFF00FF'u32 50 | color1: Color = 0x000000FF'u32 51 | 52 | var poly: seq[Coord] = @[] 53 | for p in polyLines0: 54 | poly.add(rotate(p, (0.0, 0.0), angle) * scale + pos) 55 | discard polygon(poly, color0, DrawMode.filled) 56 | 57 | for i in polyLines1: 58 | let 59 | p0 = rotate(i[0], (0.0, 0.0), angle) * scale + pos 60 | p1 = rotate(i[1], (0.0, 0.0), angle) * scale + pos 61 | discard aaLine(p0, p1, color1) 62 | 63 | 64 | proc init*(scene: MainScene) = 65 | Scene(scene).init() 66 | 67 | # Poly 68 | scene.poly = newEntity() 69 | scene.polyG = newProcGraphic() 70 | scene.polyG.procedure = polyProc 71 | scene.poly.graphic = scene.polyG 72 | scene.poly.pos = (320, 240) 73 | 74 | # add to scene 75 | scene.add(scene.poly) 76 | 77 | 78 | proc free*(scene: MainScene) = 79 | discard 80 | 81 | 82 | proc newMainScene*(): MainScene = 83 | new result, free 84 | result.init() 85 | 86 | 87 | method event*(scene: MainScene, event: Event) = 88 | if event.kind == KeyDown: 89 | case event.key.keysym.sym: 90 | of K_Escape: 91 | gameRunning = false 92 | else: discard 93 | 94 | 95 | method render*(scene: MainScene) = 96 | scene.renderScene() 97 | 98 | discard box((4, 60), (260, 92), 0x000000CC'u32) 99 | 100 | discard string((8, 64), "WSAD - move", 0xFFFFFFFF'u32) 101 | discard string((8, 72), "QE - rotate", 0xFFFFFFFF'u32) 102 | discard string((8, 80), "RF - scale", 0xFFFFFFFF'u32) 103 | 104 | 105 | method update*(scene: MainScene, elapsed: float) = 106 | scene.updateScene(elapsed) 107 | if ScancodeA.down: scene.poly.pos.x -= 1 108 | if ScancodeD.down: scene.poly.pos.x += 1 109 | if ScancodeW.down: scene.poly.pos.y -= 1 110 | if ScancodeS.down: scene.poly.pos.y += 1 111 | if ScancodeQ.down: scene.poly.rot -= 1 112 | if ScancodeE.down: scene.poly.rot += 1 113 | if ScancodeR.down: scene.poly.scale -= 0.01 114 | if ScancodeF.down: scene.poly.scale += 0.01 115 | 116 | -------------------------------------------------------------------------------- /demos/demo9/README.md: -------------------------------------------------------------------------------- 1 | Nimgame 2: Demo 9 2 | ================= 3 | 4 | Audio demo. Demonstrates sound effects. 5 | 6 | ![Screenshot](demo9.png) 7 | 8 | -------------------------------------------------------------------------------- /demos/demo9/demo9.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/settings, 4 | nimgame2/assets, 5 | nimgame2/texturegraphic, 6 | mainscene 7 | 8 | game = newGame() 9 | if game.init(w = 640, h = 480, title = "Nimgame 2: Demo 9 (Audio)", 10 | scaleQuality = 0): 11 | showInfo = true 12 | game.scene = newMainScene() 13 | game.run() 14 | 15 | -------------------------------------------------------------------------------- /demos/demo9/demo9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/demos/demo9/demo9.png -------------------------------------------------------------------------------- /demos/demo9/mainscene.nim: -------------------------------------------------------------------------------- 1 | import 2 | math, 3 | nimgame2/assets, 4 | nimgame2/audio, 5 | nimgame2/nimgame, 6 | nimgame2/draw, 7 | nimgame2/input, 8 | nimgame2/scene, 9 | nimgame2/settings, 10 | nimgame2/types, 11 | nimgame2/utils 12 | 13 | 14 | type 15 | MainScene = ref object of Scene 16 | tack: Sound 17 | 18 | 19 | var 20 | musicData: Assets[Music] 21 | 22 | 23 | proc init*(scene: MainScene) = 24 | Scene(scene).init() 25 | 26 | # Sound 27 | scene.tack = newSound("../assets/sfx/tack.wav") 28 | scene.tack.volume = Volume.high div 2 29 | 30 | # Music 31 | musicData = newAssets[Music]("../assets/mus", 32 | proc(file: string): Music = newMusic(file)) 33 | playlist = newPlaylist() 34 | for track in musicData.values: 35 | playlist.list.add(track) 36 | 37 | 38 | proc free*(scene: MainScene) = 39 | discard 40 | 41 | 42 | proc newMainScene*(): MainScene = 43 | new result, free 44 | result.init() 45 | 46 | 47 | method event*(scene: MainScene, event: Event) = 48 | if event.kind == KeyDown: 49 | case event.key.keysym.sym: 50 | of K_Escape: 51 | gameRunning = false 52 | of K_Space: 53 | discard scene.tack.play() 54 | of K_M: 55 | discard playlist.play() 56 | else: discard 57 | 58 | 59 | method render*(scene: MainScene) = 60 | scene.renderScene() 61 | 62 | discard box((4, 60), (260, 92), 0x000000CC'u32) 63 | 64 | discard string((8, 64), "Space - play sound", 0xFFFFFFFF'u32) 65 | discard string((8, 72), 66 | "Up/Down - sound volume: " & $scene.tack.volume, 0xFFFFFFFF'u32) 67 | discard string((8, 80), "M - play random music track", 0xFFFFFFFF'u32) 68 | discard string((8, 88), 69 | "PgUp/PgDn - music volume: " & $getMusicVolume(), 0xFFFFFFFF'u32) 70 | 71 | 72 | method update*(scene: MainScene, elapsed: float) = 73 | scene.updateScene(elapsed) 74 | if ScancodeUp.down: scene.tack.volumeInc(1) 75 | if ScancodeDown.down: scene.tack.volumeDec(1) 76 | if ScancodePageUp.down: musicVolumeInc(1) 77 | if ScancodePageDown.down: musicVolumeDec(1) 78 | 79 | -------------------------------------------------------------------------------- /demos/nim.cfg: -------------------------------------------------------------------------------- 1 | --multimethods:on 2 | -------------------------------------------------------------------------------- /docs/changelog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Nimgame 2 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 | 21 | 22 | 23 |
24 |

CHANGELOG

25 | 26 |

v0.5 alpha (2017-08-01)

27 |
    28 |
  • changed physics and logic systems
  • 29 |
  • platformer physics
  • 30 |
  • CoordInt type
  • 31 |
  • now collider module is autmatically included into the entity module
  • 32 |
  • group collider
  • 33 |
  • huge Tilemap optimizations
  • 34 |
  • various utility Tilemap procedures
  • 35 |
  • TextureGraphic.drawTiled
  • 36 |
  • GUI: 37 |
      38 |
    • GUIProgressBar
    • 39 |
    • widget actions
    • 40 |
    41 |
  • 42 |
  • various minor changes and upgrades
  • 43 |
  • Nim v0.17.0 transition
  • 44 |
  • documentation, snippets, and demos update
  • 45 |
  • 46 | 47 | second tutorial 48 | 49 |
50 | 51 |

v0.4 alpha (2017-05-04)

52 |
    53 |
  • GUI: 54 |
      55 |
    • RadioGroup
    • 56 |
    • RadioButton
    • 57 |
    58 |
  • 59 |
  • IndexedImage
  • 60 |
  • PerspectiveImage
  • 61 |
  • TextureAtlas
  • 62 |
  • joysticks support
  • 63 |
  • window management procedures
  • 64 |
  • 4 new demos
  • 65 |
  • 66 | 67 | first tutorial 68 | 69 |
  • 70 |
71 | 72 |

v0.3 alpha (2017-03-10)

73 | 74 |
    75 |
  • camera property (Scene)
  • 76 |
  • new collision procedures
  • 77 |
  • reworked input
  • 78 |
  • Mosaic
  • 79 |
  • parallax property (Entity)
  • 80 |
  • TextField
  • 81 |
  • GUI: 82 |
      83 |
    • Widget
    • 84 |
    • Button
    • 85 |
    • TextInput
    • 86 |
    87 |
  • 88 |
  • 3 new demos
  • 89 |
  • home page, snippets, and documentation
  • 90 |
91 | 92 |

v0.2 alpha (2017-01-31)

93 | 94 |
    95 |
  • collider optimizations
  • 96 |
  • music playlists
  • 97 |
  • random procedures
  • 98 |
  • tilemaps
  • 99 |
  • tweens
  • 100 |
  • emitters
  • 101 |
  • various fixes
  • 102 |
  • 4 new demos
  • 103 |
104 | 105 |

v0.1 alpha (2017-01-16)

106 | 107 |
    108 |
  • base scene/entity system
  • 109 |
  • assets manager
  • 110 |
  • basic sound and music
  • 111 |
  • colliders (point, box, circle, line, and polygon)
  • 112 |
  • fonts (bitmap and TrueType) and text output
  • 113 |
  • keyboard and mouse input
  • 114 |
  • vector drawing procedures
  • 115 |
116 | 117 |
118 | 119 |
120 | 121 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /docs/docs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Nimgame 2 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 | 19 | 21 | 22 |
23 |

DOCUMENTATION

24 |
25 |
26 |
27 |
28 |
29 |
30 | 31 |
32 | 33 | 35 | 36 | 37 | 38 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/favicon.ico -------------------------------------------------------------------------------- /docs/images/icons/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/icons/check.png -------------------------------------------------------------------------------- /docs/images/icons/checkn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/icons/checkn.png -------------------------------------------------------------------------------- /docs/images/icons/email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/icons/email.png -------------------------------------------------------------------------------- /docs/images/icons/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/icons/logo.png -------------------------------------------------------------------------------- /docs/images/icons/outlink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/icons/outlink.png -------------------------------------------------------------------------------- /docs/images/icons/stare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/icons/stare.png -------------------------------------------------------------------------------- /docs/images/icons/starf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/icons/starf.png -------------------------------------------------------------------------------- /docs/images/screenshots/demo14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/screenshots/demo14.png -------------------------------------------------------------------------------- /docs/images/screenshots/demo14_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/screenshots/demo14_thumb.png -------------------------------------------------------------------------------- /docs/images/screenshots/ng2gggrotto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/screenshots/ng2gggrotto.png -------------------------------------------------------------------------------- /docs/images/screenshots/ng2gggrotto_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/screenshots/ng2gggrotto_thumb.png -------------------------------------------------------------------------------- /docs/images/screenshots/ng2planetoids.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/screenshots/ng2planetoids.png -------------------------------------------------------------------------------- /docs/images/screenshots/ng2planetoids_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/screenshots/ng2planetoids_thumb.png -------------------------------------------------------------------------------- /docs/images/screenshots/ng2platformer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/screenshots/ng2platformer.png -------------------------------------------------------------------------------- /docs/images/screenshots/ng2platformer_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/screenshots/ng2platformer_thumb.png -------------------------------------------------------------------------------- /docs/images/screenshots/ng2tbk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/screenshots/ng2tbk.png -------------------------------------------------------------------------------- /docs/images/screenshots/ng2tbk_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/screenshots/ng2tbk_thumb.png -------------------------------------------------------------------------------- /docs/images/tut101_bounce/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/tut101_bounce/ball.png -------------------------------------------------------------------------------- /docs/images/tut101_bounce/colliders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/tut101_bounce/colliders.png -------------------------------------------------------------------------------- /docs/images/tut101_bounce/paddle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/tut101_bounce/paddle.png -------------------------------------------------------------------------------- /docs/images/tut101_bounce/paddles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/tut101_bounce/paddles.png -------------------------------------------------------------------------------- /docs/images/tut101_bounce/score.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/tut101_bounce/score.png -------------------------------------------------------------------------------- /docs/images/tut101_bounce/thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/tut101_bounce/thumb.png -------------------------------------------------------------------------------- /docs/images/tut101_bounce/titlescene.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/tut101_bounce/titlescene.png -------------------------------------------------------------------------------- /docs/images/tut102_platformer/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/tut102_platformer/button.png -------------------------------------------------------------------------------- /docs/images/tut102_platformer/enemy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/tut102_platformer/enemy.png -------------------------------------------------------------------------------- /docs/images/tut102_platformer/player.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/tut102_platformer/player.png -------------------------------------------------------------------------------- /docs/images/tut102_platformer/thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/tut102_platformer/thumb.png -------------------------------------------------------------------------------- /docs/images/tut102_platformer/tiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vladar4/nimgame2/afd289aefd84aa4f89435f5fa0306da62f2023cc/docs/images/tut102_platformer/tiles.png -------------------------------------------------------------------------------- /docs/links.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Nimgame 2 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 | 19 | 85 | 86 |
87 | 88 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /docs/style.css: -------------------------------------------------------------------------------- 1 | /* REFERENCE 2 | --min-width: 20rem; 3 | --max-width: 40rem; 4 | --border-color: #999; 5 | */ 6 | 7 | body { 8 | padding-left: 0; 9 | padding-right: 0; 10 | margin-left: 0; 11 | margin-right: 0; 12 | color: #333; 13 | background-color: #fcf8f4; 14 | font-family: sans-serif; 15 | overflow-y: scroll; 16 | } 17 | 18 | /* HEADER */ 19 | 20 | header { 21 | display: flex; 22 | flex-direction: column; 23 | text-align: center; 24 | } 25 | 26 | header > div, header > div > div > div { 27 | display: flex; 28 | flex-direction: row; 29 | justify-content: center; 30 | } 31 | 32 | header > div > div { 33 | display: flex; 34 | flex-direction: column; 35 | } 36 | 37 | header .logo { 38 | padding: 0.5rem; 39 | min-width: 5rem; 40 | } 41 | 42 | header .logo img { 43 | height: 4rem; 44 | width: 4rem; 45 | } 46 | 47 | header h1 { 48 | color: #000; 49 | text-shadow: 2px 2px 2px #333; 50 | } 51 | 52 | header .menu { 53 | padding: 0.5rem 1rem; 54 | border: 1px solid #999; 55 | color: #333; 56 | text-align: center; 57 | text-decoration: none; 58 | vertical-align: middle; 59 | white-space: nowrap; 60 | cursor: pointer; 61 | } 62 | 63 | header .menu:hover { 64 | background-color: #fff; 65 | } 66 | 67 | header .menu:active { 68 | background-color: #fee; 69 | } 70 | 71 | header .disabled { 72 | color: #ccc; 73 | pointer-events: none; 74 | cursor: default; 75 | } 76 | 77 | /* MAIN */ 78 | 79 | main { 80 | display: flex; 81 | flex-direction: row; 82 | flex-wrap: wrap; 83 | justify-content: flex-start; 84 | } 85 | 86 | article { 87 | display: flex; 88 | flex-direction: column; 89 | } 90 | 91 | article, footer p { 92 | min-width: 20rem; 93 | max-width: 40rem; 94 | width: 100%; 95 | margin: 0 auto; 96 | } 97 | 98 | aside { 99 | display: none; 100 | flex-direction: column; 101 | padding: 1rem; 102 | border: 1px solid #999; 103 | margin: 1rem; 104 | min-width: 15rem; 105 | height: 100%; 106 | font-size: larger; 107 | } 108 | 109 | figure { 110 | margin: 0; 111 | margin-bottom: 1rem; 112 | } 113 | 114 | figcaption { 115 | text-align: center; 116 | } 117 | 118 | footer { 119 | padding-top: 1rem; 120 | text-align: right; 121 | font-size: smaller; 122 | color: #333; 123 | } 124 | 125 | h1, h2, h3, h4 { 126 | color: #333; 127 | } 128 | 129 | h3 { 130 | font-size: 100%; 131 | margin-bottom: 0em; 132 | } 133 | 134 | h4 { 135 | font-size: 80%; 136 | font-style: italic; 137 | margin-bottom: 0rem; 138 | } 139 | 140 | hr { 141 | width: 100%; 142 | } 143 | 144 | 145 | kbd { 146 | background-color: #e0e0e0; 147 | border: 1px solid #888; 148 | border-radius: 5px; 149 | padding: 2px; 150 | } 151 | 152 | 153 | pre { 154 | background-color: #f2edeb; 155 | white-space: pre-wrap; 156 | padding: 2px; 157 | border: 1px solid #888; 158 | } 159 | 160 | .prettyprint { 161 | background-color: #f2edeb; 162 | } 163 | 164 | noscript { 165 | color: maroon; 166 | } 167 | 168 | .snippet, .section { 169 | display: flex; 170 | flex-direction: column; 171 | padding: 0.5rem; 172 | margin-bottom: 1rem; 173 | } 174 | 175 | .snippet { 176 | border: 1px solid #999; 177 | } 178 | 179 | .docs div:first-of-type { 180 | margin-left: 10%; 181 | } 182 | 183 | .links div:first-of-type{ 184 | padding-left: 12.5%; 185 | padding-right: 12.5%; 186 | } 187 | 188 | .centered { 189 | text-align: center; 190 | } 191 | 192 | .columns { 193 | display: flex; 194 | flex-direction: row; 195 | } 196 | 197 | .columns > div { 198 | width: 100%; 199 | } 200 | 201 | /* TEXT */ 202 | 203 | a { 204 | text-decoration: none; 205 | } 206 | 207 | a[href*="http"] { 208 | background: url('images/icons/outlink.png') no-repeat 100% 0; 209 | background-size: 0.75rem; 210 | padding-right: 0.85rem; 211 | } 212 | 213 | a[href*="mailto"] { 214 | background: url('images/icons/email.png') no-repeat 100% 0; 215 | background-size: 1rem; 216 | padding-right: 1.25rem; 217 | } 218 | 219 | p { 220 | margin-top: 1rem; 221 | margin-bottom: 0rem; 222 | } 223 | 224 | .checklist { 225 | padding-left: 0; 226 | } 227 | 228 | .checklist li { 229 | list-style: none; 230 | list-style-position: outside; 231 | background: url('images/icons/check.png') no-repeat 0 0.1rem; 232 | background-size: 1rem 1rem; 233 | padding-left: 1.5rem; 234 | font-size: medium; 235 | } 236 | 237 | .checklist li.wip { 238 | background: url('images/icons/checkn.png') no-repeat 0 0.1rem; 239 | background-size: 1rem 1rem; 240 | padding-left: 1.5rem; 241 | } 242 | 243 | .tutlist li { 244 | padding-bottom: 1em; 245 | } 246 | 247 | .star { 248 | width: 1rem; 249 | } 250 | 251 | hr { 252 | border: 1px solid #999; 253 | } 254 | 255 | h1, h2 { 256 | text-align: center; 257 | } 258 | 259 | -------------------------------------------------------------------------------- /docs/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Nimgame 2 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 | 21 | 22 | 23 |
24 | 25 |
26 | 27 |
28 | 29 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/template_tutorial.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Nimgame 2 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 | 19 | 21 | 22 |
23 |

TUTORIAL

24 | 25 |

Introduction

26 | 27 |
28 | 
29 | 
30 | 31 | 43 | 44 |
45 | 46 | 47 |
48 | 49 | 51 | 52 | 53 | 54 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /docs/tutorials.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Nimgame 2 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 | 19 | 21 | 22 | 49 | 50 |
51 | 52 | 54 | 55 | 56 | 57 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /nimgame2.nim: -------------------------------------------------------------------------------- 1 | import 2 | nimgame2/nimgame, 3 | nimgame2/draw, 4 | nimgame2/entity, 5 | nimgame2/settings, 6 | nimgame2/audio, 7 | nimgame2/assets, 8 | nimgame2/scene, 9 | nimgame2/font, 10 | nimgame2/bitmapfont, 11 | nimgame2/utils, 12 | nimgame2/graphic, 13 | nimgame2/procgraphic, 14 | nimgame2/indexedimage, 15 | nimgame2/perspectiveimage, 16 | nimgame2/texturegraphic, 17 | nimgame2/textgraphic, 18 | nimgame2/textfield, 19 | nimgame2/types, 20 | nimgame2/mosaic, 21 | nimgame2/input, 22 | nimgame2/tilemap, 23 | nimgame2/truetypefont, 24 | nimgame2/tween, 25 | nimgame2/typewriter, 26 | nimgame2/emitter, 27 | nimgame2/gui/widget, 28 | nimgame2/gui/button, 29 | nimgame2/gui/radio, 30 | nimgame2/gui/textinput, 31 | nimgame2/gui/progressbar, 32 | nimgame2/plugin/tar, 33 | nimgame2/plugin/zzip, 34 | nimgame2/plugin/mpeggraphic 35 | 36 | export nimgame, 37 | draw, 38 | entity, 39 | settings, 40 | audio, 41 | assets, 42 | scene, 43 | utils, 44 | graphic, 45 | procgraphic, 46 | perspectiveimage, 47 | indexedimage, 48 | texturegraphic, 49 | textgraphic, 50 | bitmapfont, 51 | font, 52 | types, 53 | input, 54 | textfield, 55 | tilemap, 56 | mosaic, 57 | truetypefont, 58 | emitter, 59 | tween, 60 | widget, 61 | radio, 62 | textinput, 63 | typewriter, 64 | progressbar, 65 | button, 66 | mpeggraphic, 67 | tar, 68 | zzip -------------------------------------------------------------------------------- /nimgame2.nimble: -------------------------------------------------------------------------------- 1 | # Package 2 | 3 | version = "0.6.2" 4 | author = "Vladar" 5 | description = "A simple 2D game engine for Nim language." 6 | license = "MIT" 7 | 8 | # Dependencies 9 | 10 | requires "nim >= 1.4.0" 11 | requires "sdl2_nim >= 2.0.14.2" 12 | 13 | # Options 14 | 15 | skipDirs = @["demos"] 16 | 17 | -------------------------------------------------------------------------------- /nimgame2/assets.nim: -------------------------------------------------------------------------------- 1 | # nimgame2/assets.nim 2 | # Copyright (c) 2016-2018 Vladimir Arabadzhi (Vladar) 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | # vladar4@gmail.com 23 | # https://github.com/Vladar4 24 | 25 | import 26 | os, math, tables 27 | 28 | 29 | export 30 | tables 31 | 32 | 33 | type 34 | Assets*[T] = OrderedTableRef[string, T] 35 | 36 | 37 | proc load[T](assets: Assets[T], 38 | files: openarray[string], 39 | init: proc(file: string):T) = 40 | assets[] = initOrderedTable[string, T](nextPowerOfTwo(files.len)) 41 | for i in files: 42 | let 43 | name = i.splitFile.name 44 | data = init(i) 45 | #assets.add(name, data) # pre-nim1.4 46 | assets[name] = data 47 | 48 | 49 | proc load[T](assets: Assets[T], 50 | dir: string, 51 | init: proc(file: string): T) = 52 | var files: seq[string] = @[] 53 | for i in walkDir(dir): 54 | if i.kind == pcFile: 55 | files.add(i.path) 56 | assets.load(files, init) 57 | 58 | 59 | iterator loadIter*[T](assets: Assets[T], 60 | files: openarray[string], 61 | init: proc(file: string):T): int = 62 | ## Iterative loader. 63 | ## 64 | ## ``Yields`` the count of files loaded so far. 65 | var count = 0 66 | assets[] = initOrderedTable[string, T](nextPowerOfTwo(files.len)) 67 | for i in files: 68 | let 69 | name = i.splitFile.name 70 | data = init(i) 71 | #assets.add(name, data) # pre-nim1.4 72 | assets[name] = data 73 | inc count 74 | yield count 75 | 76 | 77 | iterator loadIter*[T](assets: Assets[T], 78 | dir: string, 79 | init: proc(file: string): T): int = 80 | ## Iterative loader. 81 | ## 82 | ## ``Yields`` the count of files loaded so far. 83 | var files: seq[string] = @[] 84 | for i in walkDir(dir): 85 | if i.kind == pcFile: 86 | files.add(i.path) 87 | for count in assets.loadIter(files, init): 88 | yield count 89 | 90 | 91 | proc newAssets*[T](files: openarray[string], init: proc(file: string): T): Assets[T] = 92 | ## Create a new assets collection. 93 | ## 94 | ## ``files`` an array of target files. 95 | ## 96 | ## ``init`` ``T``'s init/load procedure. 97 | ## 98 | new result 99 | result.load(files, init) 100 | 101 | 102 | proc newAssets*[T](dir: string, init: proc(file: string): T): Assets[T] = 103 | ## Create a new assets collection. 104 | ## 105 | ## ``dir`` target directory. 106 | ## 107 | ## ``init`` ``T``'s init/load procedure. 108 | ## 109 | new result 110 | result.load(dir, init) 111 | 112 | -------------------------------------------------------------------------------- /nimgame2/font.nim: -------------------------------------------------------------------------------- 1 | # nimgame2/font.nim 2 | # Copyright (c) 2016-2018 Vladimir Arabadzhi (Vladar) 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | # vladar4@gmail.com 23 | # https://github.com/Vladar4 24 | 25 | import 26 | sdl2_nim/sdl, 27 | settings, types, utils 28 | 29 | 30 | const 31 | DefaultFontColor*: Color = 0xFFFFFFFF'u32 32 | 33 | 34 | type 35 | Font* = ref object of RootObj 36 | 37 | 38 | method getError(font: Font): string {.base.} = 39 | $sdl.getError() 40 | 41 | 42 | method charH*(font: Font): int {.base.} = discard 43 | 44 | 45 | method lineDim*(font: Font, text: string): Dim {.base.} = discard 46 | 47 | 48 | method render*(font: Font, 49 | line: string, 50 | color: Color = DefaultFontColor): Surface {.base.} = discard 51 | 52 | 53 | proc renderLineFont*(font: Font, 54 | line: string, 55 | color: Color = DefaultFontColor): Texture = 56 | ## Render a text ``line`` in ``font`` with given ``color``. 57 | ## 58 | let 59 | line = if line.len < 1: " " else: line 60 | lineSurface = font.render(line, color) 61 | if lineSurface == nil: 62 | sdl.logCritical(sdl.LogCategoryError, 63 | "Can't render text line: %s", 64 | font.getError()) 65 | return nil 66 | result = renderer.createTextureFromSurface(lineSurface) 67 | lineSurface.freeSurface() 68 | 69 | 70 | method renderLine*(font: Font, 71 | line: string, 72 | color: Color = DefaultFontColor): Texture {.base.} = 73 | ## Base ``renderLine()`` font method. 74 | ## 75 | renderLineFont(font, line, color) 76 | 77 | 78 | proc renderTextFont*(font: Font, 79 | text: openarray[string], 80 | align = TextAlign.left, 81 | color: Color = DefaultfontColor): Texture = 82 | ## Render a multi-line ``text`` in ``font`` 83 | ## with given ``align`` and ``color``. 84 | ## 85 | var text = @text 86 | if text.len < 1: text.add(" ") 87 | 88 | # find the longest line of text 89 | var maxw = 0 90 | 91 | for line in text: 92 | let w = font.lineDim(line).w 93 | if maxw < w: 94 | maxw = w 95 | let 96 | maxw2 = maxw div 2 97 | height = font.charH 98 | 99 | # create surface 100 | let 101 | format = renderer.textureFormat(0) 102 | dim: Dim = (maxw, height * text.len) 103 | textSurface = createRGBSurfaceWithFormat( 104 | 0, dim.w, dim.h, format.bitsPerPixel.cint, format) 105 | 106 | if textSurface == nil: 107 | sdl.logCritical(sdl.LogCategoryError, 108 | "Can't create font text surface: %s", 109 | sdl.getError()) 110 | return nil 111 | 112 | # blit 113 | var 114 | dstRect = Rect(x: 0, y: 0, w: 0, h: height) 115 | 116 | for i in 0..text.high: 117 | let ln = font.render(text[i], color) 118 | dstRect.w = ln.w 119 | dstRect.x = case align: 120 | of TextAlign.left: 0 121 | of TextAlign.center: maxw2 - dstRect.w div 2 122 | of TextAlign.right: maxw - dstRect.w 123 | dstRect.y = i * height 124 | discard ln.blitSurface(nil, textSurface, addr(dstRect)) 125 | 126 | result = renderer.createTextureFromSurface(textSurface) 127 | textSurface.freeSurface() 128 | if result == nil: 129 | sdl.logCritical(sdl.LogCategoryError, 130 | "Can't render text: %s", 131 | sdl.getError()) 132 | return nil 133 | 134 | 135 | method renderText*(font: Font, 136 | text: openarray[string], 137 | align = TextAlign.left, 138 | color: Color = DefaultfontColor): Texture {.base.} = 139 | ## Base ``renderText()`` font method. 140 | ## 141 | renderTextFont(font, text, align, color) 142 | 143 | -------------------------------------------------------------------------------- /nimgame2/graphic.nim: -------------------------------------------------------------------------------- 1 | # nimgame2/graphic.nim 2 | # Copyright (c) 2016-2018 Vladimir Arabadzhi (Vladar) 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | # vladar4@gmail.com 23 | # https://github.com/Vladar4 24 | 25 | import 26 | types 27 | 28 | 29 | type 30 | Graphic* = ref object of RootObj 31 | 32 | 33 | method w*(graphic: Graphic): int {.base.} = discard 34 | 35 | method h*(graphic: Graphic): int {.base.} = discard 36 | 37 | method dim*(graphic: Graphic): Dim {.base.} = discard 38 | 39 | method draw*(graphic: Graphic, 40 | pos: Coord = (0.0, 0.0), 41 | angle: Angle = 0.0, 42 | scale: Scale = 1.0, 43 | center: Coord = (0.0, 0.0), 44 | flip: Flip = Flip.none, 45 | region: Rect = Rect(x: 0, y: 0, w: 0, h: 0)) {.base.} = discard 46 | 47 | template rect*(graphic: Graphic, offset: Coord): Rect = 48 | Rect( 49 | x: (graphic.dim.w.float - offset.x).cint, 50 | y: (graphic.dim.h.float - offset.y).cint, 51 | w: graphic.dim.w.cint, 52 | h: graphic.dim.h.cint) 53 | 54 | -------------------------------------------------------------------------------- /nimgame2/gui/button.nim: -------------------------------------------------------------------------------- 1 | # nimgame2/button.nim 2 | # Copyright (c) 2016-2018 Vladimir Arabadzhi (Vladar) 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | # vladar4@gmail.com 23 | # https://github.com/Vladar4 24 | 25 | import 26 | ../entity, 27 | ../graphic, 28 | ../types, 29 | widget 30 | 31 | 32 | type 33 | GuiButton* = ref object of GuiWidget 34 | # Public 35 | image*: Graphic ## The graphic to render on top of a button 36 | imageOffset*: Coord ## Image drawing offset from button's center. \ 37 | ## Calcuclated automatically if the image is passed in ``init()`` 38 | imageShift*: Coord ## Image shift when button is pressed 39 | 40 | 41 | proc init*(button: GuiButton, 42 | graphic: Graphic, 43 | image: Graphic = nil, 44 | circle: bool = false) = 45 | ## GuiButton initialization. 46 | ## 47 | ## ``graphic`` 2x3 button graphic: 48 | ## defaultUp, defaultDown, focusedUp, focusedDown, disabledUp, disabledDown. 49 | ## 50 | ## ``image`` The graphic to render on top of a butotn. 51 | ## 52 | ## ``circle`` Set to `true` if you want a circle shape instead of square one. 53 | ## 54 | GuiWidget(button).init() 55 | button.graphic = graphic 56 | button.initSprite((graphic.dim.w / 2, graphic.dim.h / 3)) 57 | button.image = image 58 | button.imageOffset = if not (image == nil): 59 | (button.sprite.dim / 2 - image.dim / 2) 60 | else: 61 | (0, 0) 62 | button.imageShift = (1, 1) 63 | # Collider 64 | button.collider = if circle: 65 | button.newCircleCollider( 66 | button.sprite.dim / 2, 67 | max(button.sprite.dim.w, button.sprite.dim.h) / 2) 68 | else: 69 | button.newBoxCollider( 70 | button.sprite.dim / 2, 71 | button.sprite.dim) 72 | 73 | 74 | proc newGuiButton*(graphic: Graphic, 75 | image: Graphic = nil, 76 | circle: bool = false): GuiButton = 77 | ## Create a new GuiButton. 78 | ## 79 | ## ``graphic`` 2x3 button graphic: 80 | ## defaultUp, defaultDown, focusedUp, focusedDown, disabledUp, disabledDown. 81 | ## 82 | ## ``image`` The graphic to render on top of a butotn. 83 | ## 84 | ## ``circle`` Set to `true` if you want a circle shape instead of square one. 85 | ## 86 | result = new GuiButton 87 | result.init(graphic, image, circle) 88 | 89 | 90 | method `state=`*(button: GuiButton, val: GuiState) = 91 | ## ``Return`` ``button``'s ``state``. 92 | ## 93 | button.setState(val) 94 | button.sprite.currentFrame = val.int 95 | 96 | 97 | proc renderGuiButton*(button: GuiButton) = 98 | ## Default button render procedure. 99 | ## 100 | ## Call it from your button render method. 101 | ## 102 | button.renderEntity() 103 | if not (button.image == nil): 104 | var pos = button.absPos + button.imageOffset 105 | if button.state.isDown: 106 | pos += button.imageShift 107 | button.image.draw(pos, 108 | button.absRot, 109 | button.absScale, 110 | button.center, 111 | button.flip) 112 | 113 | 114 | method render*(button: GuiButton) = 115 | button.renderGuiButton() 116 | 117 | -------------------------------------------------------------------------------- /nimgame2/gui/radio.nim: -------------------------------------------------------------------------------- 1 | # nimgame2/radiogroup.nim 2 | # Copyright (c) 2016-2018 Vladimir Arabadzhi (Vladar) 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | # vladar4@gmail.com 23 | # https://github.com/Vladar4 24 | 25 | import 26 | ../entity, 27 | ../graphic, 28 | button, 29 | widget 30 | 31 | 32 | type 33 | GuiRadioGroup* = ref object of Entity 34 | # Public 35 | list*: seq[GuiWidget] 36 | 37 | GuiRadioButton* = ref object of GuiButton 38 | # Public 39 | group*: GuiRadioGroup 40 | 41 | 42 | #===============# 43 | # GuiRadioGroup # 44 | #===============# 45 | 46 | proc init*(radiogroup: GuiRadioGroup) = 47 | radiogroup.initEntity() 48 | radiogroup.list = @[] 49 | 50 | 51 | proc newGuiRadioGroup*(): GuiRadioGroup = 52 | result = new GuiRadioGroup 53 | result.init() 54 | 55 | 56 | proc toggle*(radiogroup: GuiRadioGroup, target: GuiWidget) = 57 | ## Toggle a ``target`` element of the ``radiogroup``. 58 | ## 59 | let idx = radiogroup.list.find(target) 60 | if idx >= 0: 61 | for i in 0..radiogroup.list.high: 62 | if i != idx: 63 | radiogroup.list[i].setToggled(false) 64 | 65 | 66 | #================# 67 | # GuiRadioButton # 68 | #================# 69 | 70 | proc init*(radiobutton: GuiRadioButton, 71 | group: GuiRadioGroup, 72 | graphic: Graphic, 73 | image: Graphic = nil, 74 | circle: bool = false) = 75 | ## GuiRadioButton initialization. 76 | ## 77 | ## ``group`` GuiRadioGroup the ``radiobutton`` belongs to. 78 | ## 79 | ## ``graphic``, ``image``, ``circle`` 80 | ## See "gui/button.nim" initialization docs. 81 | ## 82 | GuiButton(radiobutton).init(graphic, image, circle) 83 | radiobutton.toggle = true 84 | radiobutton.parent = group 85 | radiobutton.group = group 86 | group.list.add(radiobutton) 87 | 88 | 89 | proc newGuiRadioButton*(group: GuiRadioGroup, 90 | graphic: Graphic, 91 | image: Graphic = nil, 92 | circle: bool = false): GuiRadioButton = 93 | ## Create a new GuiRadioButton. 94 | ## 95 | ## ``group`` GuiRadioGroup the ``radiobutton`` belongs to. 96 | ## 97 | ## ``graphic``, ``image``, ``circle`` 98 | ## See "gui/button.nim" initialization docs. 99 | ## 100 | ## 101 | result = new GuiRadioButton 102 | result.init(group, graphic, image, circle) 103 | 104 | 105 | proc setToggled*(radiobutton: GuiRadioButton, val: bool) = 106 | ## Toggle ``radiobutton`` to a given state. 107 | ## 108 | if val: 109 | GuiWidget(radiobutton).setToggled(val) 110 | radiobutton.group.toggle(radiobutton) 111 | 112 | 113 | method `toggled=`*(radiobutton: GuiRadioButton, val: bool) = 114 | radiobutton.setToggled(val) 115 | 116 | -------------------------------------------------------------------------------- /nimgame2/gui/textinput.nim: -------------------------------------------------------------------------------- 1 | # nimgame2/textinput.nim 2 | # Copyright (c) 2016-2018 Vladimir Arabadzhi (Vladar) 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | # vladar4@gmail.com 23 | # https://github.com/Vladar4 24 | 25 | import 26 | unicode, 27 | sdl2_nim/sdl, 28 | ../entity, 29 | ../font, 30 | ../graphic, 31 | ../input, 32 | ../textfield, 33 | ../textgraphic, 34 | ../types, 35 | widget 36 | 37 | 38 | type 39 | GuiTextInput* = ref object of GuiWidget 40 | # Public 41 | text*: TextField 42 | textPos*: Coord ## Relative text position 43 | keysBackspace*, keysDelete*, keysLeft*, keysRight*, 44 | keysToFirst*, keysToLast*, keysDone*: seq[Keycode] 45 | 46 | 47 | proc init*(input: GuiTextInput, 48 | graphic: Graphic, 49 | font: Font) = 50 | ## GuiTextInput initialization. 51 | ## 52 | ## ``grapic`` 2x2 input field graphic: 53 | ## default, focused, pressed (active), disabled. 54 | ## 55 | ## ``font`` Font object for text rendering. 56 | ## 57 | GuiWidget(input).init() 58 | input.toggle = true 59 | input.keysBackspace = @[K_Backspace] 60 | input.keysDelete = @[K_Delete] 61 | input.keysLeft = @[K_Left] 62 | input.keysRight = @[K_Right] 63 | input.keysToFirst = @[K_Home] 64 | input.keysToLast = @[K_End] 65 | input.keysDone = @[K_Return, K_Escape] 66 | input.graphic = graphic 67 | input.initSprite((graphic.dim.w / 2, graphic.dim.h / 3)) 68 | # Collider 69 | input.collider = input.newBoxCollider(input.sprite.dim / 2, input.sprite.dim) 70 | # Text 71 | input.text = newTextField(font) 72 | input.textPos = ( 73 | (input.sprite.dim.h - font.charH) / 2, 74 | (input.sprite.dim.h - font.charH) / 2) 75 | 76 | 77 | proc newGuiTextInput*(graphic: Graphic, font: Font): GuiTextInput = 78 | ## Create a new GuiTextInput. 79 | ## 80 | ## ``grapic`` 2x2 input field graphic: 81 | ## default, focused, pressed (active), disabled. 82 | ## 83 | ## ``font`` Font object for text rendering. 84 | ## 85 | result = new GuiTextInput 86 | result.init(graphic, font) 87 | 88 | 89 | proc eventGuiTextInput*(input: GuiTextInput, e: Event) = 90 | if input.state.isEnabled: 91 | case e.kind: 92 | of KeyDown: 93 | if input.toggled: 94 | let key = e.key.keysym.sym 95 | if key in input.keysBackspace: 96 | input.text.bs() 97 | 98 | elif key in input.keysDelete: 99 | input.text.del() 100 | 101 | elif key in input.keysLeft: 102 | input.text.left() 103 | 104 | elif key in input.keysRight: 105 | input.text.right() 106 | 107 | elif key in input.keysToFirst: 108 | input.text.toFirst() 109 | 110 | elif key in input.keysToLast: 111 | input.text.toLast() 112 | 113 | elif key in input.keysDone: 114 | input.text.deactivate() 115 | stopTextInput() 116 | input.release() 117 | 118 | of TextInput: 119 | if input.toggled: 120 | input.text.add($e.text.text) 121 | 122 | of TextEditing: 123 | if input.toggled: 124 | discard 125 | 126 | else: 127 | discard 128 | 129 | 130 | method event*(input: GuiTextInput, e: Event) = 131 | input.eventGuiWidget(e) 132 | input.eventGuiTextInput(e) 133 | 134 | 135 | method `state=`*(input: GuiTextInput, val: GuiState) = 136 | input.setState(val) 137 | input.sprite.currentFrame = val.int 138 | 139 | 140 | proc enter*(input: GuiTextInput) = 141 | ## Start text entry mode. 142 | ## 143 | input.text.activate() 144 | startTextInput() 145 | 146 | 147 | proc click*(input: GuiTextInput, mb: MouseButton) {.inline.} = 148 | input.enter() 149 | 150 | 151 | method onClick*(input: GuiTextInput, mb: MouseButton) = 152 | input.click(mb) 153 | 154 | 155 | proc renderGuiTextInput*(input: GuiTextInput) = 156 | ## Default text input render procedure. 157 | ## 158 | ## Call it from your text input render method. 159 | ## 160 | input.renderEntity() 161 | input.text.draw(input.pos + input.textPos) 162 | 163 | 164 | method render*(input: GuiTextInput) = 165 | input.renderGuiTextInput() 166 | 167 | -------------------------------------------------------------------------------- /nimgame2/plugin/zzip.nim: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2001 Guido Draheim 3 | # Use freely under the restrictions of the ZLIB License 4 | # 5 | 6 | ## You should be able to drop it in the place of a ``sdl.rwFromFile()``. 7 | ## Then go to `X/share/myapp` and do 8 | ## ```cd graphics && zip -9r ../graphics.zip .``` 9 | ## and rename the `graphics/` subfolder - and still all your files 10 | ## are found: a filepath like `X/shared/graphics/game/greetings.bmp` 11 | ## will open `X/shared/graphics.zip` and return the zipped file 12 | ## `game/greetings.bmp` in the zip-archive (for reading that is). 13 | ## 14 | ## See original code at http://zziplib.sourceforge.net/zzip-sdl-rwops.html 15 | ## 16 | ## ``Note:`` zzip dynamic library should be available in the system. 17 | 18 | import 19 | sdl2_nim/sdl, zip/zzip 20 | 21 | 22 | # PRIVATE 23 | 24 | template rwopsZzipData(context: ptr RWops): untyped = 25 | (context.mem.unknown.data1) 26 | 27 | template rwopsZzipFile(context: ptr RWops): untyped = 28 | cast[ptr Zzip_File]((context.mem.unknown.data1)) 29 | 30 | proc zzipSeek*(context: ptr RWops, 31 | offset: int64, whence: cint): int64 {.cdecl.} = 32 | return zzipSeek(rwopsZzipFile(context), offset.int, whence) 33 | 34 | proc zzipRead*(context: ptr RWops, 35 | buf: pointer, size: csize, maxnum: csize): csize {.cdecl.} = 36 | return zzipRead(rwops_Zzip_File(context), buf, size * maxnum) div size 37 | 38 | proc zzipWrite*(context: ptr RWops, 39 | buf: pointer; size: csize, num: csize): csize {.cdecl.} = 40 | return 0 # ignored 41 | 42 | proc zzipClose*(context: ptr RWops): cint {.cdecl.} = 43 | if context == nil: 44 | return 0 45 | zzipClose(rwops_Zzip_File(context)) 46 | freeRW(context) 47 | return 0 48 | 49 | 50 | # PUBLIC 51 | 52 | proc rwFromZZip*(file, mode: string = "r"): ptr RWops = 53 | var f: ptr ZZipFile 54 | if not ('r' in mode): return rwFromFile(file, mode) 55 | f = zzipFopen(file, mode) 56 | if f == nil: 57 | return nil 58 | result = allocRW() 59 | if result == nil: 60 | zzipClose(f) 61 | raise newException(OutOfMemDefect, "allocRW(): out of memory") 62 | rwopsZzipData(result) = f 63 | result.read = zzipRead 64 | result.write = zzipWrite 65 | result.seek = zzipSeek 66 | result.close = zzipClose 67 | 68 | -------------------------------------------------------------------------------- /nimgame2/procgraphic.nim: -------------------------------------------------------------------------------- 1 | # nimgame2/procgraphic.nim 2 | # Copyright (c) 2016-2018 Vladimir Arabadzhi (Vladar) 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | # vladar4@gmail.com 23 | # https://github.com/Vladar4 24 | 25 | import 26 | sdl2_nim/sdl, 27 | graphic, types 28 | 29 | 30 | type 31 | ProcGraphic* = ref object of Graphic 32 | # Public 33 | procedure*: proc(graphic: ProcGraphic, 34 | pos: Coord, 35 | angle: Angle, 36 | scale: Scale, 37 | center: Coord, 38 | flip: Flip, 39 | region: Rect) {.locks:0.} ## Drawing procedure. 40 | dimProcedure*: proc(): Dim {.locks:0.} ## Dimensions procedure. 41 | 42 | 43 | #=============# 44 | # ProcGraphic # 45 | #=============# 46 | 47 | proc newProcGraphic*(): ProcGraphic = 48 | new result 49 | result.procedure = nil 50 | 51 | 52 | method w*(graphic: ProcGraphic): int = 53 | ## ``Return`` the width of the ``graphic`` if available, or `nil` otherwise. 54 | ## 55 | if graphic.dimProcedure == nil: 56 | return 0 57 | else: 58 | return graphic.dimProcedure().w 59 | 60 | 61 | method h*(graphic: ProcGraphic): int = 62 | ## ``Return`` the height of the ``graphic`` if available, or `nil` otherwise. 63 | ## 64 | if graphic.dimProcedure == nil: 65 | return 0 66 | else: 67 | return graphic.dimProcedure().h 68 | 69 | 70 | method dim*(graphic: ProcGraphic): Dim = 71 | ## ``Return`` the ``graphic``'s dimensions if available, or `nil` otherwise. 72 | ## 73 | if graphic.dimProcedure == nil: 74 | return (0, 0) 75 | else: 76 | return graphic.dimProcedure() 77 | 78 | 79 | proc drawProcGraphic*(graphic: ProcGraphic, 80 | pos: Coord = (0.0, 0.0), 81 | angle: Angle = 0.0, 82 | scale: Scale = 1.0, 83 | center: Coord = (0.0, 0.0), 84 | flip: Flip = Flip.none, 85 | region: Rect = Rect(x: 0, y: 0, w: 0, h: 0)) = 86 | if graphic.procedure == nil: 87 | return 88 | graphic.procedure(graphic, pos, angle, scale, center, flip, region) 89 | 90 | 91 | method draw*(graphic: ProcGraphic, 92 | pos: Coord = (0.0, 0.0), 93 | angle: Angle = 0.0, 94 | scale: Scale = 1.0, 95 | center: Coord = (0.0, 0.0), 96 | flip: Flip = Flip.none, 97 | region: Rect = Rect(x: 0, y: 0, w: 0, h: 0)) = 98 | drawProcGraphic(graphic, pos, angle, scale, center, flip, region) 99 | 100 | -------------------------------------------------------------------------------- /nimgame2/settings.nim: -------------------------------------------------------------------------------- 1 | # nimgame2/settings.nim 2 | # Copyright (c) 2016-2018 Vladimir Arabadzhi (Vladar) 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | # vladar4@gmail.com 23 | # https://github.com/Vladar4 24 | 25 | import 26 | sdl2_nim/sdl 27 | 28 | 29 | var 30 | background*: sdl.Color ## Screen clearing color 31 | renderer*: sdl.Renderer ## Game renderer pointer 32 | 33 | gameRunning*: bool ## If `false` - break main loop 34 | gamePaused*: bool ## If `true` - do not update current scene 35 | showInfo*: bool ## Show info panel 36 | fpsLimit*: int ## Limit frames per second to ``fpsLimit``,\ 37 | ## if `0` - no limit 38 | colliderOutline*: bool ## Show collider outlines 39 | colliderOutlineColor*: sdl.Color ## Color of collider outlines 40 | updateInterval*: int ## ``update()`` is called each ``updateInterval`` ms. 41 | 42 | -------------------------------------------------------------------------------- /nimgame2/textgraphic.nim: -------------------------------------------------------------------------------- 1 | # nimgame2/textgraphic.nim 2 | # Copyright (c) 2016-2018 Vladimir Arabadzhi (Vladar) 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | # vladar4@gmail.com 23 | # https://github.com/Vladar4 24 | 25 | import 26 | strutils, unicode, 27 | sdl2_nim/sdl, 28 | font, texturegraphic, types 29 | 30 | 31 | type 32 | TextGraphic* = ref object of TextureGraphic 33 | # Private 34 | fLines: seq[string] 35 | fAlign: TextAlign 36 | fColor: Color 37 | fFont: Font 38 | 39 | 40 | #=============# 41 | # TextGraphic # 42 | #=============# 43 | 44 | proc free*(text: TextGraphic) = 45 | TextureGraphic(text).free() 46 | text.fLines = @[] 47 | text.fAlign = TextAlign.left 48 | text.fColor = DefaultFontColor 49 | text.fFont = nil 50 | 51 | 52 | proc init*(text: TextGraphic, font: Font) = 53 | TextureGraphic(text).init() 54 | text.fLines = @[] 55 | text.fAlign = TextAlign.left 56 | text.fColor = DefaultFontColor 57 | text.fFont = font 58 | 59 | 60 | proc newTextGraphic*(font: Font = nil): TextGraphic = 61 | new result, free 62 | result.init(font) 63 | 64 | 65 | proc update*(text: TextGraphic) = 66 | if text.fFont == nil: 67 | return 68 | let num = text.fLines.len 69 | if num < 1: 70 | discard text.assignTexture(text.fFont.renderLine("")) 71 | elif num < 2: 72 | discard text.assignTexture( 73 | text.fFont.renderLine(text.fLines[0], text.fColor)) 74 | else: 75 | discard text.assignTexture( 76 | text.fFont.renderText(text.fLines, text.fAlign, text.fColor)) 77 | 78 | 79 | proc align*(text: TextGraphic): TextAlign {.inline.} = 80 | text.fAlign 81 | 82 | 83 | proc `align=`*(text: TextGraphic, val: TextAlign) {.inline.} = 84 | text.fAlign = val 85 | text.update() 86 | 87 | 88 | proc color*(text: TextGraphic): Color {.inline.} = 89 | text.fColor 90 | 91 | 92 | proc `color=`*(text: TextGraphic, val: Color) {.inline.} = 93 | text.fColor = val 94 | text.update() 95 | 96 | 97 | proc font*(text: TextGraphic): Font {.inline.} = 98 | text.fFont 99 | 100 | 101 | proc `font=`*(text: TextGraphic, val: Font) {.inline.} = 102 | text.fFont = val 103 | text.update() 104 | 105 | 106 | proc lines*(text: TextGraphic): seq[string] {.inline.} = 107 | text.fLines 108 | 109 | 110 | proc `lines=`*(text: TextGraphic, lines: openarray[string]) = 111 | if text.fFont == nil: 112 | return 113 | text.fLines = @lines 114 | text.freeTexture() 115 | text.update() 116 | 117 | 118 | proc text*(text: TextGraphic): string {.inline.} = 119 | ## ``Return`` ``lines``, joined in one string. 120 | ## 121 | text.fLines.join("\n") 122 | 123 | 124 | proc wordWrap(s: string, maxLineWidth: int): seq[string] = 125 | 126 | proc isNewLine(s: string): bool = 127 | for c in s: 128 | if c notin NewLines: 129 | return false 130 | return true 131 | 132 | template addIfNotSpace(lines: seq[string], newLine: string) = 133 | if not unicode.isSpace(newLine): 134 | lines.add(newLine) 135 | 136 | result = @[] 137 | let runes = s.toRunes 138 | var 139 | start = 0 140 | lastSep = -1 141 | for i in 0..runes.high: 142 | if runes[i].isWhiteSpace: 143 | lastSep = i 144 | if runeLen($runes[start..i]) > maxLineWidth or 145 | isNewLine($runes[i]): 146 | if lastSep < 0: 147 | result.addIfNotSpace($runes[start.. 0: 154 | result.addIfNotSpace($runes[start..^1]) 155 | 156 | 157 | proc setText*(text: TextGraphic, 158 | val: string, 159 | width: int = 0, 160 | seps: set[char] = Whitespace) = 161 | ## Set the text ``lines``, wrapping each ``width`` characters. 162 | ## 163 | if width < 1: 164 | text.lines = [val] 165 | else: 166 | text.lines = val.wordWrap(width) 167 | 168 | -------------------------------------------------------------------------------- /nimgame2/textureatlas.nim: -------------------------------------------------------------------------------- 1 | # nimgame2/textureatlas.nim 2 | # Copyright (c) 2016-2018 Vladimir Arabadzhi (Vladar) 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | # vladar4@gmail.com 23 | # https://github.com/Vladar4 24 | 25 | import 26 | math, tables, 27 | sdl2_nim/sdl, 28 | sdl2_nim/sdl_image as img, 29 | settings, texturegraphic, types, utils 30 | 31 | 32 | export 33 | tables 34 | 35 | 36 | type 37 | TextureAtlas* = OrderedTableRef[string, TextureGraphic] 38 | 39 | 40 | proc free*(atlas: TextureAtlas) = 41 | for graphic in atlas.values: 42 | if not (graphic == nil): 43 | graphic.free() 44 | 45 | 46 | proc generate(source: Surface, rect: Rect): TextureGraphic = 47 | var 48 | srcRect = rect 49 | surface: Surface = createRGBSurfaceWithFormat( 50 | 0, rect.w, rect.h, source.format.BitsPerPixel.cint, source.format.format) 51 | if surface == nil: 52 | sdl.logCritical(sdl.LogCategoryError, 53 | "Can't create a surface: %s", 54 | sdl.getError()) 55 | return nil 56 | # blit 57 | if not (source.blitSurface(addr(srcRect), surface, nil) == 0): 58 | sdl.logCritical(sdl.LogCategoryError, 59 | "Can't blit a surface: %s", 60 | sdl.getError()) 61 | surface.freeSurface() 62 | return nil 63 | # return and free 64 | result = newTextureGraphic() 65 | discard result.assignTexture(renderer.createTextureFromSurface(surface)) 66 | surface.freeSurface() 67 | 68 | 69 | proc load(atlas: TextureAtlas, imagefile, mapfile: string): bool = 70 | var source = loadSurface(imagefile) 71 | if source == nil: 72 | sdl.logCritical(sdl.LogCategoryError, 73 | "Can't load texture atlas image %s: %s", 74 | imagefile, img.getError()) 75 | return 76 | for mapping in mapfile.atlasValues: 77 | #atlas.add(mapping.name, source.generate(mapping.rect)) # pre-nim1.4 78 | atlas[mapping.name] = source.generate(mapping.rect) 79 | 80 | 81 | proc load(atlas: TextureAtlas, imageSrc, mapSrc: ptr RWops, 82 | freeImageSrc: bool = true, freeMapSrc: bool = true): bool = 83 | var source = loadSurface(imageSrc, freeImageSrc) 84 | if source == nil: 85 | sdl.logCritical(sdl.LogCategoryError, 86 | "Can't load texture atlas image RW: %s", 87 | img.getError()) 88 | return 89 | for mapping in mapSrc.atlasValues("", freeSrc = freeMapSrc): 90 | #atlas.add(mapping.name, source.generate(mapping.rect)) # pre nim1.4 91 | atlas[mapping.name] = source.generate(mapping.rect) 92 | 93 | 94 | proc newTextureAtlas*(imagefile, mapfile: string, 95 | count: int = 64): TextureAtlas = 96 | ## Create a new ``TextureAtlas``. 97 | ## 98 | ## ``imagefile`` file containging the image atlas. 99 | ## 100 | ## ``mapfile`` CSV file containing atlas mapping in a format of: 101 | ## 102 | ## .. code-block 103 | ## name, x, y, w, h 104 | ## ... 105 | ## 106 | ## ``count`` expected mappings count. 107 | ## 108 | new result, free 109 | result[] = initOrderedTable[string, TextureGraphic](nextPowerOfTwo(count)) 110 | discard result.load(imagefile, mapfile) 111 | 112 | 113 | proc newTextureAtlas*(imageSrc, mapSrc: ptr RWops, 114 | count: int = 64, 115 | freeImageSrc: bool = true, 116 | freeMapSrc: bool = true): TextureAtlas = 117 | new result, free 118 | result[] = initOrderedTable[string, TextureGraphic](nextPowerOfTwo(count)) 119 | discard result.load(imageSrc, mapSrc, freeImageSrc, freeMapSrc) 120 | 121 | -------------------------------------------------------------------------------- /nimgame2/truetypefont.nim: -------------------------------------------------------------------------------- 1 | # nimgame2/truetypefont.nim 2 | # Copyright (c) 2016-2018 Vladimir Arabadzhi (Vladar) 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | # vladar4@gmail.com 23 | # https://github.com/Vladar4 24 | 25 | import 26 | sdl2_nim/sdl, 27 | sdl2_nim/sdl_ttf as ttf, 28 | font, settings, types 29 | 30 | 31 | type 32 | TrueTypeFont* = ref object of font.Font 33 | # Private 34 | fFont: ttf.Font 35 | 36 | 37 | #==============# 38 | # TrueTypeFont # 39 | #==============# 40 | 41 | proc free*(font: TrueTypeFont) = 42 | if not (font.fFont == nil): 43 | font.fFont.closeFont() 44 | font.fFont = nil 45 | 46 | 47 | proc init*(font: TrueTypeFont) = 48 | font.fFont = nil 49 | 50 | 51 | proc newTrueTypeFont*(): TrueTypeFont = 52 | new result, free 53 | result.init() 54 | 55 | 56 | proc load*(font: TrueTypeFont, file: string, size: int): bool = 57 | ## Load ``font`` data from a ``file``. 58 | ## 59 | ## ``size`` required font size. 60 | ## 61 | result = true 62 | font.free() 63 | # load font 64 | font.fFont = ttf.openFont(file, size) 65 | if font.fFont == nil: 66 | sdl.logCritical(sdl.LogCategoryError, 67 | "Can't load font %s: %s", 68 | file, ttf.getError()) 69 | return false 70 | 71 | 72 | proc load*(font: TrueTypeFont, src: ptr RWops, size: int, 73 | freeSrc: bool = true): bool = 74 | ## Load ``font`` data from a ``src`` ``RWops``. 75 | ## 76 | ## ``size`` required font size. 77 | ## 78 | result = true 79 | font.free() 80 | # load font 81 | font.fFont = ttf.openFontRW(src, freeSrc, size) 82 | if font.fFont == nil: 83 | sdl.logCritical(sdl.LogCategoryError, 84 | "Can't load font RW: %s", 85 | ttf.getError()) 86 | return false 87 | 88 | 89 | method getError*(font: TrueTypeFont): string = 90 | $ttf.getError() 91 | 92 | 93 | method charH*(font: TrueTypeFont): int = 94 | ## ``Return`` a font character's height. 95 | ## 96 | if font.fFont == nil: 97 | return 0 98 | return font.fFont.fontHeight() 99 | 100 | 101 | method lineDim*(font: TrueTypeFont, line: string): Dim = 102 | ## ``Return`` dimensions of a ``line`` of text, written in ``font``. 103 | ## 104 | if font.fFont == nil: 105 | return (0, 0) 106 | var w, h: cint 107 | discard font.fFont.sizeUTF8(line, addr(w), addr(h)) 108 | return (w.int, h.int) 109 | 110 | 111 | proc renderTrueTypeFont*(font: TrueTypeFont, 112 | line: string, 113 | color: Color = DefaultFontColor): Surface = 114 | if font.fFont == nil: 115 | sdl.logCritical(sdl.LogCategoryError, 116 | "Can't render nil font") 117 | return nil 118 | if line.len < 1: 119 | return nil 120 | result = font.fFont.renderUTF8_Blended(line, color) 121 | if result.setSurfaceAlphaMod(color.a) != 0: 122 | sdl.logCritical(sdl.LogCategoryError, 123 | "Can't set surface alpha modifier: %s", 124 | sdl.getError()) 125 | 126 | 127 | method render*(font: TrueTypeFont, 128 | line: string, 129 | color: Color = DefaultFontColor): Surface = 130 | renderTrueTypeFont(font, line, color) 131 | 132 | -------------------------------------------------------------------------------- /nimgame2/typewriter.nim: -------------------------------------------------------------------------------- 1 | # nimgame2/typewriter.nim 2 | # Copyright (c) 2016-2018 Vladimir Arabadzhi (Vladar) 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | # vladar4@gmail.com 23 | # https://github.com/Vladar4 24 | 25 | import 26 | algorithm, strutils, 27 | entity, textgraphic, types 28 | 29 | 30 | type 31 | Typewriter* = ref object of Entity 32 | # Private 33 | fText: seq[char] ## typewriter's queue 34 | fRemainder: float ## internal timer (in seconds) 35 | # Public 36 | rate*: float ## typewriter's rate (in seconds) 37 | width*: int ## line width limit, no limit if `0` (default) 38 | 39 | 40 | #============# 41 | # Typewriter # 42 | #============# 43 | 44 | proc newTypewriter*(text: TextGraphic, rate: float): Typewriter = 45 | new result 46 | result.initEntity() 47 | result.graphic = text 48 | let tg = TextGraphic(result.graphic) 49 | if tg.lines.len < 1: 50 | tg.lines = [""] 51 | result.fText = @[] 52 | result.fRemainder = 0.0 53 | result.rate = rate 54 | result.width = -1 55 | 56 | 57 | proc add*(tw: Typewriter, text: string) {.inline.} = 58 | ## Add new ``text`` to the typewriter's queue. 59 | ## 60 | tw.fText = reversed(text) & tw.fText 61 | 62 | 63 | proc dump*(tw: Typewriter): string {.inline.} = 64 | ## ``Return`` the text awaiting in the typewriter's queue. 65 | ## 66 | $tw.fText 67 | 68 | 69 | proc clear*(tw: Typewriter) {.inline.} = 70 | ## Delete the text awaiting in the typewriter's queue. 71 | ## 72 | tw.fText = @[] 73 | 74 | 75 | proc force*(tw: Typewriter, text: string = "") = 76 | ## Add new ``text`` to the typewriter's queue 77 | ## and then output it all immediately. 78 | ## 79 | if text.len > 0: 80 | tw.add(text) 81 | tw.fRemainder = 0.0 82 | let tg = TextGraphic(tw.graphic) 83 | tg.setText(tg.text & reversed(tw.fText).join()) 84 | tw.clear() 85 | 86 | 87 | proc updateTypewriter*(tw: Typewriter, elapsed: float) = 88 | var str = "" 89 | tw.fRemainder += elapsed 90 | while tw.fRemainder >= tw.rate: 91 | if tw.fText.len < 1: # no text to print left 92 | tw.fRemainder = 0.0 93 | break 94 | tw.fRemainder -= tw.rate 95 | str.add(tw.fText.pop()) 96 | 97 | # update textgraphic 98 | if str.len > 0: 99 | let tg = TextGraphic(tw.graphic) 100 | tg.setText(tg.text & str, tw.width) 101 | 102 | 103 | method update*(tw: Typewriter, elapsed: float) = 104 | updateTypewriter(tw, elapsed) 105 | 106 | --------------------------------------------------------------------------------