Compare commits
2 commits
31daef03c7
...
ab74480bfd
Author | SHA1 | Date | |
---|---|---|---|
ab74480bfd | |||
e5c32b3855 |
9 changed files with 1115 additions and 131 deletions
442
Cargo.lock
generated
442
Cargo.lock
generated
|
@ -1,5 +1,35 @@
|
||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "arc-swap"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atty"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytes"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "c2-chacha"
|
name = "c2-chacha"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
|
@ -13,6 +43,50 @@ name = "cfg-if"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colored"
|
||||||
|
version = "1.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fnv"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuchsia-zircon"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuchsia-zircon-sys"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.1.13"
|
version = "0.1.13"
|
||||||
|
@ -23,16 +97,175 @@ dependencies = [
|
||||||
"wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iovec"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kernel32-sys"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.65"
|
version = "0.2.65"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio"
|
||||||
|
version = "0.6.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio-named-pipes"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio-uds"
|
||||||
|
version = "0.6.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miow"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miow"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "net2"
|
||||||
|
version = "0.2.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.42"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.6"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.7.2"
|
version = "0.7.2"
|
||||||
|
@ -70,26 +303,235 @@ dependencies = [
|
||||||
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.1.56"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sdl2"
|
||||||
|
version = "0.33.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"sdl2-sys 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sdl2-sys"
|
||||||
|
version = "0.33.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-registry"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"arc-swap 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simple_logger"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slab"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "socket2"
|
||||||
|
version = "0.3.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tetris"
|
name = "tetris"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"sdl2 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"simple_logger 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"tokio 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.1.42"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio"
|
||||||
|
version = "0.2.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-macros"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-build"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ws2_32-sys"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
|
"checksum arc-swap 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d663a8e9a99154b5fb793032533f6328da35e23aac63d5c152279aa8ba356825"
|
||||||
|
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||||
|
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||||
|
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
|
"checksum bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1"
|
||||||
"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
|
"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
|
||||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||||
|
"checksum chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
|
||||||
|
"checksum colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59"
|
||||||
|
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||||
|
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||||
|
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||||
|
"checksum futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a"
|
||||||
"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
|
"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
|
||||||
|
"checksum hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8"
|
||||||
|
"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
|
||||||
|
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||||
|
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8"
|
"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8"
|
||||||
|
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||||
|
"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
||||||
|
"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
|
||||||
|
"checksum mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3"
|
||||||
|
"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
|
||||||
|
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
||||||
|
"checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226"
|
||||||
|
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
|
||||||
|
"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
|
||||||
|
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
|
||||||
|
"checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6"
|
||||||
|
"checksum pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae"
|
||||||
"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
|
"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
|
||||||
|
"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
|
||||||
|
"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
|
||||||
"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412"
|
"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412"
|
||||||
"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
|
"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
|
||||||
"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||||
"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||||
|
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||||
|
"checksum sdl2 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f74124048ea86b5cd50236b2443f6f57cf4625a8e8818009b4e50dbb8729a43"
|
||||||
|
"checksum sdl2-sys 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2e1deb61ff274d29fb985017d4611d4004b113676eaa9c06754194caf82094e"
|
||||||
|
"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
|
||||||
|
"checksum simple_logger 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fea0c4611f32f4c2bac73754f22dca1f57e6c1945e0590dae4e5f2a077b92367"
|
||||||
|
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||||
|
"checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85"
|
||||||
|
"checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
|
||||||
|
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||||
|
"checksum tokio 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "0fa5e81d6bc4e67fe889d5783bd2a128ab2e0cfa487e0be16b6a8d177b101616"
|
||||||
|
"checksum tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
|
||||||
|
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||||
"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d"
|
"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d"
|
||||||
|
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||||
|
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
||||||
|
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||||
|
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
|
||||||
|
|
|
@ -8,3 +8,7 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rand = "0.7"
|
rand = "0.7"
|
||||||
|
tokio = { version = "0.2", features = ["full"] }
|
||||||
|
log = "0.4"
|
||||||
|
simple_logger = "1.6"
|
||||||
|
sdl2 = { version = "0.33.0", features = ["ttf"] }
|
119
src/game.rs
119
src/game.rs
|
@ -4,15 +4,124 @@
|
||||||
use crate::playfield::PlayField;
|
use crate::playfield::PlayField;
|
||||||
use crate::srs::RotationSystem;
|
use crate::srs::RotationSystem;
|
||||||
use crate::srs::SRS;
|
use crate::srs::SRS;
|
||||||
|
use crate::tetromino::Position;
|
||||||
|
use crate::Renderable;
|
||||||
|
use crate::TICKS_PER_SECOND;
|
||||||
|
use log::trace;
|
||||||
|
use sdl2::{render::Canvas, video::Window};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
pub struct Game<RS: RotationSystem> {
|
// I think this was correct, can't find source
|
||||||
|
const LINE_CLEAR_DELAY: u64 = TICKS_PER_SECOND as u64 * 41 / 60;
|
||||||
|
|
||||||
|
// Logic is based on 60 ticks / second
|
||||||
|
pub struct Game {
|
||||||
playfield: PlayField,
|
playfield: PlayField,
|
||||||
rotation_system: RS,
|
rotation_system: SRS,
|
||||||
level: u8,
|
level: u8,
|
||||||
points: u64,
|
points: u32,
|
||||||
|
pub tick: u64,
|
||||||
|
next_gravity_tick: u64,
|
||||||
|
next_lock_tick: u64,
|
||||||
|
next_spawn_tick: u64,
|
||||||
|
is_game_over: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
trait PlayerControllable {
|
impl fmt::Debug for Game {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
writeln!(f, "level: {}, points: {}", self.level, self.points)?;
|
||||||
|
writeln!(f, "tick: {}", self.tick)?;
|
||||||
|
write!(f, "{:?}", self.playfield)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Game {
|
||||||
|
fn default() -> Self {
|
||||||
|
Game {
|
||||||
|
playfield: PlayField::new(),
|
||||||
|
rotation_system: SRS::default(),
|
||||||
|
level: 1,
|
||||||
|
points: 0,
|
||||||
|
tick: 0,
|
||||||
|
next_gravity_tick: 60,
|
||||||
|
next_lock_tick: 0,
|
||||||
|
next_spawn_tick: 0,
|
||||||
|
is_game_over: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Tickable {
|
||||||
|
fn tick(&mut self);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tickable for Game {
|
||||||
|
fn tick(&mut self) {
|
||||||
|
if self.is_game_over() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tick += 1;
|
||||||
|
match self.tick {
|
||||||
|
t if t == self.next_spawn_tick => self.spawn_tetromino(),
|
||||||
|
t if t == self.next_lock_tick => {
|
||||||
|
// It's possible that the player moved the piece in the meantime.
|
||||||
|
if !self.playfield.can_active_piece_move_down() {
|
||||||
|
let positions = self.playfield.lock_active_piece();
|
||||||
|
self.is_game_over =
|
||||||
|
self.is_game_over || positions.iter().all(|Position { x: _, y }| *y < 20);
|
||||||
|
if self.clear_lines() {
|
||||||
|
self.next_spawn_tick = self.tick + LINE_CLEAR_DELAY;
|
||||||
|
} else {
|
||||||
|
self.spawn_tetromino();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t if t == self.next_gravity_tick => {
|
||||||
|
self.playfield.tick_gravity();
|
||||||
|
if !self.playfield.can_active_piece_move_down() {
|
||||||
|
self.update_lock_tick();
|
||||||
|
}
|
||||||
|
self.update_gravity_tick();
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Game {
|
||||||
|
pub fn is_game_over(&self) -> bool {
|
||||||
|
self.is_game_over || !self.playfield.is_active_piece_in_valid_position()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_gravity_tick(&mut self) {
|
||||||
|
self.next_gravity_tick = self.tick + TICKS_PER_SECOND as u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_lock_tick(&mut self) {
|
||||||
|
self.next_lock_tick = self.tick + TICKS_PER_SECOND as u64 / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn_tetromino(&mut self) {
|
||||||
|
self.playfield.spawn_tetromino();
|
||||||
|
self.playfield.tick_gravity();
|
||||||
|
self.update_gravity_tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns if some lines were cleared
|
||||||
|
fn clear_lines(&mut self) -> bool {
|
||||||
|
// todo: award points based on how lines were cleared
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Renderable for Game {
|
||||||
|
fn render(&self, canvas: &mut Canvas<Window>) -> Result<(), String> {
|
||||||
|
self.playfield.render(canvas)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Controllable {
|
||||||
fn move_left(&mut self);
|
fn move_left(&mut self);
|
||||||
fn move_up(&mut self);
|
fn move_up(&mut self);
|
||||||
fn move_right(&mut self);
|
fn move_right(&mut self);
|
||||||
|
@ -23,7 +132,7 @@ trait PlayerControllable {
|
||||||
fn hold(&mut self);
|
fn hold(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<RS: RotationSystem> PlayerControllable for Game<RS> {
|
impl Controllable for Game {
|
||||||
fn move_left(&mut self) {}
|
fn move_left(&mut self) {}
|
||||||
fn move_up(&mut self) {}
|
fn move_up(&mut self) {}
|
||||||
fn move_right(&mut self) {}
|
fn move_right(&mut self) {}
|
||||||
|
|
12
src/graphics.rs
Normal file
12
src/graphics.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
use sdl2::pixels::Color;
|
||||||
|
|
||||||
|
pub const CELL_SIZE: u32 = 32;
|
||||||
|
pub static COLOR_BACKGROUND: Color = Color::RGB(60, 60, 60);
|
||||||
|
pub static COLOR_CYAN: Color = Color::RGB(0, 255, 255);
|
||||||
|
pub static COLOR_YELLOW: Color = Color::RGB(255, 255, 0);
|
||||||
|
pub static COLOR_PURPLE: Color = Color::RGB(255, 0, 255);
|
||||||
|
pub static COLOR_GREEN: Color = Color::RGB(0, 255, 0);
|
||||||
|
pub static COLOR_RED: Color = Color::RGB(255, 0, 0);
|
||||||
|
pub static COLOR_BLUE: Color = Color::RGB(0, 0, 255);
|
||||||
|
pub static COLOR_ORANGE: Color = Color::RGB(255, 127, 0);
|
||||||
|
pub static COLOR_GRAY: Color = Color::RGB(100, 100, 100);
|
62
src/main.rs
62
src/main.rs
|
@ -1,22 +1,58 @@
|
||||||
|
use game::{Game, Tickable};
|
||||||
|
use graphics::COLOR_BACKGROUND;
|
||||||
|
use sdl2::event::Event;
|
||||||
|
use sdl2::keyboard::Keycode;
|
||||||
|
use sdl2::{render::Canvas, video::Window};
|
||||||
|
use std::time::Duration;
|
||||||
|
use tokio::time::interval;
|
||||||
|
|
||||||
mod game;
|
mod game;
|
||||||
|
mod graphics;
|
||||||
mod playfield;
|
mod playfield;
|
||||||
mod random;
|
mod random;
|
||||||
mod srs;
|
mod srs;
|
||||||
|
mod tetromino;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
const TICKS_PER_SECOND: usize = 60;
|
||||||
pub enum Tetromino {
|
|
||||||
I,
|
pub trait Renderable {
|
||||||
O,
|
fn render(&self, canvas: &mut Canvas<Window>) -> Result<(), String>;
|
||||||
T,
|
|
||||||
S,
|
|
||||||
Z,
|
|
||||||
J,
|
|
||||||
L,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
#[tokio::main]
|
||||||
let mut rs = random::RandomSystem::new();
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
for _ in 0..1000000 {
|
let sdl_context = sdl2::init()?;
|
||||||
rs.get_tetrino();
|
let video_subsystem = sdl_context.video()?;
|
||||||
|
let window = video_subsystem
|
||||||
|
.window("retris", 800, 800)
|
||||||
|
.position_centered()
|
||||||
|
.build()?;
|
||||||
|
let mut canvas = window.into_canvas().build()?;
|
||||||
|
let mut event_pump = sdl_context.event_pump()?;
|
||||||
|
let mut game = Game::default();
|
||||||
|
let mut interval = interval(Duration::from_millis(60 / TICKS_PER_SECOND as u64));
|
||||||
|
|
||||||
|
'running: while !game.is_game_over() {
|
||||||
|
for event in event_pump.poll_iter() {
|
||||||
|
match event {
|
||||||
|
Event::Quit { .. }
|
||||||
|
| Event::KeyDown {
|
||||||
|
keycode: Some(Keycode::Escape),
|
||||||
|
..
|
||||||
|
} => break 'running,
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
game.tick();
|
||||||
|
canvas.set_draw_color(COLOR_BACKGROUND);
|
||||||
|
canvas.clear();
|
||||||
|
game.render(&mut canvas)?;
|
||||||
|
canvas.present();
|
||||||
|
interval.tick().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Game over! Final game state:");
|
||||||
|
dbg!(game);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
187
src/playfield.rs
187
src/playfield.rs
|
@ -1,76 +1,187 @@
|
||||||
|
use crate::graphics::{CELL_SIZE, COLOR_BACKGROUND};
|
||||||
use crate::random::RandomSystem;
|
use crate::random::RandomSystem;
|
||||||
use crate::Tetromino;
|
use crate::tetromino::Position;
|
||||||
|
use crate::tetromino::{MinoColor, Tetromino, TetrominoType};
|
||||||
|
use crate::Renderable;
|
||||||
|
use sdl2::{pixels::Color, rect::Rect, render::Canvas, video::Window};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
pub const PLAYFIELD_HEIGHT: usize = 20;
|
||||||
enum MinoColor {
|
pub const PLAYFIELD_WIDTH: usize = 10;
|
||||||
Cyan,
|
|
||||||
Yellow,
|
pub type Matrix = [[Option<MinoColor>; PLAYFIELD_WIDTH]; 2 * PLAYFIELD_HEIGHT];
|
||||||
Purple,
|
|
||||||
Green,
|
|
||||||
Red,
|
|
||||||
Blue,
|
|
||||||
Orange,
|
|
||||||
Gray,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Movement {
|
enum Movement {
|
||||||
Rotate,
|
Rotation,
|
||||||
Gravity,
|
Gravity,
|
||||||
Translation,
|
Translation,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Position {
|
|
||||||
x: u8,
|
|
||||||
y: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PlayField {
|
pub struct PlayField {
|
||||||
can_swap_hold: bool,
|
can_swap_hold: bool,
|
||||||
hold_piece: Option<Tetromino>,
|
hold_piece: Option<TetrominoType>,
|
||||||
field: [[Option<MinoColor>; 10]; 40], // access via y, x
|
field: Matrix,
|
||||||
active_piece: Tetromino,
|
active_piece: Option<Tetromino>,
|
||||||
active_pos: Position,
|
|
||||||
bag: RandomSystem,
|
bag: RandomSystem,
|
||||||
next_pieces: VecDeque<Tetromino>,
|
next_pieces: VecDeque<TetrominoType>,
|
||||||
last_movement: Movement,
|
last_movement: Movement,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for PlayField {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match &self.active_piece {
|
||||||
|
Some(active_piece) => {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"current piece: {:?} @ {}, {}",
|
||||||
|
active_piece.piece_type, active_piece.position.x, active_piece.position.y
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
writeln!(f, "next pieces: {:?}", self.next_pieces)?;
|
||||||
|
let occupied_spaces = self
|
||||||
|
.active_piece
|
||||||
|
.and_then(|t| Some(t.get_cur_occupied_spaces()))
|
||||||
|
.unwrap_or_default();
|
||||||
|
for y in PLAYFIELD_HEIGHT..self.field.len() {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{} │",
|
||||||
|
('a' as usize - PLAYFIELD_HEIGHT + y) as u8 as char
|
||||||
|
)?;
|
||||||
|
for x in 0..PLAYFIELD_WIDTH {
|
||||||
|
if occupied_spaces.contains(&Position::new(x, y)) {
|
||||||
|
write!(f, "#")?;
|
||||||
|
} else {
|
||||||
|
match self.field[y][x] {
|
||||||
|
Some(t) => write!(f, "{:?}", t)?,
|
||||||
|
None => write!(f, " ")?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeln!(f, "│")?;
|
||||||
|
}
|
||||||
|
writeln!(f, " └{}┘", "─".repeat(PLAYFIELD_WIDTH))?;
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
" {}",
|
||||||
|
(0..PLAYFIELD_WIDTH)
|
||||||
|
.map(|e| e.to_string())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("")
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PlayField {
|
impl PlayField {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut bag = RandomSystem::new();
|
let mut bag = RandomSystem::new();
|
||||||
let active_piece = bag.get_tetrino();
|
let active_piece = Tetromino::from(bag.get_tetrino());
|
||||||
let mut next_pieces = VecDeque::with_capacity(3);
|
let mut next_pieces = VecDeque::with_capacity(3);
|
||||||
for _ in 0..next_pieces.len() {
|
for _ in 0..next_pieces.capacity() {
|
||||||
next_pieces.push_back(bag.get_tetrino());
|
next_pieces.push_back(bag.get_tetrino());
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayField {
|
PlayField {
|
||||||
can_swap_hold: true,
|
can_swap_hold: true,
|
||||||
hold_piece: None,
|
hold_piece: None,
|
||||||
field: [[None; 10]; 40],
|
field: [[None; PLAYFIELD_WIDTH]; 2 * PLAYFIELD_HEIGHT],
|
||||||
active_piece,
|
active_piece: Some(active_piece),
|
||||||
active_pos: Position { x: 0, y: 0 },
|
|
||||||
bag,
|
bag,
|
||||||
next_pieces,
|
next_pieces,
|
||||||
last_movement: Movement::Gravity,
|
last_movement: Movement::Gravity,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_new_piece(&mut self) {
|
pub fn spawn_tetromino(&mut self) {
|
||||||
self.active_piece = self
|
self.active_piece = Some(Tetromino::from(
|
||||||
.next_pieces
|
self.next_pieces
|
||||||
.pop_front()
|
.pop_front()
|
||||||
.expect("visible queue to be populated");
|
.expect("visible queue to be populated"),
|
||||||
|
));
|
||||||
self.next_pieces.push_back(self.bag.get_tetrino());
|
self.next_pieces.push_back(self.bag.get_tetrino());
|
||||||
self.reset_position();
|
|
||||||
self.can_swap_hold = true;
|
self.can_swap_hold = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Place the current Tetromino at its default spawn position and
|
pub fn tick_gravity(&mut self) {
|
||||||
/// orientation. Used for hold-swapping or spawning in a new piece.
|
match &self.active_piece {
|
||||||
fn reset_position(&mut self) {
|
Some(mut active_piece) if self.can_active_piece_move_down() => {
|
||||||
self.last_movement = Movement::Gravity;
|
active_piece.position.y += 1;
|
||||||
unimplemented!();
|
self.active_piece = Some(active_piece);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn can_active_piece_move_down(&self) -> bool {
|
||||||
|
self.active_piece
|
||||||
|
.and_then(|p| {
|
||||||
|
Some(p.get_next_occupied_spaces().iter().fold(true, |acc, pos| {
|
||||||
|
acc && pos.y < self.field.len()
|
||||||
|
&& self.field[pos.y as usize][pos.x as usize].is_none()
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lock_active_piece(&mut self) -> Vec<Position> {
|
||||||
|
match &self.active_piece {
|
||||||
|
Some(active_piece) => {
|
||||||
|
let active_color = active_piece.get_color();
|
||||||
|
let new_pieces = active_piece.get_cur_occupied_spaces();
|
||||||
|
for Position { x, y } in &new_pieces {
|
||||||
|
self.field[*y][*x] = Some(active_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.active_piece = None;
|
||||||
|
new_pieces
|
||||||
|
}
|
||||||
|
None => panic!("Tried to lock active piece while active piece doesn't exist!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_active_piece_in_valid_position(&self) -> bool {
|
||||||
|
match self.active_piece {
|
||||||
|
Some(active_piece) => active_piece.get_cur_occupied_spaces().iter().all(|Position {x, y}| self.field[*y][*x].is_none()),
|
||||||
|
None => panic!("Tried checking if active piece is in a valid position but active piece doesn't exist")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Renderable for PlayField {
|
||||||
|
fn render(&self, canvas: &mut Canvas<Window>) -> Result<(), String> {
|
||||||
|
for y in 0..PLAYFIELD_HEIGHT {
|
||||||
|
for x in 0..PLAYFIELD_WIDTH {
|
||||||
|
canvas.set_draw_color(Color::RGB(0, 0, 0));
|
||||||
|
canvas.fill_rect(Rect::new(
|
||||||
|
CELL_SIZE as i32 * x as i32,
|
||||||
|
CELL_SIZE as i32 * y as i32,
|
||||||
|
CELL_SIZE,
|
||||||
|
CELL_SIZE,
|
||||||
|
))?;
|
||||||
|
|
||||||
|
match self.field[y + PLAYFIELD_HEIGHT][x] {
|
||||||
|
Some(mino) => canvas.set_draw_color(mino),
|
||||||
|
None => canvas.set_draw_color(COLOR_BACKGROUND),
|
||||||
|
}
|
||||||
|
canvas.fill_rect(Rect::new(
|
||||||
|
CELL_SIZE as i32 * x as i32 + 2,
|
||||||
|
CELL_SIZE as i32 * y as i32 + 2,
|
||||||
|
28,
|
||||||
|
28,
|
||||||
|
))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.active_piece {
|
||||||
|
Some(piece) => piece.render(canvas)?,
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::Tetromino;
|
use crate::tetromino::TetrominoType;
|
||||||
use rand::{rngs::ThreadRng, seq::SliceRandom, thread_rng};
|
use rand::{rngs::ThreadRng, seq::SliceRandom, thread_rng};
|
||||||
|
|
||||||
pub struct RandomSystem {
|
pub struct RandomSystem {
|
||||||
rng: ThreadRng,
|
rng: ThreadRng,
|
||||||
bag: [Tetromino; 7],
|
bag: [TetrominoType; 7],
|
||||||
cur_pos: usize,
|
cur_pos: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,12 +12,12 @@ impl RandomSystem {
|
||||||
let rng = thread_rng();
|
let rng = thread_rng();
|
||||||
RandomSystem {
|
RandomSystem {
|
||||||
rng: rng,
|
rng: rng,
|
||||||
bag: [Tetromino::I; 7], // Default value, should get init on first get
|
bag: [TetrominoType::I; 7], // Default value, should get init on first get
|
||||||
cur_pos: 0,
|
cur_pos: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tetrino(&mut self) -> Tetromino {
|
pub fn get_tetrino(&mut self) -> TetrominoType {
|
||||||
if self.cur_pos == 0 {
|
if self.cur_pos == 0 {
|
||||||
self.refresh_bag();
|
self.refresh_bag();
|
||||||
}
|
}
|
||||||
|
@ -28,13 +28,13 @@ impl RandomSystem {
|
||||||
|
|
||||||
fn refresh_bag(&mut self) {
|
fn refresh_bag(&mut self) {
|
||||||
self.bag = [
|
self.bag = [
|
||||||
Tetromino::I,
|
TetrominoType::I,
|
||||||
Tetromino::O,
|
TetrominoType::O,
|
||||||
Tetromino::T,
|
TetrominoType::T,
|
||||||
Tetromino::S,
|
TetrominoType::S,
|
||||||
Tetromino::Z,
|
TetrominoType::Z,
|
||||||
Tetromino::J,
|
TetrominoType::J,
|
||||||
Tetromino::L,
|
TetrominoType::L,
|
||||||
];
|
];
|
||||||
self.bag.shuffle(&mut self.rng);
|
self.bag.shuffle(&mut self.rng);
|
||||||
self.cur_pos = 0;
|
self.cur_pos = 0;
|
||||||
|
|
138
src/srs.rs
138
src/srs.rs
|
@ -1,7 +1,7 @@
|
||||||
use crate::playfield::{PlayField, Position};
|
use crate::playfield::PlayField;
|
||||||
use crate::Tetromino;
|
use crate::tetromino::{Position, TetrominoType};
|
||||||
|
|
||||||
#[derive(Copy)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct Offset {
|
pub struct Offset {
|
||||||
x: i8,
|
x: i8,
|
||||||
y: i8,
|
y: i8,
|
||||||
|
@ -13,8 +13,10 @@ pub enum RotationDirection {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RotationSystem {
|
pub trait RotationSystem {
|
||||||
|
fn default() -> Self;
|
||||||
|
|
||||||
fn get_rotation_offset(
|
fn get_rotation_offset(
|
||||||
piece: &Tetromino,
|
piece: &TetrominoType,
|
||||||
center: &Position,
|
center: &Position,
|
||||||
direction: RotationDirection,
|
direction: RotationDirection,
|
||||||
playfield: &PlayField,
|
playfield: &PlayField,
|
||||||
|
@ -23,9 +25,19 @@ pub trait RotationSystem {
|
||||||
|
|
||||||
pub struct SRS {}
|
pub struct SRS {}
|
||||||
|
|
||||||
|
impl SRS {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RotationSystem for SRS {
|
impl RotationSystem for SRS {
|
||||||
|
fn default() -> Self {
|
||||||
|
SRS::new()
|
||||||
|
}
|
||||||
|
|
||||||
fn get_rotation_offset(
|
fn get_rotation_offset(
|
||||||
piece: &Tetromino,
|
piece: &TetrominoType,
|
||||||
center: &Position,
|
center: &Position,
|
||||||
direction: RotationDirection,
|
direction: RotationDirection,
|
||||||
playfield: &PlayField,
|
playfield: &PlayField,
|
||||||
|
@ -43,69 +55,69 @@ enum Rotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OffsetData {
|
struct OffsetData {
|
||||||
O: Vec<Offset>,
|
// O: &[Offset],
|
||||||
R: Vec<Offset>,
|
// R: &[Offset],
|
||||||
U: Vec<Offset>,
|
// U: &[Offset],
|
||||||
L: Vec<Offset>,
|
// L: &[Offset],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OffsetData {
|
impl OffsetData {
|
||||||
pub fn apply_right_rotation() {}
|
pub fn apply_right_rotation() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const JLSTZOffsetData: OffsetData = OffsetData {
|
// static JLSTZOffsetData: OffsetData = OffsetData {
|
||||||
O: vec![Offset { x: 0, y: 0 }],
|
// O: vec![Offset { x: 0, y: 0 }],
|
||||||
R: vec![
|
// R: vec![
|
||||||
Offset { x: 0, y: 0 },
|
// Offset { x: 0, y: 0 },
|
||||||
Offset { x: 1, y: 0 },
|
// Offset { x: 1, y: 0 },
|
||||||
Offset { x: 1, y: -1 },
|
// Offset { x: 1, y: -1 },
|
||||||
Offset { x: 0, y: 2 },
|
// Offset { x: 0, y: 2 },
|
||||||
Offset { x: 1, y: 2 },
|
// Offset { x: 1, y: 2 },
|
||||||
],
|
// ],
|
||||||
U: vec![Offset { x: 0, y: 0 }],
|
// U: vec![Offset { x: 0, y: 0 }],
|
||||||
L: vec![
|
// L: vec![
|
||||||
Offset { x: 0, y: 0 },
|
// Offset { x: 0, y: 0 },
|
||||||
Offset { x: -1, y: 0 },
|
// Offset { x: -1, y: 0 },
|
||||||
Offset { x: -1, y: -1 },
|
// Offset { x: -1, y: -1 },
|
||||||
Offset { x: 0, y: 2 },
|
// Offset { x: 0, y: 2 },
|
||||||
Offset { x: -1, y: 2 },
|
// Offset { x: -1, y: 2 },
|
||||||
],
|
// ],
|
||||||
};
|
// };
|
||||||
|
|
||||||
const IOffsetData: OffsetData = OffsetData {
|
// static IOffsetData: OffsetData = OffsetData {
|
||||||
O: vec![
|
// O: vec![
|
||||||
Offset { x: 0, y: 0 },
|
// Offset { x: 0, y: 0 },
|
||||||
Offset { x: -1, y: 0 },
|
// Offset { x: -1, y: 0 },
|
||||||
Offset { x: 2, y: 0 },
|
// Offset { x: 2, y: 0 },
|
||||||
Offset { x: -1, y: 0 },
|
// Offset { x: -1, y: 0 },
|
||||||
Offset { x: 2, y: 0 },
|
// Offset { x: 2, y: 0 },
|
||||||
],
|
// ],
|
||||||
R: vec![
|
// R: vec![
|
||||||
Offset { x: -1, y: 0 },
|
// Offset { x: -1, y: 0 },
|
||||||
Offset { x: 0, y: 0 },
|
// Offset { x: 0, y: 0 },
|
||||||
Offset { x: 0, y: 0 },
|
// Offset { x: 0, y: 0 },
|
||||||
Offset { x: 0, y: 1 },
|
// Offset { x: 0, y: 1 },
|
||||||
Offset { x: 0, y: -2 },
|
// Offset { x: 0, y: -2 },
|
||||||
],
|
// ],
|
||||||
U: vec![
|
// U: vec![
|
||||||
Offset { x: -1, y: 1 },
|
// Offset { x: -1, y: 1 },
|
||||||
Offset { x: 1, y: 1 },
|
// Offset { x: 1, y: 1 },
|
||||||
Offset { x: -2, y: 1 },
|
// Offset { x: -2, y: 1 },
|
||||||
Offset { x: 1, y: 0 },
|
// Offset { x: 1, y: 0 },
|
||||||
Offset { x: -2, y: 0 },
|
// Offset { x: -2, y: 0 },
|
||||||
],
|
// ],
|
||||||
L: vec![
|
// L: vec![
|
||||||
Offset { x: 0, y: 1 },
|
// Offset { x: 0, y: 1 },
|
||||||
Offset { x: 0, y: 1 },
|
// Offset { x: 0, y: 1 },
|
||||||
Offset { x: 0, y: 1 },
|
// Offset { x: 0, y: 1 },
|
||||||
Offset { x: 0, y: -1 },
|
// Offset { x: 0, y: -1 },
|
||||||
Offset { x: 0, y: 2 },
|
// Offset { x: 0, y: 2 },
|
||||||
],
|
// ],
|
||||||
};
|
// };
|
||||||
|
|
||||||
const OOffsetData: OffsetData = OffsetData {
|
// static OOffsetData: OffsetData = OffsetData {
|
||||||
O: vec![Offset { x: 0, y: 0 }],
|
// O: vec![Offset { x: 0, y: 0 }],
|
||||||
R: vec![Offset { x: 0, y: -1 }],
|
// R: vec![Offset { x: 0, y: -1 }],
|
||||||
U: vec![Offset { x: -1, y: -1 }],
|
// U: vec![Offset { x: -1, y: -1 }],
|
||||||
L: vec![Offset { x: -1, y: 0 }],
|
// L: vec![Offset { x: -1, y: 0 }],
|
||||||
};
|
// };
|
||||||
|
|
258
src/tetromino.rs
Normal file
258
src/tetromino.rs
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
use crate::{
|
||||||
|
graphics::*,
|
||||||
|
playfield::{PLAYFIELD_HEIGHT, PLAYFIELD_WIDTH},
|
||||||
|
Renderable,
|
||||||
|
};
|
||||||
|
use sdl2::{pixels::Color, rect::Rect, render::Canvas, video::Window};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum MinoColor {
|
||||||
|
Cyan,
|
||||||
|
Yellow,
|
||||||
|
Purple,
|
||||||
|
Green,
|
||||||
|
Red,
|
||||||
|
Blue,
|
||||||
|
Orange,
|
||||||
|
Gray,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for MinoColor {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
match self {
|
||||||
|
Self::Cyan => "c",
|
||||||
|
Self::Yellow => "y",
|
||||||
|
Self::Purple => "p",
|
||||||
|
Self::Green => "g",
|
||||||
|
Self::Red => "r",
|
||||||
|
Self::Blue => "b",
|
||||||
|
Self::Orange => "o",
|
||||||
|
Self::Gray => "x",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Color> for MinoColor {
|
||||||
|
fn into(self) -> Color {
|
||||||
|
match self {
|
||||||
|
Self::Cyan => COLOR_CYAN,
|
||||||
|
Self::Yellow => COLOR_YELLOW,
|
||||||
|
Self::Purple => COLOR_PURPLE,
|
||||||
|
Self::Green => COLOR_GREEN,
|
||||||
|
Self::Red => COLOR_RED,
|
||||||
|
Self::Blue => COLOR_BLUE,
|
||||||
|
Self::Orange => COLOR_ORANGE,
|
||||||
|
Self::Gray => COLOR_GRAY,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum TetrominoType {
|
||||||
|
I,
|
||||||
|
O,
|
||||||
|
T,
|
||||||
|
S,
|
||||||
|
Z,
|
||||||
|
J,
|
||||||
|
L,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Color> for TetrominoType {
|
||||||
|
fn into(self) -> Color {
|
||||||
|
match self {
|
||||||
|
Self::I => COLOR_CYAN,
|
||||||
|
Self::O => COLOR_YELLOW,
|
||||||
|
Self::T => COLOR_PURPLE,
|
||||||
|
Self::S => COLOR_GREEN,
|
||||||
|
Self::Z => COLOR_RED,
|
||||||
|
Self::J => COLOR_BLUE,
|
||||||
|
Self::L => COLOR_ORANGE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
enum RotationState {
|
||||||
|
O, // initial state
|
||||||
|
R, // clockwise rotation
|
||||||
|
L, // counter-clockwise rotation
|
||||||
|
U, // 180 deg rotation
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RotationState {
|
||||||
|
fn default() -> Self {
|
||||||
|
RotationState::O
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Position {
|
||||||
|
pub x: usize,
|
||||||
|
pub y: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Position {
|
||||||
|
pub fn new(x: usize, y: usize) -> Position {
|
||||||
|
Self {
|
||||||
|
x: x as usize,
|
||||||
|
y: y as usize,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn offset(&self, x: isize, y: isize) -> Position {
|
||||||
|
Self {
|
||||||
|
x: (x + self.x as isize) as usize,
|
||||||
|
y: (y + self.y as isize) as usize,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Tetromino {
|
||||||
|
pub position: Position,
|
||||||
|
pub piece_type: TetrominoType,
|
||||||
|
rotation_state: RotationState,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tetromino {
|
||||||
|
pub fn new(tetromino_type: TetrominoType) -> Self {
|
||||||
|
Self {
|
||||||
|
position: Self::get_start_position(tetromino_type),
|
||||||
|
piece_type: tetromino_type,
|
||||||
|
rotation_state: RotationState::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_next_occupied_spaces(&self) -> Vec<Position> {
|
||||||
|
self.get_occupied_spaces(self.position.offset(0, 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_cur_occupied_spaces(&self) -> Vec<Position> {
|
||||||
|
self.get_occupied_spaces(self.position)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_color(&self) -> MinoColor {
|
||||||
|
match self.piece_type {
|
||||||
|
TetrominoType::I => MinoColor::Cyan,
|
||||||
|
TetrominoType::O => MinoColor::Yellow,
|
||||||
|
TetrominoType::T => MinoColor::Purple,
|
||||||
|
TetrominoType::S => MinoColor::Green,
|
||||||
|
TetrominoType::Z => MinoColor::Red,
|
||||||
|
TetrominoType::J => MinoColor::Blue,
|
||||||
|
TetrominoType::L => MinoColor::Orange,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_start_position(tetromino_type: TetrominoType) -> Position {
|
||||||
|
if tetromino_type == TetrominoType::I {
|
||||||
|
Position::new(PLAYFIELD_WIDTH / 2 - 1, PLAYFIELD_HEIGHT - 1)
|
||||||
|
} else {
|
||||||
|
Position::new(PLAYFIELD_WIDTH / 2 - 1, PLAYFIELD_HEIGHT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_occupied_spaces(&self, center: Position) -> Vec<Position> {
|
||||||
|
let mut spaces = vec![center];
|
||||||
|
match self.piece_type {
|
||||||
|
TetrominoType::I => match self.rotation_state {
|
||||||
|
RotationState::O => spaces.extend_from_slice(&[
|
||||||
|
center.offset(-1, 0),
|
||||||
|
center.offset(1, 0),
|
||||||
|
center.offset(2, 0),
|
||||||
|
]),
|
||||||
|
RotationState::R => spaces.extend_from_slice(&[
|
||||||
|
center.offset(0, -1),
|
||||||
|
center.offset(0, 1),
|
||||||
|
center.offset(0, 2),
|
||||||
|
]),
|
||||||
|
RotationState::L => todo!(),
|
||||||
|
RotationState::U => todo!(),
|
||||||
|
},
|
||||||
|
TetrominoType::J => match self.rotation_state {
|
||||||
|
RotationState::O => spaces.extend_from_slice(&[
|
||||||
|
center.offset(-1, -1),
|
||||||
|
center.offset(-1, 0),
|
||||||
|
center.offset(1, 0),
|
||||||
|
]),
|
||||||
|
RotationState::R => todo!(),
|
||||||
|
RotationState::L => todo!(),
|
||||||
|
RotationState::U => todo!(),
|
||||||
|
},
|
||||||
|
TetrominoType::L => match self.rotation_state {
|
||||||
|
RotationState::O => spaces.extend_from_slice(&[
|
||||||
|
center.offset(1, -1),
|
||||||
|
center.offset(-1, 0),
|
||||||
|
center.offset(1, 0),
|
||||||
|
]),
|
||||||
|
RotationState::R => todo!(),
|
||||||
|
RotationState::L => todo!(),
|
||||||
|
RotationState::U => todo!(),
|
||||||
|
},
|
||||||
|
TetrominoType::O => match self.rotation_state {
|
||||||
|
RotationState::O => spaces.extend_from_slice(&[
|
||||||
|
center.offset(0, -1),
|
||||||
|
center.offset(1, -1),
|
||||||
|
center.offset(1, 0),
|
||||||
|
]),
|
||||||
|
RotationState::R => todo!(),
|
||||||
|
RotationState::L => todo!(),
|
||||||
|
RotationState::U => todo!(),
|
||||||
|
},
|
||||||
|
TetrominoType::S => match self.rotation_state {
|
||||||
|
RotationState::O => spaces.extend_from_slice(&[
|
||||||
|
center.offset(0, -1),
|
||||||
|
center.offset(1, -1),
|
||||||
|
center.offset(-1, 0),
|
||||||
|
]),
|
||||||
|
RotationState::R => todo!(),
|
||||||
|
RotationState::L => todo!(),
|
||||||
|
RotationState::U => todo!(),
|
||||||
|
},
|
||||||
|
TetrominoType::T => match self.rotation_state {
|
||||||
|
RotationState::O => spaces.extend_from_slice(&[
|
||||||
|
center.offset(0, -1),
|
||||||
|
center.offset(-1, 0),
|
||||||
|
center.offset(1, 0),
|
||||||
|
]),
|
||||||
|
RotationState::R => todo!(),
|
||||||
|
RotationState::L => todo!(),
|
||||||
|
RotationState::U => todo!(),
|
||||||
|
},
|
||||||
|
TetrominoType::Z => match self.rotation_state {
|
||||||
|
RotationState::O => spaces.extend_from_slice(&[
|
||||||
|
center.offset(-1, -1),
|
||||||
|
center.offset(0, -1),
|
||||||
|
center.offset(1, 0),
|
||||||
|
]),
|
||||||
|
RotationState::R => todo!(),
|
||||||
|
RotationState::L => todo!(),
|
||||||
|
RotationState::U => todo!(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
spaces
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TetrominoType> for Tetromino {
|
||||||
|
fn from(tetromino_type: TetrominoType) -> Self {
|
||||||
|
Self::new(tetromino_type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Renderable for Tetromino {
|
||||||
|
fn render(&self, canvas: &mut Canvas<Window>) -> Result<(), String> {
|
||||||
|
for Position { x, y } in self.get_cur_occupied_spaces() {
|
||||||
|
canvas.set_draw_color(self.piece_type);
|
||||||
|
let height = y as isize - PLAYFIELD_HEIGHT as isize;
|
||||||
|
canvas.fill_rect(Rect::new(32 * x as i32 + 2, 32 * height as i32 + 2, 28, 28))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue