├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── assets ├── README.md ├── dungeon.png ├── phoenix.png └── raptor.png ├── preview.gif └── src ├── ai.rs ├── animator.rs ├── components.rs ├── keyboard.rs ├── main.rs ├── physics.rs └── renderer.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "arrayvec" 3 | version = "0.4.10" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "atom" 11 | version = "0.3.5" 12 | source = "registry+https://github.com/rust-lang/crates.io-index" 13 | 14 | [[package]] 15 | name = "autocfg" 16 | version = "0.1.1" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | 19 | [[package]] 20 | name = "bitflags" 21 | version = "1.0.4" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | 24 | [[package]] 25 | name = "byteorder" 26 | version = "1.2.7" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | 29 | [[package]] 30 | name = "cfg-if" 31 | version = "0.1.6" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | 34 | [[package]] 35 | name = "cloudabi" 36 | version = "0.0.3" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | dependencies = [ 39 | "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 40 | ] 41 | 42 | [[package]] 43 | name = "crossbeam" 44 | version = "0.4.1" 45 | source = "registry+https://github.com/rust-lang/crates.io-index" 46 | dependencies = [ 47 | "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 48 | "crossbeam-deque 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 49 | "crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 50 | "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 51 | ] 52 | 53 | [[package]] 54 | name = "crossbeam-channel" 55 | version = "0.2.6" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | dependencies = [ 58 | "crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", 59 | "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 60 | "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", 61 | "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", 62 | "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", 63 | ] 64 | 65 | [[package]] 66 | name = "crossbeam-deque" 67 | version = "0.2.0" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | dependencies = [ 70 | "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 71 | "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 72 | ] 73 | 74 | [[package]] 75 | name = "crossbeam-deque" 76 | version = "0.5.2" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | dependencies = [ 79 | "crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 80 | "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 81 | ] 82 | 83 | [[package]] 84 | name = "crossbeam-epoch" 85 | version = "0.3.1" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | dependencies = [ 88 | "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", 89 | "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 90 | "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 91 | "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 92 | "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 93 | "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 94 | "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 95 | ] 96 | 97 | [[package]] 98 | name = "crossbeam-epoch" 99 | version = "0.5.2" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | dependencies = [ 102 | "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", 103 | "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 104 | "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 105 | "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 106 | "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 107 | "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 108 | ] 109 | 110 | [[package]] 111 | name = "crossbeam-epoch" 112 | version = "0.6.1" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | dependencies = [ 115 | "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", 116 | "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 117 | "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", 118 | "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 119 | "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 120 | "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 121 | ] 122 | 123 | [[package]] 124 | name = "crossbeam-utils" 125 | version = "0.2.2" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | dependencies = [ 128 | "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 129 | ] 130 | 131 | [[package]] 132 | name = "crossbeam-utils" 133 | version = "0.5.0" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | 136 | [[package]] 137 | name = "crossbeam-utils" 138 | version = "0.6.3" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | dependencies = [ 141 | "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 142 | ] 143 | 144 | [[package]] 145 | name = "derivative" 146 | version = "1.0.2" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | dependencies = [ 149 | "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", 150 | "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 151 | "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", 152 | ] 153 | 154 | [[package]] 155 | name = "either" 156 | version = "1.5.0" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | 159 | [[package]] 160 | name = "fnv" 161 | version = "1.0.6" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | 164 | [[package]] 165 | name = "fuchsia-zircon" 166 | version = "0.3.3" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | dependencies = [ 169 | "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 170 | "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 171 | ] 172 | 173 | [[package]] 174 | name = "fuchsia-zircon-sys" 175 | version = "0.3.3" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | 178 | [[package]] 179 | name = "fxhash" 180 | version = "0.2.1" 181 | source = "registry+https://github.com/rust-lang/crates.io-index" 182 | dependencies = [ 183 | "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", 184 | ] 185 | 186 | [[package]] 187 | name = "game-tutorial" 188 | version = "0.1.0" 189 | dependencies = [ 190 | "rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", 191 | "sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)", 192 | "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", 193 | "specs-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 194 | ] 195 | 196 | [[package]] 197 | name = "hibitset" 198 | version = "0.5.4" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | dependencies = [ 201 | "atom 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", 202 | "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 203 | ] 204 | 205 | [[package]] 206 | name = "lazy_static" 207 | version = "1.2.0" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | 210 | [[package]] 211 | name = "libc" 212 | version = "0.2.46" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | 215 | [[package]] 216 | name = "lock_api" 217 | version = "0.1.5" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | dependencies = [ 220 | "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 221 | "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 222 | ] 223 | 224 | [[package]] 225 | name = "log" 226 | version = "0.4.6" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | dependencies = [ 229 | "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 230 | ] 231 | 232 | [[package]] 233 | name = "memoffset" 234 | version = "0.2.1" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | 237 | [[package]] 238 | name = "mopa" 239 | version = "0.2.2" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | 242 | [[package]] 243 | name = "nodrop" 244 | version = "0.1.13" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | 247 | [[package]] 248 | name = "nonzero_signed" 249 | version = "1.0.2" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | 252 | [[package]] 253 | name = "num" 254 | version = "0.1.42" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | dependencies = [ 257 | "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", 258 | "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", 259 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 260 | ] 261 | 262 | [[package]] 263 | name = "num-integer" 264 | version = "0.1.39" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | dependencies = [ 267 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 268 | ] 269 | 270 | [[package]] 271 | name = "num-iter" 272 | version = "0.1.37" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | dependencies = [ 275 | "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", 276 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 277 | ] 278 | 279 | [[package]] 280 | name = "num-traits" 281 | version = "0.2.6" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | 284 | [[package]] 285 | name = "num_cpus" 286 | version = "1.9.0" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | dependencies = [ 289 | "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", 290 | ] 291 | 292 | [[package]] 293 | name = "owning_ref" 294 | version = "0.3.3" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | dependencies = [ 297 | "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 298 | ] 299 | 300 | [[package]] 301 | name = "owning_ref" 302 | version = "0.4.0" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | dependencies = [ 305 | "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 306 | ] 307 | 308 | [[package]] 309 | name = "parking_lot" 310 | version = "0.5.5" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | dependencies = [ 313 | "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 314 | "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", 315 | ] 316 | 317 | [[package]] 318 | name = "parking_lot" 319 | version = "0.6.4" 320 | source = "registry+https://github.com/rust-lang/crates.io-index" 321 | dependencies = [ 322 | "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 323 | "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 324 | ] 325 | 326 | [[package]] 327 | name = "parking_lot_core" 328 | version = "0.2.14" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | dependencies = [ 331 | "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", 332 | "rand 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 333 | "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", 334 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 335 | ] 336 | 337 | [[package]] 338 | name = "parking_lot_core" 339 | version = "0.3.1" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | dependencies = [ 342 | "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", 343 | "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", 344 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 345 | "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", 346 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 347 | ] 348 | 349 | [[package]] 350 | name = "proc-macro2" 351 | version = "0.4.24" 352 | source = "registry+https://github.com/rust-lang/crates.io-index" 353 | dependencies = [ 354 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 355 | ] 356 | 357 | [[package]] 358 | name = "quote" 359 | version = "0.6.10" 360 | source = "registry+https://github.com/rust-lang/crates.io-index" 361 | dependencies = [ 362 | "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", 363 | ] 364 | 365 | [[package]] 366 | name = "rand" 367 | version = "0.4.4" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | dependencies = [ 370 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 371 | "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", 372 | "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 373 | "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 374 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 375 | ] 376 | 377 | [[package]] 378 | name = "rand" 379 | version = "0.5.5" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | dependencies = [ 382 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 383 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 384 | "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", 385 | "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 386 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 387 | ] 388 | 389 | [[package]] 390 | name = "rand" 391 | version = "0.6.3" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | dependencies = [ 394 | "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 395 | "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", 396 | "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 397 | "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 398 | "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 399 | "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 400 | "rand_os 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 401 | "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 402 | "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 403 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 404 | ] 405 | 406 | [[package]] 407 | name = "rand_chacha" 408 | version = "0.1.1" 409 | source = "registry+https://github.com/rust-lang/crates.io-index" 410 | dependencies = [ 411 | "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 412 | "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 413 | ] 414 | 415 | [[package]] 416 | name = "rand_core" 417 | version = "0.2.2" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | dependencies = [ 420 | "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 421 | ] 422 | 423 | [[package]] 424 | name = "rand_core" 425 | version = "0.3.0" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | 428 | [[package]] 429 | name = "rand_hc" 430 | version = "0.1.0" 431 | source = "registry+https://github.com/rust-lang/crates.io-index" 432 | dependencies = [ 433 | "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 434 | ] 435 | 436 | [[package]] 437 | name = "rand_isaac" 438 | version = "0.1.1" 439 | source = "registry+https://github.com/rust-lang/crates.io-index" 440 | dependencies = [ 441 | "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 442 | ] 443 | 444 | [[package]] 445 | name = "rand_os" 446 | version = "0.1.0" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | dependencies = [ 449 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 450 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 451 | "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", 452 | "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 453 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 454 | ] 455 | 456 | [[package]] 457 | name = "rand_pcg" 458 | version = "0.1.1" 459 | source = "registry+https://github.com/rust-lang/crates.io-index" 460 | dependencies = [ 461 | "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 462 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 463 | ] 464 | 465 | [[package]] 466 | name = "rand_xorshift" 467 | version = "0.1.1" 468 | source = "registry+https://github.com/rust-lang/crates.io-index" 469 | dependencies = [ 470 | "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 471 | ] 472 | 473 | [[package]] 474 | name = "rayon" 475 | version = "1.0.3" 476 | source = "registry+https://github.com/rust-lang/crates.io-index" 477 | dependencies = [ 478 | "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 479 | "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 480 | "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 481 | ] 482 | 483 | [[package]] 484 | name = "rayon-core" 485 | version = "1.4.1" 486 | source = "registry+https://github.com/rust-lang/crates.io-index" 487 | dependencies = [ 488 | "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 489 | "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 490 | "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", 491 | "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 492 | ] 493 | 494 | [[package]] 495 | name = "rdrand" 496 | version = "0.4.0" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | dependencies = [ 499 | "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 500 | ] 501 | 502 | [[package]] 503 | name = "rustc_version" 504 | version = "0.2.3" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | dependencies = [ 507 | "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 508 | ] 509 | 510 | [[package]] 511 | name = "scopeguard" 512 | version = "0.3.3" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | 515 | [[package]] 516 | name = "sdl2" 517 | version = "0.32.1" 518 | source = "registry+https://github.com/rust-lang/crates.io-index" 519 | dependencies = [ 520 | "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 521 | "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 522 | "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", 523 | "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", 524 | "rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", 525 | "sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)", 526 | ] 527 | 528 | [[package]] 529 | name = "sdl2-sys" 530 | version = "0.32.5" 531 | source = "registry+https://github.com/rust-lang/crates.io-index" 532 | dependencies = [ 533 | "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 534 | ] 535 | 536 | [[package]] 537 | name = "semver" 538 | version = "0.9.0" 539 | source = "registry+https://github.com/rust-lang/crates.io-index" 540 | dependencies = [ 541 | "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 542 | ] 543 | 544 | [[package]] 545 | name = "semver-parser" 546 | version = "0.7.0" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | 549 | [[package]] 550 | name = "shred" 551 | version = "0.7.1" 552 | source = "registry+https://github.com/rust-lang/crates.io-index" 553 | dependencies = [ 554 | "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", 555 | "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 556 | "mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 557 | "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 558 | "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", 559 | ] 560 | 561 | [[package]] 562 | name = "shred-derive" 563 | version = "0.5.1" 564 | source = "registry+https://github.com/rust-lang/crates.io-index" 565 | dependencies = [ 566 | "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", 567 | "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 568 | "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", 569 | ] 570 | 571 | [[package]] 572 | name = "shrev" 573 | version = "1.0.1" 574 | source = "registry+https://github.com/rust-lang/crates.io-index" 575 | dependencies = [ 576 | "derivative 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 577 | "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", 578 | ] 579 | 580 | [[package]] 581 | name = "smallvec" 582 | version = "0.6.7" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | dependencies = [ 585 | "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 586 | ] 587 | 588 | [[package]] 589 | name = "specs" 590 | version = "0.14.3" 591 | source = "registry+https://github.com/rust-lang/crates.io-index" 592 | dependencies = [ 593 | "crossbeam 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 594 | "derivative 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 595 | "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 596 | "hibitset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", 597 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 598 | "mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 599 | "nonzero_signed 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 600 | "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 601 | "shred 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 602 | "shred-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 603 | "shrev 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 604 | "tuple_utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 605 | ] 606 | 607 | [[package]] 608 | name = "specs-derive" 609 | version = "0.4.0" 610 | source = "registry+https://github.com/rust-lang/crates.io-index" 611 | dependencies = [ 612 | "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", 613 | "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 614 | "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", 615 | ] 616 | 617 | [[package]] 618 | name = "stable_deref_trait" 619 | version = "1.1.1" 620 | source = "registry+https://github.com/rust-lang/crates.io-index" 621 | 622 | [[package]] 623 | name = "syn" 624 | version = "0.15.24" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | dependencies = [ 627 | "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", 628 | "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 629 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 630 | ] 631 | 632 | [[package]] 633 | name = "tuple_utils" 634 | version = "0.2.0" 635 | source = "registry+https://github.com/rust-lang/crates.io-index" 636 | 637 | [[package]] 638 | name = "unicode-xid" 639 | version = "0.1.0" 640 | source = "registry+https://github.com/rust-lang/crates.io-index" 641 | 642 | [[package]] 643 | name = "unreachable" 644 | version = "1.0.0" 645 | source = "registry+https://github.com/rust-lang/crates.io-index" 646 | dependencies = [ 647 | "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 648 | ] 649 | 650 | [[package]] 651 | name = "void" 652 | version = "1.0.2" 653 | source = "registry+https://github.com/rust-lang/crates.io-index" 654 | 655 | [[package]] 656 | name = "winapi" 657 | version = "0.3.6" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | dependencies = [ 660 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 661 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 662 | ] 663 | 664 | [[package]] 665 | name = "winapi-i686-pc-windows-gnu" 666 | version = "0.4.0" 667 | source = "registry+https://github.com/rust-lang/crates.io-index" 668 | 669 | [[package]] 670 | name = "winapi-x86_64-pc-windows-gnu" 671 | version = "0.4.0" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | 674 | [metadata] 675 | "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" 676 | "checksum atom 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3c86699c3f02778ec07158376991c8f783dd1f2f95c579ffaf0738dc984b2fe2" 677 | "checksum autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727" 678 | "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" 679 | "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" 680 | "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" 681 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 682 | "checksum crossbeam 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7408247b1b87f480890f28b670c5f8d9a8a4274833433fe74dc0dfd46d33650" 683 | "checksum crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b85741761b7f160bc5e7e0c14986ef685b7f8bf9b7ad081c60c604bb4649827" 684 | "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" 685 | "checksum crossbeam-deque 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7792c4a9b5a4222f654e3728a3dd945aacc24d2c3a1a096ed265d80e4929cb9a" 686 | "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" 687 | "checksum crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30fecfcac6abfef8771151f8be4abc9e4edc112c2bcb233314cafde2680536e9" 688 | "checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8" 689 | "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" 690 | "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" 691 | "checksum crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "41ee4864f4797060e52044376f7d107429ce1fb43460021b126424b7180ee21a" 692 | "checksum derivative 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6073e9676dbebdddeabaeb63e3b7cefd23c86f5c41d381ee1237cc77b1079898" 693 | "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" 694 | "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" 695 | "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" 696 | "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" 697 | "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" 698 | "checksum hibitset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6527bc88f32e0d3926c7572874b2bf17a19b36978aacd0aacf75f7d27a5992d0" 699 | "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" 700 | "checksum libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)" = "023a4cd09b2ff695f9734c1934145a315594b7986398496841c7031a5a1bbdbd" 701 | "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" 702 | "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" 703 | "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" 704 | "checksum mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a785740271256c230f57462d3b83e52f998433a7062fc18f96d5999474a9f915" 705 | "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" 706 | "checksum nonzero_signed 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d9813c459ba38abf9c40eecc8d59738eb7ebcfc45a857030967372dcb83e18de" 707 | "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" 708 | "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" 709 | "checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" 710 | "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" 711 | "checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" 712 | "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" 713 | "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" 714 | "checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" 715 | "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" 716 | "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" 717 | "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" 718 | "checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" 719 | "checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" 720 | "checksum rand 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "34106854203c08f04b364c9c683bfe657e9214b082a5eda8e6c3ebfdec3ce02c" 721 | "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" 722 | "checksum rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b65e163105a6284f841bd23100a015895f54340e88a5ffc9ca7b8b33827cfce0" 723 | "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" 724 | "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" 725 | "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" 726 | "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" 727 | "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" 728 | "checksum rand_os 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de5ac4de1c2973e1391dc305cb0fbf8788cb58068e98255439b7485a77022273" 729 | "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" 730 | "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" 731 | "checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" 732 | "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" 733 | "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" 734 | "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 735 | "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" 736 | "checksum sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebf85f207d42e4da59fa31fff977be5ff0b224873506c4bd70cc1c94b331593" 737 | "checksum sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e82803e85c2e6178d28886cef25b2c53afc2eecaeff739f2247f23ed3352e6c1" 738 | "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 739 | "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 740 | "checksum shred 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c75ec29e8d2959ad96a1087fe4cadb926c6fc17cbae9812314fa8efe720aa2a" 741 | "checksum shred-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fcf34e5e5302d3024aba7afc291f6d1ca7573ed035d3c0796976ba3f10691a1" 742 | "checksum shrev 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ec60ed6f60a4b3cdc2ceacf57215db3408fbd8990f66a38686a31558cd9da482" 743 | "checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" 744 | "checksum specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "de65613ada4338aa7ba71eca60eca24c60483433eec0077bc4f33cfc31f4bdf0" 745 | "checksum specs-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a63549fa0d4a6f76e99e6634c328f25d0c9fa8ad6f8498aef74f6c35c0b269e5" 746 | "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" 747 | "checksum syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)" = "734ecc29cd36e8123850d9bf21dfd62ef8300aaa8f879aabaa899721808be37c" 748 | "checksum tuple_utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbfecd7bb8f0a3e96b3b31c46af2677a55a588767c0091f484601424fcb20e7e" 749 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 750 | "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" 751 | "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 752 | "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" 753 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 754 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 755 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "game-tutorial" 3 | version = "0.1.0" 4 | authors = ["Sunjay Varma "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | specs = "0.14" 9 | specs-derive = "0.4" 10 | rand = "0.6" 11 | 12 | [dependencies.sdl2] 13 | version = "0.32.1" 14 | default-features = false 15 | features = ["image"] 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # game-tutorial 2 | 3 | Each commit in this repo is a step in a game development tutorial I created for 4 | some friends. The game is built in the Rust programming language using the Rust 5 | SDL2 crate and the specs ECS. 6 | 7 | We start making the game with just the SDL2 crate and then convert it to use the 8 | specs ECS as our code starts to grow. Once the ECS is added, we're able to 9 | quickly add more functionality like enemies, etc. 10 | 11 | ![game tutorial preview](./preview.gif) 12 | -------------------------------------------------------------------------------- /assets/README.md: -------------------------------------------------------------------------------- 1 | # assets 2 | 3 | These assets are from [Monsters Time Fantasy RPG Asset Pack][asset-pack]. That means that they are **paid** assets subject 4 | to a [license]. Please purchase your own copy of the assets if you want to use them for projects beyond learning game 5 | development with this tutorial. 6 | 7 | In other words, I (unintentionally) included assets in this tutorial that need to be paid for. Please support the creator 8 | of those assets by buying their work. They also have a large selection of [free assets] that they provide for both free 9 | and commercial works. We need people like this who provide great art for the game development community. The only way 10 | that is sustainable is if we support them! 11 | 12 | [asset-pack]: https://finalbossblues.itch.io/time-fantasy-monsters 13 | [license]: https://www.gamedevmarket.net/terms-conditions/#pro-licence 14 | [free assets]: http://finalbossblues.com/timefantasy/free-graphics/ 15 | -------------------------------------------------------------------------------- /assets/dungeon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunjay/rust-simple-game-dev-tutorial/cfcd515ce0b24f5af60d98684b8b552f5c70430e/assets/dungeon.png -------------------------------------------------------------------------------- /assets/phoenix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunjay/rust-simple-game-dev-tutorial/cfcd515ce0b24f5af60d98684b8b552f5c70430e/assets/phoenix.png -------------------------------------------------------------------------------- /assets/raptor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunjay/rust-simple-game-dev-tutorial/cfcd515ce0b24f5af60d98684b8b552f5c70430e/assets/raptor.png -------------------------------------------------------------------------------- /preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunjay/rust-simple-game-dev-tutorial/cfcd515ce0b24f5af60d98684b8b552f5c70430e/preview.gif -------------------------------------------------------------------------------- /src/ai.rs: -------------------------------------------------------------------------------- 1 | use specs::prelude::*; 2 | use rand::prelude::*; 3 | 4 | use crate::components::*; 5 | 6 | const ENEMY_MOVEMENT_SPEED: i32 = 10; 7 | 8 | pub struct AI; 9 | 10 | impl<'a> System<'a> for AI { 11 | type SystemData = ( 12 | ReadStorage<'a, Enemy>, 13 | WriteStorage<'a, Velocity>, 14 | ); 15 | 16 | fn run(&mut self, mut data: Self::SystemData) { 17 | //TODO: This code can be made nicer and more idiomatic using more pattern matching. 18 | // Look up "rust irrefutable patterns" and use them here. 19 | let mut rng = thread_rng(); 20 | for (_, vel) in (&data.0, &mut data.1).join() { 21 | if rng.gen_range(0, 10) == 0 { 22 | vel.speed = ENEMY_MOVEMENT_SPEED; 23 | vel.direction = match rng.gen_range(0, 4) { 24 | 0 => Direction::Up, 25 | 1 => Direction::Down, 26 | 2 => Direction::Left, 27 | 3 => Direction::Right, 28 | _ => unreachable!(), 29 | } 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/animator.rs: -------------------------------------------------------------------------------- 1 | use specs::prelude::*; 2 | 3 | use crate::components::*; 4 | 5 | pub struct Animator; 6 | 7 | impl<'a> System<'a> for Animator { 8 | type SystemData = ( 9 | WriteStorage<'a, MovementAnimation>, 10 | WriteStorage<'a, Sprite>, 11 | ReadStorage<'a, Velocity>, 12 | ); 13 | 14 | fn run(&mut self, mut data: Self::SystemData) { 15 | use self::Direction::*; 16 | //TODO: This code can be made nicer and more idiomatic using more pattern matching. 17 | // Look up "rust irrefutable patterns" and use them here. 18 | for (anim, sprite, vel) in (&mut data.0, &mut data.1, &data.2).join() { 19 | if vel.speed == 0 { 20 | continue; 21 | } 22 | 23 | let frames = match vel.direction { 24 | Left => &anim.left_frames, 25 | Right => &anim.right_frames, 26 | Up => &anim.up_frames, 27 | Down => &anim.down_frames, 28 | }; 29 | 30 | anim.current_frame = (anim.current_frame + 1) % frames.len(); 31 | *sprite = frames[anim.current_frame].clone(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/components.rs: -------------------------------------------------------------------------------- 1 | use specs::prelude::*; 2 | use specs_derive::Component; 3 | use sdl2::rect::{Point, Rect}; 4 | 5 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 6 | pub enum Direction { 7 | Up, 8 | Down, 9 | Left, 10 | Right, 11 | } 12 | 13 | #[derive(Component, Debug, Default)] 14 | #[storage(NullStorage)] 15 | pub struct KeyboardControlled; 16 | 17 | #[derive(Component, Debug, Default)] 18 | #[storage(NullStorage)] 19 | pub struct Enemy; 20 | 21 | /// The current position of a given entity 22 | #[derive(Component, Debug)] 23 | #[storage(VecStorage)] 24 | pub struct Position(pub Point); 25 | 26 | /// The current speed and direction of a given entity 27 | #[derive(Component, Debug)] 28 | #[storage(VecStorage)] 29 | pub struct Velocity { 30 | pub speed: i32, 31 | pub direction: Direction, 32 | } 33 | 34 | #[derive(Component, Debug, Clone)] 35 | #[storage(VecStorage)] 36 | pub struct Sprite { 37 | /// The specific spritesheet to render from 38 | pub spritesheet: usize, 39 | /// The current region of the spritesheet to be rendered 40 | pub region: Rect, 41 | } 42 | 43 | #[derive(Component, Debug)] 44 | #[storage(VecStorage)] 45 | pub struct MovementAnimation { 46 | // The current frame in the animation of the direction this entity is moving in 47 | pub current_frame: usize, 48 | pub up_frames: Vec, 49 | pub down_frames: Vec, 50 | pub left_frames: Vec, 51 | pub right_frames: Vec, 52 | } 53 | -------------------------------------------------------------------------------- /src/keyboard.rs: -------------------------------------------------------------------------------- 1 | use specs::prelude::*; 2 | 3 | use crate::components::*; 4 | 5 | use super::MovementCommand; 6 | 7 | const PLAYER_MOVEMENT_SPEED: i32 = 20; 8 | 9 | pub struct Keyboard; 10 | 11 | impl<'a> System<'a> for Keyboard { 12 | type SystemData = ( 13 | ReadExpect<'a, Option>, 14 | ReadStorage<'a, KeyboardControlled>, 15 | WriteStorage<'a, Velocity>, 16 | ); 17 | 18 | fn run(&mut self, mut data: Self::SystemData) { 19 | //TODO: This code can be made nicer and more idiomatic using more pattern matching. 20 | // Look up "rust irrefutable patterns" and use them here. 21 | let movement_command = match &*data.0 { 22 | Some(movement_command) => movement_command, 23 | None => return, // no change 24 | }; 25 | 26 | for (_, vel) in (&data.1, &mut data.2).join() { 27 | match movement_command { 28 | &MovementCommand::Move(direction) => { 29 | vel.speed = PLAYER_MOVEMENT_SPEED; 30 | vel.direction = direction; 31 | }, 32 | MovementCommand::Stop => vel.speed = 0, 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod components; 2 | mod physics; 3 | mod animator; 4 | mod keyboard; 5 | mod renderer; 6 | mod ai; 7 | 8 | use sdl2::event::Event; 9 | use sdl2::keyboard::Keycode; 10 | use sdl2::pixels::Color; 11 | use sdl2::rect::{Point, Rect}; 12 | // "self" imports the "image" module itself as well as everything else we listed 13 | use sdl2::image::{self, LoadTexture, InitFlag}; 14 | 15 | use specs::prelude::*; 16 | 17 | use std::time::Duration; 18 | 19 | use crate::components::*; 20 | 21 | pub enum MovementCommand { 22 | Stop, 23 | Move(Direction), 24 | } 25 | 26 | /// Returns the row of the spritesheet corresponding to the given direction 27 | fn direction_spritesheet_row(direction: Direction) -> i32 { 28 | use self::Direction::*; 29 | match direction { 30 | Up => 3, 31 | Down => 0, 32 | Left => 1, 33 | Right => 2, 34 | } 35 | } 36 | 37 | /// Create animation frames for the standard character spritesheet 38 | fn character_animation_frames(spritesheet: usize, top_left_frame: Rect, direction: Direction) -> Vec { 39 | // All assumptions about the spritesheets are now encapsulated in this function instead of in 40 | // the design of our entire system. We can always replace this function, but replacing the 41 | // entire system is harder. 42 | 43 | let (frame_width, frame_height) = top_left_frame.size(); 44 | let y_offset = top_left_frame.y() + frame_height as i32 * direction_spritesheet_row(direction); 45 | 46 | let mut frames = Vec::new(); 47 | for i in 0..3 { 48 | frames.push(Sprite { 49 | spritesheet, 50 | region: Rect::new( 51 | top_left_frame.x() + frame_width as i32 * i, 52 | y_offset, 53 | frame_width, 54 | frame_height, 55 | ), 56 | }) 57 | } 58 | 59 | frames 60 | } 61 | 62 | fn initialize_player(world: &mut World, player_spritesheet: usize) { 63 | let player_top_left_frame = Rect::new(0, 0, 94, 100); 64 | 65 | let player_animation = MovementAnimation { 66 | current_frame: 0, 67 | up_frames: character_animation_frames(player_spritesheet, player_top_left_frame, Direction::Up), 68 | down_frames: character_animation_frames(player_spritesheet, player_top_left_frame, Direction::Down), 69 | left_frames: character_animation_frames(player_spritesheet, player_top_left_frame, Direction::Left), 70 | right_frames: character_animation_frames(player_spritesheet, player_top_left_frame, Direction::Right), 71 | }; 72 | 73 | world.create_entity() 74 | .with(KeyboardControlled) 75 | .with(Position(Point::new(0, 0))) 76 | .with(Velocity {speed: 0, direction: Direction::Right}) 77 | .with(player_animation.right_frames[0].clone()) 78 | .with(player_animation) 79 | .build(); 80 | } 81 | 82 | fn initialize_enemy(world: &mut World, enemy_spritesheet: usize, position: Point) { 83 | let enemy_top_left_frame = Rect::new(0, 0, 122, 114); 84 | 85 | let enemy_animation = MovementAnimation { 86 | current_frame: 0, 87 | up_frames: character_animation_frames(enemy_spritesheet, enemy_top_left_frame, Direction::Up), 88 | down_frames: character_animation_frames(enemy_spritesheet, enemy_top_left_frame, Direction::Down), 89 | left_frames: character_animation_frames(enemy_spritesheet, enemy_top_left_frame, Direction::Left), 90 | right_frames: character_animation_frames(enemy_spritesheet, enemy_top_left_frame, Direction::Right), 91 | }; 92 | 93 | world.create_entity() 94 | .with(Enemy) 95 | .with(Position(position)) 96 | .with(Velocity {speed: 0, direction: Direction::Right}) 97 | .with(enemy_animation.right_frames[0].clone()) 98 | .with(enemy_animation) 99 | .build(); 100 | } 101 | 102 | fn main() -> Result<(), String> { 103 | let sdl_context = sdl2::init()?; 104 | let video_subsystem = sdl_context.video()?; 105 | // Leading "_" tells Rust that this is an unused variable that we don't care about. It has to 106 | // stay unused because if we don't have any variable at all then Rust will treat it as a 107 | // temporary value and drop it right away! 108 | let _image_context = image::init(InitFlag::PNG | InitFlag::JPG)?; 109 | 110 | let window = video_subsystem.window("game tutorial", 800, 600) 111 | .position_centered() 112 | .build() 113 | .expect("could not initialize video subsystem"); 114 | 115 | let mut canvas = window.into_canvas().build() 116 | .expect("could not make a canvas"); 117 | let texture_creator = canvas.texture_creator(); 118 | 119 | let mut dispatcher = DispatcherBuilder::new() 120 | .with(keyboard::Keyboard, "Keyboard", &[]) 121 | .with(ai::AI, "AI", &[]) 122 | .with(physics::Physics, "Physics", &["Keyboard", "AI"]) 123 | .with(animator::Animator, "Animator", &["Keyboard", "AI"]) 124 | .build(); 125 | 126 | let mut world = World::new(); 127 | dispatcher.setup(&mut world.res); 128 | renderer::SystemData::setup(&mut world.res); 129 | 130 | // Initialize resource 131 | let movement_command: Option = None; 132 | world.add_resource(movement_command); 133 | 134 | let textures = [ 135 | texture_creator.load_texture("assets/raptor.png")?, 136 | texture_creator.load_texture("assets/phoenix.png")?, 137 | ]; 138 | // First texture in textures array 139 | let player_spritesheet = 0; 140 | // Second texture in the textures array 141 | let enemy_spritesheet = 1; 142 | 143 | initialize_player(&mut world, player_spritesheet); 144 | 145 | initialize_enemy(&mut world, enemy_spritesheet, Point::new(-150, -150)); 146 | initialize_enemy(&mut world, enemy_spritesheet, Point::new(150, -190)); 147 | initialize_enemy(&mut world, enemy_spritesheet, Point::new(-150, 170)); 148 | 149 | let mut event_pump = sdl_context.event_pump()?; 150 | let mut i = 0; 151 | 'running: loop { 152 | // None - no change, Some(MovementCommand) - perform movement 153 | let mut movement_command = None; 154 | // Handle events 155 | for event in event_pump.poll_iter() { 156 | match event { 157 | Event::Quit {..} | 158 | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => { 159 | break 'running 160 | }, 161 | Event::KeyDown { keycode: Some(Keycode::Left), repeat: false, .. } => { 162 | movement_command = Some(MovementCommand::Move(Direction::Left)); 163 | }, 164 | Event::KeyDown { keycode: Some(Keycode::Right), repeat: false, .. } => { 165 | movement_command = Some(MovementCommand::Move(Direction::Right)); 166 | }, 167 | Event::KeyDown { keycode: Some(Keycode::Up), repeat: false, .. } => { 168 | movement_command = Some(MovementCommand::Move(Direction::Up)); 169 | }, 170 | Event::KeyDown { keycode: Some(Keycode::Down), repeat: false, .. } => { 171 | movement_command = Some(MovementCommand::Move(Direction::Down)); 172 | }, 173 | Event::KeyUp { keycode: Some(Keycode::Left), repeat: false, .. } | 174 | Event::KeyUp { keycode: Some(Keycode::Right), repeat: false, .. } | 175 | Event::KeyUp { keycode: Some(Keycode::Up), repeat: false, .. } | 176 | Event::KeyUp { keycode: Some(Keycode::Down), repeat: false, .. } => { 177 | movement_command = Some(MovementCommand::Stop); 178 | }, 179 | _ => {} 180 | } 181 | } 182 | 183 | *world.write_resource() = movement_command; 184 | 185 | // Update 186 | dispatcher.dispatch(&mut world.res); 187 | world.maintain(); 188 | 189 | // Render 190 | i = (i + 1) % 255; 191 | renderer::render(&mut canvas, Color::RGB(i, 64, 255 - i), &textures, world.system_data())?; 192 | 193 | // Time management! 194 | ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 20)); 195 | } 196 | 197 | Ok(()) 198 | } 199 | -------------------------------------------------------------------------------- /src/physics.rs: -------------------------------------------------------------------------------- 1 | use specs::prelude::*; 2 | 3 | use crate::components::*; 4 | 5 | pub struct Physics; 6 | 7 | impl<'a> System<'a> for Physics { 8 | type SystemData = (WriteStorage<'a, Position>, ReadStorage<'a, Velocity>); 9 | 10 | fn run(&mut self, mut data: Self::SystemData) { 11 | use self::Direction::*; 12 | //TODO: This code can be made nicer and more idiomatic using more pattern matching. 13 | // Look up "rust irrefutable patterns" and use them here. 14 | for (pos, vel) in (&mut data.0, &data.1).join() { 15 | match vel.direction { 16 | Left => { 17 | pos.0 = pos.0.offset(-vel.speed, 0); 18 | }, 19 | Right => { 20 | pos.0 = pos.0.offset(vel.speed, 0); 21 | }, 22 | Up => { 23 | pos.0 = pos.0.offset(0, -vel.speed); 24 | }, 25 | Down => { 26 | pos.0 = pos.0.offset(0, vel.speed); 27 | }, 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/renderer.rs: -------------------------------------------------------------------------------- 1 | use specs::prelude::*; 2 | use sdl2::rect::{Point, Rect}; 3 | use sdl2::pixels::Color; 4 | use sdl2::render::{WindowCanvas, Texture}; 5 | 6 | use crate::components::*; 7 | 8 | // Type alias for the data needed by the renderer 9 | pub type SystemData<'a> = ( 10 | ReadStorage<'a, Position>, 11 | ReadStorage<'a, Sprite>, 12 | ); 13 | 14 | pub fn render( 15 | canvas: &mut WindowCanvas, 16 | background: Color, 17 | textures: &[Texture], 18 | data: SystemData, 19 | ) -> Result<(), String> { 20 | canvas.set_draw_color(background); 21 | canvas.clear(); 22 | 23 | let (width, height) = canvas.output_size()?; 24 | 25 | for (pos, sprite) in (&data.0, &data.1).join() { 26 | let current_frame = sprite.region; 27 | 28 | // Treat the center of the screen as the (0, 0) coordinate 29 | let screen_position = pos.0 + Point::new(width as i32 / 2, height as i32 / 2); 30 | let screen_rect = Rect::from_center(screen_position, current_frame.width(), current_frame.height()); 31 | canvas.copy(&textures[sprite.spritesheet], current_frame, screen_rect)?; 32 | } 33 | 34 | canvas.present(); 35 | 36 | Ok(()) 37 | } 38 | --------------------------------------------------------------------------------